Jump to content

[1.7.10] Changing Player Model - Multiplayer issue with Models Showing Up


Recommended Posts

Posted

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

Posted

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?

Posted

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;
}
  	}
   }
   }

Posted

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);
		}

}

Posted

Im not sure how to get my model to be at the location of the player that initiated the model change. Whenever this player moves you see the model animate but at the location of the other player (the one who did not change his model) Anyone know how to fix this?

Posted

1. Make Github/Bitbucket

2. Upload code

3. Post link

4. ???

5. Profit!

 

Seriously, this needs debugging (if you followed my instructions and everything else is working, the problem is in rendering).

1.7.10 is no longer supported by forge, you are on your own.

Posted

inside my PacketOverlord these are the three methods that I use to send my packets

 

 

/**
 * 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) {
	PacketOverlord.dispatcher.sendTo(message, (EntityPlayerMP) player);
	}
	}
/**
 * This sends a message to the server. See
 * {@link SimpleNetworkWrapper#sendToServer(IMessage)}
 */
public static final void sendToServer(IMessage message) {
	PacketOverlord.dispatcher.sendToServer(message);
}

 

 

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

 

 

PacketOverlord.sendToServer(new PacketMorphBtnPressed(wasMorphPressed));

 

 

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

 

 


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);
     Set<EntityPlayer> players = ((WorldServer) player.worldObj).getEntityTracker().getTrackingPlayers(player);
     PacketOverlord.sendToPlayers(new PacketUpdateClientPlayersAroundMe(battlePlayerProperties.isMorphed, modelID, player.getEntityId()), players);
     System.out.println("Player ID " + player.getEntityId());
     }
   }}

 

 

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

 

 

public class PacketUpdateIsMorphed  extends AbstractClientMessage<PacketUpdateIsMorphed> {

boolean isMorphed;
int modelID;

public PacketUpdateIsMorphed() {}
public PacketUpdateIsMorphed(boolean isMorphed, int modelID) {

	this.isMorphed = isMorphed;
	System.out.println("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;
  	}
   }
   }

 

 

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

 

 

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");
if(player.worldObj.isRemote){
EntityPlayer playerWhoChanged = (EntityPlayer) player.worldObj.getEntityByID(this.entityID);
if(playerWhoChanged != null){
BattlePlayerProperties battlePlayerProperties = BattlePlayerProperties.get(playerWhoChanged);
battlePlayerProperties.isMorphed = isMorphed;
    battlePlayerProperties.modelID= modelID;
}
  	}
   }
   }

 

 

 

PlayerEvent.StartTracking event as it currently exists

 

 

public class EventUpdateWhoIsTrackingMe {
@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
	}
}
}

 

The rendering event that replaces the model

@SubscribeEvent
public void onRenderPlayerPre(RenderPlayerEvent.Pre pre) {
	if(!(pre.entityPlayer instanceof EntityOtherPlayerMP)){
	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);
		System.out.println("blah " + pre.entityPlayer);
		int modelId = playerProperties.getModelId();	//default = 25
		Render renderModel = PlayerRenderingRegistry.getRendererByModelId(modelId);
		renderModel.doRender(pre.entityPlayer, 0F, modelYOffset, 0F, 0F, 0.0625F);
		}
	}
}

 

 

The PlayerRenderingRegistry class

 

 

//used for storing player renderers for each model class, since RenderLiving doesn't work for player rendering,
//and RenderLivingEntity always renders name tags
public class PlayerRenderingRegistry {

private static LinkedHashMap<Integer, RendererLivingEntity> renderers = new LinkedHashMap();

public static void addRenderer(int modelId, RendererLivingEntity renderer ){
	renderers.put(modelId, renderer);
}

public static RendererLivingEntity getRendererByModelId(int modelId){
	return renderers.get(modelxId);
}
}

 

 

my IEEP class

 

 

public class BattlePlayerProperties implements IExtendedEntityProperties
{

private final EntityPlayer player;
public boolean isInBattle = false;
public boolean isMorphed = false;
public boolean openBattleGUI = false;
public boolean isPlayerInThirdPersonView = false;
public boolean bKeyPressed = false;
public boolean wasAttacked = false;

public int modelId = 25;	//the id of the model the player should render as (default 25)

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);
}


}

 

 

Posted

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.

Posted

So many issues, you didn't understand anything i told you. Start from begining, read my posts, You still have bad Tracking, bad usage of StartTracking, bad data-holding, bad instanceof (why check if player is EntityPlayer for example), a lot of small mistakes, damn, too much for me :D

 

If you want to solve this FAST (as I don't have time on my hands - I have finals this and next week) call my Skype (ernio333), otherwise, READ everything from begining and debug from very basic level.

 

 

Edit: And why am I so Skype-hyped - writing is waste of time, this is probably one of things (next to sleeping which is also waste of time) that I loathe the most.

1.7.10 is no longer supported by forge, you are on your own.

Posted

ok well I added you, it is kinda odd that youre so skype hyped but meh im using my friends really old really bad laptop n he doesnt care about it cause its getting thrown out soon

Posted

Thanks Ernio,

 

Like I said since you liked the models I made if you need any gimme a shout i can make you some. (you didnt even see the best ones haha) Oh try to keep the mod I am making a secret I want it to be a surprise since im not done yet

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.