diff --git a/src/main/java/com/troblecodings/signals/core/LinkedPositions.java b/src/main/java/com/troblecodings/signals/core/LinkedPositions.java index a5870773f..fb5ac1fda 100644 --- a/src/main/java/com/troblecodings/signals/core/LinkedPositions.java +++ b/src/main/java/com/troblecodings/signals/core/LinkedPositions.java @@ -29,10 +29,15 @@ public class LinkedPositions { private static final String SIGNAL_NAME = "signalName"; private static final String ALL_POS = "allPos"; + private final BlockPos thisPos; private final Map signals = new HashMap<>(); private final Map linkedBlocks = new HashMap<>(); private final Map> possibleSubsidiaries = new HashMap<>(); + public LinkedPositions(final BlockPos thisPos) { + this.thisPos = thisPos; + } + private final SignalStateListener listener = (stateInfo, properties, changed) -> { if (changed.equals(ChangedState.UPDATED) || changed.equals(ChangedState.ADDED_TO_CACHE)) { loadPossibleSubsidiaires(stateInfo, properties); @@ -45,6 +50,8 @@ public void addSignal(final BlockPos signalPos, final Signal signal, final World signals.put(signalPos, signal); final SignalStateInfo info = new SignalStateInfo(world, signalPos, signal); SignalConfig.reset(info); + SignalStateHandler.loadSignal( + new StateLoadHolder(info, new LoadHolder<>(new StateInfo(world, thisPos)))); loadPossibleSubsidiaires(info, SignalStateHandler.getStates(info)); } @@ -77,11 +84,12 @@ public Map getAllLinkedPos() { } public void unlink(final BlockPos tilePos, final World world) { - final List signalsToUnload = new ArrayList<>(); + final List signalsToUnload = new ArrayList<>(); signals.forEach((pos, signal) -> { final SignalStateInfo info = new SignalStateInfo(world, pos, signal); SignalConfig.reset(info); - signalsToUnload.add(info); + signalsToUnload.add( + new StateLoadHolder(info, new LoadHolder<>(new StateInfo(world, tilePos)))); SignalStateHandler.removeListener(info, listener); }); linkedBlocks.entrySet().stream().filter(entry -> !entry.getValue().equals(LinkType.SIGNAL)) @@ -127,10 +135,12 @@ public void read(final NBTWrapper wrapper) { public void loadSignals(final World world) { if (world.isRemote) return; - final List signalInfos = new ArrayList<>(); + final List signalInfos = new ArrayList<>(); signals.forEach((pos, signal) -> { final SignalStateInfo info = new SignalStateInfo(world, pos, signal); SignalStateHandler.addListener(info, listener); + signalInfos.add( + new StateLoadHolder(info, new LoadHolder<>(new StateInfo(world, thisPos)))); }); SignalStateHandler.loadSignals(signalInfos); } @@ -138,8 +148,10 @@ public void loadSignals(final World world) { public void unloadSignals(final World world) { if (world.isRemote) return; - final List signalInfos = new ArrayList<>(); - signals.forEach((pos, signal) -> signalInfos.add(new SignalStateInfo(world, pos, signal))); + final List signalInfos = new ArrayList<>(); + signals.forEach((pos, signal) -> signalInfos + .add(new StateLoadHolder(new SignalStateInfo(world, pos, signal), + new LoadHolder<>(new StateInfo(world, thisPos))))); SignalStateHandler.unloadSignals(signalInfos); } diff --git a/src/main/java/com/troblecodings/signals/core/LoadHolder.java b/src/main/java/com/troblecodings/signals/core/LoadHolder.java new file mode 100644 index 000000000..6abba4882 --- /dev/null +++ b/src/main/java/com/troblecodings/signals/core/LoadHolder.java @@ -0,0 +1,30 @@ +package com.troblecodings.signals.core; + +import java.util.Objects; + +public class LoadHolder { + + public final T holder; + + public LoadHolder(final T holder) { + this.holder = holder; + } + + @Override + public int hashCode() { + return Objects.hash(holder); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final LoadHolder other = (LoadHolder) obj; + return Objects.equals(holder, other.holder); + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/core/StateLoadHolder.java b/src/main/java/com/troblecodings/signals/core/StateLoadHolder.java new file mode 100644 index 000000000..cbf235610 --- /dev/null +++ b/src/main/java/com/troblecodings/signals/core/StateLoadHolder.java @@ -0,0 +1,34 @@ +package com.troblecodings.signals.core; + +import java.util.Objects; + +import com.troblecodings.signals.handler.SignalStateInfo; + +public class StateLoadHolder { + + public final SignalStateInfo info; + public final LoadHolder holder; + + public StateLoadHolder(final SignalStateInfo info, final LoadHolder holder) { + this.info = info; + this.holder = holder; + } + + @Override + public int hashCode() { + return Objects.hash(holder, info); + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final StateLoadHolder other = (StateLoadHolder) obj; + return Objects.equals(holder, other.holder) && Objects.equals(info, other.info); + } + +} \ No newline at end of file diff --git a/src/main/java/com/troblecodings/signals/handler/SignalBoxHandler.java b/src/main/java/com/troblecodings/signals/handler/SignalBoxHandler.java index 92e5e368c..b68e0b1fd 100644 --- a/src/main/java/com/troblecodings/signals/handler/SignalBoxHandler.java +++ b/src/main/java/com/troblecodings/signals/handler/SignalBoxHandler.java @@ -120,7 +120,8 @@ public static void readTileNBT(final StateInfo identifier, final NBTWrapper wrap return; LinkedPositions holder; synchronized (ALL_LINKED_POS) { - holder = ALL_LINKED_POS.computeIfAbsent(identifier, _u -> new LinkedPositions()); + holder = ALL_LINKED_POS.computeIfAbsent(identifier, + _u -> new LinkedPositions(identifier.pos)); } holder.read(wrapper); PathwayHolder grid; @@ -161,7 +162,8 @@ public static boolean linkPosToSignalBox(final StateInfo identifier, final Block return false; LinkedPositions holder; synchronized (ALL_LINKED_POS) { - holder = ALL_LINKED_POS.computeIfAbsent(identifier, _u -> new LinkedPositions()); + holder = ALL_LINKED_POS.computeIfAbsent(identifier, + _u -> new LinkedPositions(identifier.pos)); } final boolean linked = holder.addLinkedPos(linkPos, type); if (!linked) diff --git a/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java b/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java index 37c460165..1ad469130 100644 --- a/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java +++ b/src/main/java/com/troblecodings/signals/handler/SignalStateHandler.java @@ -20,7 +20,9 @@ import com.troblecodings.signals.OpenSignalsMain; import com.troblecodings.signals.SEProperty; import com.troblecodings.signals.blocks.Signal; +import com.troblecodings.signals.core.LoadHolder; import com.troblecodings.signals.core.SignalStateListener; +import com.troblecodings.signals.core.StateLoadHolder; import com.troblecodings.signals.core.WriteBuffer; import com.troblecodings.signals.enums.ChangedState; import com.troblecodings.signals.tileentitys.SignalTileEntity; @@ -30,6 +32,7 @@ import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.network.PacketBuffer; import net.minecraft.network.play.client.CPacketCustomPayload; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; @@ -50,7 +53,7 @@ private SignalStateHandler() { private static ExecutorService IO_SERVICE = Executors.newFixedThreadPool(3); private static final Map> CURRENTLY_LOADED_STATES = new HashMap<>(); private static final Map ALL_LEVEL_FILES = new HashMap<>(); - private static final Map SIGNAL_COUNTER = new HashMap<>(); + private static final Map>> SIGNAL_COUNTER = new HashMap<>(); private static final Map> ALL_LISTENERS = new HashMap<>(); private static final String CHANNELNAME = "statehandlernet"; private static FMLEventChannel channel; @@ -84,8 +87,10 @@ public static void createStates(final SignalStateInfo info, CURRENTLY_LOADED_STATES.put(info, ImmutableMap.copyOf(states)); } new Thread(() -> { + final List> list = new ArrayList<>(); + list.add(new LoadHolder<>(new ChunkPos(info.pos))); synchronized (SIGNAL_COUNTER) { - SIGNAL_COUNTER.put(info, 1); + SIGNAL_COUNTER.put(info, list); } sendToAll(info, states); createToFile(info, states); @@ -344,7 +349,7 @@ public static void onChunkWatch(final ChunkWatchEvent.Watch event) { return; final EntityPlayer player = event.getPlayer(); - final List states = new ArrayList<>(); + final List states = new ArrayList<>(); synchronized (ALL_LEVEL_FILES) { if (!ALL_LEVEL_FILES.containsKey(world)) { ALL_LEVEL_FILES.put(world, @@ -360,7 +365,7 @@ public static void onChunkWatch(final ChunkWatchEvent.Watch event) { final SignalTileEntity signalTile = (SignalTileEntity) tile; final SignalStateInfo info = new SignalStateInfo(world, pos, signalTile.getSignal()); - states.add(info); + states.add(new StateLoadHolder(info, new LoadHolder<>(new ChunkPos(pos)))); synchronized (CURRENTLY_LOADED_STATES) { if (CURRENTLY_LOADED_STATES.containsKey(info)) { sendToPlayer(info, CURRENTLY_LOADED_STATES.get(info), player); @@ -377,91 +382,97 @@ public static void onChunkUnWatch(final ChunkWatchEvent.UnWatch event) { final World world = chunk.getWorld(); if (world.isRemote) return; - final List states = new ArrayList<>(); + final List states = new ArrayList<>(); chunk.getTileEntityMap().forEach((pos, tile) -> { if (tile instanceof SignalTileEntity) { final SignalTileEntity signalTile = (SignalTileEntity) tile; - states.add(new SignalStateInfo(world, pos, signalTile.getSignal())); + states.add( + new StateLoadHolder(new SignalStateInfo(world, pos, signalTile.getSignal()), + new LoadHolder<>(new ChunkPos(pos)))); } }); unloadSignals(states); } - public static void loadSignal(final SignalStateInfo info) { + public static void loadSignal(final StateLoadHolder info) { loadSignal(info, null); } - public static void loadSignals(final List signals) { + public static void loadSignals(final List signals) { loadSignals(signals, null); } - public static void loadSignal(final SignalStateInfo info, final @Nullable EntityPlayer player) { + public static void loadSignal(final StateLoadHolder info, final @Nullable EntityPlayer player) { loadSignals(ImmutableList.of(info), player); } - public static void loadSignals(final List signals, + public static void loadSignals(final List signals, final @Nullable EntityPlayer player) { if (signals == null || signals.isEmpty() || IO_SERVICE.isShutdown()) return; IO_SERVICE.execute(() -> { signals.forEach(info -> { synchronized (ALL_LEVEL_FILES) { - if (!ALL_LEVEL_FILES.containsKey(info.world)) { - ALL_LEVEL_FILES.put(info.world, + if (!ALL_LEVEL_FILES.containsKey(info.info.world)) { + ALL_LEVEL_FILES.put(info.info.world, new SignalStateFile(Paths.get("osfiles/signalfiles/" - + ((WorldServer) info.world).getMinecraftServer().getName() - .replace(":", "").replace("/", "").replace("\\", "") - + "/" + ((WorldServer) info.world).provider + + ((WorldServer) info.info.world).getMinecraftServer() + .getName().replace(":", "").replace("/", "") + .replace("\\", "") + + "/" + ((WorldServer) info.info.world).provider .getDimensionType().getName().replace(":", "")))); } } synchronized (SIGNAL_COUNTER) { - Integer count = SIGNAL_COUNTER.get(info); - if (count != null && count > 0) { - SIGNAL_COUNTER.put(info, ++count); + List> holders = SIGNAL_COUNTER.get(info.info); + if (holders != null && holders.size() > 0) { + if (!holders.contains(info.holder)) + holders.add(info.holder); return; } - SIGNAL_COUNTER.put(info, 1); + holders = new ArrayList<>(); + holders.add(info.holder); + SIGNAL_COUNTER.put(info.info, holders); } - final Map properties = readAndSerialize(info); + final Map properties = readAndSerialize(info.info); synchronized (CURRENTLY_LOADED_STATES) { - CURRENTLY_LOADED_STATES.put(info, properties); + CURRENTLY_LOADED_STATES.put(info.info, properties); } if (player == null) { - sendToAll(info, properties); + sendToAll(info.info, properties); } else { - sendToPlayer(info, properties, player); + sendToPlayer(info.info, properties, player); } - updateListeners(info, properties, ChangedState.ADDED_TO_CACHE); + updateListeners(info.info, properties, ChangedState.ADDED_TO_CACHE); }); }); } - public static void unloadSignal(final SignalStateInfo info) { + public static void unloadSignal(final StateLoadHolder info) { unloadSignals(ImmutableList.of(info)); } - public static void unloadSignals(final List signals) { + public static void unloadSignals(final List signals) { if (signals == null || signals.isEmpty() || IO_SERVICE.isShutdown()) return; IO_SERVICE.execute(() -> { signals.forEach(info -> { synchronized (SIGNAL_COUNTER) { - Integer count = SIGNAL_COUNTER.get(info); - if (count != null && count > 1) { - SIGNAL_COUNTER.put(info, --count); + final List> holders = SIGNAL_COUNTER.getOrDefault(info.info, + new ArrayList<>()); + holders.remove(info.holder); + if (!holders.isEmpty()) return; - } - SIGNAL_COUNTER.remove(info); } + SIGNAL_COUNTER.remove(info.info); Map properties; synchronized (CURRENTLY_LOADED_STATES) { - properties = CURRENTLY_LOADED_STATES.remove(info); + properties = CURRENTLY_LOADED_STATES.remove(info.info); } if (properties == null) return; - createToFile(info, properties); - updateListeners(info, properties, ChangedState.REMOVED_FROM_CACHE); + createToFile(info.info, properties); + updateListeners(info.info, properties, ChangedState.REMOVED_FROM_CACHE); }); }); } diff --git a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxTileEntity.java b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxTileEntity.java index a11ef7b78..f7ccc4775 100644 --- a/src/main/java/com/troblecodings/signals/signalbox/SignalBoxTileEntity.java +++ b/src/main/java/com/troblecodings/signals/signalbox/SignalBoxTileEntity.java @@ -6,7 +6,9 @@ import com.troblecodings.signals.OpenSignalsMain; import com.troblecodings.signals.blocks.BasicBlock; import com.troblecodings.signals.blocks.Signal; +import com.troblecodings.signals.core.LoadHolder; import com.troblecodings.signals.core.StateInfo; +import com.troblecodings.signals.core.StateLoadHolder; import com.troblecodings.signals.enums.LinkType; import com.troblecodings.signals.handler.SignalBoxHandler; import com.troblecodings.signals.handler.SignalStateHandler; @@ -74,8 +76,10 @@ public boolean link(final BlockPos pos, final NBTTagCompound tag) { } else if (block == OSBlocks.REDSTONE_OUT) { type = LinkType.OUTPUT; } - if (type.equals(LinkType.SIGNAL)) { - SignalStateHandler.loadSignal(new SignalStateInfo(world, pos, (Signal) block)); + if (type.equals(LinkType.SIGNAL) && !world.isRemote) { + SignalStateHandler + .loadSignal(new StateLoadHolder(new SignalStateInfo(world, pos, (Signal) block), + new LoadHolder<>(new StateInfo(world, pos)))); } return SignalBoxHandler.linkPosToSignalBox(new StateInfo(world, this.pos), pos, (BasicBlock) block, type); diff --git a/src/main/java/com/troblecodings/signals/tileentitys/SignalControllerTileEntity.java b/src/main/java/com/troblecodings/signals/tileentitys/SignalControllerTileEntity.java index aff1ef847..c139fd2da 100644 --- a/src/main/java/com/troblecodings/signals/tileentitys/SignalControllerTileEntity.java +++ b/src/main/java/com/troblecodings/signals/tileentitys/SignalControllerTileEntity.java @@ -14,7 +14,10 @@ import com.troblecodings.signals.SEProperty; import com.troblecodings.signals.blocks.RedstoneInput; import com.troblecodings.signals.blocks.Signal; +import com.troblecodings.signals.core.LoadHolder; import com.troblecodings.signals.core.SignalStateListener; +import com.troblecodings.signals.core.StateInfo; +import com.troblecodings.signals.core.StateLoadHolder; import com.troblecodings.signals.enums.ChangedState; import com.troblecodings.signals.enums.EnumMode; import com.troblecodings.signals.enums.EnumState; @@ -228,7 +231,8 @@ public void onLoad() { final SignalStateInfo info = new SignalStateInfo(world, linkedSignalPosition, linkedSignal); if (linkedSignalPosition != null && linkedSignal != null) { - SignalStateHandler.loadSignal(info); + SignalStateHandler.loadSignal( + new StateLoadHolder(info, new LoadHolder<>(new StateInfo(world, pos)))); SignalStateHandler.addListener(info, listener); } } @@ -236,8 +240,9 @@ public void onLoad() { public void unloadSignal() { if (linkedSignalPosition != null & linkedSignal != null) - SignalStateHandler - .unloadSignal(new SignalStateInfo(world, linkedSignalPosition, linkedSignal)); + SignalStateHandler.unloadSignal(new StateLoadHolder( + new SignalStateInfo(world, linkedSignalPosition, linkedSignal), + new LoadHolder<>(new StateInfo(world, pos)))); } public BlockPos getLinkedPosition() {