Skip to content

Commit

Permalink
UpdateEntry memory "leak" fix (#882)
Browse files Browse the repository at this point in the history
* Retire UpdateEntry and use an int : byte[] map

- Allows new data to override old data if they have the same discriminator and if the packet hasn't been sent yet, this normally happens when no players are watching the chunk where the update occurred
- Fix large amounts of memory being occupied and not flushed because of the indefinite queuing of `UpdateEntry`
- Eliminates strain when sending packets as well, the structure has been slightly changed to be tiny bit lighter

* Fix reading wrong tag onDataPacket
  • Loading branch information
Rongmario authored Apr 11, 2022
1 parent eea741e commit ffc98c2
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 30 deletions.
51 changes: 22 additions & 29 deletions src/main/java/gregtech/api/metatileentity/SyncedTileEntityBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@
import gregtech.api.block.BlockStateTileEntity;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.play.server.SPacketUpdateTileEntity;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.Constants;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

public abstract class SyncedTileEntityBase extends BlockStateTileEntity {
Expand All @@ -25,53 +26,45 @@ public abstract class SyncedTileEntityBase extends BlockStateTileEntity {

public abstract void receiveCustomData(int discriminator, PacketBuffer buf);

private static class UpdateEntry {
private final int discriminator;
private final byte[] updateData;

public UpdateEntry(int discriminator, byte[] updateData) {
this.discriminator = discriminator;
this.updateData = updateData;
}
}

protected final List<UpdateEntry> updateEntries = new ArrayList<>();
protected final Int2ObjectMap<byte[]> updates = new Int2ObjectArrayMap<>(5);

public void writeCustomData(int discriminator, Consumer<PacketBuffer> dataWriter) {
ByteBuf backedBuffer = Unpooled.buffer();
dataWriter.accept(new PacketBuffer(backedBuffer));
byte[] updateData = Arrays.copyOfRange(backedBuffer.array(), 0, backedBuffer.writerIndex());
updateEntries.add(new UpdateEntry(discriminator, updateData));
updates.put(discriminator, updateData);
@SuppressWarnings("deprecation")
IBlockState blockState = getBlockType().getStateFromMeta(getBlockMetadata());
world.notifyBlockUpdate(getPos(), blockState, blockState, 0);
}

@Override
public SPacketUpdateTileEntity getUpdatePacket() {
if (this.updates.isEmpty()) {
return null;
}
NBTTagCompound updateTag = new NBTTagCompound();
NBTTagList tagList = new NBTTagList();
for (UpdateEntry updateEntry : updateEntries) {
NBTTagList listTag = new NBTTagList();
for (Int2ObjectMap.Entry<byte[]> entry : updates.int2ObjectEntrySet()) {
NBTTagCompound entryTag = new NBTTagCompound();
entryTag.setInteger("i", updateEntry.discriminator);
entryTag.setByteArray("d", updateEntry.updateData);
tagList.appendTag(entryTag);
entryTag.setByteArray(Integer.toString(entry.getIntKey()), entry.getValue());
listTag.appendTag(entryTag);
}
this.updateEntries.clear();
updateTag.setTag("d", tagList);
updateTag.setTag("d", listTag);
this.updates.clear();
return new SPacketUpdateTileEntity(getPos(), 0, updateTag);
}

@Override
public void onDataPacket(@Nonnull NetworkManager net, SPacketUpdateTileEntity pkt) {
NBTTagCompound updateTag = pkt.getNbtCompound();
NBTTagList tagList = updateTag.getTagList("d", NBT.TAG_COMPOUND);
for (int i = 0; i < tagList.tagCount(); i++) {
NBTTagCompound entryTag = tagList.getCompoundTagAt(i);
int discriminator = entryTag.getInteger("i");
byte[] updateData = entryTag.getByteArray("d");
ByteBuf backedBuffer = Unpooled.copiedBuffer(updateData);
receiveCustomData(discriminator, new PacketBuffer(backedBuffer));
NBTTagList listTag = updateTag.getTagList("d", Constants.NBT.TAG_COMPOUND);
for (NBTBase entryBase : listTag) {
NBTTagCompound entryTag = (NBTTagCompound) entryBase;
for (String discriminatorKey : entryTag.getKeySet()) {
ByteBuf backedBuffer = Unpooled.copiedBuffer(entryTag.getByteArray(discriminatorKey));
receiveCustomData(Integer.parseInt(discriminatorKey), new PacketBuffer(backedBuffer));
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void transferDataFrom(IPipeTile<PipeType, NodeDataType> tileEntity) {
this.paintingColor = tileEntity.getPaintingColor();
this.connections = tileEntity.getConnections();
if (tileEntity instanceof TileEntityPipeBase) {
this.updateEntries.addAll(((TileEntityPipeBase<?, ?>) tileEntity).updateEntries);
this.updates.putAll(((TileEntityPipeBase<?, ?>) tileEntity).updates);
}
tileEntity.getCoverableImplementation().transferDataTo(coverableImplementation);
}
Expand Down

0 comments on commit ffc98c2

Please sign in to comment.