From 970485f68c271bc5a199bf50ead099f9ef732f3b Mon Sep 17 00:00:00 2001 From: BallOfEnergy <66693744+BallOfEnergy1@users.noreply.github.com> Date: Mon, 4 Nov 2024 21:34:48 -0600 Subject: [PATCH] there's actually so many optimizations here that it'd be impossible for be to explain them all --- .../com/hbm/handler/ImpactWorldHandler.java | 28 +- .../hbm/handler/neutron/NeutronHandler.java | 74 ++ .../com/hbm/handler/neutron/NeutronNode.java | 6 + .../hbm/handler/neutron/NeutronNodeWorld.java | 8 +- .../hbm/handler/neutron/NeutronStream.java | 39 +- .../handler/neutron/PileNeutronHandler.java | 39 -- .../handler/neutron/RBMKNeutronHandler.java | 190 +++-- .../handler/threading/BufPacketThreading.java | 57 ++ .../java/com/hbm/main/ModEventHandler.java | 648 +++++++++--------- .../java/com/hbm/main/NetworkHandler.java | 79 +++ .../java/com/hbm/packet/PacketDispatcher.java | 12 +- .../com/hbm/packet/toclient/BufPacket.java | 11 +- .../hbm/tileentity/IBufPacketReceiver.java | 11 +- .../hbm/tileentity/TileEntityMachineBase.java | 3 +- .../tileentity/machine/rbmk/RBMKDials.java | 181 +++-- .../machine/rbmk/TileEntityRBMKRod.java | 41 +- .../machine/rbmk/TileEntityRBMKRodReaSim.java | 9 +- .../java/com/hbm/util/GameRuleHelper.java | 17 +- 18 files changed, 860 insertions(+), 593 deletions(-) create mode 100644 src/main/java/com/hbm/handler/neutron/NeutronHandler.java create mode 100644 src/main/java/com/hbm/handler/threading/BufPacketThreading.java create mode 100644 src/main/java/com/hbm/main/NetworkHandler.java diff --git a/src/main/java/com/hbm/handler/ImpactWorldHandler.java b/src/main/java/com/hbm/handler/ImpactWorldHandler.java index fc528fc6d..365f17cd4 100644 --- a/src/main/java/com/hbm/handler/ImpactWorldHandler.java +++ b/src/main/java/com/hbm/handler/ImpactWorldHandler.java @@ -31,28 +31,32 @@ public class ImpactWorldHandler { return; } + TomSaveData data = TomSaveData.forWorld(world); + + if (data.dust <= 0 && data.fire <= 0) + return; + WorldServer serv = (WorldServer) world; List list = serv.theChunkProviderServer.loadedChunks; int listSize = list.size(); - + if(listSize > 0) { for(int i = 0; i < 3; i++) { - + Chunk chunk = list.get(serv.rand.nextInt(listSize)); ChunkCoordIntPair coord = chunk.getChunkCoordIntPair(); - + for(int x = 0; x < 16; x++) { for(int z = 0; z < 16; z++) { - + if(world.rand.nextBoolean()) continue; - + int X = coord.getCenterXPos() - 8 + x; int Z = coord.getCenterZPosition() - 8 + z; int Y = world.getHeightValue(X, Z) - world.rand.nextInt(Math.max(1, world.getHeightValue(X, Z))); - TomSaveData data = TomSaveData.forWorld(world); - + if(data.dust > 0) { die(world, X, Y, Z); } @@ -70,7 +74,7 @@ public class ImpactWorldHandler { TomSaveData data = TomSaveData.forWorld(world); int light = Math.max(world.getSavedLightValue(EnumSkyBlock.Block, x, y + 1, z), (int) (world.getBlockLightValue(x, y + 1, z) * (1 - data.dust))); - + if(light < 4) { if(world.getBlock(x, y, z) == Blocks.grass) { world.setBlock(x, y, z, Blocks.dirt); @@ -86,18 +90,18 @@ public class ImpactWorldHandler { /// Burn the world. public static void burn(World world, int x, int y, int z) { - + Block b = world.getBlock(x, y, z); if(b.isFlammable(world, x, y, z, ForgeDirection.UP) && world.getBlock(x, y + 1, z) == Blocks.air && world.getSavedLightValue(EnumSkyBlock.Sky, x, y + 1, z) >= 7) { if(b instanceof BlockLeaves || b instanceof BlockBush) { world.setBlockToAir(x, y, z); } world.setBlock(x, y + 1, z, Blocks.fire); - + } else if((b == Blocks.grass || b == Blocks.mycelium || b == ModBlocks.waste_earth || b == ModBlocks.frozen_grass || b == ModBlocks.waste_mycelium) && !world.canLightningStrikeAt(x, y, z) && world.getSavedLightValue(EnumSkyBlock.Sky, x, y + 1, z) >= 7) { world.setBlock(x, y, z, ModBlocks.burning_earth); - + } else if(b == ModBlocks.frozen_dirt && world.getSavedLightValue(EnumSkyBlock.Sky, x, y + 1, z) >= 7) { world.setBlock(x, y, z, Blocks.dirt); } @@ -125,4 +129,4 @@ public class ImpactWorldHandler { if(world != lastSyncWorld) return false; return impact; } -} \ No newline at end of file +} diff --git a/src/main/java/com/hbm/handler/neutron/NeutronHandler.java b/src/main/java/com/hbm/handler/neutron/NeutronHandler.java new file mode 100644 index 000000000..a6bd17f4f --- /dev/null +++ b/src/main/java/com/hbm/handler/neutron/NeutronHandler.java @@ -0,0 +1,74 @@ +package com.hbm.handler.neutron; + +import com.hbm.tileentity.machine.rbmk.RBMKDials; +import com.hbm.util.fauxpointtwelve.BlockPos; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + +// General neutron handler because I didn't feel like having each handler class have its own interaction function. +public class NeutronHandler { + + private static int ticks = 0; + + public static void onWorldTick() { + // Remove `StreamWorld` objects if they have no streams. + { // aflghdkljghlkbhfjkghgilurbhlkfjghkffdjgn + List toRemove = new ArrayList<>(); + NeutronNodeWorld.streamWorlds.forEach((world, streamWorld) -> { + if (streamWorld.streams.isEmpty()) + toRemove.add(world); + }); + + for (World world : toRemove) { + NeutronNodeWorld.streamWorlds.remove(world); + } + } + + for (Map.Entry world : NeutronNodeWorld.streamWorlds.entrySet()) { + + // Gamerule caching because this apparently is kinda slow? + // meh, good enough + RBMKNeutronHandler.reflectorEfficiency = RBMKDials.getReflectorEfficiency(world.getKey()); + RBMKNeutronHandler.absorberEfficiency = RBMKDials.getAbsorberEfficiency(world.getKey()); + RBMKNeutronHandler.moderatorEfficiency = RBMKDials.getModeratorEfficiency(world.getKey()); + + // I hate this. + // this broke everything because it was ONE OFF + // IT'S NOT THE TOTAL HEIGHT IT'S THE AMOUNT OF BLOCKS ABOVE AAAAAAAAAAAAA + RBMKNeutronHandler.columnHeight = RBMKDials.getColumnHeight(world.getKey()) + 1; + RBMKNeutronHandler.fluxRange = RBMKDials.getFluxRange(world.getKey()); + + for (NeutronStream stream : world.getValue().streams) { + stream.runStreamInteraction(world.getKey()); + } + world.getValue().removeAllStreams(); + } + + // Freshen the node cache every `cacheTime` ticks to prevent huge RAM usage from idle nodes. + int cacheTime = 20; + if (ticks >= cacheTime) { + ticks = 0; + List toRemove = new ArrayList<>(); + for (NeutronNode cachedNode : NeutronNodeWorld.nodeCache.values()) { + if (cachedNode.type == NeutronStream.NeutronType.RBMK) { + RBMKNeutronHandler.RBMKNeutronNode node = (RBMKNeutronHandler.RBMKNeutronNode) cachedNode; + toRemove.addAll(node.checkNode()); + } + /* + if (cachedNode.type == NeutronStream.NeutronType.PILE) { + PileNeutronNode node = (PileNeutronNode) cachedNode; + toRemove.addAll(node.checkNode()); + } + */ + } + + toRemove.forEach(NeutronNodeWorld::removeNode); + + } + ticks++; + } +} diff --git a/src/main/java/com/hbm/handler/neutron/NeutronNode.java b/src/main/java/com/hbm/handler/neutron/NeutronNode.java index e85a14081..0c11d3a05 100644 --- a/src/main/java/com/hbm/handler/neutron/NeutronNode.java +++ b/src/main/java/com/hbm/handler/neutron/NeutronNode.java @@ -1,6 +1,7 @@ package com.hbm.handler.neutron; import com.hbm.handler.neutron.NeutronStream.NeutronType; +import com.hbm.util.fauxpointtwelve.BlockPos; import net.minecraft.tileentity.TileEntity; import java.util.HashMap; @@ -9,7 +10,11 @@ import java.util.Map; public abstract class NeutronNode { protected NeutronType type; + + protected BlockPos pos; + protected TileEntity tile; + // like NBT but less fucking CANCER // Holds things like cached RBMK lid values. protected Map data = new HashMap<>(); @@ -17,5 +22,6 @@ public abstract class NeutronNode { public NeutronNode(TileEntity tile, NeutronType type) { this.type = type; this.tile = tile; + this.pos = new BlockPos(tile); } } diff --git a/src/main/java/com/hbm/handler/neutron/NeutronNodeWorld.java b/src/main/java/com/hbm/handler/neutron/NeutronNodeWorld.java index 796589b6e..1f544ae7f 100644 --- a/src/main/java/com/hbm/handler/neutron/NeutronNodeWorld.java +++ b/src/main/java/com/hbm/handler/neutron/NeutronNodeWorld.java @@ -12,7 +12,7 @@ public class NeutronNodeWorld { protected static HashMap nodeCache = new HashMap<>(); public static void addNode(NeutronNode node) { - nodeCache.put(new BlockPos(node.tile), node); + nodeCache.put(node.pos, node); } public static void removeNode(BlockPos position) { @@ -54,9 +54,9 @@ public class NeutronNodeWorld { } toRemove.forEach((stream) -> streams.remove(stream)); } + } - public static void removeAllWorlds() { - streamWorlds.clear(); - } + public static void removeAllWorlds() { + streamWorlds.clear(); } } diff --git a/src/main/java/com/hbm/handler/neutron/NeutronStream.java b/src/main/java/com/hbm/handler/neutron/NeutronStream.java index 69b1d8eeb..7de1cc4aa 100644 --- a/src/main/java/com/hbm/handler/neutron/NeutronStream.java +++ b/src/main/java/com/hbm/handler/neutron/NeutronStream.java @@ -5,13 +5,12 @@ import net.minecraft.util.Vec3; import net.minecraft.world.World; import com.hbm.handler.neutron.NeutronNodeWorld.StreamWorld; -import java.util.ArrayList; -import java.util.List; +import java.util.Iterator; public abstract class NeutronStream { public enum NeutronType { - DUMMY, // Dummy streams for testing + DUMMY, // Dummy streams for node decaying RBMK, // RBMK neutron streams PILE // Chicago pile streams } @@ -34,11 +33,13 @@ public abstract class NeutronStream { public NeutronStream(NeutronNode origin, Vec3 vector) { this.origin = origin; this.vector = vector; + posInstance = origin.pos.clone(); } public NeutronStream(NeutronNode origin, Vec3 vector, double flux, double ratio, NeutronType type) { this.origin = origin; this.vector = vector; + posInstance = origin.pos.clone(); this.fluxQuantity = flux; this.fluxRatio = ratio; this.type = type; @@ -51,19 +52,31 @@ public abstract class NeutronStream { NeutronNodeWorld.streamWorlds.get(worldObj).addStream(this); } + protected BlockPos posInstance; + + private int i; + // USES THE CACHE!!! - public List getBlocks(int range) { - List positions = new ArrayList<>(); + public Iterator getBlocks(int range) { - for (int i = 1; i <= range; i++) { - int x = (int) Math.floor(0.5 + vector.xCoord * i); - int z = (int) Math.floor(0.5 + vector.zCoord * i); + i = 1; - BlockPos pos = new BlockPos(origin.tile).add(x, 0, z); - positions.add(pos); - } - return positions; + return new Iterator() { + @Override + public boolean hasNext() { + return i <= range; + } + + @Override + public BlockPos next() { + int x = (int) Math.floor(0.5 + vector.xCoord * i); + int z = (int) Math.floor(0.5 + vector.zCoord * i); + + i++; + return posInstance.mutate(origin.tile.xCoord + x, origin.tile.yCoord, origin.tile.zCoord + z); + } + }; } public abstract void runStreamInteraction(World worldObj); -} \ No newline at end of file +} diff --git a/src/main/java/com/hbm/handler/neutron/PileNeutronHandler.java b/src/main/java/com/hbm/handler/neutron/PileNeutronHandler.java index c38993127..965f1ed0b 100644 --- a/src/main/java/com/hbm/handler/neutron/PileNeutronHandler.java +++ b/src/main/java/com/hbm/handler/neutron/PileNeutronHandler.java @@ -12,9 +12,7 @@ import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.Vec3; import net.minecraft.world.World; -import java.util.ArrayList; import java.util.List; -import java.util.Map; public class PileNeutronHandler { @@ -41,10 +39,6 @@ public class PileNeutronHandler { public static class PileNeutronStream extends NeutronStream { - public PileNeutronStream(NeutronNode origin, Vec3 vector) { - super(origin, vector); - } - public PileNeutronStream(NeutronNode origin, Vec3 vector, double flux) { super(origin, vector, flux, 0D, NeutronType.PILE); } @@ -52,12 +46,6 @@ public class PileNeutronHandler { @Override public void runStreamInteraction(World worldObj) { - //Random rand = origin.tile.getWorldObj().rand; - //Vec3 vec = Vec3.createVectorHelper(1, 0, 0); - //vec.rotateAroundZ((float)(rand.nextDouble() * Math.PI * 2D)); - //vec.rotateAroundY((float)(rand.nextDouble() * Math.PI * 2D)); - //vec.rotateAroundX((float)(rand.nextDouble() * Math.PI * 2D)); - TileEntityPileBase originTE = (TileEntityPileBase) origin.tile; BlockPos pos = new BlockPos(originTE); @@ -126,31 +114,4 @@ public class PileNeutronHandler { } } } - - // The big one!! Runs all interactions for neutrons. - public static void runAllInteractions() { - - // Remove `StreamWorld` objects if they have no streams. - { // aflghdkljghlkbhfjkghgilurbhlkfjghkffdjgn - List toRemove = new ArrayList<>(); - NeutronNodeWorld.streamWorlds.forEach((world, streamWorld) -> { - if (streamWorld.streams.isEmpty()) - toRemove.add(world); - }); - - for (World world : toRemove) { - NeutronNodeWorld.streamWorlds.remove(world); - } - } - - for (Map.Entry world : NeutronNodeWorld.streamWorlds.entrySet()) { - - for (NeutronStream stream : world.getValue().streams) { - if (stream.type == NeutronStream.NeutronType.PILE) - stream.runStreamInteraction(world.getKey()); - } - world.getValue().removeAllStreamsOfType(NeutronStream.NeutronType.PILE); - } - - } } diff --git a/src/main/java/com/hbm/handler/neutron/RBMKNeutronHandler.java b/src/main/java/com/hbm/handler/neutron/RBMKNeutronHandler.java index d02c17629..437fd28c3 100644 --- a/src/main/java/com/hbm/handler/neutron/RBMKNeutronHandler.java +++ b/src/main/java/com/hbm/handler/neutron/RBMKNeutronHandler.java @@ -7,7 +7,7 @@ import com.hbm.util.fauxpointtwelve.BlockPos; import java.util.ArrayList; import java.util.List; -import java.util.Map.Entry; +import java.util.Iterator; import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; @@ -50,6 +50,7 @@ public class RBMKNeutronHandler { super(tile, NeutronStream.NeutronType.RBMK); this.data.put("hasLid", hasLid); this.data.put("type", type); + posInstance = new BlockPos(tile); } public void addLid() { @@ -60,13 +61,41 @@ public class RBMKNeutronHandler { this.data.replace("hasLid", false); } - public List getReaSimNodes() { - List list = new ArrayList<>(); - for (int x = -fluxRange; x <= fluxRange; x++) - for (int z = -fluxRange; z <= fluxRange; z++) - if (Math.pow(x, 2) + Math.pow(z, 2) <= fluxRange * fluxRange) - list.add(new BlockPos(tile).add(x, 0, z)); - return list; + protected BlockPos posInstance; + + private int x; + private int z; + + public Iterator getReaSimNodes() { + + x = -fluxRange; + z = -fluxRange; + + return new Iterator() { + @Override + public boolean hasNext() { + return (fluxRange + x) * (fluxRange * 2 + 1) + z + fluxRange + 1 < (fluxRange * 2 + 1) * (fluxRange * 2 + 1); + } + + @Override + public BlockPos next() { + if (Math.pow(x, 2) + Math.pow(z, 2) <= fluxRange * fluxRange) { + z++; + if (z > fluxRange) { + z = -fluxRange; + x++; + } + return posInstance.mutate(tile.xCoord + x, tile.yCoord, tile.zCoord + z); + } else { + z++; + if (z > fluxRange) { + z = -fluxRange; + x++; + } + return null; + } + } + }; } public List checkNode() { @@ -74,11 +103,12 @@ public class RBMKNeutronHandler { BlockPos pos = new BlockPos(this.tile); - List streams = new ArrayList<>(); + RBMKNeutronStream[] streams = new RBMKNeutronStream[TileEntityRBMKRod.fluxDirs.length]; // Simulate streams coming out of the RBMK rod. - for (ForgeDirection dir : TileEntityRBMKRod.fluxDirs) { - streams.add(new RBMKNeutronStream(this, Vec3.createVectorHelper(dir.offsetX, 0, dir.offsetZ))); + ForgeDirection[] fluxDirs = TileEntityRBMKRod.fluxDirs; + for (int i = 0; i < fluxDirs.length; i++) { + streams[i] = (new RBMKNeutronStream(this, Vec3.createVectorHelper(fluxDirs[i].offsetX, 0, fluxDirs[i].offsetZ))); } // Check if the rod should uncache nodes. @@ -87,38 +117,47 @@ public class RBMKNeutronHandler { if (!rod.hasRod || rod.lastFluxQuantity == 0) { for (RBMKNeutronStream stream : streams) { - stream.getNodes(false).forEach(node -> list.add(new BlockPos(node.tile))); + for(RBMKNeutronNode node : stream.getNodes(false)) + if (node != null) + list.add(new BlockPos(node.tile)); } return list; } } - List points = getReaSimNodes(); + { + Iterator reaSimNodes = getReaSimNodes(); - // Check if the ReaSim rod should be culled from the cache due to no rod or no flux. - if (tile instanceof TileEntityRBMKRodReaSim) { // fuckkkkkkk - TileEntityRBMKRodReaSim rod = (TileEntityRBMKRodReaSim) tile; - if (!rod.hasRod || rod.lastFluxQuantity == 0) { - list.addAll(points); - return list; + // Check if the ReaSim rod should be culled from the cache due to no rod or no flux. + if (tile instanceof TileEntityRBMKRodReaSim) { // fuckkkkkkk + TileEntityRBMKRodReaSim rod = (TileEntityRBMKRodReaSim) tile; + if (!rod.hasRod || rod.lastFluxQuantity == 0) { + reaSimNodes.forEachRemaining((a) -> { + if (a != null) + list.add(a.clone()); // ae The RAM usage will be really high here but hopefully the GC can take care of it :pray: + }); + return list; + } } } // Check if non-rod nodes should be uncached... but now with ReaSim! { // Yeah, I don't want to contaminate the surrounding scope. - List nodes = new ArrayList<>(); - points.forEach(nodePos -> { - RBMKNeutronNode node = (RBMKNeutronNode) NeutronNodeWorld.getNode(nodePos); - if (node != null) - nodes.add(node); - }); + Iterator reaSimNodes = getReaSimNodes(); boolean hasRod = false; - for (RBMKNeutronNode node : nodes) { + while(reaSimNodes.hasNext()) { - if (node.tile instanceof TileEntityRBMKRod) { + BlockPos nodePos = reaSimNodes.next(); + + if(nodePos == null) + continue; + + NeutronNode node = NeutronNodeWorld.nodeCache.get(nodePos); + + if (node != null && node.tile instanceof TileEntityRBMKRod) { TileEntityRBMKRod rod = (TileEntityRBMKRod) node.tile; @@ -129,7 +168,7 @@ public class RBMKNeutronHandler { } } - if (nodes.isEmpty() || !hasRod) { + if (!hasRod) { list.add(pos); return list; } @@ -138,10 +177,10 @@ public class RBMKNeutronHandler { // Check if non-rod nodes should be uncached due to no rod in range. for (RBMKNeutronStream stream : streams) { - List nodes = stream.getNodes(false); + RBMKNeutronNode[] nodes = stream.getNodes(false); for (RBMKNeutronNode node : nodes) { - if (node.tile instanceof TileEntityRBMKRod) + if (!(node == null) && node.tile instanceof TileEntityRBMKRod) return list; } } @@ -170,24 +209,26 @@ public class RBMKNeutronHandler { // Does NOT include the origin node // USES THE CACHE!!! - public List getNodes(boolean addNode) { - List positions = new ArrayList<>(); + public RBMKNeutronNode[] getNodes(boolean addNode) { + RBMKNeutronNode[] positions = new RBMKNeutronNode[fluxRange]; + + BlockPos pos = new BlockPos(origin.tile); for (int i = 1; i <= fluxRange; i++) { int x = (int) Math.floor(0.5 + vector.xCoord * i); int z = (int) Math.floor(0.5 + vector.zCoord * i); - BlockPos pos = new BlockPos(origin.tile).add(x, 0, z); + pos.mutate(origin.tile.xCoord + x, origin.tile.yCoord, origin.tile.zCoord + z); if (NeutronNodeWorld.nodeCache.containsKey(pos)) - positions.add((RBMKNeutronNode) NeutronNodeWorld.getNode(pos)); + positions[i - 1] = (RBMKNeutronNode) NeutronNodeWorld.getNode(pos); else if (this.origin.tile.getBlockType() instanceof RBMKBase) { TileEntity te = blockPosToTE(this.origin.tile.getWorldObj(), pos); if (te instanceof TileEntityRBMKBase) { TileEntityRBMKBase rbmkBase = (TileEntityRBMKBase) te; RBMKNeutronNode node = makeNode(rbmkBase); - positions.add(node); + positions[i - 1] = node; if (addNode) NeutronNodeWorld.addNode(node); } @@ -218,7 +259,11 @@ public class RBMKNeutronHandler { int moderatedCount = 0; - for (BlockPos nodePos : getBlocks(fluxRange)) { + Iterator iterator = getBlocks(fluxRange); + + while(iterator.hasNext()) { + + BlockPos nodePos = iterator.next(); if (fluxQuantity == 0D) // Whoops, used it all up! return; @@ -315,22 +360,26 @@ public class RBMKNeutronHandler { } } - List nodes = getNodes(true); - if (nodes.isEmpty()) - return; + RBMKNeutronNode[] nodes = getNodes(true); - RBMKNeutronNode lastNode = nodes.get(nodes.size() - 1); + RBMKNeutronNode lastNode = nodes[(nodes.length - 1)]; + + if(lastNode == null) { // This implies that there was *no* last node, meaning either way it was never caught. + // There is really no good way to figure out where exactly it should irradiate, so just irradiate at the origin tile. + irradiateFromFlux(new BlockPos(origin.tile.xCoord + this.vector.xCoord, origin.tile.yCoord, origin.tile.zCoord + this.vector.zCoord)); + return; + } RBMKType lastNodeType = (RBMKType) lastNode.data.get("type"); if (lastNodeType != RBMKType.REFLECTOR && lastNodeType != RBMKType.ABSORBER && lastNodeType != RBMKType.CONTROL_ROD) - irradiateFromFlux((new BlockPos(lastNode.tile)).add(this.vector.xCoord, 0.0D, this.vector.zCoord)); + irradiateFromFlux(new BlockPos(lastNode.tile.xCoord + this.vector.xCoord, lastNode.tile.yCoord, lastNode.tile.zCoord + this.vector.zCoord)); if (lastNodeType == RBMKType.CONTROL_ROD) { TileEntityRBMKControl rod = (TileEntityRBMKControl) lastNode.tile; if (rod.getMult() > 0.0D) { this.fluxQuantity *= rod.getMult(); - irradiateFromFlux((new BlockPos(lastNode.tile)).add(this.vector.xCoord, 0.0D, this.vector.zCoord)); + irradiateFromFlux(new BlockPos(lastNode.tile.xCoord + this.vector.xCoord, lastNode.tile.yCoord, lastNode.tile.zCoord + this.vector.zCoord)); } } } @@ -364,61 +413,4 @@ public class RBMKNeutronHandler { } } - - private static int ticks = 0; - - // The big one!! Runs all interactions for neutrons. - public static void runAllInteractions() { - - // Remove `StreamWorld` objects if they have no streams. - { // aflghdkljghlkbhfjkghgilurbhlkfjghkffdjgn - List toRemove = new ArrayList<>(); - NeutronNodeWorld.streamWorlds.forEach((world, streamWorld) -> { - if (streamWorld.streams.isEmpty()) - toRemove.add(world); - }); - - for (World world : toRemove) { - NeutronNodeWorld.streamWorlds.remove(world); - } - } - - for (Entry world : NeutronNodeWorld.streamWorlds.entrySet()) { - - // Gamerule caching because this apparently is kinda slow? - // meh, good enough - reflectorEfficiency = RBMKDials.getReflectorEfficiency(world.getKey()); - absorberEfficiency = RBMKDials.getAbsorberEfficiency(world.getKey()); - moderatorEfficiency = RBMKDials.getModeratorEfficiency(world.getKey()); - - // I hate this. - // this broke everything because it was ONE OFF - // IT'S NOT THE TOTAL HEIGHT IT'S THE AMOUNT OF BLOCKS ABOVE AAAAAAAAAAAAA - columnHeight = RBMKDials.getColumnHeight(world.getKey()) + 1; - fluxRange = RBMKDials.getFluxRange(world.getKey()); - - for (NeutronStream stream : world.getValue().streams) { - if (stream.type == NeutronStream.NeutronType.RBMK) - stream.runStreamInteraction(world.getKey()); - } - world.getValue().removeAllStreamsOfType(NeutronStream.NeutronType.RBMK); - } - - // Freshen the node cache every `cacheTime` ticks to prevent huge RAM usage. - int cacheTime = 40; - if (ticks >= cacheTime) { - ticks = 0; - List toRemove = new ArrayList<>(); - for(NeutronNode cachedNode : NeutronNodeWorld.nodeCache.values()) { - if (cachedNode.type == NeutronStream.NeutronType.RBMK) { - RBMKNeutronNode node = (RBMKNeutronNode) cachedNode; - toRemove.addAll(node.checkNode()); - } - } - - for(BlockPos pos : toRemove) - NeutronNodeWorld.removeNode(pos); - } - ticks++; - } } diff --git a/src/main/java/com/hbm/handler/threading/BufPacketThreading.java b/src/main/java/com/hbm/handler/threading/BufPacketThreading.java new file mode 100644 index 000000000..86400ae3c --- /dev/null +++ b/src/main/java/com/hbm/handler/threading/BufPacketThreading.java @@ -0,0 +1,57 @@ +package com.hbm.handler.threading; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.hbm.main.MainRegistry; +import com.hbm.packet.PacketDispatcher; +import com.hbm.packet.toclient.BufPacket; +import com.hbm.tileentity.IBufPacketReceiver; +import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import net.minecraft.tileentity.TileEntity; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.*; + +public class BufPacketThreading { + + private static final ThreadFactory packetThreadFactory = new ThreadFactoryBuilder().setNameFormat("NTM-Packet-Thread").build(); + + private static final ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(1, packetThreadFactory); + + private static int total = 0; + + private static final List> futureList = new ArrayList<>(); + + public static void createBufPacket(IMessage message, TargetPoint target) { + Runnable task = () -> PacketDispatcher.wrapper.sendToAllAround(message, target); + total++; + futureList.add(threadPool.submit(task)); + } + + public static void createBufPacket(IBufPacketReceiver that, int range) { + Runnable task = () -> { + TileEntity te = (TileEntity) that; + TargetPoint target = new TargetPoint(te.getWorldObj().provider.dimensionId, te.xCoord, te.yCoord, te.zCoord, range); + BufPacket message = new BufPacket(te.xCoord, te.yCoord, te.zCoord, that); + PacketDispatcher.wrapper.sendToAllAround(message, target); + }; + total++; + futureList.add(threadPool.submit(task)); + } + + public static void waitUntilThreadFinished() { + try { + for(Future future : futureList) { + future.get(200, TimeUnit.MILLISECONDS); // I HATE EVERYTHING + } + } catch (ExecutionException ignored) { + // impossible + } catch (TimeoutException e) { + MainRegistry.logger.warn("A packet has taken >200ms to process, discarding {}/{} ({}%) packets to prevent pausing of main thread.", threadPool.getQueue().size(), total, (double) (threadPool.getQueue().size() / total * 100)); + threadPool.getQueue().clear(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); // maybe not the best thing but it's gotta be here + } + } +} diff --git a/src/main/java/com/hbm/main/ModEventHandler.java b/src/main/java/com/hbm/main/ModEventHandler.java index a1c5b9cde..c86c2208f 100644 --- a/src/main/java/com/hbm/main/ModEventHandler.java +++ b/src/main/java/com/hbm/main/ModEventHandler.java @@ -9,9 +9,16 @@ import java.util.Map; import java.util.Random; import java.util.UUID; +import com.hbm.handler.neutron.NeutronHandler; import com.hbm.handler.neutron.NeutronNodeWorld; -import com.hbm.handler.neutron.PileNeutronHandler; -import com.hbm.handler.neutron.RBMKNeutronHandler; +import com.hbm.tileentity.machine.rbmk.RBMKDials; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import com.hbm.handler.threading.BufPacketThreading; +import net.minecraft.command.CommandGameRule; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraftforge.event.CommandEvent; import org.apache.commons.lang3.math.NumberUtils; import org.apache.logging.log4j.Level; @@ -142,17 +149,17 @@ import net.minecraftforge.event.world.BlockEvent.BreakEvent; import net.minecraftforge.event.world.WorldEvent; public class ModEventHandler { - + private static Random rand = new Random(); - + @SubscribeEvent public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { if(!event.player.worldObj.isRemote) { - + if(GeneralConfig.enableMOTD) { event.player.addChatMessage(new ChatComponentText("Loaded world with Hbm's Nuclear Tech Mod " + RefStrings.VERSION + " for Minecraft 1.7.10!")); - + if(HTTPHandler.newVersion) { event.player.addChatMessage( new ChatComponentText("New version " + HTTPHandler.versionNumber + " is available! Click ") @@ -168,14 +175,14 @@ 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(GeneralConfig.enableGuideBook) { 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(); @@ -184,17 +191,17 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { - + EntityPlayer player = event.player; - + if((player.getUniqueID().toString().equals(ShadyUtil.Dr_Nostalgia) || player.getDisplayName().equals("Dr_Nostalgia")) && !player.worldObj.isRemote) { - + if(!player.inventory.hasItem(ModItems.hat)) player.inventory.addItemStackToInventory(new ItemStack(ModItems.hat)); - + if(!player.inventory.hasItem(ModItems.beta)) player.inventory.addItemStackToInventory(new ItemStack(ModItems.beta)); } @@ -202,18 +209,18 @@ public class ModEventHandler { @SubscribeEvent public void onEntityConstructing(EntityEvent.EntityConstructing event) { - + if(event.entity instanceof EntityPlayer) { - + EntityPlayer player = (EntityPlayer) event.entity; HbmPlayerProps.getData(player); //this already calls the register method if it's null so no further action required - + if(event.entity == MainRegistry.proxy.me()) BlockAshes.ashes = 0; } - + if(event.entity instanceof EntityLivingBase) { - + EntityLivingBase living = (EntityLivingBase) event.entity; HbmLivingProps.getData(living); //ditto } @@ -226,44 +233,44 @@ public class ModEventHandler { data.setKeyPressed(EnumKeybind.JETPACK, false); data.setKeyPressed(EnumKeybind.DASH, false); } - + @SubscribeEvent(priority = EventPriority.HIGHEST) public void onEntityDeathFirst(LivingDeathEvent event) { - + for(int i = 1; i < 5; i++) { - + ItemStack stack = event.entityLiving.getEquipmentInSlot(i); - + if(stack != null && stack.getItem() instanceof ItemArmor && ArmorModHandler.hasMods(stack)) { - + ItemStack revive = ArmorModHandler.pryMods(stack)[ArmorModHandler.extra]; - + if(revive != null) { - + //Classic revive if(revive.getItem() instanceof ItemModRevive) { revive.setItemDamage(revive.getItemDamage() + 1); - + if(revive.getItemDamage() >= revive.getMaxDamage()) { ArmorModHandler.removeMod(stack, ArmorModHandler.extra); } else { ArmorModHandler.applyMod(stack, revive); } - + event.entityLiving.setHealth(event.entityLiving.getMaxHealth()); event.entityLiving.addPotionEffect(new PotionEffect(Potion.resistance.id, 60, 99)); event.setCanceled(true); return; } - + //Shackles if(revive.getItem() instanceof ItemModShackles && HbmLivingProps.getRadiation(event.entityLiving) < 1000F) { - + revive.setItemDamage(revive.getItemDamage() + 1); - + int dmg = revive.getItemDamage(); ArmorModHandler.applyMod(stack, revive); - + event.entityLiving.setHealth(event.entityLiving.getMaxHealth()); HbmLivingProps.incrementRadiation(event.entityLiving, dmg * dmg); event.setCanceled(true); @@ -272,104 +279,104 @@ public class ModEventHandler { } } } - + } - + @SubscribeEvent public void onEntityDeath(LivingDeathEvent event) { - + HbmLivingProps.setRadiation(event.entityLiving, 0); - + if(event.entity.worldObj.isRemote) return; - + if(GeneralConfig.enableCataclysm) { EntityBurningFOEQ foeq = new EntityBurningFOEQ(event.entity.worldObj); foeq.setPositionAndRotation(event.entity.posX, 500, event.entity.posZ, 0.0F, 0.0F); event.entity.worldObj.spawnEntityInWorld(foeq); } - + if(event.entity.getUniqueID().toString().equals(ShadyUtil.HbMinecraft) || event.entity.getCommandSenderName().equals("HbMinecraft")) { event.entity.dropItem(ModItems.book_of_, 1); } - + if(event.entity instanceof EntityCreeperTainted && event.source == ModDamageSource.boxcar) { - + for(Object o : event.entity.worldObj.getEntitiesWithinAABB(EntityPlayer.class, event.entity.boundingBox.expand(50, 50, 50))) { EntityPlayer player = (EntityPlayer)o; player.triggerAchievement(MainRegistry.bobHidden); } } - + if(!event.entityLiving.worldObj.isRemote) { - + if(event.source instanceof EntityDamageSource && ((EntityDamageSource)event.source).getEntity() instanceof EntityPlayer && !(((EntityDamageSource)event.source).getEntity() instanceof FakePlayer)) { - + if(event.entityLiving instanceof EntitySpider && event.entityLiving.getRNG().nextInt(500) == 0) { event.entityLiving.dropItem(ModItems.spider_milk, 1); } - + if(event.entityLiving instanceof EntityCaveSpider && event.entityLiving.getRNG().nextInt(100) == 0) { event.entityLiving.dropItem(ModItems.serum, 1); } - + if(event.entityLiving instanceof EntityAnimal && event.entityLiving.getRNG().nextInt(500) == 0) { event.entityLiving.dropItem(ModItems.bandaid, 1); } - + if(event.entityLiving instanceof IMob) { if(event.entityLiving.getRNG().nextInt(1000) == 0) event.entityLiving.dropItem(ModItems.heart_piece, 1); if(event.entityLiving.getRNG().nextInt(250) == 0) event.entityLiving.dropItem(ModItems.key_red_cracked, 1); if(event.entityLiving.getRNG().nextInt(250) == 0) event.entityLiving.dropItem(ModItems.launch_code_piece, 1); } - + if(event.entityLiving instanceof EntityCyberCrab && event.entityLiving.getRNG().nextInt(500) == 0) { event.entityLiving.dropItem(ModItems.wd40, 1); } } } } - + @SubscribeEvent(priority = EventPriority.LOWEST) public void onEntityDeathLast(LivingDeathEvent event) { - + if(event.entityLiving instanceof EntityPlayer) { - + EntityPlayer player = (EntityPlayer) event.entityLiving; - + for(int i = 0; i < player.inventory.getSizeInventory(); i++) { - + ItemStack stack = player.inventory.getStackInSlot(i); - + if(stack != null && stack.getItem() == ModItems.detonator_deadman) { - + if(stack.stackTagCompound != null) { - + int x = stack.stackTagCompound.getInteger("x"); int y = stack.stackTagCompound.getInteger("y"); int z = stack.stackTagCompound.getInteger("z"); if(!player.worldObj.isRemote && player.worldObj.getBlock(x, y, z) instanceof IBomb) { - + ((IBomb) player.worldObj.getBlock(x, y, z)).explode(player.worldObj, x, y, z); - + if(GeneralConfig.enableExtendedLogging) MainRegistry.logger.log(Level.INFO, "[DET] Tried to detonate block at " + x + " / " + y + " / " + z + " by dead man's switch from " + player.getDisplayName() + "!"); } - + player.inventory.setInventorySlotContents(i, null); } } } } } - + @SubscribeEvent public void decorateMob(LivingSpawnEvent event) { EntityLivingBase entity = event.entityLiving; World world = event.world; - + if(!MobConfig.enableMobGear || entity.isChild() || world.isRemote) return; @@ -388,7 +395,7 @@ public class ModEventHandler { entity.setCurrentItemOrArmor(4, new ItemStack(ModItems.mask_of_infamy, 1, world.rand.nextInt(100))); if(rand.nextInt(1024) == 0) entity.setCurrentItemOrArmor(3, new ItemStack(ModItems.starmetal_plate, 1, world.rand.nextInt(ModItems.starmetal_plate.getMaxDamage()))); - + if(rand.nextInt(128) == 0) entity.setCurrentItemOrArmor(0, new ItemStack(ModItems.pipe_lead, 1, world.rand.nextInt(100))); if(rand.nextInt(128) == 0) @@ -416,7 +423,7 @@ public class ModEventHandler { } if(rand.nextInt(64) == 0) entity.setCurrentItemOrArmor(3, new ItemStack(ModItems.steel_plate, 1, world.rand.nextInt(ModItems.steel_plate.getMaxDamage()))); - + float soot = PollutionHandler.getPollution(entity.worldObj, MathHelper.floor_double(event.x), MathHelper.floor_double(event.y), MathHelper.floor_double(event.z), PollutionType.SOOT); ItemStack bowReplacement = getSkelegun(soot, entity.worldObj.rand); if(bowReplacement != null) { @@ -462,7 +469,7 @@ public class ModEventHandler { entity.tasks.addTask(3, new EntityAIFireGun(entity)); } - + @SubscribeEvent public void addAITasks(EntityJoinWorldEvent event) { if(event.world.isRemote || !(event.entity instanceof EntityLiving)) return; @@ -474,96 +481,96 @@ public class ModEventHandler { addFireTask(living); } } - + @SubscribeEvent public void onItemToss(ItemTossEvent event) { - + ItemStack yeet = event.entityItem.getEntityItem(); - + if(yeet.getItem() instanceof ItemArmor && ArmorModHandler.hasMods(yeet)) { - + ItemStack[] mods = ArmorModHandler.pryMods(yeet); ItemStack cladding = mods[ArmorModHandler.cladding]; - + if(cladding != null && cladding.getItem() == ModItems.cladding_obsidian) { ReflectionHelper.setPrivateValue(Entity.class, event.entityItem, true, "field_149119_a", "field_83001_bt", "field_149500_a", "invulnerable"); } } - + if(yeet.getItem() == ModItems.bismuth_tool) { ReflectionHelper.setPrivateValue(Entity.class, event.entityItem, true, "field_149119_a", "field_83001_bt", "field_149500_a", "invulnerable"); } } - + @SubscribeEvent public void onLivingDrop(LivingDropsEvent event) { - + if(!event.entityLiving.worldObj.isRemote) { boolean contaminated = HbmLivingProps.getContagion(event.entityLiving) > 0; - + if(contaminated) { - + for(EntityItem item : event.drops) { ItemStack stack = item.getEntityItem(); - + if(!stack.hasTagCompound()) { stack.stackTagCompound = new NBTTagCompound(); } - + stack.stackTagCompound.setBoolean("ntmContagion", true); } } } } - + @SubscribeEvent public void onLivingUpdate(LivingUpdateEvent event) { - + ItemStack[] prevArmor = event.entityLiving.previousEquipment; - if(event.entityLiving instanceof EntityPlayer && prevArmor != null && event.entityLiving.getHeldItem() != null + if(event.entityLiving instanceof EntityPlayer && prevArmor != null && event.entityLiving.getHeldItem() != null && (prevArmor[0] == null || prevArmor[0].getItem() != event.entityLiving.getHeldItem().getItem()) && event.entityLiving.getHeldItem().getItem() instanceof IEquipReceiver) { ((IEquipReceiver)event.entityLiving.getHeldItem().getItem()).onEquip((EntityPlayer) event.entityLiving, event.entityLiving.getHeldItem()); } - + for(int i = 1; i < 5; i++) { - + ItemStack prev = prevArmor != null ? prevArmor[i] : null; ItemStack armor = event.entityLiving.getEquipmentInSlot(i); - + boolean reapply = prevArmor != null && !ItemStack.areItemStacksEqual(prev, armor); - + if(reapply) { - + if(prev != null && ArmorModHandler.hasMods(prev)) { - + for(ItemStack mod : ArmorModHandler.pryMods(prev)) { - + if(mod != null && mod.getItem() instanceof ItemArmorMod) { - + Multimap map = ((ItemArmorMod)mod.getItem()).getModifiers(prev); - + if(map != null) event.entityLiving.getAttributeMap().removeAttributeModifiers(map); } } } } - + if(armor != null && ArmorModHandler.hasMods(armor)) { - + for(ItemStack mod : ArmorModHandler.pryMods(armor)) { - + if(mod != null && mod.getItem() instanceof ItemArmorMod) { ((ItemArmorMod)mod.getItem()).modUpdate(event.entityLiving, armor); HazardSystem.applyHazards(mod, event.entityLiving); - + if(reapply) { - + Multimap map = ((ItemArmorMod)mod.getItem()).getModifiers(armor); - + if(map != null) event.entityLiving.getAttributeMap().applyAttributeModifiers(map); } @@ -571,14 +578,14 @@ public class ModEventHandler { } } } - + EntityEffectHandler.onUpdate(event.entityLiving); - + if(!event.entity.worldObj.isRemote && !(event.entityLiving instanceof EntityPlayer)) { HazardSystem.updateLivingInventory(event.entityLiving); } } - + @SubscribeEvent(priority = EventPriority.LOWEST) public void onLoad(WorldEvent.Load event) { BobmazonOfferFactory.init(); @@ -586,19 +593,19 @@ public class ModEventHandler { @SubscribeEvent public void onUnload(WorldEvent.Unload event) { - NeutronNodeWorld.StreamWorld.removeAllWorlds(); // Remove world from worlds when unloaded to avoid world issues. + NeutronNodeWorld.removeAllWorlds(); // Remove world from worlds when unloaded to avoid world issues. NeutronNodeWorld.removeAllNodes(); // Remove all nodes. } - + public static boolean didSit = false; public static Field reference = null; - + @SubscribeEvent public void worldTick(WorldTickEvent event) { - + /// RADIATION STUFF START /// if(event.world != null && !event.world.isRemote) { - + if(reference != null) { for(Object player : event.world.playerEntities) { if(((EntityPlayer) player).ridingEntity != null) { didSit = true; } @@ -607,37 +614,37 @@ public class ModEventHandler { try { reference.setFloat(null, (float) (rand.nextGaussian() * 0.1 + Math.PI)); } catch(Throwable e) { } } } - + int thunder = AuxSavedData.getThunder(event.world); - + if(thunder > 0) AuxSavedData.setThunder(event.world, thunder - 1); - + if(!event.world.loadedEntityList.isEmpty()) { - + List oList = new ArrayList(); oList.addAll(event.world.loadedEntityList); - + /** * REMOVE THIS V V V */ for(Object e : oList) { if(e instanceof EntityLivingBase) { - + //effect for radiation EntityLivingBase entity = (EntityLivingBase) e; - + if(entity instanceof EntityPlayer && ((EntityPlayer)entity).capabilities.isCreativeMode) continue; - + float eRad = HbmLivingProps.getRadiation(entity); - + if(entity.getClass().equals(EntityCreeper.class) && eRad >= 200 && entity.getHealth() > 0) { - + if(event.world.rand.nextInt(3) == 0 ) { EntityCreeperNuclear creep = new EntityCreeperNuclear(event.world); creep.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch); - + if(!entity.isDead) if(!event.world.isRemote) event.world.spawnEntityInWorld(creep); @@ -646,7 +653,7 @@ public class ModEventHandler { entity.attackEntityFrom(ModDamageSource.radiation, 100F); } continue; - + } else if(entity instanceof EntityCow && !(entity instanceof EntityMooshroom) && eRad >= 50) { EntityMooshroom creep = new EntityMooshroom(event.world); creep.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch); @@ -656,47 +663,47 @@ public class ModEventHandler { event.world.spawnEntityInWorld(creep); entity.setDead(); continue; - + } else if(entity instanceof EntityVillager && eRad >= 500) { EntityZombie creep = new EntityZombie(event.world); creep.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch); - + if(!entity.isDead) if(!event.world.isRemote) event.world.spawnEntityInWorld(creep); entity.setDead(); continue; } else if(entity.getClass().equals(EntityDuck.class) && eRad >= 200) { - + EntityQuackos quacc = new EntityQuackos(event.world); quacc.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch); - + if(!entity.isDead && !event.world.isRemote) event.world.spawnEntityInWorld(quacc); - + entity.setDead(); continue; } - + if(eRad < 200 || ContaminationUtil.isRadImmune(entity)) continue; - + if(eRad > 2500) HbmLivingProps.setRadiation(entity, 2500); - + if(eRad >= 1000) { entity.attackEntityFrom(ModDamageSource.radiation, 1000F); HbmLivingProps.setRadiation(entity, 0); - + if(entity.getHealth() > 0) { entity.setHealth(0); entity.onDeath(ModDamageSource.radiation); } - + if(entity instanceof EntityPlayer) ((EntityPlayer)entity).triggerAchievement(MainRegistry.achRadDeath); - + } else if(eRad >= 800) { if(event.world.rand.nextInt(300) == 0) entity.addPotionEffect(new PotionEffect(Potion.confusion.id, 5 * 30, 0)); @@ -708,7 +715,7 @@ public class ModEventHandler { entity.addPotionEffect(new PotionEffect(Potion.poison.id, 3 * 20, 2)); if(event.world.rand.nextInt(700) == 0) entity.addPotionEffect(new PotionEffect(Potion.wither.id, 3 * 20, 1)); - + } else if(eRad >= 600) { if(event.world.rand.nextInt(300) == 0) entity.addPotionEffect(new PotionEffect(Potion.confusion.id, 5 * 30, 0)); @@ -718,7 +725,7 @@ public class ModEventHandler { entity.addPotionEffect(new PotionEffect(Potion.weakness.id, 10 * 20, 2)); if(event.world.rand.nextInt(500) == 0) entity.addPotionEffect(new PotionEffect(Potion.poison.id, 3 * 20, 1)); - + } else if(eRad >= 400) { if(event.world.rand.nextInt(300) == 0) entity.addPotionEffect(new PotionEffect(Potion.confusion.id, 5 * 30, 0)); @@ -726,18 +733,18 @@ public class ModEventHandler { entity.addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 5 * 20, 0)); if(event.world.rand.nextInt(300) == 0) entity.addPotionEffect(new PotionEffect(Potion.weakness.id, 5 * 20, 1)); - + } else if(eRad >= 200) { if(event.world.rand.nextInt(300) == 0) entity.addPotionEffect(new PotionEffect(Potion.confusion.id, 5 * 20, 0)); if(event.world.rand.nextInt(500) == 0) entity.addPotionEffect(new PotionEffect(Potion.weakness.id, 5 * 20, 0)); - + if(entity instanceof EntityPlayer) ((EntityPlayer)entity).triggerAchievement(MainRegistry.achRadPoison); } } - + if(e instanceof EntityItem) { EntityItem item = (EntityItem) e; HazardSystem.updateDroppedItem(item); @@ -748,36 +755,36 @@ public class ModEventHandler { */ } /// RADIATION STUFF END /// - - + + if(event.phase == Phase.END) { EntityRailCarBase.updateMotion(event.world); } } - + if(event.phase == Phase.START) { BossSpawnHandler.rollTheDice(event.world); TimedGenerator.automaton(event.world, 100); } } - + @SubscribeEvent public void onEntityAttacked(LivingAttackEvent event) { - + EntityLivingBase e = event.entityLiving; if(e instanceof EntityPlayer) { - + EntityPlayer player = (EntityPlayer) e; - + if(ArmorUtil.checkArmor(player, ModItems.euphemium_helmet, ModItems.euphemium_plate, ModItems.euphemium_legs, ModItems.euphemium_boots)) { HbmPlayerProps.plink(player, "random.break", 0.5F, 1.0F + e.getRNG().nextFloat() * 0.5F); event.setCanceled(true); } - + if(player.inventory.armorInventory[2] != null && player.inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)player.inventory.armorInventory[2].getItem()).handleAttack(event); - + for(ItemStack stack : player.inventory.armorInventory) { if(stack != null && stack.getItem() instanceof IAttackHandler) { ((IAttackHandler)stack.getItem()).handleAttack(event, stack); @@ -785,16 +792,16 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void onEntityDamaged(LivingHurtEvent event) { - + EntityLivingBase e = event.entityLiving; - + if(e instanceof EntityPlayer) { - + EntityPlayer player = (EntityPlayer) e; - + HbmPlayerProps props = HbmPlayerProps.getData(player); if(props.shield > 0) { float reduce = Math.min(props.shield, event.ammount); @@ -803,35 +810,35 @@ public class ModEventHandler { } props.lastDamage = player.ticksExisted; } - + if(HbmLivingProps.getContagion(e) > 0 && event.ammount < 100) event.ammount *= 2F; - + /// ARMOR MODS /// for(int i = 1; i < 5; i++) { - + ItemStack armor = e.getEquipmentInSlot(i); - + if(armor != null && ArmorModHandler.hasMods(armor)) { - + for(ItemStack mod : ArmorModHandler.pryMods(armor)) { - + if(mod != null && mod.getItem() instanceof ItemArmorMod) { ((ItemArmorMod)mod.getItem()).modDamage(event, armor); } } } } - + if(e instanceof EntityPlayer) { - + EntityPlayer player = (EntityPlayer) e; - + /// FSB ARMOR /// if(player.inventory.armorInventory[2] != null && player.inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)player.inventory.armorInventory[2].getItem()).handleHurt(event); - - + + for(ItemStack stack : player.inventory.armorInventory) { if(stack != null && stack.getItem() instanceof IDamageHandler) { ((IDamageHandler)stack.getItem()).handleDamage(event, stack); @@ -839,103 +846,103 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void onPlayerFall(PlayerFlyableFallEvent event) { - + EntityPlayer e = event.entityPlayer; - + if(e.inventory.armorInventory[2] != null && e.inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)e.inventory.armorInventory[2].getItem()).handleFall(e); } - + @SubscribeEvent public void onPlayerPunch(AttackEntityEvent event) { - + EntityPlayer player = event.entityPlayer; ItemStack chestplate = player.inventory.armorInventory[2]; - + if(!player.worldObj.isRemote && player.getHeldItem() == null && chestplate != null && ArmorModHandler.hasMods(chestplate)) { ItemStack[] mods = ArmorModHandler.pryMods(chestplate); ItemStack servo = mods[ArmorModHandler.servos]; - + if(servo != null && servo.getItem() == ModItems.ballistic_gauntlet) { - + BulletConfiguration firedConfig = null; for(Integer config : HbmCollection.g12) { BulletConfiguration cfg = BulletConfigSyncingUtil.pullConfig(config); - + if(InventoryUtil.doesPlayerHaveAStack(player, cfg.ammo, true, true)) { firedConfig = cfg; break; } } - + if(firedConfig != null) { int bullets = firedConfig.bulletsMin; - + if(firedConfig.bulletsMax > firedConfig.bulletsMin) { bullets += player.getRNG().nextInt(firedConfig.bulletsMax - firedConfig.bulletsMin); } - + for(int i = 0; i < bullets; i++) { EntityBulletBaseNT bullet = new EntityBulletBaseNT(player.worldObj, BulletConfigSyncingUtil.getKey(firedConfig), player); player.worldObj.spawnEntityInWorld(bullet); } - + player.worldObj.playSoundAtEntity(player, "hbm:weapon.shotgunShoot", 1.0F, 1.0F); } } } } - + @SubscribeEvent public void onEntityJump(LivingJumpEvent event) { - + EntityLivingBase e = event.entityLiving; - + if(e instanceof EntityPlayer && ((EntityPlayer)e).inventory.armorInventory[2] != null && ((EntityPlayer)e).inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)((EntityPlayer)e).inventory.armorInventory[2].getItem()).handleJump((EntityPlayer)e); } - + @SubscribeEvent public void onEntityFall(LivingFallEvent event) { - + EntityLivingBase e = event.entityLiving; - + if(e instanceof EntityPlayer && ((EntityPlayer)e).inventory.armorInventory[2] != null && ((EntityPlayer)e).inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)((EntityPlayer)e).inventory.armorInventory[2].getItem()).handleFall((EntityPlayer)e); } - + private static final UUID fopSpeed = UUID.fromString("e5a8c95d-c7a0-4ecf-8126-76fb8c949389"); - + @SubscribeEvent public void onWingFlop(TickEvent.PlayerTickEvent event) { EntityPlayer player = event.player; - + if(event.phase == TickEvent.Phase.START) { - + if(player.getCurrentArmor(2) == null && !player.onGround) { - + if(player.getUniqueID().toString().equals(ShadyUtil.Barnaby99_x) || player.getDisplayName().equals("pheo7")) { ArmorUtil.resetFlightTime(player); HbmPlayerProps props = HbmPlayerProps.getData(player); - + if(props.isJetpackActive()) { - + if(player.motionY < 0.4D) player.motionY += 0.1D; - + Vec3 look = player.getLookVec(); - + if(Vec3.createVectorHelper(player.motionX, player.motionY, player.motionZ).lengthVector() < 2) { player.motionX += look.xCoord * 0.2; player.motionY += look.yCoord * 0.2; player.motionZ += look.zCoord * 0.2; - + if(look.yCoord > 0) player.fallDistance = 0; } @@ -944,42 +951,42 @@ public class ModEventHandler { if(player.fallDistance > 0) player.fallDistance = 0; } } - + boolean isBob = player.getUniqueID().toString().equals(ShadyUtil.HbMinecraft) || player.getDisplayName().equals("HbMinecraft"); boolean isOther = player.getUniqueID().toString().equals(ShadyUtil.the_NCR) || player.getDisplayName().equals("the_NCR"); - + if(isBob || isOther) { - + ArmorUtil.resetFlightTime(player); - + if(player.fallDistance > 0) player.fallDistance = 0; - + if(player.motionY < -0.4D) player.motionY = -0.4D; - + HbmPlayerProps props = HbmPlayerProps.getData(player); - + if(isBob || player.getFoodStats().getFoodLevel() > 6) { - + if(props.isJetpackActive()) { - + double cap = (isBob ? 0.8D : 0.4D); - + if(player.motionY < cap) player.motionY += 0.15D; else player.motionY = cap + 0.15D; - + if(isOther) { if(player.getFoodStats().getSaturationLevel() > 0F) player.addExhaustion(4F); //burn up saturation so that super-saturating foods have no effect else player.addExhaustion(0.2F); //4:1 -> 0.05 hunger per tick or 1 per second } - + } else if(props.enableBackpack && !player.isSneaking()) { - + if(player.motionY < -1) player.motionY += 0.4D; else if(player.motionY < -0.1) @@ -993,35 +1000,35 @@ public class ModEventHandler { else player.addExhaustion(0.04F); } - + } else if(!props.enableBackpack && player.isSneaking()) { - + if(player.motionY < -0.08) { - + double mo = player.motionY * (isBob ? -0.6 : -0.4); player.motionY += mo; - + Vec3 vec = player.getLookVec(); vec.xCoord *= mo; vec.yCoord *= mo; vec.zCoord *= mo; - + player.motionX += vec.xCoord; player.motionY += vec.yCoord; player.motionZ += vec.zCoord; } } } - + Vec3 orig = player.getLookVec(); Vec3 look = Vec3.createVectorHelper(orig.xCoord, 0, orig.zCoord).normalize(); double mod = props.enableBackpack ? (isBob ? 0.5D : 0.25D) : 0.125D; - + if(player.moveForward != 0) { player.motionX += look.xCoord * 0.35 * player.moveForward * mod; player.motionZ += look.zCoord * 0.35 * player.moveForward * mod; } - + if(player.moveStrafing != 0) { look.rotateAroundY((float) Math.PI * 0.5F); player.motionX += look.xCoord * 0.15 * player.moveStrafing * mod; @@ -1029,65 +1036,65 @@ public class ModEventHandler { } } } - + if(player.getUniqueID().toString().equals(ShadyUtil.LePeeperSauvage) || player.getDisplayName().equals("LePeeperSauvage")) { - + Multimap multimap = HashMultimap.create(); multimap.put(SharedMonsterAttributes.movementSpeed.getAttributeUnlocalizedName(), new AttributeModifier(fopSpeed, "FOP SPEED", 0.5, 1)); player.getAttributeMap().removeAttributeModifiers(multimap); - + if(player.isSprinting()) { player.getAttributeMap().applyAttributeModifiers(multimap); } } } } - + @SubscribeEvent public void onPlayerTick(TickEvent.PlayerTickEvent event) { - + EntityPlayer player = event.player; - + if(player.inventory.armorInventory[2] != null && player.inventory.armorInventory[2].getItem() instanceof ArmorFSB) ((ArmorFSB)player.inventory.armorInventory[2].getItem()).handleTick(event); - + if(player.ticksExisted == 100 || player.ticksExisted == 200) CraftingManager.crumple(); - + if(event.phase == TickEvent.Phase.START) { int x = MathHelper.floor_double(player.posX); int y = MathHelper.floor_double(player.posY - player.yOffset - 0.01); int z = MathHelper.floor_double(player.posZ); Block b = player.worldObj.getBlock(x, y, z); - + if(b instanceof IStepTickReceiver && !player.capabilities.isFlying) { IStepTickReceiver step = (IStepTickReceiver) b; step.onPlayerStep(player.worldObj, x, y, z, player); } } - + if(!player.worldObj.isRemote && event.phase == TickEvent.Phase.START) { - + /// GHOST FIX START /// - + if(!Float.isFinite(player.getHealth()) || !Float.isFinite(player.getAbsorptionAmount())) { player.addChatComponentMessage(new ChatComponentText("Your health has been restored!")); player.worldObj.playSoundAtEntity(player, "hbm:item.syringe", 1.0F, 1.0F); player.setHealth(player.getMaxHealth()); player.setAbsorptionAmount(0); } - + /// GHOST FIX END /// - + /// BETA HEALTH START /// if(player.inventory.hasItem(ModItems.beta)) { - + if(player.getFoodStats().getFoodLevel() > 10) { player.heal(player.getFoodStats().getFoodLevel() - 10); } - + if(player.getFoodStats().getFoodLevel() != 10) { - + // Why can't you be normal?? try { Field food = ReflectionHelper.findField(FoodStats.class, "field_75127_a", "foodLevel"); @@ -1098,27 +1105,27 @@ public class ModEventHandler { /// BETA HEALTH END /// /// PU RADIATION START /// - + if(player.getUniqueID().toString().equals(ShadyUtil.Pu_238)) { - + List entities = player.worldObj.getEntitiesWithinAABB(EntityLivingBase.class, player.boundingBox.expand(3, 3, 3)); - + for(EntityLivingBase e : entities) { - + if(e != player) { e.addPotionEffect(new PotionEffect(HbmPotion.radiation.id, 300, 2)); } } } - + /// PU RADIATION END /// - + /*if(player instanceof EntityPlayerMP) { int x = (int) Math.floor(player.posX); int y = (int) Math.floor(player.posY - 0.01); int z = (int) Math.floor(player.posZ); - + if(player.worldObj.getTileEntity(x, y, z) instanceof IEnergyConductor) { PacketDispatcher.wrapper.sendTo(new PlayerInformPacket(((IEnergyConductor) player.worldObj.getTileEntity(x, y, z)).getPowerNet() + ""), (EntityPlayerMP) player); } @@ -1127,46 +1134,46 @@ public class ModEventHandler { /// NEW ITEM SYS START /// HazardSystem.updatePlayerInventory(player); /// NEW ITEM SYS END /// - + /// SYNC START /// if(!player.worldObj.isRemote && player instanceof EntityPlayerMP) PacketDispatcher.wrapper.sendTo(new PermaSyncPacket((EntityPlayerMP) player), (EntityPlayerMP) player); /// SYNC END /// } if(player.worldObj.isRemote && event.phase == event.phase.START && !player.isInvisible() && !player.isSneaking()) { - + if(player.getUniqueID().toString().equals(ShadyUtil.Pu_238)) { - + Vec3 vec = Vec3.createVectorHelper(3 * rand.nextDouble(), 0, 0); vec.rotateAroundZ((float) (rand.nextDouble() * Math.PI)); vec.rotateAroundY((float) (rand.nextDouble() * Math.PI * 2)); player.worldObj.spawnParticle("townaura", player.posX + vec.xCoord, player.posY + 1 + vec.yCoord, player.posZ + vec.zCoord, 0.0, 0.0, 0.0); } } - + // OREDBG /*if(!event.player.worldObj.isRemote) { for(BedrockOreType type : BedrockOreType.values()) { PacketDispatcher.wrapper.sendTo(new PlayerInformPacket(StatCollector.translateToLocalFormatted("item.bedrock_ore.type." + type.suffix + ".name") + ": " + ((int) (ItemBedrockOreBase.getOreLevel((int) Math.floor(player.posX), (int) Math.floor(player.posZ), type) * 100) / 100D), 777 + type.ordinal()), (EntityPlayerMP) player); } }*/ - + // PRISMDBG /*if(!event.player.worldObj.isRemote) { ChunkRadiationHandlerPRISM prism = (ChunkRadiationHandlerPRISM) ChunkRadiationManager.proxy; - + RadPerWorld perWorld = prism.perWorld.get(player.worldObj); - + if(perWorld != null) { SubChunk[] chunk = perWorld.radiation.get(new ChunkCoordIntPair(((int) Math.floor(player.posX)) >> 4, ((int) Math.floor(player.posZ)) >> 4)); - + if(chunk != null) { - + int y = ((int) Math.floor(player.posY)) >> 4; - + if(y >= 0 && y <= 15) { SubChunk sub = chunk[y]; - + if(sub != null) { float xSum = 0, ySum = 0, zSum = 0; for(int i = 0; i < 16; i++) { @@ -1190,25 +1197,50 @@ public class ModEventHandler { } }*/ } - + @SubscribeEvent public void onServerTick(TickEvent.ServerTickEvent event) { - - if(event.phase == event.phase.START) { + + if(event.phase == Phase.START) { + + NetworkHandler.flush(); // Flush ALL network packets. + // Yes this technically happens a tick late, I am aware. + // I was encountering some kind of race condition when I flushed packets at the end of the tick, + // leading to occasional ticks of incorrect packets. + + NeutronHandler.onWorldTick(); // All neutron interactions + + // do other shit I guess? RTTYSystem.updateBroadcastQueue(); RequestNetwork.updateEntries(); TileEntityMachineRadarNT.updateSystem(); Nodespace.updateNodespace(); - // RBMK!!!! - RBMKNeutronHandler.runAllInteractions(); - // Chicago Pile!!!! - PileNeutronHandler.runAllInteractions(); + // bob i beg of you i need fluid nodespace :pray: + } + + if(event.phase == Phase.END) { + // As ByteBufs are added to the queue in `com.hbm.packet.toclient.BufPacketThreading`, they are processed by the packet thread. + // This waits until the thread is finished, which most of the time will be instantly since it has plenty of time to process in parallel to everything else. + BufPacketThreading.waitUntilThreadFinished(); } } - + + @SubscribeEvent + public void commandEvent(CommandEvent event) { + ICommand command = event.command; + ICommandSender sender = event.sender; + if(command instanceof CommandGameRule) { + if(command.canCommandSenderUseCommand(sender)) { + command.processCommand(sender,event.parameters); + RBMKDials.refresh(sender.getEntityWorld()); + event.setCanceled(true); + } + } + } + @SubscribeEvent public void enteringChunk(EnteringChunk evt) { - + /*if(evt.entity instanceof EntityMissileBaseNT) { ((EntityMissileBaseNT) evt.entity).loadNeighboringChunks(evt.newChunkX, evt.newChunkZ); } @@ -1217,41 +1249,41 @@ public class ModEventHandler { ((EntityMissileCustom) evt.entity).loadNeighboringChunks(evt.newChunkX, evt.newChunkZ); }*/ } - + @SubscribeEvent public void onPlayerClone(net.minecraftforge.event.entity.player.PlayerEvent.Clone event) { - - NBTTagCompound data = new NBTTagCompound(); - HbmPlayerProps.getData(event.original).saveNBTData(data); - HbmPlayerProps.getData(event.entityPlayer).loadNBTData(data); + + ByteBuf buf = Unpooled.buffer(); + HbmPlayerProps.getData(event.original).serialize(buf); + HbmPlayerProps.getData(event.entityPlayer).deserialize(buf); } - + @SubscribeEvent public void itemCrafted(PlayerEvent.ItemCraftedEvent e) { AchievementHandler.fire(e.player, e.crafting); } - + @SubscribeEvent public void itemSmelted(PlayerEvent.ItemSmeltedEvent e) { AchievementHandler.fire(e.player, e.smelting); - + if(!e.player.worldObj.isRemote && e.smelting.getItem() == Items.iron_ingot && e.player.getRNG().nextInt(64) == 0) { - + if(!e.player.inventory.addItemStackToInventory(new ItemStack(ModItems.lodestone))) e.player.dropPlayerItemWithRandomChoice(new ItemStack(ModItems.lodestone), false); else e.player.inventoryContainer.detectAndSendChanges(); } - + if(!e.player.worldObj.isRemote && e.smelting.getItem() == ModItems.ingot_uranium && e.player.getRNG().nextInt(64) == 0) { - + if(!e.player.inventory.addItemStackToInventory(new ItemStack(ModItems.quartz_plutonium))) e.player.dropPlayerItemWithRandomChoice(new ItemStack(ModItems.quartz_plutonium), false); else e.player.inventoryContainer.detectAndSendChanges(); } } - + @SubscribeEvent public void onItemPickup(PlayerEvent.ItemPickupEvent event) { if(event.pickedUp.getEntityItem().getItem() == ModItems.canned_conserve && EnumUtil.grabEnumSafely(EnumFoodType.class, event.pickedUp.getEntityItem().getItemDamage()) == EnumFoodType.JIZZ) @@ -1259,40 +1291,40 @@ public class ModEventHandler { if(event.pickedUp.getEntityItem().getItem() == Items.slime_ball) event.player.triggerAchievement(MainRegistry.achSlimeball); } - + @SubscribeEvent public void onBlockBreak(BreakEvent event) { - + EntityPlayer player = event.getPlayer(); - + if(!(player instanceof EntityPlayerMP)) return; - + if(event.block == ModBlocks.stone_gneiss && !((EntityPlayerMP) player).func_147099_x().hasAchievementUnlocked(MainRegistry.achStratum)) { event.getPlayer().triggerAchievement(MainRegistry.achStratum); event.setExpToDrop(500); } - + if(event.block == Blocks.coal_ore || event.block == Blocks.coal_block || event.block == ModBlocks.ore_lignite) { - + for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { int x = event.x + dir.offsetX; int y = event.y + dir.offsetY; int z = event.z + dir.offsetZ; - + if(event.world.rand.nextInt(2) == 0 && event.world.getBlock(x, y, z) == Blocks.air) event.world.setBlock(x, y, z, ModBlocks.gas_coal); } } - + if(RadiationConfig.enablePollution && RadiationConfig.enableLeadFromBlocks) { if(!ArmorRegistry.hasProtection(player, 3, HazardClass.PARTICLE_FINE)) { - + float metal = PollutionHandler.getPollution(player.worldObj, event.x, event.y, event.z, PollutionType.HEAVYMETAL); - + if(metal < 5) return; - + if(metal < 10) { player.addPotionEffect(new PotionEffect(HbmPotion.lead.id, 100, 0)); } else if(metal < 25) { @@ -1303,7 +1335,7 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void onClickSign(PlayerInteractEvent event) { @@ -1311,13 +1343,13 @@ public class ModEventHandler { int y = event.y; int z = event.z; World world = event.world; - + if(!world.isRemote && event.action == Action.RIGHT_CLICK_BLOCK && world.getTileEntity(x, y, z) instanceof TileEntitySign) { - + TileEntitySign sign = (TileEntitySign)world.getTileEntity(x, y, z); - + String result = ShadyUtil.smoosh(sign.signText[0], sign.signText[1], sign.signText[2], sign.signText[3]); - + if(ShadyUtil.hashes.contains(result)) { world.func_147480_a(x, y, z, false); EntityItem entityitem = new EntityItem(world, x, y, z, new ItemStack(ModItems.bobmazon_hidden)); @@ -1326,22 +1358,22 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void chatEvent(ServerChatEvent event) { - + EntityPlayerMP player = event.player; String message = event.message; - + //boolean conditions for the illiterate, edition 1 //bellow you can see the header of an if-block. inside the brackets, there is a boolean statement. //that means nothing other than its value totaling either 'true' or 'false' //examples: 'true' would just mean true //'1 > 3' would equal false //'i < 10' would equal true if 'i' is smaller than 10, if equal or greater, it will result in false - + //let's start from the back: - + //this part means that the message's first character has to equal a '!': ----------------------------+ // | //this is a logical AND operator: ----------------------------------------------------------------+ | @@ -1367,72 +1399,72 @@ public class ModEventHandler { //the config file: | | | | | | // V V V V V V if(GeneralConfig.enableDebugMode && player.getUniqueID().toString().equals(ShadyUtil.HbMinecraft) && message.startsWith("!")) { - + String[] msg = message.split(" "); - + String m = msg[0].substring(1, msg[0].length()).toLowerCase(Locale.US); - + if("gv".equals(m)) { - + int id = 0; int size = 1; int meta = 0; - + if(msg.length > 1 && NumberUtils.isNumber(msg[1])) { id = (int)(double)NumberUtils.createDouble(msg[1]); } - + if(msg.length > 2 && NumberUtils.isNumber(msg[2])) { size = (int)(double)NumberUtils.createDouble(msg[2]); } - + if(msg.length > 3 && NumberUtils.isNumber(msg[3])) { meta = (int)(double)NumberUtils.createDouble(msg[3]); } - + Item item = Item.getItemById(id); - + if(item != null && size > 0 && meta >= 0) { player.inventory.addItemStackToInventory(new ItemStack(item, size, meta)); } } - + player.inventoryContainer.detectAndSendChanges(); event.setCanceled(true); } } - + @SubscribeEvent public void anvilUpdateEvent(AnvilUpdateEvent event) { - + if(event.left.getItem() instanceof ItemGunBase && event.right.getItem() == Items.enchanted_book) { - + event.output = event.left.copy(); - + Map mapright = EnchantmentHelper.getEnchantments(event.right); Iterator itr = mapright.keySet().iterator(); - + while(itr.hasNext()) { - + int i = ((Integer) itr.next()).intValue(); int j = ((Integer) mapright.get(Integer.valueOf(i))).intValue(); Enchantment e = Enchantment.enchantmentsList[i]; - + EnchantmentUtil.removeEnchantment(event.output, e); EnchantmentUtil.addEnchantment(event.output, e, j); } - + event.cost = 10; } } - + @SubscribeEvent public void onFoodEaten(PlayerUseItemEvent.Finish event) { - + ItemStack stack = event.item; - + if(stack != null && stack.getItem() instanceof ItemFood) { - + if(stack.hasTagCompound() && stack.getTagCompound().getBoolean("ntmCyanide")) { for(int i = 0; i < 10; i++) { event.entityPlayer.attackEntityFrom(rand.nextBoolean() ? ModDamageSource.euthanizedSelf : ModDamageSource.euthanizedSelf2, 1000); @@ -1440,17 +1472,17 @@ public class ModEventHandler { } } } - + @SubscribeEvent public void filterBrokenEntity(EntityJoinWorldEvent event) { - + Entity entity = event.entity; Entity[] parts = entity.getParts(); - + //MainRegistry.logger.error("Trying to spawn entity " + entity.getClass().getCanonicalName()); - + if(parts != null) { - + for(int i = 0; i < parts.length; i++) { if(parts[i] == null) { MainRegistry.logger.error("Prevented spawning of multipart entity " + entity.getClass().getCanonicalName() + " due to parts being null!"); diff --git a/src/main/java/com/hbm/main/NetworkHandler.java b/src/main/java/com/hbm/main/NetworkHandler.java new file mode 100644 index 000000000..99d8a4e8c --- /dev/null +++ b/src/main/java/com/hbm/main/NetworkHandler.java @@ -0,0 +1,79 @@ +package com.hbm.main; + +import cpw.mods.fml.common.network.FMLEmbeddedChannel; +import cpw.mods.fml.common.network.FMLOutboundHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.simpleimpl.*; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.entity.player.EntityPlayerMP; + +import java.util.EnumMap; + +// Essentially the `SimpleNetworkWrapper` from FML but doesn't flush the packets immediately. +public class NetworkHandler { + + private static FMLEmbeddedChannel clientChannel; + private static FMLEmbeddedChannel serverChannel; + + private static SimpleIndexedCodec packetCodec; + + public NetworkHandler(String name) { + packetCodec = new SimpleIndexedCodec(); + EnumMap channels = NetworkRegistry.INSTANCE.newChannel(name, packetCodec); + clientChannel = channels.get(Side.CLIENT); + serverChannel = channels.get(Side.SERVER); + } + + public void registerMessage(Class> messageHandler, Class requestMessageType, int discriminator, Side side) { + + packetCodec.addDiscriminator(discriminator, requestMessageType); + FMLEmbeddedChannel channel; + if(side.isClient()) + channel = clientChannel; + else + channel = serverChannel; + String type = channel.findChannelHandlerNameForType(SimpleIndexedCodec.class); + SimpleChannelHandlerWrapper handler; + if (side == Side.SERVER) { + handler = new SimpleChannelHandlerWrapper<>(messageHandler, side, requestMessageType); + } else { + handler = new SimpleChannelHandlerWrapper<>(messageHandler, side, requestMessageType); + } + channel.pipeline().addAfter(type, messageHandler.getName(), handler); + } + + public static void flush() { + clientChannel.flush(); + serverChannel.flush(); + } + + public void sendToServer(IMessage message) { + clientChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER); + clientChannel.write(message); + } + + public void sendToDimension(IMessage message, int dimensionId) { + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION); + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId); + serverChannel.write(message); + + } + + public void sendToAllAround(IMessage message, NetworkRegistry.TargetPoint point) { + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT); + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point); + serverChannel.write(message); + + } + + public void sendTo(IMessage message, EntityPlayerMP player) { + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER); + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player); + serverChannel.write(message); + } + + public void sendToAll(IMessage message) { + serverChannel.attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL); + serverChannel.write(message); + } +} diff --git a/src/main/java/com/hbm/packet/PacketDispatcher.java b/src/main/java/com/hbm/packet/PacketDispatcher.java index 903a7939a..2d5cd9583 100644 --- a/src/main/java/com/hbm/packet/PacketDispatcher.java +++ b/src/main/java/com/hbm/packet/PacketDispatcher.java @@ -1,21 +1,23 @@ package com.hbm.packet; import com.hbm.lib.RefStrings; +import com.hbm.main.NetworkHandler; import com.hbm.packet.toclient.*; import com.hbm.packet.toserver.*; +import cpw.mods.fml.common.network.FMLEventChannel; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; import cpw.mods.fml.relauncher.Side; public class PacketDispatcher { - //Mark 1 Packet Sending Device - public static final SimpleNetworkWrapper wrapper = NetworkRegistry.INSTANCE.newSimpleChannel(RefStrings.MODID); + //Mark 1.5 Packet Sending Device + public static final NetworkHandler wrapper = new NetworkHandler(RefStrings.MODID); - public static final void registerPackets() { + public static void registerPackets() { int i = 0; - + //Sound packet that keeps client and server separated wrapper.registerMessage(LoopedSoundPacket.Handler.class, LoopedSoundPacket.class, i++, Side.CLIENT); //Signals server to consume items and create template @@ -83,5 +85,5 @@ public class PacketDispatcher { //wrapper.registerMessage(NBTPacket.Handler.class, NBTPacket.class, i++, Side.CLIENT); //The convenient but laggy one wrapper.registerMessage(BufPacket.Handler.class, BufPacket.class, i++, Side.CLIENT); //The not-so-convenient but not laggy one } - + } diff --git a/src/main/java/com/hbm/packet/toclient/BufPacket.java b/src/main/java/com/hbm/packet/toclient/BufPacket.java index 383f9dd71..720be19df 100644 --- a/src/main/java/com/hbm/packet/toclient/BufPacket.java +++ b/src/main/java/com/hbm/packet/toclient/BufPacket.java @@ -1,5 +1,6 @@ package com.hbm.packet.toclient; +import com.hbm.main.MainRegistry; import com.hbm.tileentity.IBufPacketReceiver; import cpw.mods.fml.common.network.simpleimpl.IMessage; @@ -8,8 +9,6 @@ import cpw.mods.fml.common.network.simpleimpl.MessageContext; import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.tileentity.TileEntity; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; public class BufPacket implements IMessage { @@ -58,11 +57,9 @@ public class BufPacket implements IMessage { try { ((IBufPacketReceiver) te).deserialize(m.buf); } catch(Exception e) { // just in case I fucked up - Logger logger = LogManager.getLogger("HBM"); - logger.warn("A ByteBuf packet failed to be read and has thrown an error. This normally means that there was a buffer underflow and more data was read than was actually in the packet."); - logger.warn("Tile: {}", te.getBlockType().getUnlocalizedName()); - logger.warn(e.getMessage()); - + MainRegistry.logger.warn("A ByteBuf packet failed to be read and has thrown an error. This normally means that there was a buffer underflow and more data was read than was actually in the packet."); + MainRegistry.logger.warn("Tile: {}", te.getBlockType().getUnlocalizedName()); + MainRegistry.logger.warn(e.getMessage()); } } diff --git a/src/main/java/com/hbm/tileentity/IBufPacketReceiver.java b/src/main/java/com/hbm/tileentity/IBufPacketReceiver.java index 04d1fe52a..7c1422820 100644 --- a/src/main/java/com/hbm/tileentity/IBufPacketReceiver.java +++ b/src/main/java/com/hbm/tileentity/IBufPacketReceiver.java @@ -1,19 +1,14 @@ package com.hbm.tileentity; -import com.hbm.packet.PacketDispatcher; -import com.hbm.packet.toclient.BufPacket; - -import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; +import com.hbm.handler.threading.BufPacketThreading; import io.netty.buffer.ByteBuf; -import net.minecraft.tileentity.TileEntity; public interface IBufPacketReceiver { public void serialize(ByteBuf buf); public void deserialize(ByteBuf buf); - + public default void sendStandard(int range) { - TileEntity te = (TileEntity) this; - PacketDispatcher.wrapper.sendToAllAround(new BufPacket(te.xCoord, te.yCoord, te.zCoord, this), new TargetPoint(te.getWorldObj().provider.dimensionId, te.xCoord, te.yCoord, te.zCoord, range)); + BufPacketThreading.createBufPacket(this, range); } } diff --git a/src/main/java/com/hbm/tileentity/TileEntityMachineBase.java b/src/main/java/com/hbm/tileentity/TileEntityMachineBase.java index 24231d3ef..82eb25fa1 100644 --- a/src/main/java/com/hbm/tileentity/TileEntityMachineBase.java +++ b/src/main/java/com/hbm/tileentity/TileEntityMachineBase.java @@ -3,6 +3,7 @@ package com.hbm.tileentity; import com.hbm.packet.PacketDispatcher; import com.hbm.packet.toclient.AuxGaugePacket; import com.hbm.packet.toclient.BufPacket; +import com.hbm.handler.threading.BufPacketThreading; import com.hbm.util.fauxpointtwelve.DirPos; import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; @@ -179,7 +180,7 @@ public abstract class TileEntityMachineBase extends TileEntityLoadedBase impleme } this.lastPackedBuf = buf; - PacketDispatcher.wrapper.sendToAllAround(packet, new TargetPoint(this.worldObj.provider.dimensionId, xCoord, yCoord, zCoord, range)); + BufPacketThreading.createBufPacket(packet, new TargetPoint(this.worldObj.provider.dimensionId, xCoord, yCoord, zCoord, range)); } @Override public void serialize(ByteBuf buf) { diff --git a/src/main/java/com/hbm/tileentity/machine/rbmk/RBMKDials.java b/src/main/java/com/hbm/tileentity/machine/rbmk/RBMKDials.java index a25703556..40efccc6b 100644 --- a/src/main/java/com/hbm/tileentity/machine/rbmk/RBMKDials.java +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/RBMKDials.java @@ -1,77 +1,118 @@ package com.hbm.tileentity.machine.rbmk; import com.hbm.config.GeneralConfig; +import com.hbm.main.MainRegistry; import com.hbm.util.GameRuleHelper; -import net.minecraft.util.MathHelper; +import com.hbm.util.Tuple; import net.minecraft.world.GameRules; import net.minecraft.world.World; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + public class RBMKDials { - public static final String KEY_SAVE_DIALS = "dialSaveDials"; + public enum RBMKKeys { + KEY_SAVE_DIALS("dialSaveDials", true), + KEY_PASSIVE_COOLING("dialPassiveCooling", 1.0), + KEY_COLUMN_HEAT_FLOW("dialColumnHeatFlow", 0.2), + KEY_FUEL_DIFFUSION_MOD("dialDiffusionMod", 1.0), + KEY_HEAT_PROVISION("dialHeatProvision", 0.2), + KEY_COLUMN_HEIGHT("dialColumnHeight", 4), + KEY_PERMANENT_SCRAP("dialEnablePermaScrap", true), + KEY_BOILER_HEAT_CONSUMPTION("dialBoilerHeatConsumption", 0.1), + KEY_CONTROL_SPEED_MOD("dialControlSpeed", 1.0), + KEY_REACTIVITY_MOD("dialReactivityMod", 1.0), + KEY_OUTGASSER_MOD("dialOutgasserSpeedMod", 1.0), + KEY_SURGE_MOD("dialControlSurgeMod", 1.0), + KEY_FLUX_RANGE("dialFluxRange", 5), + KEY_REASIM_RANGE("dialReasimRange", 10), + KEY_REASIM_COUNT("dialReasimCount", 6), + KEY_REASIM_MOD("dialReasimOutputMod", 1.0), + KEY_REASIM_BOILERS("dialReasimBoilers", false), + KEY_REASIM_BOILER_SPEED("dialReasimBoilerSpeed", 0.05), + KEY_DISABLE_MELTDOWNS("dialDisableMeltdowns", false), + KEY_ENABLE_MELTDOWN_OVERPRESSURE("dialEnableMeltdownOverpressure", false), + KEY_MODERATOR_EFFICIENCY("dialModeratorEfficiency", 1.0), + KEY_ABSORBER_EFFICIENCY("dialAbsorberEfficiency", 1.0), + KEY_REFLECTOR_EFFICIENCY("dialReflectorEfficiency", 1.0); - public static final String KEY_PASSIVE_COOLING = "dialPassiveCooling"; - public static final String KEY_COLUMN_HEAT_FLOW = "dialColumnHeatFlow"; - public static final String KEY_FUEL_DIFFUSION_MOD = "dialDiffusionMod"; - public static final String KEY_HEAT_PROVISION = "dialHeatProvision"; - public static final String KEY_COLUMN_HEIGHT = "dialColumnHeight"; - public static final String KEY_PERMANENT_SCRAP = "dialEnablePermaScrap"; - public static final String KEY_BOILER_HEAT_CONSUMPTION = "dialBoilerHeatConsumption"; - public static final String KEY_CONTROL_SPEED_MOD = "dialControlSpeed"; - public static final String KEY_REACTIVITY_MOD = "dialReactivityMod"; - public static final String KEY_OUTGASSER_MOD = "dialOutgasserSpeedMod"; - public static final String KEY_SURGE_MOD = "dialControlSurgeMod"; - public static final String KEY_FLUX_RANGE = "dialFluxRange"; - public static final String KEY_REASIM_RANGE = "dialReasimRange"; - public static final String KEY_REASIM_COUNT = "dialReasimCount"; - public static final String KEY_REASIM_MOD = "dialReasimOutputMod"; - public static final String KEY_REASIM_BOILERS = "dialReasimBoilers"; - public static final String KEY_REASIM_BOILER_SPEED = "dialReasimBoilerSpeed"; - public static final String KEY_DISABLE_MELTDOWNS = "dialDisableMeltdowns"; - public static final String KEY_ENABLE_MELTDOWN_OVERPRESSURE = "dialEnableMeltdownOverpressure"; + public final String keyString; + public final Object defValue; - public static final String KEY_MODERATOR_EFFICIENCY = "dialModeratorEfficiency"; - public static final String KEY_ABSORBER_EFFICIENCY = "dialAbsorberEfficiency"; - public static final String KEY_REFLECTOR_EFFICIENCY = "dialReflectorEfficiency"; + RBMKKeys(String key, Object def) { + keyString = key; + defValue = def; + } + } + + public static HashMap>> gameRules = new HashMap<>(); public static void createDials(World world) { GameRules rules = world.getGameRules(); - if(!rules.getGameRuleBooleanValue(KEY_SAVE_DIALS)) { - rules.setOrCreateGameRule(KEY_PASSIVE_COOLING, "1.0"); - rules.setOrCreateGameRule(KEY_COLUMN_HEAT_FLOW, "0.2"); - rules.setOrCreateGameRule(KEY_FUEL_DIFFUSION_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_HEAT_PROVISION, "0.2"); - rules.setOrCreateGameRule(KEY_COLUMN_HEIGHT, "4"); - rules.setOrCreateGameRule(KEY_PERMANENT_SCRAP, "true"); - rules.setOrCreateGameRule(KEY_BOILER_HEAT_CONSUMPTION, "0.1"); - rules.setOrCreateGameRule(KEY_CONTROL_SPEED_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_REACTIVITY_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_SAVE_DIALS, "true"); - rules.setOrCreateGameRule(KEY_OUTGASSER_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_SURGE_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_FLUX_RANGE, "5"); - rules.setOrCreateGameRule(KEY_REASIM_RANGE, "10"); - rules.setOrCreateGameRule(KEY_REASIM_COUNT, "6"); - rules.setOrCreateGameRule(KEY_REASIM_MOD, "1.0"); - rules.setOrCreateGameRule(KEY_REASIM_BOILERS, "false"); - rules.setOrCreateGameRule(KEY_REASIM_BOILER_SPEED, "0.05"); - rules.setOrCreateGameRule(KEY_DISABLE_MELTDOWNS, "false"); - rules.setOrCreateGameRule(KEY_ENABLE_MELTDOWN_OVERPRESSURE, "false"); - rules.setOrCreateGameRule(KEY_MODERATOR_EFFICIENCY, "1.0"); - rules.setOrCreateGameRule(KEY_ABSORBER_EFFICIENCY, "1.0"); - rules.setOrCreateGameRule(KEY_REFLECTOR_EFFICIENCY, "1.0"); + for(RBMKKeys key : RBMKKeys.values()) + gameRules.put(key, new ArrayList<>()); + refresh(world); + + if(!rules.getGameRuleBooleanValue(RBMKKeys.KEY_SAVE_DIALS.keyString)) { + for(RBMKKeys key : RBMKKeys.values()) + rules.setOrCreateGameRule(key.keyString, String.valueOf(key.defValue)); } } + // Refresh all gamerules. + public static void refresh(World world) { + for(List> values : gameRules.values()) { + values.removeAll(values.stream().filter(a -> a.key == world).collect(Collectors.toList())); + } + + gameRules.get(RBMKKeys.KEY_PASSIVE_COOLING).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_PASSIVE_COOLING, 0.0D))); + gameRules.get(RBMKKeys.KEY_COLUMN_HEAT_FLOW).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_COLUMN_HEAT_FLOW, 0.0D, 1.0D))); + gameRules.get(RBMKKeys.KEY_FUEL_DIFFUSION_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_FUEL_DIFFUSION_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_HEAT_PROVISION).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_HEAT_PROVISION, 0.0D, 1.0D))); + gameRules.get(RBMKKeys.KEY_COLUMN_HEIGHT).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedInt(world, RBMKKeys.KEY_COLUMN_HEIGHT, 2, 16) - 1)); + gameRules.get(RBMKKeys.KEY_PERMANENT_SCRAP).add(new Tuple.Pair<>(world, world.getGameRules().getGameRuleBooleanValue(RBMKKeys.KEY_PERMANENT_SCRAP.keyString))); + gameRules.get(RBMKKeys.KEY_BOILER_HEAT_CONSUMPTION).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_BOILER_HEAT_CONSUMPTION, 0D))); + gameRules.get(RBMKKeys.KEY_CONTROL_SPEED_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_CONTROL_SPEED_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_REACTIVITY_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_REACTIVITY_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_OUTGASSER_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_OUTGASSER_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_SURGE_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_SURGE_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_FLUX_RANGE).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedInt(world, RBMKKeys.KEY_FLUX_RANGE, 1, 100))); + gameRules.get(RBMKKeys.KEY_REASIM_RANGE).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedInt(world, RBMKKeys.KEY_REASIM_RANGE, 1, 100))); + gameRules.get(RBMKKeys.KEY_REASIM_COUNT).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedInt(world, RBMKKeys.KEY_REASIM_COUNT, 1, 24))); + gameRules.get(RBMKKeys.KEY_REASIM_MOD).add(new Tuple.Pair<>(world, GameRuleHelper.getDoubleMinimum(world, RBMKKeys.KEY_REASIM_MOD, 0.0D))); + gameRules.get(RBMKKeys.KEY_REASIM_BOILERS).add(new Tuple.Pair<>(world, world.getGameRules().getGameRuleBooleanValue(RBMKKeys.KEY_REASIM_BOILERS.keyString) || (GeneralConfig.enable528 && GeneralConfig.enable528ReasimBoilers))); + gameRules.get(RBMKKeys.KEY_REASIM_BOILER_SPEED).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_REASIM_BOILER_SPEED, 0.0D, 1.0D))); + gameRules.get(RBMKKeys.KEY_DISABLE_MELTDOWNS).add(new Tuple.Pair<>(world, world.getGameRules().getGameRuleBooleanValue(RBMKKeys.KEY_DISABLE_MELTDOWNS.keyString))); + gameRules.get(RBMKKeys.KEY_ENABLE_MELTDOWN_OVERPRESSURE).add(new Tuple.Pair<>(world, world.getGameRules().getGameRuleBooleanValue(RBMKKeys.KEY_ENABLE_MELTDOWN_OVERPRESSURE.keyString))); + gameRules.get(RBMKKeys.KEY_MODERATOR_EFFICIENCY).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_MODERATOR_EFFICIENCY, 0.0D, 1.0D))); + gameRules.get(RBMKKeys.KEY_ABSORBER_EFFICIENCY).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_ABSORBER_EFFICIENCY, 0.0D, 1.0D))); + gameRules.get(RBMKKeys.KEY_REFLECTOR_EFFICIENCY).add(new Tuple.Pair<>(world, GameRuleHelper.getClampedDouble(world, RBMKKeys.KEY_REFLECTOR_EFFICIENCY, 0.0D, 1.0D))); + } + + public static Object getGameRule(World world, RBMKKeys rule) { + List> rulesList = gameRules.get(rule).stream().filter(a -> a.key == world).collect(Collectors.toList()); + + if(rulesList.isEmpty()) + throw new NullPointerException("No gamerule found for " + rule.keyString); + else if(rulesList.size() > 1) + // what??? why??? + MainRegistry.logger.warn("Duplicate values for gamerules detected! Found {} rules for gamerule {}", rulesList.size(), rule.keyString); + + return rulesList.get(0).value; // realistically there should only be one of this gamerule that satisfies the filter sooooo... + } + /** * Returns the amount of heat per tick removed from components passively * @param world * @return >0 */ public static double getPassiveCooling(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_PASSIVE_COOLING), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_PASSIVE_COOLING); } /** @@ -80,7 +121,7 @@ public class RBMKDials { * @return [0;1] */ public static double getColumnHeatFlow(World world) { - return MathHelper.clamp_double(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_COLUMN_HEAT_FLOW), 0.2D), 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_COLUMN_HEAT_FLOW); } /** @@ -89,7 +130,7 @@ public class RBMKDials { * @return >0 */ public static double getFuelDiffusionMod(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_FUEL_DIFFUSION_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_FUEL_DIFFUSION_MOD); } /** @@ -98,7 +139,7 @@ public class RBMKDials { * @return [0;1] */ public static double getFuelHeatProvision(World world) { - return MathHelper.clamp_double(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_HEAT_PROVISION), 0.2D), 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_HEAT_PROVISION); } /** @@ -107,7 +148,7 @@ public class RBMKDials { * @return [0;15] */ public static int getColumnHeight(World world) { - return MathHelper.clamp_int(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(KEY_COLUMN_HEIGHT), 4), 2, 16) - 1; + return (int) getGameRule(world, RBMKKeys.KEY_COLUMN_HEIGHT); } /** @@ -116,7 +157,7 @@ public class RBMKDials { * @return */ public static boolean getPermaScrap(World world) { - return world.getGameRules().getGameRuleBooleanValue(KEY_PERMANENT_SCRAP); + return (boolean) getGameRule(world, RBMKKeys.KEY_PERMANENT_SCRAP); } /** @@ -125,7 +166,7 @@ public class RBMKDials { * @return >0 */ public static double getBoilerHeatConsumption(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_BOILER_HEAT_CONSUMPTION), 0.1D), 0D); + return (double) getGameRule(world, RBMKKeys.KEY_BOILER_HEAT_CONSUMPTION); } /** @@ -134,7 +175,7 @@ public class RBMKDials { * @return >0 */ public static double getControlSpeed(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_CONTROL_SPEED_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_CONTROL_SPEED_MOD); } /** @@ -143,7 +184,7 @@ public class RBMKDials { * @return >0 */ public static double getReactivityMod(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_REACTIVITY_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_REACTIVITY_MOD); } /** @@ -152,7 +193,7 @@ public class RBMKDials { * @return >0 */ public static double getOutgasserMod(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_OUTGASSER_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_OUTGASSER_MOD); } /** @@ -161,7 +202,7 @@ public class RBMKDials { * @return >0 */ public static double getSurgeMod(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_SURGE_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_SURGE_MOD); } /** @@ -170,7 +211,7 @@ public class RBMKDials { * @return [1;100] */ public static int getFluxRange(World world) { - return MathHelper.clamp_int(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(KEY_FLUX_RANGE), 5), 1, 100); + return (int) getGameRule(world, RBMKKeys.KEY_FLUX_RANGE); } /** @@ -179,7 +220,7 @@ public class RBMKDials { * @return [1;100] */ public static int getReaSimRange(World world) { - return MathHelper.clamp_int(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(KEY_REASIM_RANGE), 10), 1, 100); + return (int) getGameRule(world, RBMKKeys.KEY_REASIM_RANGE); } /** @@ -188,7 +229,7 @@ public class RBMKDials { * @return [1;24] */ public static int getReaSimCount(World world) { - return MathHelper.clamp_int(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(KEY_REASIM_COUNT), 6), 1, 24); + return (int) getGameRule(world, RBMKKeys.KEY_REASIM_COUNT); } /** @@ -197,7 +238,7 @@ public class RBMKDials { * @return >0 */ public static double getReaSimOutputMod(World world) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_REASIM_MOD), 1.0D), 0.0D); + return (double) getGameRule(world, RBMKKeys.KEY_REASIM_MOD); } /** @@ -206,7 +247,7 @@ public class RBMKDials { * @return */ public static boolean getReasimBoilers(World world) { - return world.getGameRules().getGameRuleBooleanValue(KEY_REASIM_BOILERS) || (GeneralConfig.enable528 && GeneralConfig.enable528ReasimBoilers); + return (boolean) getGameRule(world, RBMKKeys.KEY_REASIM_BOILERS); } /** @@ -215,7 +256,7 @@ public class RBMKDials { * @return [0;1] */ public static double getReaSimBoilerSpeed(World world) { - return MathHelper.clamp_double(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(KEY_REASIM_BOILER_SPEED), 0.05D), 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_REASIM_BOILER_SPEED); } /** @@ -225,7 +266,7 @@ public class RBMKDials { * @return */ public static boolean getMeltdownsDisabled(World world) { - return world.getGameRules().getGameRuleBooleanValue(KEY_DISABLE_MELTDOWNS); + return (boolean) getGameRule(world, RBMKKeys.KEY_DISABLE_MELTDOWNS); } /** @@ -234,7 +275,7 @@ public class RBMKDials { * @return */ public static boolean getOverpressure(World world) { - return world.getGameRules().getGameRuleBooleanValue(KEY_ENABLE_MELTDOWN_OVERPRESSURE); + return (boolean) getGameRule(world, RBMKKeys.KEY_ENABLE_MELTDOWN_OVERPRESSURE); } /** @@ -243,7 +284,7 @@ public class RBMKDials { * @return */ public static double getModeratorEfficiency(World world) { - return GameRuleHelper.getClampedDouble(world, world.getGameRules().getGameRuleStringValue(KEY_MODERATOR_EFFICIENCY), 1D, 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_MODERATOR_EFFICIENCY); } /** @@ -252,7 +293,7 @@ public class RBMKDials { * @return */ public static double getAbsorberEfficiency(World world) { - return GameRuleHelper.getClampedDouble(world, world.getGameRules().getGameRuleStringValue(KEY_ABSORBER_EFFICIENCY), 1D, 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_ABSORBER_EFFICIENCY); } /** @@ -261,6 +302,6 @@ public class RBMKDials { * @return */ public static double getReflectorEfficiency(World world) { - return GameRuleHelper.getClampedDouble(world, world.getGameRules().getGameRuleStringValue(KEY_REFLECTOR_EFFICIENCY), 1D, 0.0D, 1.0D); + return (double) getGameRule(world, RBMKKeys.KEY_REFLECTOR_EFFICIENCY); } } 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 6fb3d9ee7..6a7acf1bf 100644 --- a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRod.java @@ -48,6 +48,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM public double fluxRatio; public double fluxQuantity; public double lastFluxQuantity; + public double lastFluxRatio; public boolean hasRod; @@ -129,6 +130,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM } else { this.meltdown(); } + this.lastFluxRatio = 0; this.lastFluxQuantity = 0; this.fluxQuantity = 0; return; @@ -136,11 +138,13 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM if(this.heat > 10_000) this.heat = 10_000; - this.lastFluxQuantity = this.fluxQuantity; - //for spreading, we want the buffered flux to be 0 because we want to know exactly how much gets reflected back + this.lastFluxQuantity = this.fluxQuantity; + this.lastFluxRatio = this.fluxRatio; + this.fluxQuantity = 0; + this.fluxRatio = 0; spreadFlux(fluxQuantityOut, fluxRatioOut); @@ -148,6 +152,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM } else { + this.lastFluxRatio = 0; this.lastFluxQuantity = 0; this.fluxQuantity = 0; this.fluxRatio = 0; @@ -177,9 +182,12 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM ForgeDirection.WEST }; + private BlockPos pos; + public void spreadFlux(double flux, double ratio) { - BlockPos pos = new BlockPos(this); + if(pos == null) + pos = new BlockPos(this); if (flux == 0) { // simple way to remove the node from the cache when no flux is going into it! @@ -202,7 +210,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM new RBMKNeutronHandler.RBMKNeutronStream(node, neutronVector, flux, ratio); } } - + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); @@ -221,28 +229,25 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM this.hasRod = nbt.getBoolean("hasRod"); } + @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - nbt.setDouble("fluxQuantity", this.fluxQuantity); - nbt.setDouble("fluxMod", this.fluxRatio); - nbt.setBoolean("hasRod", this.hasRod); - } - - // aaaaaaaa - public void writeToNBTDiag(NBTTagCompound nbt) { - super.writeToNBT(nbt); - - nbt.setDouble("fluxSlow", this.lastFluxQuantity * (1 - fluxRatio)); - nbt.setDouble("fluxFast", this.lastFluxQuantity * fluxRatio); + if (!diag) { + nbt.setDouble("fluxQuantity", this.lastFluxQuantity); + nbt.setDouble("fluxMod", this.lastFluxRatio); + } else { + nbt.setDouble("fluxSlow", this.fluxQuantity * (1 - fluxRatio)); + nbt.setDouble("fluxFast", this.fluxQuantity * fluxRatio); + } nbt.setBoolean("hasRod", this.hasRod); } @Override public void serialize(ByteBuf buf) { super.serialize(buf); - buf.writeDouble(this.fluxQuantity); - buf.writeDouble(this.fluxRatio); + buf.writeDouble(this.lastFluxQuantity); + buf.writeDouble(this.lastFluxRatio); buf.writeBoolean(this.hasRod); } @@ -256,7 +261,7 @@ public class TileEntityRBMKRod extends TileEntityRBMKSlottedBase implements IRBM public void getDiagData(NBTTagCompound nbt) { diag = true; - this.writeToNBTDiag(nbt); + this.writeToNBT(nbt); diag = false; if(slots[0] != null && slots[0].getItem() instanceof ItemRBMKRod) { diff --git a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRodReaSim.java b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRodReaSim.java index d638e4795..a23c5f2e3 100644 --- a/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRodReaSim.java +++ b/src/main/java/com/hbm/tileentity/machine/rbmk/TileEntityRBMKRodReaSim.java @@ -10,7 +10,7 @@ import net.minecraft.util.Vec3; import static com.hbm.handler.neutron.RBMKNeutronHandler.*; public class TileEntityRBMKRodReaSim extends TileEntityRBMKRod { - + public TileEntityRBMKRodReaSim() { super(); } @@ -19,11 +19,14 @@ public class TileEntityRBMKRodReaSim extends TileEntityRBMKRod { public String getName() { return "container.rbmkReaSim"; } - + + private BlockPos pos; + @Override public void spreadFlux(double flux, double ratio) { - BlockPos pos = new BlockPos(this); + if(pos == null) + pos = new BlockPos(this); if (flux == 0) { // simple way to remove the node from the cache when no flux is going into it! diff --git a/src/main/java/com/hbm/util/GameRuleHelper.java b/src/main/java/com/hbm/util/GameRuleHelper.java index 45f19ed9b..1551d02d1 100644 --- a/src/main/java/com/hbm/util/GameRuleHelper.java +++ b/src/main/java/com/hbm/util/GameRuleHelper.java @@ -1,21 +1,26 @@ package com.hbm.util; +import com.hbm.tileentity.machine.rbmk.RBMKDials; import net.minecraft.util.MathHelper; import net.minecraft.world.GameRules; import net.minecraft.world.World; public class GameRuleHelper { - public static double getClampedDouble(World world, String rule, double def, double min, double max) { - return MathHelper.clamp_double(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(rule), def), min, max); + public static double getClampedDouble(World world, RBMKDials.RBMKKeys rule, double min, double max) { + return MathHelper.clamp_double(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(rule.keyString), (double) rule.defValue), min, max); } - public static double getDoubleMinimum(World world, String rule, double def, double min) { - return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(rule), def), min); + public static int getClampedInt(World world, RBMKDials.RBMKKeys rule, int min, int max) { + return MathHelper.clamp_int(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(rule.keyString), (int) rule.defValue), min, max); } - public static int getIntegerMinimum(World world, String rule, int def, int min) { - return Math.max(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(rule), def), min); + public static double getDoubleMinimum(World world, RBMKDials.RBMKKeys rule, double min) { + return Math.max(GameRuleHelper.parseDouble(world, world.getGameRules().getGameRuleStringValue(rule.keyString), (double) rule.defValue), min); + } + + public static int getIntegerMinimum(World world, RBMKDials.RBMKKeys rule, int min) { + return Math.max(GameRuleHelper.parseInt(world, world.getGameRules().getGameRuleStringValue(rule.keyString), (int) rule.defValue), min); } public static double parseDouble(World world, String s, double def) {