
Thornack
Members-
Posts
629 -
Joined
-
Last visited
Everything posted by Thornack
-
Ya I actually am not a fan of 1.8 either, too hard to update everything froom 1.7.10 to 1.8 as so much changed. Breaks a ton in my mod so I didnt bother might reconsider later but still, I actually found using the horse code for custom vehicles fairly tough to get right (especially the jumping code) eventually I just wrote everything from scratch cause it was hard to use
-
oh ya oops that is my custom stats class I forgot to include that public Stats stats = new Stats(); and the class is public class PokemonStats { public int modelID; public String ownerName = ""; //current stats public int level = 0; public int hp, currentHp; public int att, currentAtt; public int def, currentDef; public int spAtt, currentSpAtt; public int spDef, currentSpDef; public int spd, currentSpd; //determinant values. These should be initialized when the entity is created, and should //never change. public int DV_HP; public int DV_Att; public int DV_Def; public int DV_SpAtt; public int DV_SpDef; public int DV_Spd; //effort values - gained through battling public int EV_HP; public int EV_Att; public int EV_Def; public int EV_SpAtt; public int EV_SpDef; public int EV_Spd; //total experience gained from battling public int exp; //important: make sure the stats are written/read in the same order. If they are not, they will be mixed up! public void fromBytes(ByteBuf buf){ try{ modelID = buf.readInt(); level = buf.readInt(); hp = buf.readInt(); currentHp = buf.readInt(); att = buf.readInt(); currentAtt = buf.readInt(); def = buf.readInt(); currentDef = buf.readInt(); spAtt = buf.readInt(); currentSpAtt = buf.readInt(); spDef = buf.readInt(); currentSpDef = buf.readInt(); spd = buf.readInt(); currentSpd = buf.readInt(); DV_HP = buf.readInt(); DV_Att = buf.readInt(); DV_Def = buf.readInt(); DV_SpAtt = buf.readInt(); DV_SpDef = buf.readInt(); DV_Spd = buf.readInt(); EV_HP = buf.readInt(); EV_Att = buf.readInt(); EV_Def = buf.readInt(); EV_SpAtt = buf.readInt(); EV_SpDef = buf.readInt(); EV_Spd = buf.readInt(); exp = buf.readInt(); //read string owner name. Need to store and read the length of string. int ownerNameLength = buf.readInt(); StringBuilder stringBuilder = new StringBuilder(); for(int i=0;i<ownerNameLength;i++){ stringBuilder.append(buf.readChar()); } ownerName = stringBuilder.toString(); } catch(Exception e){ System.out.println(e.toString()); } } //important: make sure the stats are written/read in the same order. If they are not, they will be mixed up! public void toBytes(ByteBuf buf){ buf.writeInt(modelxID); buf.writeInt(level); buf.writeInt(hp); buf.writeInt(currentHp); buf.writeInt(att); buf.writeInt(currentAtt); buf.writeInt(def); buf.writeInt(currentDef); buf.writeInt(spAtt); buf.writeInt(currentSpAtt); buf.writeInt(spDef); buf.writeInt(currentSpDef); buf.writeInt(spd); buf.writeInt(currentSpd); buf.writeInt(DV_HP); buf.writeInt(DV_Att); buf.writeInt(DV_Def); buf.writeInt(DV_SpAtt); buf.writeInt(DV_SpDef); buf.writeInt(DV_Spd); buf.writeInt(EV_HP); buf.writeInt(EV_Att); buf.writeInt(EV_Def); buf.writeInt(EV_SpAtt); buf.writeInt(EV_SpDef); buf.writeInt(EV_Spd); buf.writeInt(exp); buf.writeInt(ownerName.length()); for(int i=0;i<ownerName.length();i++){ buf.writeChar(ownerName.charAt(i)); } } }
-
Ok so I have a custom entity that is tameable using my own custom system. When the entity is tamed it gets the name of the player that tamed it and this name is displayed above the entity via a text box (like minecraft does). This works perfectly while the player is logged in. The problem starts when I log off the name is thrown away into oblivion, And I know that it is my entity that remains in the world since its UUID's match before log on and after log off. This is the order of events: Player tames entity -> entity is written to NBT -> If I call readEntityFromNBT at this point I get "ON READ THE OWNER NAME IS Player567" outprinted to consol -> The Owner name shows up above my entity and all is well. Then I hit the Esc key -> writeEntityToNBT is called -> I get "ON WRITE THE OWNER NAME IS Player567" outprinted to the consol -> and I click Log off. So everything should be good right? But it isnt when I log back on and I see my entity the Owner name does not show up above my entity, the readEntityFromNBT method outprints "ON READ THE OWNER NAME IS " with no name, and when I hit esc the writeEntityToNBT is called -> I get "ON WRITE THE OWNER NAME IS " outprinted to the consol with no name? Why is it being thrown out into oblivion when I log off? and while I am logged on and I tamed it I can call the read method whenever I feel like it and I always get the owner name printing to consol? Please note my entity class is highly customized and HUGE but this is the relevant code for the owner name and the NBT stuff (I had to remove a lot of code to make this more easily readable) Any help is appreciated public class EntityCustom extends EntityAnimal implements IEntityAdditionalSpawnData{ //IDs for DataWatcher private static final int ownerDataID = 25; public EntityCustom(World world) { super(world); this.setSize(0.9F, 0.9F); // hitbox size? } } protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(ownerDataID, ""); } @Override public String getCustomNameTag(){ if(this.getOwnerName().length() > 0){ return this.getOwnerName() + "'s " + this.getName(); } return ""; } //Add a textbox on top of entity if it has an owner public boolean hasCustomNameTag(){ return this.getOwnerName().length() > 0; //return true; } @Override public boolean getAlwaysRenderNameTag(){ return this.dataWatcher.getWatchableObjectByte(11) == 1; } public void setNameTagVisible(boolean visible){ this.dataWatcher.updateObject(11, (byte)(visible ? 1 : 0)); } public String getName(){ return this.getEntityString(); } public String getOwnerName(){ return this.dataWatcher.getWatchableObjectString(this.ownerDataID); } public EntityLivingBase getOwner(){ return this.worldObj.getPlayerEntityByName(this.getOwnerName()); } public void setOwner(String ownerName){ this.dataWatcher.updateObject(this.ownerDataID, ownerName); } @Override public void readEntityFromNBT(NBTTagCompound nbtCompound) { super.readEntityFromNBT(nbtCompound); nbtCompound.getString("EntName"); stats.ownerName = nbtCompound.getString("ownerName"); System.out.println("ON READ THE OWNER NAME IS " +stats.ownerName); } @Override public void writeEntityToNBT(NBTTagCompound nbtCompound) { super.writeEntityToNBT(nbtCompound); nbtCompound.setString("EntName", EntityList.getEntityString(this)); nbtCompound.setString("ownerName", this.getOwnerName()); System.out.println("ON WRITE THE OWNER NAME IS " + this.getOwnerName()); } @Override public EntityCustom createChild(EntityAgeable entityageable) { return new EntityCustom(this.worldObj); } }
-
That should be everything except the registration stuff but that is done correctly since the events fire and the packets actually send only issue is the weird one where if there are two Clients on my dedicated server Client 1 updates model while Client 2 is looking at Client 1, Client 1 sees his own model change on his screen and everything is all good Client 2 sees Client 1's Steve model vanish where only his shadow remains and sees Client 1's model appear on top of his own steve model. Whenever Client 2 moves around, Client 1's new model stays on top of Client 2 and does not animate Whenever Client 1 moves around, Client 2 sees Client 1's shadow moving around and Client 1's model animate/move legs/turn etc etc... while it is on top of his(Client 2's) steve model (Client 2 should see the model move/animate at the position of the shadow rather than on top of his own model but this is not the case) When Client 1 moves around, on Client 1's screen you just simply see his own model as if it were normally replaced and all is fine in the world here, unless Client 2 changes then Client 1 sees Client 2 vanish and Client 1 sees Client 2's model appear on top of his own model and the same above nonsense occurs.
-
inside my PacketOverlord these are the three methods that I use to send my packets This is how I send my request packet from client to server to notify server of model change request (I call this client side only) when my HUD element is clicked and this is the actual request for model change packet that is sent, its constructor is called client side only and it takes the request for model change validates it on server side and then updates the client players server side counterpart IEEP by sending a packet then gets the players that are tracking my player and sends a second packet to update all of those players about my player the first packet, this packet is sent from server to client to update the server players Client side counterpart IEEP so that they are synced it does not update any other players just the player that requested the model change the second packet, this packet is sent to all players that are tracking the player that requested a model change in order to update their client side IEEP values about the player that made his model change, it is sent from server to client PlayerEvent.StartTracking event as it currently exists The PlayerRenderingRegistry class my IEEP class
-
This is my rendering event I dont think it is a GL issue because no matter where I go the other players model comes with my player. Also when I look away from where the player is standing their model vanishes off of mine until I look back. @SubscribeEvent public void onRenderPlayerPre(RenderPlayerEvent.Pre pre) { BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(pre.entityPlayer); // Client Side Player if (battlePlayerProperties == null) { return; } if(battlePlayerProperties.isInBattle == true || battlePlayerProperties.isMorphed == true ){ pre.setCanceled(true); // this stops the player from rendering float modelYOffset = -1.625F; BattlePlayerProperties playerProperties = BattlePlayerProperties.get(pre.entityPlayer); int modelId = playerProperties.getModelId(); //pikachu Render renderModel = PlayerRenderingRegistry.getRendererByModelId(modelId); renderModel.doRender(pre.entity, 0F, modelYOffset, 0F, 0F, 0.0625F); } }
-
I changed it to EntityID and I get the issue; The issue, I have two players on two computers we will call them Client1 and Client2 Client1 initiates model change via button press, then request packet is sent to server, server validates request and processes it - changes server side IEEP -> then it updates Client 1 via 1 packet and the model change is seen by Client1 on his screen, Upon recieving the request and during processing the server also sends a second packet to Client2 Client2 recieves packet and sees Client1's Steve model vanish and the chosen model appear at his position (on top of Client 2's steve model which is not where it should be), whenever Client1 moves around Client 2 sees model animate on top of his model. public class PacketUpdateClientPlayersAroundMe extends AbstractClientMessage<PacketUpdateClientPlayersAroundMe > { boolean isMorphed; int modelID; int entityID; public PacketUpdateClientPlayersAroundMe() {} public PacketUpdateClientPlayersAroundMe(boolean isMorphed, int modelID, int entityID) { this.isMorphed = isMorphed; this.entityID = entityID; this.modelID = modelID; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); modelID = buffer.readInt(); entityID = buffer.readInt(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); buffer.writeInt(modelID); buffer.writeInt(entityID); } @Override public void process(EntityPlayer player, Side side) { System.out.println("process"); // this is now being called if(player.worldObj.isRemote){ EntityPlayer playerWhoChanged = EntityPlayer playerWhoChanged = (EntityPlayer) player.worldObj.getEntityByID(this.entityID) if(playerWhoChanged != null){ BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(playerWhoChanged); battlePlayerProperties.isMorphed = isMorphed; battlePlayerProperties.modelId = modelID; } } } }
-
Ok I fixed that bit and the process method is called it was because in my packet I didnt notice that I had AbstractServerMessage<PacketUpdateClientPlayersAroundMe > when I needed AbstractClientMessage<PacketUpdateClientPlayersAroundMe >. But for some reason I get a crash now where playerWhoChanged is null for some reason. Dunno why is it due to the way im passing the uuid? isnt the uuid the id that I wanna use and not just the regular EntityId?
-
so like this right public class PacketUpdateClientPlayersAroundMe extends AbstractServerMessage<PacketUpdateClientPlayersAroundMe > { boolean isMorphed; int modelID; long uniqueID; public PacketUpdateClientPlayersAroundMe() {} public PacketUpdateClientPlayersAroundMe(boolean isMorphed, int modelID, long uniqueID) { System.out.println("CONSTRUCTOR IS CALLED"); this.isMorphed = isMorphed; this.uniqueID = uniqueID; this.modelID = modelID; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); modelID = buffer.readInt(); uniqueID = buffer.readLong(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); buffer.writeInt(modelID); buffer.writeLong(uniqueID); } @Override public void process(EntityPlayer player, Side side) { System.out.println("PROCESS IS NOT CALLED DUNNO WHY"); if(player.worldObj.isRemote){ //player is only the client side player here using if(!player.worldObj.isRemote) does not work nothing is called EntityPlayer playerWhoChanged = (EntityPlayer) player.worldObj.getEntityByID((int) this.uniqueID); BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(playerWhoChanged); battlePlayerProperties.isMorphed = isMorphed; battlePlayerProperties.modelId = modelID; } } } What is weird is that the process method is never called dunno why but my constructor method is called this packet is called in the process method on server side public class PacketMorphBtnPressed extends AbstractServerMessage<PacketMorphBtnPressed> { private boolean isMorphed = false; public PacketMorphBtnPressed() {} public PacketMorphBtnPressed(boolean isMorphed) { this.isMorphed = isMorphed; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); } @Override public void process(EntityPlayer player, Side side) { if(!player.worldObj.isRemote && isMorphed == true){ BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(player);// server side player and his battle properties battlePlayerProperties.isMorphed = isMorphed; int modelID = battlePlayerProperties.getModelId(); PacketOverlord.sendTo(new PacketUpdateIsMorphed(battlePlayerProperties.isMorphed, modelID),(EntityPlayerMP) player); //THIS IS WHERE I GET THE PLAYERS THAT ARE TRACKING MY PLAYER I THINK Set<EntityPlayer> players = ((WorldServer) player.worldObj).getEntityTracker().getTrackingPlayers(player); //THIS IS WHERE I PASS IN MY PLAYERS UUID PacketOverlord.sendToPlayers(new PacketUpdateClientPlayersAroundMe(battlePlayerProperties.isMorphed, modelID, player.getUniqueID().getMostSignificantBits()), players); System.out.println("PacketUpdateClientPlayers 41"); //THIS GETS CALLED } }} Inside my Packet Handler Class I have the following methods /** * This message is sent to the specified player's client-side counterpart. See * {@link SimpleNetworkWrapper#sendTo(IMessage, EntityPlayerMP)} */ public static final void sendTo(IMessage message, EntityPlayerMP player) { PacketOverlord.dispatcher.sendTo(message, player); } public static final void sendToPlayers(IMessage message, Set<EntityPlayer> players) { for(EntityPlayer player : players) { System.out.println("player"+player); // THIS DOES OUTPRINT and contains player data System.out.println("players"+players); // THIS DOES OUTPRINT and contains player data PacketOverlord.dispatcher.sendTo(message, (EntityPlayerMP) player); } } no idea why my process method doesnt get called
-
I think I understand the "theoretical portion of what needs to happen here" but the actual practical bit I am fuzzy on. Player clicks btn - sends request to server - server processes request - changes server IEEP for player - sends packet to client players counterpart and updates this client players IEEP to sync up the IEEP. I know how to do that and this works. Here is where I am stuck, I know I have to go My player clicks btn - send request to server - server processes request - changes server IEEP for my player - find who tracks my player - send update packet to these players to update them about me 1) where do I -> (find who tracks my player - send update packet to these players to update them about me). Do I do this inside my packet that sends request to server notifying server of button press? Because this packet does processing on the server side (would that be where I would do the find who tracks my player - send update packet to these players to update them about me) would I do this inside its process method by doing @Override public void process(EntityPlayer player, Side side) { if(!player.worldObj.isRemote && isMorphed == true){ BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(player);// server side player and his battle properties battlePlayerProperties.isMorphed = isMorphed; int modelID = battlePlayerProperties.getModelId(); PacketOverlord.sendTo(new PacketUpdateIsMorphed(battlePlayerProperties.isMorphed, modelID),(EntityPlayerMP) player); // Would I do the find who tracks my player - send update packet to these players to update them about me here ?? Set<EntityPlayer> players = ((WorldServer) player.worldObj).getEntityTracker().getTrackingPlayers(player); PacketOverlord.sendToPlayers(new PacketUpdateClientPlayersAroundMe(battlePlayerProperties.isMorphed, modelID, player), players); } }} Then inside my PacketUpdateClientPlayersAroundMe would I do the following? public class PacketUpdateClientPlayersAroundMe extends AbstractServerMessage<PacketUpdateClientPlayersAroundMe > { boolean isMorphed; int modelID; EntityPlayer player; public PacketUpdateClientPlayersAroundMe() {} public PacketUpdateClientPlayersAroundMe(boolean isMorphed, int modelID, EntityPlayer player) { System.out.println("Updating Client Players Sending a Packet"); this.isMorphed = isMorphed; this.player = player; this.modelID = modelID; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); modelID = buffer.readInt(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); buffer.writeInt(modelID); } @Override public void process(EntityPlayer player, Side side) { if(player.worldObj.isRemote){ //player is only the client side player here using if(!player.worldObj.isRemote) does not work nothing is called BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(this.player); battlePlayerProperties.isMorphed = isMorphed; battlePlayerProperties.modelId = modelID; } } } 2) for Dynamic Updating -> in the PlayerEvent.StartTracking event I know I have to get the data from the player that shows up (the player that I start tracking) when the event is called. and I know I have to send this data to my player (me). Im not sure how to do that. Wouldn't this involve sending a packet from the event?
-
currently this packet is sent from Client to server when I change my model. This packet then updates the server values for my IEEP class and then sends a packet to the client in its process method so that the client version is updated. (i think this is Client 1 going -> request change -> server processes change -> updates client counterpart. Thats it. No external players are updated here. I presume what I should do instead here is I should send the packet to update all players that I see including myself correct? And I presume the event is how I do that correct? Im just not sure how public class PacketMorphBtnPressed extends AbstractServerMessage<PacketMorphBtnPressed> { private boolean isMorphed = false; public PacketMorphBtnPressed() {} public PacketMorphBtnPressed(boolean isMorphed) { System.out.println("Updating MorphBtnPress Sending a Packet"); this.isMorphed = isMorphed; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); } @Override public void process(EntityPlayer player, Side side) { if(!player.worldObj.isRemote && isMorphed == true){ BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(player);// server side player and his battle properties battlePlayerProperties.isMorphed = isMorphed; int modelID = battlePlayerProperties.getModelId(); PacketOverlord.sendTo(new PacketUpdateIsMorphed(battlePlayerProperties.isMorphed, modelID),(EntityPlayerMP) player); } }}
-
ok, so starting with the event I have the following (I removed the packet) public class EventPlayerModelDataUpdate { @SubscribeEvent(priority=EventPriority.NORMAL) public void onTracking(PlayerEvent.StartTracking event) { if (event.entityPlayer != null && event.entityPlayer instanceof EntityPlayer ){ EntityTracker et = ((WorldServer) event.entityPlayer.worldObj).getEntityTracker(); // player is the one that sent change to his model Set<EntityPlayer> players = ((WorldServer) event.entityPlayer.worldObj).getEntityTracker().getTrackingPlayers(event.entityPlayer); } } } What am I using this event for, As in how do I go on the sevrer "oh my client counterpart requested a model change so I changed his model (<-I do part this already) then lets send a packet to the players I can "see" so that they can update their client" Im not sure where the packet should be sent from and how to structure this givent he information you have shared
-
I think the problem is in the packet. I put a System.out.println("isMorphed " + isMorphed); line inside the process method and when the process method is called after the packet is sent from my PlayerEvent.StartTracking event, the isMorphed boolean is set to be false for Client 1 since I presume due to Client 2 not morphing he updates Client 1 so that he also doesnt morph (which has the effect of changing the model back to the original. @Override public void process(EntityPlayer player, Side side) { if(player.worldObj.isRemote){ //player is only the client side player here using if(!player.worldObj.isRemote) does not work nothing is called BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(player); battlePlayerProperties.isMorphed = isMorphed; System.out.println("isMorphed " + isMorphed); battlePlayerProperties.modelId = modelID; } I placed the same line into the packets constructor and isMorphed is true on the server side which is what it should be public PacketUpdateIsMorphed(boolean isMorphed, int modelID) { System.out.println("Updating is Morphed after Btn Press Sending a Packet"); this.isMorphed = isMorphed; System.out.println("isMorphed " + isMorphed); this.modelID = modelID; }
-
Haha Ya thanks, I noticed that after I posted it and fixed it to use the for loop So The packet seems to send but there is a problem. Situation 1: There is Server and 2 Clients, Client ONE and TWO are logged in and see themselves, Client ONE clicks button, changes model: - Server IEEP is updated - On Client ONE, the IEEP ONE is updated and model changes but then after a few seconds the model changes back to original steve model. Im just setting up debug statements now - on Client Two, nothing shows up model change isnt seen at all. My event @SubscribeEvent(priority=EventPriority.NORMAL) public void onRenderPre(PlayerEvent.StartTracking event) { if (event.entityPlayer != null && event.entityPlayer instanceof EntityPlayer ){ EntityTracker et = ((WorldServer) event.entityPlayer.worldObj).getEntityTracker(); // player is the one that sent change to his model Set<EntityPlayer> players = ((WorldServer) event.entityPlayer.worldObj).getEntityTracker().getTrackingPlayers(EntityPlayer); System.out.println("found player" + players);// I find players when there is two or more, when it is just me I get "found player []" printed to consol if(players!=null){ PacketOverlord.sendToPlayers(new PacketUpdateModel(), players); // crashes } } } The packet: this packet is sent from the server to client to update values client side in its process method. I send this packet from the process method of my other packet that I send from client to server upon button click that notifies server of button click. public class PacketUpdateIsMorphed extends AbstractClientMessage<PacketUpdateIsMorphed> { boolean isMorphed; int modelID; public PacketUpdateIsMorphed() {} public PacketUpdateIsMorphed(boolean isMorphed, int modelID) { System.out.println("Updating is Morphed after Btn Press Sending a Packet"); this.isMorphed = isMorphed; this.modelID = modelID; } @Override protected void read(PacketBuffer buffer) throws IOException { isMorphed = buffer.readBoolean(); modelID = buffer.readInt(); } @Override protected void write(PacketBuffer buffer) throws IOException { buffer.writeBoolean(isMorphed); buffer.writeInt(modelID); } @Override public void process(EntityPlayer player, Side side) { if(player.worldObj.isRemote){ //player is only the client side player here using if(!player.worldObj.isRemote) does not work nothing is called BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(player); battlePlayerProperties.isMorphed = isMorphed; battlePlayerProperties.modelId = modelID; } } }
-
So far I have the following part down, keyboard button pressed -> sends msg that btn was pressed to server, in the process method of that packet: I update a boolean (that is in my IEEP class) on server side and send a packet to client to update the boolean client side and then free up the mouse to make the HUD element clickable. On Hud element click -> send msg that it was clicked to server, in that packets process method: I update another boolean (that is in my IEEP class) on server side and send a packet to client to update the boolean client side. Once boolean has been updated on both sides inside my onRender.pre event I run a check for if the correct booleans are true and then cancel the players render, get the model id, get a renderer from model id and render my new model. Im stuck at the next part using the PlayerEvent.StartTracking to check if that entity is EntityPlayer and update it's values. I know how to check if it is EntityPlayer and my event fires only when I "see" a player (by that i mean it fires all the time if I am near enough to a player) but what I dont know how to do is send an update to update all players around using the system I have already in place for handling packets. when server-side IEEP's model vallue is changed.Im not sure how to send updates to all that need that value using the EntityTracker stuff. my IEEP properties class looks like this (I had to delete a lot of stuff from this class that isnt relevant to this problem but the class does compile and does work perfectly (disclaimer in case someone notices something stupidly funky and tells me to "Learn Java") Anyway this is the relevant code. private final EntityPlayer player; public boolean isInBattle = false; public boolean isModelChanged = false; public boolean openBattleHUD = false; public boolean isPlayerInThirdPersonView = false; public boolean battleKeyPressed = false; public boolean wasAttacked = false; public int modelId = 25; //the id of the model the player should render as public static final int ModelId_Watcher = 31; public BattlePlayerProperties(EntityPlayer player) { this.player = player; this.player.getDataWatcher().addObject(ModelId_Watcher,modelId); } /** * Used to register these extended properties for the player during EntityConstructing event */ public static final void register(EntityPlayer player) { player.registerExtendedProperties("BattleMobExtendedPlayerHelper", new BattlePlayerProperties(player)); } /** * Returns BattleMobExtendedPlayerHelper properties for player */ public static final BattlePlayerProperties get(EntityPlayer player) { return (BattlePlayerProperties) player.getExtendedProperties("BattleMobExtendedPlayerHelper"); } /** * Copies additional player data from the given BattleMobExtendedPlayerHelper instance * Avoids NBT disk I/O overhead when cloning a player after respawn */ public void copy(BattlePlayerProperties props) { } @Override public final void saveNBTData(NBTTagCompound compound) { NBTTagCompound properties = new NBTTagCompound(); properties.setInteger("ModelId", modelId); compound.setTag("BattleMobExtendedPlayerHelper", properties); } @Override public final void loadNBTData(NBTTagCompound compound) { NBTTagCompound properties = (NBTTagCompound) compound.getTag("BattleMobExtendedPlayerHelper"); player.getDataWatcher().updateObject(ModelId_Watcher, properties.getInteger("ModelId")); } @Override public void init(Entity entity, World world) {} public void setModelId(int modelId){ this.modelId = modelId; this.player.getDataWatcher().updateObject(ModelId_Watcher, this.modelId); } public int getModelId(){ return this.player.getDataWatcher().getWatchableObjectInt(ModelId_Watcher); } } My event where I change my model @SubscribeEvent public void onRenderPlayerPre(RenderPlayerEvent.Pre pre) { BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(pre.entityPlayer); // Client Side Player if (battlePlayerProperties == null) { return; } if(battlePlayerProperties.isInBattle == true || battlePlayerProperties.isMorphed == true ){ pre.setCanceled(true); // this stops the player from rendering float modelYOffset = -1.625F; BattlePlayerProperties playerProperties = BattlePlayerProperties.get(pre.entityPlayer); int modelId = playerProperties.getModelId(); //default 25 Render renderModel = PlayerRenderingRegistry.getRendererByModelId(modelId); System.out.println("rendering player" + pre.entityPlayer); renderModel.doRender(pre.entity, 0F, modelYOffset, 0F, 0F, 0.0625F); } } At this point I am sure my client and server values for my booleans are synced up.The problem is that if(battlePlayerProperties.isInBattle == true || battlePlayerProperties.isMorphed == true){} <-- These are never true for other players because the client has no idea that these have changed for these players when I "see" them. This is where I am stuck, I am not sure how to do the updating bit. Do I need to store the instances of other players in each players IEEP and use packets to update the values of the model id in each instance??