Blood-Asp / GT5-Unofficial

Decompiled and modified version of GT5.07.07
160 stars 97 forks source link

Several issues about large plasma generator #721

Closed Anikilulala closed 7 years ago

Anikilulala commented 8 years ago

HI, I'm playing newest version of Gregtech5U and meeting with some unexpected plasma generator explosions. I spent some time looking into the code ,and found some problem that might cause these unexpected explosions. 1.Optflow calculated in the code is NOT same with GUI description.

 aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Gas flow(EU burnvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 50) + EnumChatFormatting.GRAY + "EU/t");
aList.add(tOffset + 3, EnumChatFormatting.WHITE + "Optimal Plasma flow(Plasma energyvalue per tick): " + EnumChatFormatting.LIGHT_PURPLE + Math.max(Float.MIN_NORMAL, tStats.getSpeedMultiplier() * getPrimaryMaterial(aStack).mToolSpeed * 1000) + EnumChatFormatting.GRAY + "EU/t");

GUI says the optimal flow of a plasma generator is 20 times as a gas generator. But actually it's 40 times:

aOptFlow *= 40;

2.FLOAT to INT conversion. Some high energy plasma have huge amount of Eu per L. That means conversion from FLOAT to INT may greatly changes the EU/T output.

actualOptimalFlow = (int) ((aOptFlow + fuelValue - 1) / fuelValue);

Assuming we are using nickel plasma and a 30000 EU/T 100% EFF turbine. aOptFlow/fuelValue=30000/59392=0.5 less than 1. actualOptimalFlow=1 EU/T=59392 .If we are using a LUV output, it will explode as soon as the machine running efficiency reaches about 50%. That means Eu/t output could be much higher than OptimalFlow(EU/T) * turbine efficiency.

3 UP TO 125% COST RULE As the example mentioned above suggests, if aOptFlow/fuelValue is small enough , the 125% COST RULE will be no longer reasonable.

I tried to do little code in order to solve those issues, so far it seems working all right, but i'm not sure, may need further tests. Here is the code:

Anikilulala commented 8 years ago
aOptFlow *= 40;  // should be 20?
        int tEU = 0;

        int actualOptimalFlow = 0;
        float computeOptFlow = 0;
        float chanceFlow =0;

        if (aFluids.size() >= 1) {
            FluidStack firstFuelType = new FluidStack(aFluids.get(0), 0); // Identify a SINGLE type of fluid to process.  Doesn't matter which one. Ignore the rest!
            int fuelValue = getFuelValue(firstFuelType);
            // actualOptimalFlow = (int) ((aOptFlow + fuelValue - 1) / fuelValue);

            computeOptFlow= (float)aOptFlow / (float)fuelValue;
            actualOptimalFlow = (int) ((aOptFlow) / fuelValue);
            chanceFlow = computeOptFlow - actualOptimalFlow;
            if(chanceFlow > 0 && (chanceFlow * 1013+1 ) > (System.currentTimeMillis() % 1013)) {
                actualOptimalFlow+=1; 
            }// 1013 is a prime number to avoid meet same time cycle of one tick . Plus 1 to avoid chanceFlow too small.

            this.realOptFlow = actualOptimalFlow; // For scanner info

            //int remainingFlow = (int) (actualOptimalFlow * 1.25f); // Allowed to use up to 125% of optimal flow.  Variable required outside of loop for multi-hatch scenarios.
            int remainingFlow = (int) (actualOptimalFlow);

            int flow = 0;
            int totalFlow = 0;

            int aFluids_sS=aFluids.size();
            for (int i = 0; i < aFluids_sS; i++) {
                if (aFluids.get(i).isFluidEqual(firstFuelType)) {
                    flow = aFluids.get(i).amount; // Get all (steam) in hatch
                    //flow = Math.min(flow, Math.min(remainingFlow, (int) (actualOptimalFlow * 1.25f))); // try to use up to 125% of optimal flow w/o exceeding remainingFlow
                    flow = Math.min(flow, Math.min(remainingFlow, (int) (actualOptimalFlow)));
                    depleteInput(new FluidStack(aFluids.get(i), flow)); // deplete that amount
                    this.storedFluid = aFluids.get(i).amount;
                    remainingFlow -= flow; // track amount we're allowed to continue depleting from hatches
                    totalFlow += flow; // track total input used
                }
            }
            String fn = FluidRegistry.getFluidName(firstFuelType);
            String[] nameSegments = fn.split("\\.",2);
            if (nameSegments.length==2){
                String outputName=nameSegments[1];
                FluidStack output = FluidRegistry.getFluidStack(outputName, totalFlow);
                if (output==null){
                    output = FluidRegistry.getFluidStack("molten."+outputName, totalFlow);
                }
                if (output!=null) {
                    addOutput(output);
                }
            }

            //tEU = (int) (Math.min((float) actualOptimalFlow, totalFlow) * fuelValue);
            tEU = (int) (Math.min((float) computeOptFlow, totalFlow) * fuelValue);

            if (totalFlow != actualOptimalFlow) {
                float efficiency = 1.0f - Math.abs(((totalFlow - (float) actualOptimalFlow) / actualOptimalFlow));
                if(totalFlow>aOptFlow){efficiency = 1.0f;}
                if (efficiency < 0)
                    efficiency = 0; // Can happen with really ludicrously poor inefficiency.
                tEU *= efficiency;
                tEU = Math.max(1, (int)((long)tEU * (long)aBaseEff / 10000L));
            } else {
                tEU = (int)((long)tEU * (long)aBaseEff / 10000L);
            }

            return tEU;

        }
        return 0;

Here is a new float variable called computeOptFlow, which is used to calculate the eu/t .It could make sure the eu/t will NOT be affected by the FLOAT to INT conversion. Also I have defined chanceFlow to solve the float part of fuel cost. 1.6 L/t means 60% chance consumes 2L and 40% chance consumes 1L. 2 * 0.6+1 * 0.4=1.6 . Fuel and energy is balance in statistics meaning. Notice the code above is not include 125% rule, although it is not too difficult in coding, but it seems impossible do exactly control in gameplay if aOptFlow/fuelValue is small enough. So i have not do this part of code.

Blood-Asp commented 7 years ago

The 20/40 times optimal flow of gas turbine was a tooltip error and is fixed.

Having these issues with the too slow flow would mean it is recommended to use bigger rotors. The large turbines are meant to be complicated to set up, so the efficiency gain compared to the single block generators is balanced.

Anikilulala commented 7 years ago

For large generators such as gas and steam, a larger rotor may works. But for plasma generator, things are not so easy. Even the largest rotor seems not big enough. Also a smallest rotor could produce 60k Eu per tick almost the same with the big one. The result is, if using the highest plasma fuel ,all rotor of different outflow are all the same…

Anikilulala commented 7 years ago

For large generators such as gas and steam, a larger rotor may works. But for plasma generator, things are not so easy. Even the largest rotor seems not big enough. Also a smallest rotor could produce 60k Eu per tick almost the same with the big one. The result is, if using the highest plasma fuel ,all rotor of different optflow are all the same…