diff --git a/dependencies.gradle b/dependencies.gradle index 9d0593a4..b9738109 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,6 +1,6 @@ dependencies { shadeCompile("com.github.GTNewHorizons:ZenScript:1.0.0-GTNH") compileOnly("net.industrial-craft:industrialcraft-2:2.2.828-experimental:dev") - implementation("codechicken:codechickencore-mc1.7.10:1.3.2-mega:dev") - compileOnly("codechicken:notenoughitems-mc1.7.10:2.1.6-gtmega:dev") + implementation("codechicken:codechickencore-mc1.7.10:1.4.0-mega:dev") + compileOnly("codechicken:notenoughitems-mc1.7.10:2.3.0-mega:dev") } diff --git a/src/main/java/minetweaker/api/logger/MTLogger.java b/src/main/java/minetweaker/api/logger/MTLogger.java index c5caf8f7..b0207358 100644 --- a/src/main/java/minetweaker/api/logger/MTLogger.java +++ b/src/main/java/minetweaker/api/logger/MTLogger.java @@ -63,7 +63,12 @@ public void logWarning(String message) { if(players.isEmpty()) { unprocessed.add(message2); } else { - for(IPlayer player : players) { + for (int i = 0; i < players.size(); i++) { + IPlayer player = players.get(i); + if (player.brokenReference()) { + players.remove(i--); + continue; + } player.sendChat(message2); } } @@ -85,7 +90,12 @@ public void logError(String message, Throwable exception) { if(players.isEmpty()) { unprocessed.add(message2); } else { - for(IPlayer player : players) { + for (int i = 0; i < players.size(); i++) { + IPlayer player = players.get(i); + if (player.brokenReference()) { + players.remove(i--); + continue; + } player.sendChat(message2); } } diff --git a/src/main/java/minetweaker/api/player/IPlayer.java b/src/main/java/minetweaker/api/player/IPlayer.java index 17a2edcb..ac58f0e2 100644 --- a/src/main/java/minetweaker/api/player/IPlayer.java +++ b/src/main/java/minetweaker/api/player/IPlayer.java @@ -69,4 +69,8 @@ public interface IPlayer { // not an exposed method, so far. would it be useful? void copyToClipboard(String value); + + default boolean brokenReference() { + return false; + } } diff --git a/src/main/java/minetweaker/mc1710/player/MCPlayer.java b/src/main/java/minetweaker/mc1710/player/MCPlayer.java index 08c26b1a..b7beb5d0 100644 --- a/src/main/java/minetweaker/mc1710/player/MCPlayer.java +++ b/src/main/java/minetweaker/mc1710/player/MCPlayer.java @@ -22,19 +22,38 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.IChatComponent; +import java.lang.ref.WeakReference; +import java.util.function.Consumer; +import java.util.function.Function; + /** * * @author Stan */ public class MCPlayer implements IPlayer { - private final EntityPlayer player; + private final WeakReference player; public MCPlayer(EntityPlayer player) { - this.player = player; + this.player = new WeakReference<>(player); } public EntityPlayer getInternal() { - return player; + return player.get(); + } + + private T ifPresent(Function fn, T defaultValue) { + EntityPlayer plr = player.get(); + if (plr != null) { + return fn.apply(plr); + } + return defaultValue; + } + + private void ifPresent(Consumer fn) { + EntityPlayer plr = player.get(); + if (plr != null) { + fn.accept(plr); + } } @Override @@ -44,126 +63,157 @@ public String getId() { @Override public String getName() { - return player.getCommandSenderName(); + return ifPresent(EntityPlayer::getCommandSenderName, "MISSING"); } @Override public IData getData() { - return NBTConverter.from(player.getEntityData(), true); + return ifPresent(player -> NBTConverter.from(player.getEntityData(), true), null); } @Override public int getXP() { - return player.experienceLevel; + return ifPresent(player -> player.experienceLevel, 0); } @Override public void setXP(int xp) { - player.experienceLevel = 0; - player.addExperienceLevel(xp); + ifPresent(player -> { + player.experienceLevel = 0; + player.addExperienceLevel(xp); + }); } @Override public void removeXP(int xp) { - final int newLvl = Math.max(0, player.experienceLevel - xp); - player.experienceLevel = 0; - player.addExperienceLevel(newLvl); + ifPresent(player -> { + final int newLvl = Math.max(0, player.experienceLevel - xp); + player.experienceLevel = 0; + player.addExperienceLevel(newLvl); + }); } @Override public void update(IData data) { - NBTConverter.updateMap(player.getEntityData(), data); + ifPresent(player -> { + NBTConverter.updateMap(player.getEntityData(), data); + }); } @Override public void sendChat(IChatMessage message) { - Object internal = message.getInternal(); - if (!(internal instanceof IChatComponent)) { - MineTweakerAPI.logError("not a valid chat message"); - return; - } - player.addChatMessage((IChatComponent) internal); + ifPresent(player -> { + Object internal = message.getInternal(); + if (!(internal instanceof IChatComponent)) { + MineTweakerAPI.logError("not a valid chat message"); + return; + } + player.addChatMessage((IChatComponent) internal); + }); } @Override - public void sendChat(String message) { - if (message.length() > MAX_CHAT_MESSAGE_LENGTH) - { - message = message.substring(0, MAX_CHAT_MESSAGE_LENGTH); - } - player.addChatMessage(new ChatComponentText(message)); + public void sendChat(String msg) { + ifPresent(player -> { + String message = msg; + if (message.length() > MAX_CHAT_MESSAGE_LENGTH) + { + message = message.substring(0, MAX_CHAT_MESSAGE_LENGTH); + } + player.addChatMessage(new ChatComponentText(message)); + }); } @Override public int getHotbarSize() { - return 9; + return ifPresent(p -> 9, 0); } @Override public IItemStack getHotbarStack(int i) { - return i < 0 || i >= 9 ? null : MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)); + return ifPresent(player -> i < 0 || i >= 9 ? null : MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)), null); } @Override public int getInventorySize() { - return player.inventory.getSizeInventory(); + return ifPresent(player -> player.inventory.getSizeInventory(), 0); } @Override public IItemStack getInventoryStack(int i) { - return MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)); + return ifPresent(player -> MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)), null); } @Override public IItemStack getCurrentItem() { - return MineTweakerMC.getIItemStack(player.getCurrentEquippedItem()); + return ifPresent(player -> MineTweakerMC.getIItemStack(player.getCurrentEquippedItem()), null); } @Override public boolean isCreative() { - return player.capabilities.isCreativeMode; + return ifPresent(player -> player.capabilities.isCreativeMode, false); } @Override public boolean isAdventure() { - return !player.capabilities.allowEdit; + return ifPresent(player -> !player.capabilities.allowEdit, false); } @Override public void openBrowser(String url) { - if (player instanceof EntityPlayerMP && MineTweakerConfig.handleDesktopPackets) { - MineTweakerMod.NETWORK.sendTo( - new MineTweakerOpenBrowserPacket(url), - (EntityPlayerMP) player); - } + ifPresent(player -> { + if (player instanceof EntityPlayerMP && MineTweakerConfig.handleDesktopPackets) { + MineTweakerMod.NETWORK.sendTo( + new MineTweakerOpenBrowserPacket(url), + (EntityPlayerMP) player); + } + }); } @Override public void copyToClipboard(String value) { - if (player instanceof EntityPlayerMP && MineTweakerConfig.handleDesktopPackets) { - MineTweakerMod.NETWORK.sendTo( - new MineTweakerCopyClipboardPacket(value), - (EntityPlayerMP) player); - } + ifPresent(player -> { + if (player instanceof EntityPlayerMP && MineTweakerConfig.handleDesktopPackets) { + MineTweakerMod.NETWORK.sendTo( + new MineTweakerCopyClipboardPacket(value), + (EntityPlayerMP) player); + } + }); } @Override public boolean equals(Object other) { if (other.getClass() != this.getClass()) return false; - - return ((MCPlayer) other).player == player; + MCPlayer o = (MCPlayer) other; + return ifPresent(p1 -> o.ifPresent(p2 -> p1 == p2, false), false); } + private volatile Integer hash; + @Override public int hashCode() { - int hash = 5; - hash = 23 * hash + (this.player != null ? this.player.hashCode() : 0); + if (hash == null) { + synchronized (this) { + if (hash == null) { + hash = ifPresent(player -> { + int h = 5; + h = 23 * h + player.hashCode(); + return h; + }, 0); + } + } + } return hash; } @Override public void give(IItemStack stack) { - player.inventory.addItemStackToInventory(MineTweakerMC.getItemStack(stack).copy()); + ifPresent(player -> player.inventory.addItemStackToInventory(MineTweakerMC.getItemStack(stack).copy())); + } + + @Override + public boolean brokenReference() { + return ifPresent(p -> false, true); } }