Skip to content
Permalink
Browse files

Cache sent item stacks into a big message queue. Helps fix part of #4393

.
  • Loading branch information...
AlexIIL committed Apr 16, 2019
1 parent 6b0b3cd commit 68d1c1131db308ebe1ce6824da8a4925968a48e5
@@ -1,4 +1,4 @@
mc_version=1.12.2
forge_version=14.23.0.2544
mappings_version=snapshot_20171120
mod_version=7.99.23
mod_version=7.99.24-pre1
@@ -81,7 +81,7 @@ public void onGetCollisionBoxesForQuarry(GetCollisionBoxesEvent event) {
iter.remove();
continue;
}
for (AxisAlignedBB aabb : quarry.collisionBoxes) {
for (AxisAlignedBB aabb : quarry.getCollisionBoxes()) {
if (event.getAabb().intersects(aabb)) {
event.getCollisionBoxesList().add(aabb);
}
@@ -111,7 +111,10 @@
public Vec3d clientDrillPos;
public Vec3d prevClientDrillPos;
private long debugPowerRate = 0;
public List<AxisAlignedBB> collisionBoxes = ImmutableList.of();

private List<AxisAlignedBB> collisionBoxes = ImmutableList.of();
private Vec3d collisionDrillPos;

private final IWorldEventListener worldEventListener = new WorldEventListenerAdapter() {
@Override
public void notifyBlockUpdate(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState oldState,
@@ -487,18 +490,9 @@ private void updatePoses() {

@Override
public void update() {
if (drillPos != null) {
Vec3d max = VecUtil.convertCenter(frameBox.max());
Vec3d min = VecUtil.replaceValue(VecUtil.convertCenter(frameBox.min()), Axis.Y, max.y);
collisionBoxes = ImmutableList.of(
BoundingBoxUtil.makeFrom(VecUtil.replaceValue(min, Axis.X, drillPos.x + 0.5),
VecUtil.replaceValue(max, Axis.X, drillPos.x + 0.5), 0.25),
BoundingBoxUtil.makeFrom(VecUtil.replaceValue(min, Axis.Z, drillPos.z + 0.5),
VecUtil.replaceValue(max, Axis.Z, drillPos.z + 0.5), 0.25),
BoundingBoxUtil.makeFrom(drillPos.addVector(0.5, 0, 0.5),
VecUtil.replaceValue(drillPos, Axis.Y, max.y).addVector(0.5, 0, 0.5), 0.25));
} else {
if (drillPos == null) {
collisionBoxes = ImmutableList.of();
collisionDrillPos = null;
}

if (world.isRemote) {
@@ -625,6 +619,22 @@ public void update() {
}
}

public List<AxisAlignedBB> getCollisionBoxes() {
if (drillPos != null && drillPos != collisionDrillPos) {
Vec3d max = VecUtil.convertCenter(frameBox.max());
Vec3d min = VecUtil.replaceValue(VecUtil.convertCenter(frameBox.min()), Axis.Y, max.y);
collisionBoxes = ImmutableList.of(
BoundingBoxUtil.makeFrom(VecUtil.replaceValue(min, Axis.X, drillPos.x + 0.5),
VecUtil.replaceValue(max, Axis.X, drillPos.x + 0.5), 0.25),
BoundingBoxUtil.makeFrom(VecUtil.replaceValue(min, Axis.Z, drillPos.z + 0.5),
VecUtil.replaceValue(max, Axis.Z, drillPos.z + 0.5), 0.25),
BoundingBoxUtil.makeFrom(drillPos.addVector(0.5, 0, 0.5),
VecUtil.replaceValue(drillPos, Axis.Y, max.y).addVector(0.5, 0, 0.5), 0.25));
collisionDrillPos = drillPos;
}
return collisionBoxes;
}

@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
@@ -38,6 +38,12 @@ public boolean equals(Object obj) {
if (obj.getClass() != this.getClass()) return false;
ItemStackKey other = (ItemStackKey) obj;
if (hash != other.hash) return false;
if (baseStack.getItem() != other.baseStack.getItem()) {
return false;
}
if (baseStack.getMetadata() != other.baseStack.getMetadata()) {
return false;
}
return baseStack.serializeNBT().equals(other.baseStack.serializeNBT());
}

@@ -8,6 +8,7 @@

import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collector;
import java.util.stream.Collectors;

@@ -397,6 +398,9 @@ public static int hash(@Nonnull ItemStack stack) {
if (stack.isEmpty()) {
return 0;
}
if (!stack.hasTagCompound()) {
return Objects.hash(stack.getItem(), stack.getMetadata());
}
return stack.serializeNBT().hashCode();
}

@@ -15,6 +15,7 @@
import net.minecraftforge.fml.common.event.FMLInterModComms.IMCMessage;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent.ServerTickEvent;
import net.minecraftforge.fml.common.network.NetworkRegistry;

import buildcraft.api.BCModules;
@@ -33,6 +34,7 @@

import buildcraft.core.BCCore;
import buildcraft.silicon.plug.FacadeStateManager;
import buildcraft.transport.net.PipeItemMessageQueue;
import buildcraft.transport.pipe.SchematicBlockPipe;

//@formatter:off
@@ -15,6 +15,7 @@
import net.minecraftforge.fml.relauncher.SideOnly;

import buildcraft.transport.client.render.PipeWireRenderer;
import buildcraft.transport.net.PipeItemMessageQueue;
import buildcraft.transport.wire.WorldSavedDataWireSystems;

public enum BCTransportEventDist {
@@ -27,6 +28,11 @@ public void onWorldTick(TickEvent.WorldTickEvent event) {
}
}

@SubscribeEvent
public void onServerTick(TickEvent.ServerTickEvent event) {
PipeItemMessageQueue.serverTick();
}

@SubscribeEvent
public void onChunkWatch(ChunkWatchEvent event) {
WorldSavedDataWireSystems.get(event.getPlayer().world).changedPlayers.add(event.getPlayer());
@@ -40,11 +46,11 @@ public void onTextureStitch(TextureStitchEvent.Post event) {

@SubscribeEvent
public void onBlockPlace(BlockEvent.PlaceEvent event) {
//event.setCanceled(true);
// event.setCanceled(true);
}

@SubscribeEvent
public void onBlockBreak(BlockEvent.BreakEvent event) {
//event.setCanceled(true);
// event.setCanceled(true);
}
}
@@ -34,6 +34,7 @@
import buildcraft.transport.gui.GuiDiamondWoodPipe;
import buildcraft.transport.gui.GuiEmzuliPipe_BC8;
import buildcraft.transport.gui.GuiFilteredBuffer;
import buildcraft.transport.net.MessageMultiPipeItem;
import buildcraft.transport.pipe.behaviour.PipeBehaviourDiamond;
import buildcraft.transport.pipe.behaviour.PipeBehaviourEmzuli;
import buildcraft.transport.pipe.behaviour.PipeBehaviourWoodDiamond;
@@ -114,6 +115,7 @@ public Object getClientGuiElement(int id, EntityPlayer player, World world, int
public void fmlPreInit() {
MessageManager.registerMessageClass(BCModules.TRANSPORT, MessageWireSystems.class, Side.CLIENT);
MessageManager.registerMessageClass(BCModules.TRANSPORT, MessageWireSystemsPowered.class, Side.CLIENT);
MessageManager.registerMessageClass(BCModules.TRANSPORT, MessageMultiPipeItem.class, Side.CLIENT);
}

public void fmlInit() {}
@@ -137,6 +139,7 @@ public void fmlPreInit() {

MessageManager.setHandler(MessageWireSystems.class, MessageWireSystems.HANDLER, Side.CLIENT);
MessageManager.setHandler(MessageWireSystemsPowered.class, MessageWireSystemsPowered.HANDLER, Side.CLIENT);
MessageManager.setHandler(MessageMultiPipeItem.class, MessageMultiPipeItem.HANDLER, Side.CLIENT);
}

@Override
@@ -0,0 +1,152 @@
package buildcraft.transport.net;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.Nullable;

import io.netty.buffer.ByteBuf;

import net.minecraft.client.Minecraft;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;

import buildcraft.api.transport.pipe.IPipeHolder;
import buildcraft.api.transport.pipe.PipeFlow;

import buildcraft.lib.misc.MessageUtil;
import buildcraft.lib.net.PacketBufferBC;

import buildcraft.transport.pipe.flow.PipeFlowItems;

public class MessageMultiPipeItem implements IMessage {

private static final int MAX_ITEMS_PER_PIPE = 10;
private static final int MAX_POSITIONS = 4000;
public final Map<BlockPos, List<TravellingItemData>> items = new HashMap<>();

public MessageMultiPipeItem() {

}

@Override
public void fromBytes(ByteBuf buffer) {
PacketBufferBC buf = PacketBufferBC.asPacketBufferBc(buffer);
int blockCount = buf.readShort();
for (int b = 0; b < blockCount; b++) {
BlockPos pos = buf.readBlockPos();
List<TravellingItemData> posItems = new ArrayList<>();
items.put(pos, posItems);
int itemCount = buf.readUnsignedByte();
for (int i = 0; i < itemCount; i++) {
posItems.add(new TravellingItemData(buf));
}
}
}

@Override
public void toBytes(ByteBuf buffer) {
PacketBufferBC buf = PacketBufferBC.asPacketBufferBc(buffer);
int blockCount = Math.min(items.size(), MAX_POSITIONS);
buf.writeShort(blockCount);
int blockIndex = 0;
for (Entry<BlockPos, List<TravellingItemData>> entry : items.entrySet()) {
buf.writeBlockPos(entry.getKey());
List<TravellingItemData> list = entry.getValue();
int itemCount = Math.min(list.size(), MAX_ITEMS_PER_PIPE);
buf.writeByte(itemCount);
for (int i = 0; i < itemCount; i++) {
list.get(i).toBuffer(buf);
}
if (++blockIndex >= blockCount) {
break;
}
}
}

public void append(BlockPos pos, int stackId, byte stackCount, boolean toCenter, EnumFacing side,
EnumDyeColor colour, byte timeToDest) {
List<TravellingItemData> list = items.get(pos);
if (list == null) {
if (items.size() >= MAX_POSITIONS) {
return;
}
list = new ArrayList<>();
items.put(pos, list);
}
if (list.size() >= MAX_ITEMS_PER_PIPE) {
return;
}
list.add(new TravellingItemData(stackId, stackCount, toCenter, side, colour, timeToDest));
}

public static class TravellingItemData {
public final int stackId;
public final byte stackCount;
public final boolean toCenter;
public final EnumFacing side;
public final @Nullable EnumDyeColor colour;
public final byte timeToDest;

public TravellingItemData(int stackId, byte stackCount, boolean toCenter, EnumFacing side, EnumDyeColor colour,
byte timeToDest) {
this.stackId = stackId;
this.stackCount = stackCount;
this.toCenter = toCenter;
this.side = side;
this.colour = colour;
this.timeToDest = timeToDest;
}

TravellingItemData(PacketBufferBC buf) {
stackId = buf.readVarInt();
stackCount = buf.readByte();
toCenter = buf.readBoolean();
side = buf.readEnumValue(EnumFacing.class);
colour = MessageUtil.readEnumOrNull(buf, EnumDyeColor.class);
timeToDest = buf.readByte();
}

void toBuffer(PacketBufferBC buf) {
buf.writeVarInt(stackId);
buf.writeByte(stackCount);
buf.writeBoolean(toCenter);
buf.writeEnumValue(side);
MessageUtil.writeEnumOrNull(buf, colour);
buf.writeByte(timeToDest);
}
}

public static final IMessageHandler<MessageMultiPipeItem, IMessage> HANDLER =
new IMessageHandler<MessageMultiPipeItem, IMessage>() {

@Override
public IMessage onMessage(MessageMultiPipeItem message, MessageContext ctx) {
World world = Minecraft.getMinecraft().world;
if (world == null) {
return null;
}
for (Entry<BlockPos, List<TravellingItemData>> entry : message.items.entrySet()) {
BlockPos pos = entry.getKey();
TileEntity tile = world.getTileEntity(pos);
if (tile instanceof IPipeHolder) {
PipeFlow flow = ((IPipeHolder)tile).getPipe().getFlow();
if (flow instanceof PipeFlowItems) {
((PipeFlowItems)flow).handleClientReceviedItems(entry.getValue());
}
}
}
return null;
}
};
}
@@ -0,0 +1,52 @@
package buildcraft.transport.net;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.WeakHashMap;

import javax.annotation.Nullable;

import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.server.management.PlayerChunkMapEntry;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;

import buildcraft.lib.net.MessageManager;

public class PipeItemMessageQueue {

private static final Map<EntityPlayerMP, MessageMultiPipeItem> cachedPlayerPackets = new WeakHashMap<>();

public static void serverTick() {
for (Entry<EntityPlayerMP, MessageMultiPipeItem> entry : cachedPlayerPackets.entrySet()) {
MessageManager.sendTo(entry.getValue(), entry.getKey());
}
cachedPlayerPackets.clear();
}

public static void appendTravellingItem(World world, BlockPos pos, int stackId, byte stackCount, boolean toCenter,
EnumFacing side, @Nullable EnumDyeColor colour, byte timeToDest) {
WorldServer server = (WorldServer) world;
PlayerChunkMapEntry playerChunkMap = server.getPlayerChunkMap().getEntry(pos.getX() >> 4, pos.getZ() >> 4);
if (playerChunkMap == null) {
// No-one was watching this chunk.
return;
}
List<EntityPlayerMP> players = new ArrayList<>();
// Slightly ugly hack to iterate through all players watching the chunk
playerChunkMap.hasPlayerMatchingInRange(0, player -> {
players.add(player);
// Always return false so that the iteration doesn't stop early
return false;
});
for (EntityPlayerMP player : players) {
cachedPlayerPackets.computeIfAbsent(player, pl -> new MessageMultiPipeItem()).append(pos, stackId,
stackCount, toCenter, side, colour, timeToDest);
}
}
}

1 comment on commit 68d1c11

@AlexIIL

This comment has been minimized.

Copy link
Member Author

commented on 68d1c11 Apr 16, 2019

Woops, it looks like this also includes a WIP fix for the quarry. Hopefully that won't break anything? :P

Please sign in to comment.
You can’t perform that action at this time.