From 549ecc091775678a7f8cecac105bdb75cb83475c Mon Sep 17 00:00:00 2001 From: Boblet Date: Thu, 24 Aug 2023 16:38:55 +0200 Subject: [PATCH] fancier PWR gauges, larger PWRs, fixes, finite corium fluid --- changelog | 8 ++ src/main/java/com/hbm/blocks/ModBlocks.java | 2 +- .../com/hbm/blocks/fluid/CoriumFinite.java | 84 ++++++++++++++++++ .../blocks/machine/MachinePWRController.java | 12 ++- .../entity/projectile/EntityThrowableNT.java | 2 +- .../java/com/hbm/extprop/HbmPlayerProps.java | 4 + .../java/com/hbm/inventory/gui/GUIPWR.java | 42 ++++++++- .../java/com/hbm/main/ModEventHandler.java | 7 +- .../machine/TileEntityPWRController.java | 2 +- .../machine/rbmk/TileEntityRBMKRod.java | 8 +- .../hbm/textures/gui/reactors/gui_pwr.png | Bin 5927 -> 5847 bytes 11 files changed, 153 insertions(+), 18 deletions(-) create mode 100644 src/main/java/com/hbm/blocks/fluid/CoriumFinite.java diff --git a/changelog b/changelog index 868f93cb8..3b57b26e4 100644 --- a/changelog +++ b/changelog @@ -10,6 +10,10 @@ * Liquid sodium * Valid PWR coolant with high efficiency rating * Made by liquefacting sodium +* Liquid thorium salt + * Valid PWR coolant + * Has a high flux multiplication rate, boosting fuels + * After cooling, the depleted salt has to be reprocessed using a chemical plant ## Changed * Bedrock fluorite ore now yields actual ore instead of fluorite directly @@ -18,6 +22,7 @@ * The automatic buzzsaw can now use wood oil, ethanol, fish oil and heavy oil to run * Fluorite ore is now centrifugable * Fluorite crystals now centrifuge into slightly less fluorite but also yield sodalite +* Blast resistance values for most resistant blocks have been changed, most blocks now have much lower resistance which means there's now a practical difference between concrete and ducrete. Resistance values also match the block's cost more closely. ## Fixed * Fixed FEnSU's IO limit not working properly @@ -28,3 +33,6 @@ * Fixed blast furnace output overstacking * Fixed potential crash caused by centrifuges trying to create a recipe using non-registered items * Fixed chemplant GUI crashing when too many upgrades are applied to a short duration recipe +* Corium is now a finite fluid, fixing an issue where a single fuel rod can be used to create a giant blob of corium, lagging out the server +* Fixed bullets not being able to pass things like tall grass +* Whether the player has received a guide book is now saved as part of the extprop which might fix an issue where offline mode players get a new book on every start diff --git a/src/main/java/com/hbm/blocks/ModBlocks.java b/src/main/java/com/hbm/blocks/ModBlocks.java index c9ab74c54..ecd81f4fd 100644 --- a/src/main/java/com/hbm/blocks/ModBlocks.java +++ b/src/main/java/com/hbm/blocks/ModBlocks.java @@ -2384,7 +2384,7 @@ public class ModBlocks { corium_fluid = new CoriumFluid().setDensity(600000).setViscosity(12000).setLuminosity(10).setTemperature(1500).setUnlocalizedName("corium_fluid"); FluidRegistry.registerFluid(corium_fluid); - corium_block = new CoriumBlock(corium_fluid, fluidcorium).setBlockName("corium_block").setResistance(500F); + corium_block = new CoriumFinite(corium_fluid, fluidcorium).setBlockName("corium_block").setResistance(500F); volcanic_lava_fluid = new VolcanicFluid().setLuminosity(15).setDensity(3000).setViscosity(3000).setTemperature(1300).setUnlocalizedName("volcanic_lava_fluid"); FluidRegistry.registerFluid(volcanic_lava_fluid); diff --git a/src/main/java/com/hbm/blocks/fluid/CoriumFinite.java b/src/main/java/com/hbm/blocks/fluid/CoriumFinite.java new file mode 100644 index 000000000..1861e41b9 --- /dev/null +++ b/src/main/java/com/hbm/blocks/fluid/CoriumFinite.java @@ -0,0 +1,84 @@ +package com.hbm.blocks.fluid; + +import java.util.Random; + +import com.hbm.blocks.ModBlocks; +import com.hbm.lib.ModDamageSource; +import com.hbm.util.ContaminationUtil; +import com.hbm.util.ContaminationUtil.ContaminationType; +import com.hbm.util.ContaminationUtil.HazardType; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; + +public class CoriumFinite extends GenericFiniteFluid { + + public CoriumFinite(Fluid fluid, Material material) { + super(fluid, material, "corium_still", "corium_flowing"); + setQuantaPerBlock(5); + this.tickRate = 30; + } + + @Override + public boolean canDisplace(IBlockAccess world, int x, int y, int z) { + Block b = world.getBlock(x, y, z); + float res = (float) (Math.sqrt(b.getExplosionResistance(null)) * 3); + + if(res < 1) + return true; + Random rand = new Random(); + + return b.getMaterial().isLiquid() || rand.nextInt((int) res) == 0; + } + + @Override + public boolean displaceIfPossible(World world, int x, int y, int z) { + + if(world.getBlock(x, y, z).getMaterial().isLiquid()) { + return false; + } + return canDisplace(world, x, y, z); + } + + @Override + public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) { + entity.setInWeb(); + entity.setFire(3); + entity.attackEntityFrom(ModDamageSource.radiation, 2F); + + if(entity instanceof EntityLivingBase) + ContaminationUtil.contaminate((EntityLivingBase)entity, HazardType.RADIATION, ContaminationType.CREATIVE, 1F); + } + + @Override + public void updateTick(World world, int x, int y, int z, Random rand) { + + super.updateTick(world, x, y, z, rand); + + if(!world.isRemote && rand.nextInt(10) == 0 && world.getBlock(x, y - 1, z) != this) { + + if(rand.nextInt(3) == 0) + world.setBlock(x, y, z, ModBlocks.block_corium); + else + world.setBlock(x, y, z, ModBlocks.block_corium_cobble); + } + } + + @Override + @SideOnly(Side.CLIENT) + public int getRenderBlockPass() { + return 0; + } + + @Override + public boolean isReplaceable(IBlockAccess world, int x, int y, int z) { + return false; + } +} diff --git a/src/main/java/com/hbm/blocks/machine/MachinePWRController.java b/src/main/java/com/hbm/blocks/machine/MachinePWRController.java index 1f2580451..e40163c91 100644 --- a/src/main/java/com/hbm/blocks/machine/MachinePWRController.java +++ b/src/main/java/com/hbm/blocks/machine/MachinePWRController.java @@ -94,7 +94,7 @@ public class MachinePWRController extends BlockContainer implements ITooltipProv private static HashMap fuelRods = new HashMap(); private static HashMap sources = new HashMap(); private static boolean errored; - private static final int maxSize = 1024; + private static final int maxSize = 4096; public void assemble(World world, int x, int y, int z, EntityPlayer player) { assembly.clear(); @@ -107,7 +107,15 @@ public class MachinePWRController extends BlockContainer implements ITooltipProv errored = false; floodFill(world, x + dir.offsetX, y, z + dir.offsetZ, player); - if(fuelRods.size() == 0 || sources.size() == 0) errored = true; + if(fuelRods.size() == 0){ + sendError(world, x, y, z, "Fuel rods required", player); + errored = true; + } + + if(sources.size() == 0) { + sendError(world, x, y, z, "Neutron sources required", player); + errored = true; + } TileEntityPWRController controller = (TileEntityPWRController) world.getTileEntity(x, y, z); diff --git a/src/main/java/com/hbm/entity/projectile/EntityThrowableNT.java b/src/main/java/com/hbm/entity/projectile/EntityThrowableNT.java index 15cda441f..c07a22bd8 100644 --- a/src/main/java/com/hbm/entity/projectile/EntityThrowableNT.java +++ b/src/main/java/com/hbm/entity/projectile/EntityThrowableNT.java @@ -177,7 +177,7 @@ public abstract class EntityThrowableNT extends Entity implements IProjectile { Vec3 pos = Vec3.createVectorHelper(this.posX, this.posY, this.posZ); Vec3 nextPos = Vec3.createVectorHelper(this.posX + this.motionX * motionMult(), this.posY + this.motionY * motionMult(), this.posZ + this.motionZ * motionMult()); MovingObjectPosition mop = null; - if(!this.isSpectral()) mop = this.worldObj.rayTraceBlocks(pos, nextPos); + if(!this.isSpectral()) mop = this.worldObj.func_147447_a(pos, nextPos, false, true, false); pos = Vec3.createVectorHelper(this.posX, this.posY, this.posZ); nextPos = Vec3.createVectorHelper(this.posX + this.motionX * motionMult(), this.posY + this.motionY * motionMult(), this.posZ + this.motionZ * motionMult()); diff --git a/src/main/java/com/hbm/extprop/HbmPlayerProps.java b/src/main/java/com/hbm/extprop/HbmPlayerProps.java index 63ee89a86..46d4c4a95 100644 --- a/src/main/java/com/hbm/extprop/HbmPlayerProps.java +++ b/src/main/java/com/hbm/extprop/HbmPlayerProps.java @@ -18,6 +18,8 @@ public class HbmPlayerProps implements IExtendedEntityProperties { public static final String key = "NTM_EXT_PLAYER"; public EntityPlayer player; + public boolean hasReceivedBook = false; + public boolean enableHUD = true; public boolean enableBackpack = true; @@ -150,6 +152,7 @@ public class HbmPlayerProps implements IExtendedEntityProperties { NBTTagCompound props = new NBTTagCompound(); + props.setBoolean("hasReceivedBook", hasReceivedBook); props.setFloat("shield", shield); props.setFloat("maxShield", maxShield); props.setBoolean("enableBackpack", enableBackpack); @@ -164,6 +167,7 @@ public class HbmPlayerProps implements IExtendedEntityProperties { NBTTagCompound props = (NBTTagCompound) nbt.getTag("HbmPlayerProps"); if(props != null) { + this.hasReceivedBook = props.getBoolean("hasReceivedBook"); this.shield = props.getFloat("shield"); this.maxShield = props.getFloat("maxShield"); this.enableBackpack = props.getBoolean("enableBackpack"); diff --git a/src/main/java/com/hbm/inventory/gui/GUIPWR.java b/src/main/java/com/hbm/inventory/gui/GUIPWR.java index b8888ec02..1b88a5084 100644 --- a/src/main/java/com/hbm/inventory/gui/GUIPWR.java +++ b/src/main/java/com/hbm/inventory/gui/GUIPWR.java @@ -9,8 +9,6 @@ import com.hbm.items.ModItems; import com.hbm.lib.RefStrings; import com.hbm.packet.NBTControlPacket; import com.hbm.packet.PacketDispatcher; -import com.hbm.render.util.GaugeUtil; -import com.hbm.render.util.GaugeUtil.Gauge; import com.hbm.tileentity.machine.TileEntityPWRController; import net.minecraft.client.Minecraft; @@ -18,6 +16,7 @@ import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; @@ -25,6 +24,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Vec3; public class GUIPWR extends GuiInfoContainer { @@ -118,8 +118,11 @@ public class GUIPWR extends GuiInfoContainer { int c = (int) (controller.rodLevel * 52 / 100); drawTexturedModalRect(guiLeft + 53, guiTop + 54, 176, 40, c, 2); - GaugeUtil.renderGauge(Gauge.ROUND_SMALL, guiLeft + 115, guiTop + 31, this.zLevel, (double) controller.coreHeat / (double) controller.coreHeatCapacity); - GaugeUtil.renderGauge(Gauge.ROUND_SMALL, guiLeft + 151, guiTop + 31, this.zLevel, (double) controller.hullHeat / (double) controller.hullHeatCapacity); + //GaugeUtil.renderGauge(Gauge.ROUND_SMALL, guiLeft + 115, guiTop + 31, this.zLevel, (double) controller.coreHeat / (double) controller.coreHeatCapacity); + //GaugeUtil.renderGauge(Gauge.ROUND_SMALL, guiLeft + 151, guiTop + 31, this.zLevel, (double) controller.hullHeat / (double) controller.hullHeatCapacity); + + drawGauge(guiLeft + 124, guiTop + 40, (double) controller.coreHeat / (double) controller.coreHeatCapacity); + drawGauge(guiLeft + 160, guiTop + 40, (double) controller.hullHeat / (double) controller.hullHeatCapacity); if(controller.typeLoaded != -1 && controller.amountLoaded > 0) { ItemStack display = new ItemStack(ModItems.pwr_fuel, 1, controller.typeLoaded); @@ -135,6 +138,37 @@ public class GUIPWR extends GuiInfoContainer { this.field.drawTextBox(); } + + private void drawGauge(int x, int y, double d) { + GL11.glDisable(GL11.GL_TEXTURE_2D); + + d = MathHelper.clamp_double(d, 0, 1); + + float angle = (float) Math.toRadians(-d * 270 - 45); + Vec3 tip = Vec3.createVectorHelper(0, 5, 0); + Vec3 left = Vec3.createVectorHelper(1, -2, 0); + Vec3 right = Vec3.createVectorHelper(-1, -2, 0); + + tip.rotateAroundZ(angle); + left.rotateAroundZ(angle); + right.rotateAroundZ(angle); + + Tessellator tess = Tessellator.instance; + tess.startDrawing(GL11.GL_TRIANGLES); + tess.setColorOpaque_F(0F, 0F, 0F); + double mult = 1.5; + tess.addVertex(x + tip.xCoord * mult, y + tip.yCoord * mult, this.zLevel); + tess.addVertex(x + left.xCoord * mult, y + left.yCoord * mult, this.zLevel); + tess.addVertex(x + right.xCoord * mult, y + right.yCoord * mult, this.zLevel); + tess.setColorOpaque_F(0.75F, 0F, 0F); + tess.addVertex(x + tip.xCoord, y + tip.yCoord, this.zLevel); + tess.addVertex(x + left.xCoord, y + left.yCoord, this.zLevel); + tess.addVertex(x + right.xCoord, y + right.yCoord, this.zLevel); + tess.draw(); + + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glEnable(GL11.GL_TEXTURE_2D); + } @Override protected void mouseClicked(int mouseX, int mouseY, int i) { diff --git a/src/main/java/com/hbm/main/ModEventHandler.java b/src/main/java/com/hbm/main/ModEventHandler.java index 7197df144..9b99a5f7a 100644 --- a/src/main/java/com/hbm/main/ModEventHandler.java +++ b/src/main/java/com/hbm/main/ModEventHandler.java @@ -176,10 +176,13 @@ public class ModEventHandler { if(MobConfig.enableDucks && event.player instanceof EntityPlayerMP && !event.player.getEntityData().getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG).getBoolean("hasDucked")) PacketDispatcher.wrapper.sendTo(new PlayerInformPacket("Press O to Duck!", MainRegistry.proxy.ID_DUCK, 30_000), (EntityPlayerMP) event.player); - if(event.player instanceof EntityPlayerMP && !event.player.getEntityData().getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG).getBoolean("hasGuide")) { + + HbmPlayerProps props = HbmPlayerProps.getData(event.player); + + if(!props.hasReceivedBook) { event.player.inventory.addItemStackToInventory(new ItemStack(ModItems.book_guide, 1, BookType.STARTER.ordinal())); event.player.inventoryContainer.detectAndSendChanges(); - event.player.getEntityData().getCompoundTag(EntityPlayer.PERSISTED_NBT_TAG).setBoolean("hasGuide", true); + props.hasReceivedBook = true; } } } diff --git a/src/main/java/com/hbm/tileentity/machine/TileEntityPWRController.java b/src/main/java/com/hbm/tileentity/machine/TileEntityPWRController.java index 44fd69cf8..113669ab2 100644 --- a/src/main/java/com/hbm/tileentity/machine/TileEntityPWRController.java +++ b/src/main/java/com/hbm/tileentity/machine/TileEntityPWRController.java @@ -297,7 +297,7 @@ public class TileEntityPWRController extends TileEntityMachineBase implements IG double coolingEff = (double) this.channelCount / (double) this.rodCount * 0.1D; //10% cooling if numbers match if(coolingEff > 1D) coolingEff = 1D; - int heatToUse = (int) (this.hullHeat * coolingEff * trait.getEfficiency(HeatingType.PWR)); + int heatToUse = Math.min(this.hullHeat, (int) (this.hullHeat * coolingEff * trait.getEfficiency(HeatingType.PWR))); HeatingStep step = trait.getFirstStep(); int coolCycles = tanks[0].getFill() / step.amountReq; int hotCycles = (tanks[1].getMaxFill() - tanks[1].getFill()) / step.amountProduced; diff --git a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java index 9ec5ccd87..1b1f607d4 100644 --- a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java @@ -22,7 +22,6 @@ import li.cil.oc.api.machine.Context; import li.cil.oc.api.network.SimpleComponent; import net.minecraft.client.gui.GuiScreen; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; import net.minecraft.inventory.Container; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -305,12 +304,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM if(corium) { for(int i = h; i >= 0; i--) { - - if(i <= h + 1 - reduce) { - worldObj.setBlock(xCoord, yCoord + i, zCoord, ModBlocks.corium_block); - } else { - worldObj.setBlock(xCoord, yCoord + i, zCoord, Blocks.air); - } + worldObj.setBlock(xCoord, yCoord + i, zCoord, ModBlocks.corium_block, 5, 3); worldObj.markBlockForUpdate(xCoord, yCoord + i, zCoord); } diff --git a/src/main/resources/assets/hbm/textures/gui/reactors/gui_pwr.png b/src/main/resources/assets/hbm/textures/gui/reactors/gui_pwr.png index 6910df3ee915d9ac2b1ce46a822bff5d4b139ab1..a90a45e0cb94c64fb42c70e5978afcfd6f8ac843 100644 GIT binary patch literal 5847 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 qRSS}lTzmz3o163hMGO6L3<`F