From 7c3958c4dcdfa866993d9b774097bf88221169b5 Mon Sep 17 00:00:00 2001 From: Arthur Uzulin Date: Thu, 1 May 2014 22:43:42 +1000 Subject: [PATCH] Upgraded to 1.7.2 Yeah, that's right! RecMod has been finally updated to 1.7.2! Note: KeyBinds broken --- build.gradle | 2 +- build.properties | 4 +- pub_build/RecStatusMod-v1.3-MC1.7.2.jar | Bin 0 -> 59571 bytes resources/mcmod.info | 4 +- src/fuj1n/recmod/RecMod.java | 167 +++++++------- .../client/event/EventEntityJoinWorld.java | 4 +- .../recmod/client/event/EventRenderGame.java | 32 +-- src/fuj1n/recmod/client/gui/GuiSimple.java | 2 +- .../client/keybind/KeyHandlerRecMod.java | 111 +++++++--- src/fuj1n/recmod/command/CommandRec.java | 79 ++----- src/fuj1n/recmod/network/PacketHandler.java | 89 -------- src/fuj1n/recmod/network/PlayerTracker.java | 52 ++--- .../recmod/network/packet/AbstractPacket.java | 43 ++++ .../packet/PacketChangeUISettings.java | 49 ++++ .../network/packet/PacketChangeUISheet.java | 39 ++++ .../recmod/network/packet/PacketPipeline.java | 209 ++++++++++++++++++ .../network/packet/PacketRemovePlayer.java | 41 ++++ .../packet/PacketUpdatePlayerStatus.java | 48 ++++ 18 files changed, 656 insertions(+), 319 deletions(-) create mode 100644 pub_build/RecStatusMod-v1.3-MC1.7.2.jar delete mode 100644 src/fuj1n/recmod/network/PacketHandler.java create mode 100644 src/fuj1n/recmod/network/packet/AbstractPacket.java create mode 100644 src/fuj1n/recmod/network/packet/PacketChangeUISettings.java create mode 100644 src/fuj1n/recmod/network/packet/PacketChangeUISheet.java create mode 100644 src/fuj1n/recmod/network/packet/PacketPipeline.java create mode 100644 src/fuj1n/recmod/network/packet/PacketRemovePlayer.java create mode 100644 src/fuj1n/recmod/network/packet/PacketUpdatePlayerStatus.java diff --git a/build.gradle b/build.gradle index e632ff6..2edc861 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ buildscript { } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:1.0-SNAPSHOT' + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' } } diff --git a/build.properties b/build.properties index 83a6056..e0aca65 100644 --- a/build.properties +++ b/build.properties @@ -1,2 +1,2 @@ -minecraft_version=1.6.4 -forge_version=9.11.1.964 \ No newline at end of file +minecraft_version=1.7.2 +forge_version=10.12.1.1060 \ No newline at end of file diff --git a/pub_build/RecStatusMod-v1.3-MC1.7.2.jar b/pub_build/RecStatusMod-v1.3-MC1.7.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..705772c2903567380396a11c0b4d85c470dbc3b4 GIT binary patch literal 59571 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 literal 0 HcmV?d00001 diff --git a/resources/mcmod.info b/resources/mcmod.info index 07e74b3..ece8203 100644 --- a/resources/mcmod.info +++ b/resources/mcmod.info @@ -3,8 +3,8 @@ "modid": "fuj1n.recmod", "name": "Recording Status Mod", "description": "Record/Stream status in the players list, /rec to toggle", - "version": "v1.1", - "mcversion": "1.6.4", + "version": "v1.3", + "mcversion": "1.7.2", "url": "", "updateUrl": "", "authors": [ diff --git a/src/fuj1n/recmod/RecMod.java b/src/fuj1n/recmod/RecMod.java index 932bbf5..be06be7 100644 --- a/src/fuj1n/recmod/RecMod.java +++ b/src/fuj1n/recmod/RecMod.java @@ -1,126 +1,132 @@ package fuj1n.recmod; -import fuj1n.recmod.command.CommandRec; +import java.io.*; +import java.util.*; import cpw.mods.fml.common.*; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.event.*; -import cpw.mods.fml.common.network.*; -import cpw.mods.fml.common.registry.GameRegistry; import cpw.mods.fml.relauncher.Side; import fuj1n.recmod.client.event.*; import fuj1n.recmod.client.keybind.KeyHandlerRecMod; -import fuj1n.recmod.network.*; -import java.io.*; -import java.util.*; +import fuj1n.recmod.command.CommandRec; +import fuj1n.recmod.network.PlayerTracker; +import fuj1n.recmod.network.packet.*; import net.minecraft.command.ServerCommandManager; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.entity.player.*; import net.minecraft.server.MinecraftServer; import net.minecraftforge.common.MinecraftForge; -@Mod(name="Recording Status Mod", version="1.3", modid="fuj1n.recmod") -@NetworkMod(clientSideRequired=true, channels = {"recModData", "recModDataC", "recModUI"}, packetHandler=PacketHandler.class, serverSideRequired=false) -public class RecMod { +@Mod(name = "Recording Status Mod", version = "v1.3", modid = "fuj1n.recmod") +public class RecMod { + @Instance("fuj1n.recmod") public static RecMod instance; + + public static final PacketPipeline packetPipeline = new PacketPipeline(); private static HashMap recorders = new HashMap(); private static HashMap streamers = new HashMap(); - + public boolean showSelf = true; public boolean showUI = false; - + public String sheetLocation = "recmod:textures/sheets/indicators.png"; - + public boolean showSelfDef = false; - + public File configFile; - + @EventHandler - public void preinit(FMLPreInitializationEvent event){ - GameRegistry.registerPlayerTracker(new PlayerTracker()); + public void preinit(FMLPreInitializationEvent event) { + MinecraftForge.EVENT_BUS.register(new PlayerTracker()); configFile = new File(event.getModConfigurationDirectory(), "recmod.ui"); - - if(event.getSide() == Side.CLIENT){ + + if (event.getSide() == Side.CLIENT) { readFromFile(); MinecraftForge.EVENT_BUS.register(new EventRenderGame()); MinecraftForge.EVENT_BUS.register(new EventEntityJoinWorld()); - - //WIP + KeyHandlerRecMod.registerSelf(); } } - + @EventHandler - public void init(FMLInitializationEvent event){ + public void init(FMLInitializationEvent event) { + packetPipeline.initialise(); + PacketPipeline pp = packetPipeline; + //Packet Registration + pp.registerPacket(PacketUpdatePlayerStatus.class); + pp.registerPacket(PacketRemovePlayer.class); + pp.registerPacket(PacketChangeUISettings.class); + pp.registerPacket(PacketChangeUISheet.class); } - + @EventHandler - public void postinit(FMLPostInitializationEvent event){ - + public void postinit(FMLPostInitializationEvent event) { + packetPipeline.postInitialise(); } - + @EventHandler - public void serverStart(FMLServerStartedEvent event){ + public void serverStart(FMLServerStartedEvent event) { if (MinecraftServer.getServer() == null) { return; } - + recorders = new HashMap(); streamers = new HashMap(); - - ServerCommandManager handler = (ServerCommandManager)MinecraftServer.getServer().getCommandManager(); + + ServerCommandManager handler = (ServerCommandManager) MinecraftServer.getServer().getCommandManager(); handler.registerCommand(new CommandRec()); } - - public void updatePlayerInformation(String username, int type, boolean flag){ + + public void updatePlayerInformation(String username, int type, boolean flag) { HashMap modifyMap; - if(type == 0){ + if (type == 0) { modifyMap = recorders; - }else{ + } else { modifyMap = streamers; } - + modifyMap.put(username, flag); } - - public boolean isPlayerRecording(String username){ - if(username == null){ + + public boolean isPlayerRecording(String username) { + if (username == null) { return false; } return recorders.get(username) != null ? recorders.get(username) : false; } - - public boolean isPlayerStreaming(String username){ - if(username == null){ + + public boolean isPlayerStreaming(String username) { + if (username == null) { return false; } return streamers.get(username) != null ? streamers.get(username) : false; } - - public void onUIStateChanged(){ + + public void onUIStateChanged() { writeToFile(); } - - public void onSheetChanged(){ + + public void onSheetChanged() { writeToFile(); } - + public void readFromFile() { - if(!configFile.exists()){ + if (!configFile.exists()) { return; } - + try { BufferedReader b = new BufferedReader(new FileReader(configFile)); String line1 = b.readLine(); String line2 = b.readLine(); String line3 = b.readLine(); - + showSelfDef = convertToBoolean(line1); showUI = convertToBoolean(line2); sheetLocation = line3 != null && !line3.equals("") ? line3 : sheetLocation; @@ -131,14 +137,15 @@ public void readFromFile() { //e.printStackTrace(); } } - - public boolean convertToBoolean(String s){ - try{ + + public boolean convertToBoolean(String s) { + try { return Boolean.parseBoolean(s); - }catch(Exception e){} + } catch (Exception e) { + } return false; } - + public void writeToFile() { configFile.delete(); try { @@ -154,46 +161,36 @@ public void writeToFile() { e.printStackTrace(); } } - - public int calculateNumber(){ + + public int calculateNumber() { ArrayList list = new ArrayList(); - - - + return list.size(); } - - public void removeUnneededData(String username){ + + public void removeUnneededData(String username) { recorders.remove(username); streamers.remove(username); } - - public void sendDataToPlayer(EntityPlayer player){ - for(int i = 0; i < recorders.size(); i++){ + + public void sendDataToPlayer(EntityPlayer player) { + for (int i = 0; i < recorders.size(); i++) { sendPacket(player, recorders.keySet().toArray()[i].toString(), 0, Boolean.parseBoolean(recorders.values().toArray()[i].toString())); } - - for(int i = 0; i < streamers.size(); i++){ + + for (int i = 0; i < streamers.size(); i++) { sendPacket(player, streamers.keySet().toArray()[i].toString(), 1, Boolean.parseBoolean(streamers.values().toArray()[i].toString())); } } - - public void sendPacket(EntityPlayer target, String player, int type, boolean flag){ - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - try { - outputStream.writeUTF(player); - outputStream.writeInt(type); - outputStream.writeBoolean(flag); - } catch (Exception ex) { - ex.printStackTrace(); - } - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "recModData"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - PacketDispatcher.sendPacketToPlayer(packet, (Player)target); + public void sendPacket(EntityPlayer target, String player, int type, boolean flag) { + PacketUpdatePlayerStatus pckt = new PacketUpdatePlayerStatus(player, type, flag); + if(target instanceof EntityPlayerMP){ + System.out.println("target = MP"); + packetPipeline.sendTo(pckt, (EntityPlayerMP)target); + }else{ + System.out.println("target != MP"); + } } - + } diff --git a/src/fuj1n/recmod/client/event/EventEntityJoinWorld.java b/src/fuj1n/recmod/client/event/EventEntityJoinWorld.java index dcff1e3..ea39533 100644 --- a/src/fuj1n/recmod/client/event/EventEntityJoinWorld.java +++ b/src/fuj1n/recmod/client/event/EventEntityJoinWorld.java @@ -1,14 +1,14 @@ package fuj1n.recmod.client.event; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import fuj1n.recmod.RecMod; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; -import net.minecraftforge.event.ForgeSubscribe; import net.minecraftforge.event.entity.EntityJoinWorldEvent; public class EventEntityJoinWorld { - @ForgeSubscribe + @SubscribeEvent public void onEntityJoin(EntityJoinWorldEvent event){ if(event.entity instanceof EntityPlayer){ Minecraft mc = Minecraft.getMinecraft().getMinecraft(); diff --git a/src/fuj1n/recmod/client/event/EventRenderGame.java b/src/fuj1n/recmod/client/event/EventRenderGame.java index 7a58a91..5dfbc59 100644 --- a/src/fuj1n/recmod/client/event/EventRenderGame.java +++ b/src/fuj1n/recmod/client/event/EventRenderGame.java @@ -1,26 +1,25 @@ package fuj1n.recmod.client.event; -import org.lwjgl.input.Keyboard; +import java.util.List; -import fuj1n.recmod.lib.IndexReference; +import org.lwjgl.opengl.GL11; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; import fuj1n.recmod.RecMod; -import java.util.List; +import fuj1n.recmod.lib.IndexReference; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.*; -import net.minecraft.client.multiplayer.NetClientHandler; -import net.minecraft.scoreboard.*; -import net.minecraft.util.*; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.event.ForgeSubscribe; -import org.lwjgl.opengl.GL11; public class EventRenderGame extends Gui { private String sheetLocation = RecMod.instance.sheetLocation; private ResourceLocation indicators = new ResourceLocation(sheetLocation); - @ForgeSubscribe + @SubscribeEvent public void onRenderGameOverlay(RenderGameOverlayEvent event) { if(!sheetLocation.equals(RecMod.instance.sheetLocation)){ sheetLocation = RecMod.instance.sheetLocation; @@ -31,9 +30,10 @@ public void onRenderGameOverlay(RenderGameOverlayEvent event) { return; } Minecraft mc = Minecraft.getMinecraft(); - if (mc.gameSettings.keyBindPlayerList.pressed && (!mc.isIntegratedServerRunning() || mc.thePlayer.sendQueue.playerInfoList.size() > 1)) { - NetClientHandler netclienthandler = mc.thePlayer.sendQueue; - List list = netclienthandler.playerInfoList; + if (mc.gameSettings.keyBindPlayerList.getIsKeyPressed() && (!mc.isIntegratedServerRunning() || mc.thePlayer.sendQueue.playerInfoList.size() > 1 || mc.theWorld.getScoreboard().func_96539_a(0) != null)) { + mc.mcProfiler.startSection("playerList"); + NetHandlerPlayClient nethandlerplayclient = mc.thePlayer.sendQueue; + List list = nethandlerplayclient.playerInfoList; int k = event.resolution.getScaledWidth(); int i2; @@ -43,7 +43,7 @@ public void onRenderGameOverlay(RenderGameOverlayEvent event) { int i3; int j3; int k3; - j2 = netclienthandler.currentServerMaxPlayers; + j2 = nethandlerplayclient.currentServerMaxPlayers; l2 = j2; for (k2 = 1; l2 > 20; l2 = (j2 + k2 - 1) / k2) { @@ -86,12 +86,12 @@ public void onRenderGameOverlay(RenderGameOverlayEvent event) { } } } - }else if(!mc.gameSettings.keyBindPlayerList.pressed && RecMod.instance.showSelf && mc.currentScreen == null){ + }else if(!mc.gameSettings.keyBindPlayerList.getIsKeyPressed() && RecMod.instance.showSelf && mc.currentScreen == null){ int x = event.resolution.getScaledWidth() - 32; int y = 0; - int indicatorRecIndex = RecMod.instance.isPlayerRecording(mc.thePlayer.username) ? 1 : 0; - int indicatorStrIndex = RecMod.instance.isPlayerStreaming(mc.thePlayer.username) ? 2 : 0; + int indicatorRecIndex = RecMod.instance.isPlayerRecording(mc.thePlayer.getCommandSenderName()) ? 1 : 0; + int indicatorStrIndex = RecMod.instance.isPlayerStreaming(mc.thePlayer.getCommandSenderName()) ? 2 : 0; mc.getTextureManager().bindTexture(indicators); drawTexturedModalRect(x, y, indicatorRecIndex * 16, (int)Math.floor(indicatorRecIndex / 16) * 16 + IndexReference.RESOLUTION_SPLIT_Y, 16, 16); diff --git a/src/fuj1n/recmod/client/gui/GuiSimple.java b/src/fuj1n/recmod/client/gui/GuiSimple.java index ad73251..1a9a0e2 100644 --- a/src/fuj1n/recmod/client/gui/GuiSimple.java +++ b/src/fuj1n/recmod/client/gui/GuiSimple.java @@ -17,7 +17,7 @@ public GuiSimple() { @Override public void drawGuiContainerForegroundLayer(int par1, int par2) { - this.fontRenderer.drawString("Simple Gui", 8, this.ySize - 96 + 2, 4210752); + this.fontRendererObj.drawString("Simple Gui", 8, this.ySize - 96 + 2, 4210752); } @Override diff --git a/src/fuj1n/recmod/client/keybind/KeyHandlerRecMod.java b/src/fuj1n/recmod/client/keybind/KeyHandlerRecMod.java index 06edb11..a94e04a 100644 --- a/src/fuj1n/recmod/client/keybind/KeyHandlerRecMod.java +++ b/src/fuj1n/recmod/client/keybind/KeyHandlerRecMod.java @@ -1,53 +1,106 @@ package fuj1n.recmod.client.keybind; +import java.util.ArrayList; + +import org.lwjgl.input.*; + +import com.google.common.collect.Lists; + +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.*; +import cpw.mods.fml.common.gameevent.TickEvent.Phase; +import cpw.mods.fml.common.gameevent.TickEvent.Type; +import cpw.mods.fml.relauncher.Side; import net.minecraft.client.Minecraft; +import net.minecraft.client.settings.*; +import net.minecraftforge.common.MinecraftForge; -import cpw.mods.fml.client.registry.*; -import cpw.mods.fml.client.registry.KeyBindingRegistry.KeyHandler; -import cpw.mods.fml.common.TickType; -import java.util.EnumSet; -import net.minecraft.client.settings.KeyBinding; +public class KeyHandlerRecMod { -public class KeyHandlerRecMod extends KeyHandler { + public KeyBinding[] keyBindings; + public boolean[] keyDown; + public boolean[] repeatings; + public boolean isDummy; Minecraft mc = Minecraft.getMinecraft(); boolean b = false; - + public KeyHandlerRecMod(KeyBinding[] keyBindings, boolean[] repeatings) { - super(keyBindings, repeatings); + assert keyBindings.length == repeatings.length : "You need to pass two arrays of identical length"; + this.keyBindings = keyBindings; + this.repeatings = repeatings; + this.keyDown = new boolean[keyBindings.length]; + isDummy = false; } - @Override - public String getLabel() { - return "fuj1n.RecMod.KeyBindingTickHandler"; - } + @SubscribeEvent + public void onTick(TickEvent event) { + System.out.println("Key Tick"); + if (event.side == Side.CLIENT) { + if (event.phase == Phase.START) + keyTick(event.type, false); + else if (event.phase == Phase.END) + keyTick(event.type, true); + } - @Override - public void keyDown(EnumSet types, KeyBinding kb, boolean tickEnd, boolean isRepeat) { } - @Override - public void keyUp(EnumSet types, KeyBinding kb, boolean tickEnd) { - if(mc.theWorld != null && mc.currentScreen == null && /*mc.gameSettings.keyBindPlayerList.pressed &&*/ (!mc.isIntegratedServerRunning() || mc.thePlayer.sendQueue.playerInfoList.size() > 1)) - if(b){ - if (kb == keyBindings[0]) { - mc.thePlayer.sendChatMessage("/rec r"); - } else if (kb == keyBindings[1]) { - mc.thePlayer.sendChatMessage("/rec s"); + public void keyTick(Type type, boolean tickEnd) { + for (int i = 0; i < keyBindings.length; i++) { + KeyBinding keyBinding = keyBindings[i]; + int keyCode = keyBinding.getKeyCode(); + boolean state = (keyCode < 0 ? Mouse.isButtonDown(keyCode + 100) : Keyboard.isKeyDown(keyCode)); + if (state != keyDown[i] || (state && repeatings[i])) { + if (state) { + keyDown(type, keyBinding, tickEnd, state != keyDown[i]); + } else { + keyUp(type, keyBinding, tickEnd); + } + if (tickEnd) { + keyDown[i] = state; + } } } - b = !b; } - @Override - public EnumSet ticks() { - return EnumSet.of(TickType.CLIENT); + public void keyDown(Type types, KeyBinding kb, boolean tickEnd, boolean isRepeat) { + + } + + public void keyUp(Type types, KeyBinding kb, boolean tickEnd) { + if (mc.theWorld != null && mc.currentScreen == null && /*mc.gameSettings.keyBindPlayerList.pressed &&*/(!mc.isIntegratedServerRunning() || mc.thePlayer.sendQueue.playerInfoList.size() > 1)) + if (b) { + if (kb == keyBindings[0]) { + mc.thePlayer.sendChatMessage("/rec r"); + } else if (kb == keyBindings[1]) { + mc.thePlayer.sendChatMessage("/rec s"); + } + } + b = !b; } public static void registerSelf() { - KeyBinding recBinding = new KeyBinding("ToggleRecording", 44); - KeyBinding streamBinding = new KeyBinding("ToggleStreaming", 45); - KeyBindingRegistry.registerKeyBinding(new KeyHandlerRecMod(new KeyBinding[] { recBinding, streamBinding }, new boolean[] { false, false })); + System.out.println("Key system register"); + String keyCategory = "Recording Mod Bindings"; + KeyBinding recBinding = new KeyBinding("Toggle Recording", 44, keyCategory); + KeyBinding streamBinding = new KeyBinding("Toggle Streaming", 45, keyCategory); + KeyHandlerRecMod keyh = new KeyHandlerRecMod(new KeyBinding[] { recBinding, streamBinding }, new boolean[] { false, false }); + MinecraftForge.EVENT_BUS.register(keyh); + keyh.aggregateKeys(); } + private void aggregateKeys() { + GameSettings settings = Minecraft.getMinecraft().gameSettings; + ArrayList harvestedBindings = Lists.newArrayList(); + for (KeyBinding kb : keyBindings) { + harvestedBindings.add(kb); + } + + KeyBinding[] modKeyBindings = harvestedBindings.toArray(new KeyBinding[harvestedBindings.size()]); + KeyBinding[] allKeys = new KeyBinding[settings.keyBindings.length + modKeyBindings.length]; + System.arraycopy(settings.keyBindings, 0, allKeys, 0, settings.keyBindings.length); + System.arraycopy(modKeyBindings, 0, allKeys, settings.keyBindings.length, modKeyBindings.length); + settings.keyBindings = allKeys; + settings.loadOptions(); + } } diff --git a/src/fuj1n/recmod/command/CommandRec.java b/src/fuj1n/recmod/command/CommandRec.java index c5c80b2..0f0a9fb 100644 --- a/src/fuj1n/recmod/command/CommandRec.java +++ b/src/fuj1n/recmod/command/CommandRec.java @@ -1,14 +1,15 @@ package fuj1n.recmod.command; -import cpw.mods.fml.common.network.*; -import fuj1n.recmod.RecMod; -import java.io.*; import java.util.*; + +import fuj1n.recmod.RecMod; +import fuj1n.recmod.network.packet.*; +import ibxm.Player; import net.minecraft.command.*; -import net.minecraft.network.packet.Packet250CustomPayload; +import net.minecraft.entity.player.*; import net.minecraft.network.rcon.RConConsoleSource; import net.minecraft.server.MinecraftServer; -import net.minecraft.util.ChatMessageComponent; +import net.minecraft.util.ChatComponentText; public class CommandRec extends CommandBase { @@ -24,11 +25,11 @@ public String getCommandName() { @Override public String getCommandUsage(ICommandSender icommandsender) { - icommandsender.sendChatToPlayer(ChatMessageComponent.createFromText("\u00A7cRec Usage: ")); - icommandsender.sendChatToPlayer(ChatMessageComponent.createFromText("\u00A7c (displays an easy to use GUI)")); - icommandsender.sendChatToPlayer(ChatMessageComponent.createFromText("\u00A7c (toggle recording or streaming")); - icommandsender.sendChatToPlayer(ChatMessageComponent.createFromText("\u00A7c [p] (toggle self ui - p toggles disabled by default)")); - icommandsender.sendChatToPlayer(ChatMessageComponent.createFromText("\u00A7c (replace the texture sheet used)")); + icommandsender.addChatMessage(new ChatComponentText("\u00A7cRec Usage: ")); + icommandsender.addChatMessage(new ChatComponentText("\u00A7c (displays an easy to use GUI)")); + icommandsender.addChatMessage(new ChatComponentText("\u00A7c (toggle recording or streaming")); + icommandsender.addChatMessage(new ChatComponentText("\u00A7c [p] (toggle self ui - p toggles disabled by default)")); + icommandsender.addChatMessage(new ChatComponentText("\u00A7c (replace the texture sheet used)")); return "Wut?"; } @@ -51,9 +52,9 @@ public void processCommand(ICommandSender icommandsender, String[] astring) { } else if((astring.length == 2 || (astring.length == 3 && astring[2].equals("p"))) && astring[0].equals("ui") && (astring[1].equals("self") || astring[1].equals("sidebar")) && icommandsender instanceof Player){ boolean isSelf = astring[1].equals("self"); boolean isOverride = astring.length == 3 && astring[2].equals("p"); - sendUIUpdatePacket((Player)icommandsender, isSelf, isOverride); + sendUIUpdatePacket((EntityPlayer)icommandsender, isSelf, isOverride); } else if(astring.length == 2 && astring[0].equals("sheet")){ - sendSheetChangePacket((Player)icommandsender, astring[1]); + sendSheetChangePacket((EntityPlayer)icommandsender, astring[1]); } else if(astring.length == 1 && astring[0].equals("gui")){ } else { @@ -82,56 +83,22 @@ public void processCommand(ICommandSender icommandsender, String[] astring) { // } public void spreadData(String playerName, int typeData, boolean flag) { - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - try { - outputStream.writeUTF(playerName); - outputStream.writeInt(typeData); - outputStream.writeBoolean(flag); - } catch (Exception ex) { - ex.printStackTrace(); - } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "recModData"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - PacketDispatcher.sendPacketToAllPlayers(packet); + PacketUpdatePlayerStatus pckt = new PacketUpdatePlayerStatus(playerName, typeData, flag); + RecMod.packetPipeline.sendToAll(pckt); } - public void sendUIUpdatePacket(Player p, boolean isSelf, boolean isOverride){ - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - try { - outputStream.writeInt(0); - outputStream.writeBoolean(isSelf); - outputStream.writeBoolean(isOverride); - } catch (Exception ex) { - ex.printStackTrace(); + public void sendUIUpdatePacket(EntityPlayer p, boolean isSelf, boolean isOverride){ + if(p instanceof EntityPlayerMP){ + PacketChangeUISettings pckt = new PacketChangeUISettings(isSelf, isOverride); + RecMod.packetPipeline.sendTo(pckt, (EntityPlayerMP)p); } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "recModUI"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - PacketDispatcher.sendPacketToPlayer(packet, p); } - public void sendSheetChangePacket(Player p, String newSheet){ - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - try { - outputStream.writeInt(1); - outputStream.writeUTF(newSheet); - } catch (Exception ex) { - ex.printStackTrace(); + public void sendSheetChangePacket(EntityPlayer p, String newSheet){ + if(p instanceof EntityPlayerMP){ + PacketChangeUISheet pckt = new PacketChangeUISheet(newSheet); + RecMod.packetPipeline.sendTo(pckt, (EntityPlayerMP)p); } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "recModUI"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - PacketDispatcher.sendPacketToPlayer(packet, p); } @Override diff --git a/src/fuj1n/recmod/network/PacketHandler.java b/src/fuj1n/recmod/network/PacketHandler.java deleted file mode 100644 index 7ee39cf..0000000 --- a/src/fuj1n/recmod/network/PacketHandler.java +++ /dev/null @@ -1,89 +0,0 @@ -package fuj1n.recmod.network; - -import net.minecraft.util.ChatMessageComponent; - -import cpw.mods.fml.common.network.*; -import fuj1n.recmod.RecMod; -import java.io.*; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.INetworkManager; -import net.minecraft.network.packet.Packet250CustomPayload; - -public class PacketHandler implements IPacketHandler { - - @Override - public void onPacketData(INetworkManager manager, Packet250CustomPayload packet, Player player) { - DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(packet.data)); - if (packet.channel.equals("recModData")) { - String playerName = ""; - int typeData = 0; - boolean flag = false; - - try { - playerName = inputStream.readUTF(); - typeData = inputStream.readInt(); - flag = inputStream.readBoolean(); - - } catch (IOException e) { - e.printStackTrace(); - } - RecMod.instance.updatePlayerInformation(playerName, typeData, flag); - } else if (packet.channel.equals("recModDataC")) { - String playerName = ""; - - try{ - playerName = inputStream.readUTF(); - }catch(IOException e){ - e.printStackTrace(); - } - RecMod.instance.removeUnneededData(playerName); - } else if (packet.channel.equals("recModUI")) { - int type = -1; - try { - type = inputStream.readInt(); - } catch (IOException e) { - e.printStackTrace(); - } - if (type == 0) { - boolean isSelf = false; - boolean isOverride = false; - - try { - isSelf = inputStream.readBoolean(); - isOverride = inputStream.readBoolean(); - } catch (IOException e) { - e.printStackTrace(); - } - - if (isSelf) { - RecMod.instance.showSelf = !RecMod.instance.showSelf; - RecMod.instance.showSelfDef = isOverride ? !RecMod.instance.showSelfDef : RecMod.instance.showSelfDef; - - RecMod.instance.onUIStateChanged(); - } else { - RecMod.instance.showUI = !RecMod.instance.showUI; - - RecMod.instance.onUIStateChanged(); - } - }else if(type == 1){ - String newSheet = RecMod.instance.sheetLocation; - - try { - newSheet = inputStream.readUTF(); - } catch (IOException e) { - e.printStackTrace(); - } - - net.minecraft.util.ResourceLocation testLocation = new net.minecraft.util.ResourceLocation(newSheet); -// if(!new File(testLocation.getResourcePath()).exists()){ -// if(player instanceof EntityPlayer){ -// ((EntityPlayer)player).sendChatToPlayer(ChatMessageComponent.createFromText("Location not found: " + testLocation.getResourcePath())); -// } -// }else{ - RecMod.instance.sheetLocation = newSheet; - RecMod.instance.onSheetChanged(); -// } - } - } - } -} diff --git a/src/fuj1n/recmod/network/PlayerTracker.java b/src/fuj1n/recmod/network/PlayerTracker.java index 1ea4039..7decc73 100644 --- a/src/fuj1n/recmod/network/PlayerTracker.java +++ b/src/fuj1n/recmod/network/PlayerTracker.java @@ -1,55 +1,35 @@ package fuj1n.recmod.network; -import cpw.mods.fml.common.*; -import cpw.mods.fml.common.network.PacketDispatcher; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent; import cpw.mods.fml.relauncher.Side; import fuj1n.recmod.RecMod; -import java.io.*; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.network.packet.Packet250CustomPayload; +import fuj1n.recmod.network.packet.PacketRemovePlayer; -public class PlayerTracker implements IPlayerTracker { +public class PlayerTracker { - @Override - public void onPlayerLogin(EntityPlayer player) { + @SubscribeEvent + public void onPlayerLogin(PlayerLoggedInEvent event) { if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { - RecMod.instance.updatePlayerInformation(player.getCommandSenderName(), 0, false); - RecMod.instance.updatePlayerInformation(player.getCommandSenderName(), 1, false); - RecMod.instance.sendDataToPlayer(player); + RecMod.instance.updatePlayerInformation(event.player.getCommandSenderName(), 0, false); + RecMod.instance.updatePlayerInformation(event.player.getCommandSenderName(), 1, false); + RecMod.instance.sendDataToPlayer(event.player); } } - @Override - public void onPlayerLogout(EntityPlayer player) { + @SubscribeEvent + public void onPlayerLogout(PlayerLoggedOutEvent event) { if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { - removePlayerName(player.getCommandSenderName()); + removePlayerName(event.player.getCommandSenderName()); } } public void removePlayerName(String name) { RecMod.instance.removeUnneededData(name); - ByteArrayOutputStream bos = new ByteArrayOutputStream(8); - DataOutputStream outputStream = new DataOutputStream(bos); - try { - outputStream.writeUTF(name); - } catch (Exception ex) { - ex.printStackTrace(); - } - - Packet250CustomPayload packet = new Packet250CustomPayload(); - packet.channel = "recModDataC"; - packet.data = bos.toByteArray(); - packet.length = bos.size(); - PacketDispatcher.sendPacketToAllPlayers(packet); - } - - @Override - public void onPlayerChangedDimension(EntityPlayer player) { + PacketRemovePlayer pckt = new PacketRemovePlayer(name); + RecMod.packetPipeline.sendToAll(pckt); } - - @Override - public void onPlayerRespawn(EntityPlayer player) { - } - } diff --git a/src/fuj1n/recmod/network/packet/AbstractPacket.java b/src/fuj1n/recmod/network/packet/AbstractPacket.java new file mode 100644 index 0000000..c9f7fa8 --- /dev/null +++ b/src/fuj1n/recmod/network/packet/AbstractPacket.java @@ -0,0 +1,43 @@ +package fuj1n.recmod.network.packet; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; + +import net.minecraft.entity.player.EntityPlayer; + +/** + * AbstractPacket class. Should be the parent of all packets wishing to use the PacketPipeline. + * @author sirgingalot + */ +public abstract class AbstractPacket { + + /** + * Encode the packet data into the ByteBuf stream. Complex data sets may need specific data handlers (See @link{cpw.mods.fml.common.network.ByteBuffUtils}) + * + * @param ctx channel context + * @param buffer the buffer to encode into + */ + public abstract void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer); + + /** + * Decode the packet data from the ByteBuf stream. Complex data sets may need specific data handlers (See @link{cpw.mods.fml.common.network.ByteBuffUtils}) + * + * @param ctx channel context + * @param buffer the buffer to decode from + */ + public abstract void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer); + + /** + * Handle a packet on the client side. Note this occurs after decoding has completed. + * + * @param player the player reference + */ + public abstract void handleClientSide(EntityPlayer player); + + /** + * Handle a packet on the server side. Note this occurs after decoding has completed. + * + * @param player the player reference + */ + public abstract void handleServerSide(EntityPlayer player); +} diff --git a/src/fuj1n/recmod/network/packet/PacketChangeUISettings.java b/src/fuj1n/recmod/network/packet/PacketChangeUISettings.java new file mode 100644 index 0000000..a34e16e --- /dev/null +++ b/src/fuj1n/recmod/network/packet/PacketChangeUISettings.java @@ -0,0 +1,49 @@ +package fuj1n.recmod.network.packet; + +import fuj1n.recmod.RecMod; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.entity.player.EntityPlayer; + +public class PacketChangeUISettings extends AbstractPacket { + + private boolean isSelf, isOverride; + + public PacketChangeUISettings(boolean isSelf, boolean isOverride) { + this.isSelf = isSelf; + this.isOverride = isOverride; + } + + public PacketChangeUISettings() {} + + @Override + public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + buffer.writeBoolean(isSelf); + buffer.writeBoolean(isOverride); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + isSelf = buffer.readBoolean(); + isOverride = buffer.readBoolean(); + } + + @Override + public void handleClientSide(EntityPlayer player) { + if (isSelf) { + RecMod.instance.showSelf = !RecMod.instance.showSelf; + RecMod.instance.showSelfDef = isOverride ? !RecMod.instance.showSelfDef : RecMod.instance.showSelfDef; + + RecMod.instance.onUIStateChanged(); + } else { + RecMod.instance.showUI = !RecMod.instance.showUI; + + RecMod.instance.onUIStateChanged(); + } + } + + @Override + public void handleServerSide(EntityPlayer player) {} + +} diff --git a/src/fuj1n/recmod/network/packet/PacketChangeUISheet.java b/src/fuj1n/recmod/network/packet/PacketChangeUISheet.java new file mode 100644 index 0000000..812d091 --- /dev/null +++ b/src/fuj1n/recmod/network/packet/PacketChangeUISheet.java @@ -0,0 +1,39 @@ +package fuj1n.recmod.network.packet; + +import fuj1n.recmod.RecMod; + +import cpw.mods.fml.common.network.ByteBufUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.entity.player.EntityPlayer; + +public class PacketChangeUISheet extends AbstractPacket { + + String newSheet; + + public PacketChangeUISheet(String newSheet) { + this.newSheet = newSheet; + } + + public PacketChangeUISheet() {} + + @Override + public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + ByteBufUtils.writeUTF8String(buffer, newSheet); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + newSheet = ByteBufUtils.readUTF8String(buffer); + } + + @Override + public void handleClientSide(EntityPlayer player) { + RecMod.instance.sheetLocation = newSheet; + RecMod.instance.onSheetChanged(); + } + + @Override + public void handleServerSide(EntityPlayer player) {} +} diff --git a/src/fuj1n/recmod/network/packet/PacketPipeline.java b/src/fuj1n/recmod/network/packet/PacketPipeline.java new file mode 100644 index 0000000..a763485 --- /dev/null +++ b/src/fuj1n/recmod/network/packet/PacketPipeline.java @@ -0,0 +1,209 @@ +package fuj1n.recmod.network.packet; + +import java.util.*; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToMessageCodec; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.INetHandler; +import net.minecraft.network.NetHandlerPlayServer; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.network.FMLEmbeddedChannel; +import cpw.mods.fml.common.network.FMLOutboundHandler; +import cpw.mods.fml.common.network.NetworkRegistry; +import cpw.mods.fml.common.network.internal.FMLProxyPacket; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; + +/** + * Packet pipeline class. Directs all registered packet data to be handled by the packets themselves. + * @author sirgingalot + * some code from: cpw + */ +@ChannelHandler.Sharable +public class PacketPipeline extends MessageToMessageCodec { + + private EnumMap channels; + private LinkedList> packets = new LinkedList>(); + private boolean isPostInitialised = false; + + /** + * Register your packet with the pipeline. Discriminators are automatically set. + * + * @param clazz the class to register + * + * @return whether registration was successful. Failure may occur if 256 packets have been registered or if the registry already contains this packet + */ + public boolean registerPacket(Class clazz) { + if (this.packets.size() > 256) { + // TODO Log + return false; + } + + if (this.packets.contains(clazz)) { + // TODO Log + return false; + } + + if (this.isPostInitialised) { + // TODO Log + return false; + } + + this.packets.add(clazz); + return true; + } + + // In line encoding of the packet, including discriminator setting + @Override + protected void encode(ChannelHandlerContext ctx, AbstractPacket msg, List out) throws Exception { + ByteBuf buffer = Unpooled.buffer(); + Class clazz = msg.getClass(); + if (!this.packets.contains(msg.getClass())) { + throw new NullPointerException("No Packet Registered for: " + msg.getClass().getCanonicalName()); + } + + byte discriminator = (byte) this.packets.indexOf(clazz); + buffer.writeByte(discriminator); + msg.encodeInto(ctx, buffer); + FMLProxyPacket proxyPacket = new FMLProxyPacket(buffer.copy(), ctx.channel().attr(NetworkRegistry.FML_CHANNEL).get()); + out.add(proxyPacket); + } + + // In line decoding and handling of the packet + @Override + protected void decode(ChannelHandlerContext ctx, FMLProxyPacket msg, List out) throws Exception { + ByteBuf payload = msg.payload(); + byte discriminator = payload.readByte(); + Class clazz = this.packets.get(discriminator); + if (clazz == null) { + throw new NullPointerException("No packet registered for discriminator: " + discriminator); + } + + AbstractPacket pkt = clazz.newInstance(); + pkt.decodeInto(ctx, payload.slice()); + + EntityPlayer player; + switch (FMLCommonHandler.instance().getEffectiveSide()) { + case CLIENT: + player = this.getClientPlayer(); + pkt.handleClientSide(player); + break; + + case SERVER: + INetHandler netHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get(); + player = ((NetHandlerPlayServer) netHandler).playerEntity; + pkt.handleServerSide(player); + break; + + default: + } + + out.add(pkt); + } + + // Method to call from FMLInitializationEvent + public void initialise() { + this.channels = NetworkRegistry.INSTANCE.newChannel("fuj1n.RecMod", this); + } + + // Method to call from FMLPostInitializationEvent + // Ensures that packet discriminators are common between server and client by using logical sorting + public void postInitialise() { + if (this.isPostInitialised) { + return; + } + + this.isPostInitialised = true; + Collections.sort(this.packets, new Comparator>() { + + @Override + public int compare(Class clazz1, Class clazz2) { + int com = String.CASE_INSENSITIVE_ORDER.compare(clazz1.getCanonicalName(), clazz2.getCanonicalName()); + if (com == 0) { + com = clazz1.getCanonicalName().compareTo(clazz2.getCanonicalName()); + } + + return com; + } + }); + } + + @SideOnly(Side.CLIENT) + private EntityPlayer getClientPlayer() { + return Minecraft.getMinecraft().thePlayer; + } + + /** + * Send this message to everyone. + *

+ * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper + * + * @param message The message to send + */ + public void sendToAll(AbstractPacket message) { + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALL); + this.channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to the specified player. + *

+ * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper + * + * @param message The message to send + * @param player The player to send it to + */ + public void sendTo(AbstractPacket message, EntityPlayerMP player) { + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.PLAYER); + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(player); + this.channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to everyone within a certain range of a point. + *

+ * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper + * + * @param message The message to send + * @param point The {@link cpw.mods.fml.common.network.NetworkRegistry.TargetPoint} around which to send + */ + public void sendToAllAround(AbstractPacket message, NetworkRegistry.TargetPoint point) { + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.ALLAROUNDPOINT); + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(point); + this.channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to everyone within the supplied dimension. + *

+ * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper + * + * @param message The message to send + * @param dimensionId The dimension id to target + */ + public void sendToDimension(AbstractPacket message, int dimensionId) { + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.DIMENSION); + this.channels.get(Side.SERVER).attr(FMLOutboundHandler.FML_MESSAGETARGETARGS).set(dimensionId); + this.channels.get(Side.SERVER).writeAndFlush(message); + } + + /** + * Send this message to the server. + *

+ * Adapted from CPW's code in cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper + * + * @param message The message to send + */ + public void sendToServer(AbstractPacket message) { + this.channels.get(Side.CLIENT).attr(FMLOutboundHandler.FML_MESSAGETARGET).set(FMLOutboundHandler.OutboundTarget.TOSERVER); + this.channels.get(Side.CLIENT).writeAndFlush(message); + } +} \ No newline at end of file diff --git a/src/fuj1n/recmod/network/packet/PacketRemovePlayer.java b/src/fuj1n/recmod/network/packet/PacketRemovePlayer.java new file mode 100644 index 0000000..e119ff1 --- /dev/null +++ b/src/fuj1n/recmod/network/packet/PacketRemovePlayer.java @@ -0,0 +1,41 @@ +package fuj1n.recmod.network.packet; + +import java.io.IOException; + +import fuj1n.recmod.RecMod; + +import cpw.mods.fml.common.network.ByteBufUtils; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.entity.player.EntityPlayer; + +public class PacketRemovePlayer extends AbstractPacket { + + private String player; + + public PacketRemovePlayer(String player){ + this.player = player; + } + + public PacketRemovePlayer(){} + + @Override + public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + ByteBufUtils.writeUTF8String(buffer, player); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + player = ByteBufUtils.readUTF8String(buffer); + } + + @Override + public void handleClientSide(EntityPlayer player) { + RecMod.instance.removeUnneededData(this.player); + } + + @Override + public void handleServerSide(EntityPlayer player) {} + +} diff --git a/src/fuj1n/recmod/network/packet/PacketUpdatePlayerStatus.java b/src/fuj1n/recmod/network/packet/PacketUpdatePlayerStatus.java new file mode 100644 index 0000000..52be751 --- /dev/null +++ b/src/fuj1n/recmod/network/packet/PacketUpdatePlayerStatus.java @@ -0,0 +1,48 @@ +package fuj1n.recmod.network.packet; + +import java.io.IOException; + +import fuj1n.recmod.RecMod; + +import cpw.mods.fml.common.network.ByteBufUtils; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import net.minecraft.entity.player.EntityPlayer; + +public class PacketUpdatePlayerStatus extends AbstractPacket { + + private String player; + private int type; + private boolean flag; + + public PacketUpdatePlayerStatus(String player, int type, boolean flag) { + this.player = player; + this.type = type; + this.flag = flag; + } + + public PacketUpdatePlayerStatus() {} + + @Override + public void encodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + ByteBufUtils.writeUTF8String(buffer, player); + buffer.writeInt(type); + buffer.writeBoolean(flag); + } + + @Override + public void decodeInto(ChannelHandlerContext ctx, ByteBuf buffer) { + player = ByteBufUtils.readUTF8String(buffer); + type = buffer.readInt(); + flag = buffer.readBoolean(); + } + + @Override + public void handleClientSide(EntityPlayer player) { + RecMod.instance.updatePlayerInformation(this.player, type, flag); + } + + @Override + public void handleServerSide(EntityPlayer player) {} + +}