there's actually so many optimizations here that it'd be impossible for be to explain them all

This commit is contained in:
BallOfEnergy 2024-11-04 21:34:48 -06:00
parent 354860c610
commit 970485f68c
18 changed files with 860 additions and 593 deletions

View File

@ -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<Chunk> 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;
}
}
}

View File

@ -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<World> 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.StreamWorld> 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<BlockPos> 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++;
}
}

View File

@ -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<String, Object> 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);
}
}

View File

@ -12,7 +12,7 @@ public class NeutronNodeWorld {
protected static HashMap<BlockPos, NeutronNode> 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();
}
}

View File

@ -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<BlockPos> getBlocks(int range) {
List<BlockPos> positions = new ArrayList<>();
public Iterator<BlockPos> 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<BlockPos>() {
@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);
}
}

View File

@ -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<World> 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.StreamWorld> 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);
}
}
}

View File

@ -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<BlockPos> getReaSimNodes() {
List<BlockPos> 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<BlockPos> getReaSimNodes() {
x = -fluxRange;
z = -fluxRange;
return new Iterator<BlockPos>() {
@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<BlockPos> checkNode() {
@ -74,11 +103,12 @@ public class RBMKNeutronHandler {
BlockPos pos = new BlockPos(this.tile);
List<RBMKNeutronStream> 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<BlockPos> points = getReaSimNodes();
{
Iterator<BlockPos> 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<RBMKNeutronNode> nodes = new ArrayList<>();
points.forEach(nodePos -> {
RBMKNeutronNode node = (RBMKNeutronNode) NeutronNodeWorld.getNode(nodePos);
if (node != null)
nodes.add(node);
});
Iterator<BlockPos> 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<RBMKNeutronNode> 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<RBMKNeutronNode> getNodes(boolean addNode) {
List<RBMKNeutronNode> 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<BlockPos> 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<RBMKNeutronNode> 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<World> 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.StreamWorld> 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<BlockPos> 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++;
}
}

View File

@ -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<Future<?>> 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
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -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<Side, FMLEmbeddedChannel> channels = NetworkRegistry.INSTANCE.newChannel(name, packetCodec);
clientChannel = channels.get(Side.CLIENT);
serverChannel = channels.get(Side.SERVER);
}
public <REQ extends IMessage, REPLY extends IMessage> void registerMessage(Class<? extends IMessageHandler<REQ, REPLY>> messageHandler, Class<REQ> 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<REQ, REPLY> 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);
}
}

View File

@ -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
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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<RBMKKeys, List<Tuple.Pair<World, Object>>> 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<Tuple.Pair<World, Object>> 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<Tuple.Pair<World, Object>> 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);
}
}

View File

@ -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) {

View File

@ -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!

View File

@ -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) {