From 053197e0df0d2ff5e66b0c7fc4374a875b3260e9 Mon Sep 17 00:00:00 2001 From: NotAPenguin Date: Mon, 23 Sep 2024 12:26:49 +0200 Subject: [PATCH 1/3] refactor wireless data implementation to be much more robust --- .../common/WirelessComputationPacket.java | 76 ++++++++----------- .../hatch/MTEHatchDataOutput.java | 4 + .../MTEHatchWirelessComputationOutput.java | 13 +++- .../multi/MTEQuantumComputer.java | 12 +-- 4 files changed, 48 insertions(+), 57 deletions(-) diff --git a/src/main/java/gregtech/common/WirelessComputationPacket.java b/src/main/java/gregtech/common/WirelessComputationPacket.java index 1b485a63c9a..e4d3fcb3282 100644 --- a/src/main/java/gregtech/common/WirelessComputationPacket.java +++ b/src/main/java/gregtech/common/WirelessComputationPacket.java @@ -4,8 +4,6 @@ import java.util.UUID; -import com.gtnewhorizon.structurelib.util.Vec3Impl; - import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.common.misc.spaceprojects.SpaceProjectManager; import tectech.mechanics.dataTransport.QuantumDataPacket; @@ -15,24 +13,33 @@ public class WirelessComputationPacket { public boolean wirelessEnabled = false; // The main idea: 'Clearing' the computation net advances the index and sets the computation stored - // for this index to zero. Uploading is always done to the current index, but data can be downloaded from - // both indices + // for this index to zero. Uploading is always done to the current index, downloading is always done from the + // other index. This is essentially just a double buffered computation storage. The reason for this is that + // every upload needs to be done before every download happens. private final long[] computationStored = new long[] { 0, 0 }; - private long computationDownloaded = 0; private int currentIndex = 0; + private long lastUpdateTick = -1; - public Vec3Impl controllerPosition = null; + private int uploadIndex() { + return currentIndex; + } - public long getTotalComputationStored() { - return computationStored[0] + computationStored[1]; + private int downloadIndex() { + return (currentIndex + 1) % 2; } - private long getAvailableComputationStored() { - return getTotalComputationStored() - computationDownloaded; + public long getAvailableComputationStored() { + return computationStored[downloadIndex()]; } private QuantumDataPacket download(long dataIn, long aTick) { - if (!wirelessEnabled || controllerPosition == null) return new QuantumDataPacket(0L); + if (!wirelessEnabled) return new QuantumDataPacket(0L); + + // If the net hasn't been updated yet this tick, make sure to do so + if (lastUpdateTick < aTick) { + this.update(); + lastUpdateTick = aTick; + } // If we have enough computation 'stored', download it // Note that this means that if you do not have enough computation to go to all @@ -40,34 +47,21 @@ private QuantumDataPacket download(long dataIn, long aTick) { // This also means that if you don't have enough computation for a hatch, it will not receive any computation // at all. This is also fine. if (getAvailableComputationStored() >= dataIn) { - computationDownloaded += dataIn; + computationStored[downloadIndex()] -= dataIn; return new QuantumDataPacket(dataIn); } else return new QuantumDataPacket(0L); } - private void update(IGregTechTileEntity entity, long aTick) { + private void update() { // The reason we want this complex index cycling system is because hatches may upload and download computation // in the same tick as the currently stored computation is cleared. To avoid interruptions, we want to // try to double buffer these updates. This means that we keep two computation values around, and every update - // we only clear one of them. Only the most recent entry can be used for uploading computation, but we allow - // downloading computation from both the current and the previous index. + // we only clear one of them. // Remove downloaded computation previous index (which is also the next index since there are only two), // then remove the leftover from current index. - int nextIndex = (currentIndex + 1) % 2; - long availableInPrevious = computationStored[nextIndex]; - // Clear stored computation for the next index, since we don't want to allow players to accumulate - // computation in their wireless network indefinitely. This would allow for cheesing research by passively - // banking computation and then setting the input hatch to a high value when the computation is needed. - computationStored[nextIndex] = 0; - if (computationDownloaded > availableInPrevious) { - long toDrainFromCurrent = computationDownloaded - availableInPrevious; - computationStored[currentIndex] -= toDrainFromCurrent; - } - // Reset our current tally of downloaded computation - computationDownloaded = 0; - // Now advance the current index to the next index - currentIndex = nextIndex; + computationStored[downloadIndex()] = 0; + currentIndex = (currentIndex + 1) % 2; } private void setWirelessEnabled(boolean wirelessEnabled) { @@ -75,8 +69,13 @@ private void setWirelessEnabled(boolean wirelessEnabled) { } private void upload(long dataOut, long aTick) { + // If the net hasn't been updated yet this tick, make sure to do so + if (lastUpdateTick < aTick) { + this.update(); + lastUpdateTick = aTick; + } // Store computation that is uploaded internally - computationStored[currentIndex] += dataOut; + computationStored[uploadIndex()] += dataOut; } public static QuantumDataPacket downloadData(UUID userId, long dataIn, long aTick) { @@ -87,26 +86,11 @@ public static void uploadData(UUID userId, long dataOut, long aTick) { getPacketByUserId(userId).upload(dataOut, aTick); } - public static void updatePacket(IGregTechTileEntity entity, long aTick) { - getPacketByUserId(entity.getOwnerUuid()).update(entity, aTick); - } - - public static boolean enableWirelessNetWork(IGregTechTileEntity entity) { - var packet = getPacketByUserId(entity.getOwnerUuid()); - Vec3Impl pos = new Vec3Impl(entity.getXCoord(), entity.getYCoord(), entity.getZCoord()); - if (packet.wirelessEnabled && packet.controllerPosition != null - && pos.compareTo(packet.controllerPosition) != 0) return false; + public static void enableWirelessNetWork(IGregTechTileEntity entity) { getPacketByUserId(entity.getOwnerUuid()).setWirelessEnabled(true); - if (packet.controllerPosition == null) { - packet.controllerPosition = new Vec3Impl(entity.getXCoord(), entity.getYCoord(), entity.getZCoord()); - } - return true; } public static void disableWirelessNetWork(IGregTechTileEntity entity) { - var packet = getPacketByUserId(entity.getOwnerUuid()); - Vec3Impl pos = new Vec3Impl(entity.getXCoord(), entity.getYCoord(), entity.getZCoord()); - if (packet.controllerPosition != null && packet.controllerPosition.compareTo(pos) != 0) return; getPacketByUserId(entity.getOwnerUuid()).setWirelessEnabled(false); } diff --git a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchDataOutput.java b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchDataOutput.java index 094423cb0a6..52bc4aeca69 100644 --- a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchDataOutput.java +++ b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchDataOutput.java @@ -72,6 +72,10 @@ public boolean canConnectData(ForgeDirection side) { return isOutputFacing(side); } + public void providePacket(QuantumDataPacket packet) { + this.q = packet; + } + @Override public void moveAround(IGregTechTileEntity aBaseMetaTileEntity) { IConnectsToDataPipe current = this, source = this, next; diff --git a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java index 8495f95e6f7..038e8853590 100644 --- a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java +++ b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java @@ -6,8 +6,10 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.common.WirelessComputationPacket; +import tectech.mechanics.dataTransport.QuantumDataPacket; public class MTEHatchWirelessComputationOutput extends MTEHatchDataOutput { + private int clearDelay = 0; public MTEHatchWirelessComputationOutput(int aID, String aName, String aNameRegional, int aTier) { super(aID, aName, aNameRegional, aTier); @@ -39,12 +41,21 @@ public boolean canConnectData(ForgeDirection side) { return false; } + @Override + public void providePacket(QuantumDataPacket packet) { + super.providePacket(packet); + // Keep providing to wireless net for 21 ticks, because after this time a new packet from the computer should have arrived + this.clearDelay = 21; + } + @Override public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { super.onPreTick(aBaseMetaTileEntity, aTick); if (aBaseMetaTileEntity.isServerSide() && q != null) { WirelessComputationPacket.uploadData(aBaseMetaTileEntity.getOwnerUuid(), q.getContent(), aTick); - q = null; + if (clearDelay-- == 0) { + q = null; + } } } diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/MTEQuantumComputer.java b/src/main/java/tectech/thing/metaTileEntity/multi/MTEQuantumComputer.java index 25dd5f6ec67..4c57cbe3769 100644 --- a/src/main/java/tectech/thing/metaTileEntity/multi/MTEQuantumComputer.java +++ b/src/main/java/tectech/thing/metaTileEntity/multi/MTEQuantumComputer.java @@ -234,14 +234,6 @@ public void loadNBTData(NBTTagCompound aNBT) { } } - @Override - public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { - super.onPreTick(aBaseMetaTileEntity, aTick); - if (aBaseMetaTileEntity.isServerSide() && wirelessModeEnabled && aTick % 20 == 0) { - WirelessComputationPacket.updatePacket(aBaseMetaTileEntity, aTick); - } - } - @Override public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { super.onPostTick(aBaseMetaTileEntity, aTick); @@ -346,7 +338,7 @@ public void outputAfterRecipe_EM() { } for (MTEHatchDataOutput o : eOutputData) { - o.q = pack; + o.providePacket(pack); } } } @@ -570,7 +562,7 @@ public String[] getInfoData() { data.add("Wireless mode: " + EnumChatFormatting.GREEN + "enabled"); data.add( "Total wireless computation available: " + EnumChatFormatting.YELLOW - + wirelessComputationPacket.getTotalComputationStored()); + + wirelessComputationPacket.getAvailableComputationStored()); } else { data.add("Wireless mode: " + EnumChatFormatting.RED + "disabled"); } From e9c2e5f4180a484a75c86f1dd013d43789d9670f Mon Sep 17 00:00:00 2001 From: NotAPenguin Date: Mon, 23 Sep 2024 12:47:23 +0200 Subject: [PATCH 2/3] refactor wireless data stick implementation to be much more robust --- .../gregtech/common/WirelessDataStore.java | 25 +++++++++++++------ .../MTEHatchWirelessComputationOutput.java | 19 +++++++++++++- .../hatch/MTEHatchWirelessDataItemsInput.java | 23 ++++++++++++++--- .../MTEHatchWirelessDataItemsOutput.java | 11 ++------ .../metaTileEntity/multi/MTEDataBank.java | 13 ---------- 5 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/main/java/gregtech/common/WirelessDataStore.java b/src/main/java/gregtech/common/WirelessDataStore.java index 4016a2440bc..3276a7e6948 100644 --- a/src/main/java/gregtech/common/WirelessDataStore.java +++ b/src/main/java/gregtech/common/WirelessDataStore.java @@ -12,17 +12,28 @@ public class WirelessDataStore { - private final ArrayList dataSticks = new ArrayList<>(); + public static final long UPLOAD_TICK = 200; + public static final long DOWNLOAD_TICK = UPLOAD_TICK + 1; - public void clearData() { - dataSticks.clear(); - } + private long lastUploadTick = -1; + private long lastDownloadTick = -1; + private final ArrayList uploadedSticks = new ArrayList<>(); + private final ArrayList dataSticks = new ArrayList<>(); - public void uploadData(List sticks) { - dataSticks.addAll(sticks); + public void uploadData(List sticks, long tick) { + if (lastUploadTick < tick) { + uploadedSticks.clear(); + lastUploadTick = tick; + } + uploadedSticks.addAll(sticks); } - public List downloadData() { + public List downloadData(long tick) { + if (lastDownloadTick < tick) { + dataSticks.clear(); + dataSticks.addAll(uploadedSticks); + lastDownloadTick = tick; + } return dataSticks; } diff --git a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java index 038e8853590..712cd26d80d 100644 --- a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java +++ b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessComputationOutput.java @@ -1,5 +1,6 @@ package tectech.thing.metaTileEntity.hatch; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.ForgeDirection; import gregtech.api.interfaces.ITexture; @@ -9,6 +10,7 @@ import tectech.mechanics.dataTransport.QuantumDataPacket; public class MTEHatchWirelessComputationOutput extends MTEHatchDataOutput { + private int clearDelay = 0; public MTEHatchWirelessComputationOutput(int aID, String aName, String aNameRegional, int aTier) { @@ -41,10 +43,25 @@ public boolean canConnectData(ForgeDirection side) { return false; } + @Override + public void loadNBTData(NBTTagCompound aNBT) { + super.loadNBTData(aNBT); + if (aNBT.hasKey("clearDelay")) { + this.clearDelay = aNBT.getInteger("clearDelay"); + } + } + + @Override + public void saveNBTData(NBTTagCompound aNBT) { + super.saveNBTData(aNBT); + aNBT.setInteger("clearDelay", this.clearDelay); + } + @Override public void providePacket(QuantumDataPacket packet) { super.providePacket(packet); - // Keep providing to wireless net for 21 ticks, because after this time a new packet from the computer should have arrived + // Keep providing to wireless net for 21 ticks, because after this time a new packet from the computer should + // have arrived this.clearDelay = 21; } diff --git a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsInput.java b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsInput.java index e7d604328ae..f3e4619c05b 100644 --- a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsInput.java +++ b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsInput.java @@ -18,6 +18,8 @@ import org.apache.commons.lang3.reflect.FieldUtils; +import com.google.common.collect.ImmutableList; + import gregtech.api.enums.Dyes; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; @@ -32,6 +34,8 @@ public class MTEHatchWirelessDataItemsInput extends MTEHatchDataAccess { private String clientLocale = "en_US"; + private List dataItems = null; + public MTEHatchWirelessDataItemsInput(int aID, String aName, String aNameRegional, int aTier) { super(aID, aName, aNameRegional, aTier); TTUtility.setTier(aTier, this); @@ -118,14 +122,25 @@ public String[] getDescription() { @Override public List getInventoryItems(Predicate filter) { - WirelessDataStore wirelessData = WirelessDataStore - .getWirelessDataSticks(getBaseMetaTileEntity().getOwnerUuid()); - return wirelessData.downloadData() - .stream() + if (this.dataItems == null) return ImmutableList.of(); + return this.dataItems.stream() .filter(stack -> stack != null && filter.test(stack)) .collect(Collectors.toList()); } + @Override + public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + if (aBaseMetaTileEntity.isServerSide()) { + // Upload data packet and mark it as uploaded, so it will not be uploaded again + // until the data bank resets the wireless network + if (aTick % WirelessDataStore.DOWNLOAD_TICK == 0) { + WirelessDataStore wirelessDataStore = WirelessDataStore + .getWirelessDataSticks(getBaseMetaTileEntity().getOwnerUuid()); + this.dataItems = wirelessDataStore.downloadData(aTick); + } + } + } + @Override public boolean isGivingInformation() { return true; diff --git a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsOutput.java b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsOutput.java index 2765598475d..df4af869ea7 100644 --- a/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsOutput.java +++ b/src/main/java/tectech/thing/metaTileEntity/hatch/MTEHatchWirelessDataItemsOutput.java @@ -27,8 +27,6 @@ public class MTEHatchWirelessDataItemsOutput extends MTEHatch { public InventoryDataPacket dataPacket = null; - public boolean uploadedSinceReset = false; - public MTEHatchWirelessDataItemsOutput(int aID, String aName, String aNameRegional, int aTier) { super( aID, @@ -94,7 +92,6 @@ public void saveNBTData(NBTTagCompound aNBT) { if (dataPacket != null) { aNBT.setTag("eDATA", dataPacket.toNbt()); } - aNBT.setBoolean("uploadedSinceReset", uploadedSinceReset); } @Override @@ -103,9 +100,6 @@ public void loadNBTData(NBTTagCompound aNBT) { if (aNBT.hasKey("eDATA")) { dataPacket = new InventoryDataPacket(aNBT.getCompoundTag("eDATA")); } - if (aNBT.hasKey("uploadedSinceReset")) { - uploadedSinceReset = aNBT.getBoolean("uploadedSinceReset"); - } } @Override @@ -113,11 +107,10 @@ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { if (aBaseMetaTileEntity.isServerSide()) { // Upload data packet and mark it as uploaded, so it will not be uploaded again // until the data bank resets the wireless network - if (dataPacket != null && !uploadedSinceReset) { + if (dataPacket != null && (aTick % WirelessDataStore.UPLOAD_TICK) == 0) { WirelessDataStore wirelessDataStore = WirelessDataStore .getWirelessDataSticks(getBaseMetaTileEntity().getOwnerUuid()); - wirelessDataStore.uploadData(Arrays.asList(dataPacket.getContent())); - uploadedSinceReset = true; + wirelessDataStore.uploadData(Arrays.asList(dataPacket.getContent()), aTick); } } } diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java b/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java index 30a417ae918..671e01c194b 100644 --- a/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java +++ b/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java @@ -41,7 +41,6 @@ import gregtech.api.util.IGTHatchAdder; import gregtech.api.util.MultiblockTooltipBuilder; import gregtech.common.WirelessComputationPacket; -import gregtech.common.WirelessDataStore; import tectech.Reference; import tectech.mechanics.dataTransport.InventoryDataPacket; import tectech.recipe.TTRecipeAdder; @@ -251,18 +250,6 @@ public final boolean addDataBankHatchToMachineList(IGregTechTileEntity aTileEnti @Override public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { super.onPreTick(aBaseMetaTileEntity, aTick); - // Every 200 ticks, clear wireless data store so hatches need to provide their data again in - // their onPostTick() call. This also happens every 200 ticks - if (mMachine && aBaseMetaTileEntity.isActive() && wirelessModeEnabled && aTick % 200 == 0) { - WirelessDataStore wirelessStore = WirelessDataStore - .getWirelessDataSticks(aBaseMetaTileEntity.getOwnerUuid()); - wirelessStore.clearData(); - - // After reset, clear uploadedSinceReset of all connected hatches - for (MTEHatchWirelessDataItemsOutput hatch : eWirelessStacksDataOutputs) { - hatch.uploadedSinceReset = false; - } - } } @Override From 273bd4abf85405f0a8b1fc2ba0f75713f1e77616 Mon Sep 17 00:00:00 2001 From: NotAPenguin Date: Mon, 23 Sep 2024 22:11:00 +0200 Subject: [PATCH 3/3] remove unnecessary onPreTick override in databank --- .../java/tectech/thing/metaTileEntity/multi/MTEDataBank.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java b/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java index 671e01c194b..d3e52b97161 100644 --- a/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java +++ b/src/main/java/tectech/thing/metaTileEntity/multi/MTEDataBank.java @@ -247,11 +247,6 @@ public final boolean addDataBankHatchToMachineList(IGregTechTileEntity aTileEnti return false; } - @Override - public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { - super.onPreTick(aBaseMetaTileEntity, aTick); - } - @Override public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (getBaseMetaTileEntity().isServerSide()) {