From 6b6f6732d5fddec15753be59542091b84879792f Mon Sep 17 00:00:00 2001 From: johni0702 Date: Sun, 30 Aug 2015 15:54:48 +0200 Subject: [PATCH] Add basic replay restriction system (no restrictions yet) --- .../events/handlers/GuiEventHandler.java | 10 ---- .../replaymod/recording/PacketListener.java | 15 ++++-- .../replaymod/replay/ReplayHandler.java | 23 ++++++++ .../replaymod/replay/ReplaySender.java | 37 ++++++++++++- .../replaymod/replay/Restrictions.java | 52 +++++++++++++++++++ .../assets/replaymod/lang/en_US.lang | 6 ++- 6 files changed, 127 insertions(+), 16 deletions(-) create mode 100644 src/main/java/eu/crushedpixel/replaymod/replay/Restrictions.java diff --git a/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java index d471c682..b50f5e2c 100755 --- a/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/events/handlers/GuiEventHandler.java @@ -8,8 +8,6 @@ import eu.crushedpixel.replaymod.gui.online.GuiReplayCenter; import eu.crushedpixel.replaymod.gui.replayeditor.GuiReplayEditor; import eu.crushedpixel.replaymod.gui.replayviewer.GuiReplayViewer; import eu.crushedpixel.replaymod.online.authentication.AuthenticationHandler; -import eu.crushedpixel.replaymod.registry.LightingHandler; -import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.replay.ReplayProcess; import eu.crushedpixel.replaymod.studio.VersionValidator; @@ -193,16 +191,8 @@ public class GuiEventHandler { event.button.enabled = false; - LightingHandler.setLighting(false); - - ReplayHandler.lastExit = System.currentTimeMillis(); - - mc.theWorld.sendQuittingDisconnectingPacket(); - mc.loadWorld(null); mc.displayGuiScreen(new GuiMainMenu()); - ReplayGuiRegistry.show(); - ReplayHandler.endReplay(); } } diff --git a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java b/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java index d61cab5d..e1ff97a6 100755 --- a/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java +++ b/src/main/java/eu/crushedpixel/replaymod/recording/PacketListener.java @@ -10,6 +10,7 @@ import eu.crushedpixel.replaymod.chat.ChatMessageHandler; import eu.crushedpixel.replaymod.holders.AdvancedPosition; import eu.crushedpixel.replaymod.holders.Keyframe; import eu.crushedpixel.replaymod.holders.Marker; +import eu.crushedpixel.replaymod.replay.Restrictions; import eu.crushedpixel.replaymod.utils.ReplayFileIO; import io.netty.channel.ChannelHandlerContext; import net.minecraft.client.Minecraft; @@ -25,10 +26,8 @@ import net.minecraft.entity.DataWatcher; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.client.C19PacketResourcePackStatus; -import net.minecraft.network.play.server.S0CPacketSpawnPlayer; -import net.minecraft.network.play.server.S0DPacketCollectItem; -import net.minecraft.network.play.server.S0FPacketSpawnMob; -import net.minecraft.network.play.server.S48PacketResourcePackSend; +import net.minecraft.network.play.server.*; +import net.minecraft.util.ChatComponentText; import net.minecraft.util.HttpUtil; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; @@ -106,6 +105,14 @@ public class PacketListener extends DataListener { } dataWriter.writePacket(getPacketData(packet)); + + if (packet instanceof S3FPacketCustomPayload) { + S3FPacketCustomPayload p = (S3FPacketCustomPayload) packet; + if (Restrictions.PLUGIN_CHANNEL.equals(p.getChannelName())) { + packet = new S40PacketDisconnect(new ChatComponentText("Please update to view this replay.")); + dataWriter.writePacket(getPacketData(packet)); + } + } } catch(Exception e) { e.printStackTrace(); } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java index 02c5aca2..dda32de5 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplayHandler.java @@ -11,7 +11,9 @@ import eu.crushedpixel.replaymod.events.ReplayExitEvent; import eu.crushedpixel.replaymod.gui.overlay.GuiReplayOverlay; import eu.crushedpixel.replaymod.holders.*; import eu.crushedpixel.replaymod.interpolation.KeyframeList; +import eu.crushedpixel.replaymod.registry.LightingHandler; import eu.crushedpixel.replaymod.registry.PlayerHandler; +import eu.crushedpixel.replaymod.registry.ReplayGuiRegistry; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.utils.ReplayFile; import eu.crushedpixel.replaymod.utils.ReplayFileIO; @@ -74,6 +76,11 @@ public class ReplayHandler { */ private static ReplayFile currentReplayFile; + /** + * Currently active replay restrictions. + */ + private static Restrictions restrictions; + public static KeyframeSet[] getKeyframeRepository() { return keyframeRepository; } @@ -335,6 +342,8 @@ public class ReplayHandler { setCameraTilt(0); + restrictions = new Restrictions(); + networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { @@ -399,6 +408,8 @@ public class ReplayHandler { channel.close(); } + restrictions = new Restrictions(); + networkManager = new NetworkManager(EnumPacketDirection.CLIENTBOUND) { @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) { @@ -459,8 +470,16 @@ public class ReplayHandler { resetKeyframes(true); PlayerHandler.resetHiddenPlayers(); + ReplayGuiRegistry.show(); + LightingHandler.setLighting(false); + + if (mc.theWorld != null) { + mc.theWorld.sendQuittingDisconnectingPacket(); + mc.loadWorld(null); + } inReplay = false; + lastExit = System.currentTimeMillis(); FMLCommonHandler.instance().bus().post(new ReplayExitEvent()); } @@ -553,4 +572,8 @@ public class ReplayHandler { positionKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); timeKeyframes.recalculate(ReplayMod.replaySettings.isLinearMovement()); } + + public static Restrictions getRestrictions() { + return restrictions; + } } diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java index f1888061..a001ba51 100755 --- a/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java +++ b/src/main/java/eu/crushedpixel/replaymod/replay/ReplaySender.java @@ -14,11 +14,14 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiDownloadTerrain; +import net.minecraft.client.gui.GuiErrorScreen; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.Entity; import net.minecraft.network.EnumConnectionState; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.*; +import net.minecraft.util.IChatComponent; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import net.minecraft.world.WorldSettings.GameType; @@ -290,6 +293,38 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { * @return The processed packet or {@code null} if no packet shall be sent */ protected Packet processPacket(Packet p) throws Exception { + if (p instanceof S3FPacketCustomPayload) { + S3FPacketCustomPayload packet = (S3FPacketCustomPayload) p; + if (Restrictions.PLUGIN_CHANNEL.equals(packet.getChannelName())) { + final String unknown = ReplayHandler.getRestrictions().handle(packet); + if (unknown == null) { + return null; + } else { + // Failed to parse options, make sure that under no circumstances further packets are parsed + terminateReplay(); + // Then end replay and show error GUI + mc.addScheduledTask(new Runnable() { + @Override + public void run() { + ReplayHandler.endReplay(); + mc.displayGuiScreen(new GuiErrorScreen( + I18n.format("replaymod.error.unknownrestriction1"), + I18n.format("replaymod.error.unknownrestriction2", unknown) + )); + } + }); + } + } + } + if (p instanceof S40PacketDisconnect) { + IChatComponent reason = ((S40PacketDisconnect) p).func_149165_c(); + if ("Please update to view this replay.".equals(reason.getUnformattedText())) { + // This version of the mod supports replay restrictions so we are allowed + // to remove this packet. + return null; + } + } + if(BAD_PACKETS.contains(p.getClass())) return null; if(ReplayProcess.isVideoRecording() && ReplayHandler.isInPath()) { @@ -484,7 +519,7 @@ public class ReplaySender extends ChannelInboundHandlerAdapter { Thread.sleep(10); } REPLAY_LOOP: - while (true) { + while (!terminate) { synchronized (ReplaySender.this) { if (dis == null) { dis = new DataInputStream(replayFile.recording().get()); diff --git a/src/main/java/eu/crushedpixel/replaymod/replay/Restrictions.java b/src/main/java/eu/crushedpixel/replaymod/replay/Restrictions.java new file mode 100644 index 00000000..a02f348e --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/replay/Restrictions.java @@ -0,0 +1,52 @@ +package eu.crushedpixel.replaymod.replay; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S3FPacketCustomPayload; + +/** + * Restrictions set by the server, + * @see Replay Restrictions Gist + */ +public class Restrictions { + public static final String PLUGIN_CHANNEL = "Replay|Restrict"; + private boolean noXray; + private boolean noNoclip; + private boolean onlyFirstPerson; + private boolean onlyRecordingPlayer; + + public String handle(S3FPacketCustomPayload packet) { + PacketBuffer buffer = packet.getBufferData(); + while (buffer.isReadable()) { + String name = buffer.readStringFromBuffer(64); + boolean active = buffer.readBoolean(); +// if ("no_xray".equals(name)) { +// noXray = active; +// } else if ("no_noclip".equals(name)) { +// noNoclip = active; +// } else if ("only_first_person".equals(name)) { +// onlyFirstPerson = active; +// } else if ("only_recording_player".equals(name)) { +// onlyRecordingPlayer = active; +// } else { + return name; +// } + } + return null; + } + + public boolean isNoXray() { + return noXray; + } + + public boolean isNoNoclip() { + return noNoclip; + } + + public boolean isOnlyFirstPerson() { + return onlyFirstPerson; + } + + public boolean isOnlyRecordingPlayer() { + return onlyRecordingPlayer; + } +} diff --git a/src/main/resources/assets/replaymod/lang/en_US.lang b/src/main/resources/assets/replaymod/lang/en_US.lang index 35c106a2..6668357c 100644 --- a/src/main/resources/assets/replaymod/lang/en_US.lang +++ b/src/main/resources/assets/replaymod/lang/en_US.lang @@ -414,4 +414,8 @@ replaymod.gui.objects.properties.opacity=Opacity replaymod.gui.objects.properties.name=Object Name replaymod.gui.objects.empty=No Objects added replaymod.gui.objects.defaultname=New Object -replaymod.gui.objects=Custom Objects \ No newline at end of file +replaymod.gui.objects=Custom Objects + +#Errors +replaymod.error.unknownrestriction1=This replay cannot be played with your current version. +replaymod.error.unknownrestriction2=It tried to enforce %s which is unknown. \ No newline at end of file