Jump to content

Recommended Posts

Posted

I've been working a bit on some Server > Client IExtendedEntityProperties syncing stuff, and I'm just a little confused about one thing.

 

When handling the message on the Client side, the only instance of EntityPlayer I can get is Minecraft.getMinecraft().thePlayer (or alternatively FMLClientHandler.instance().getClientPlayerEntity()), right? However, when I use certain events that occur on both Client and Server side (LivingEvent.LivingUpdateEvent, for example), the client instance of EntityPlayer doesn't seem to be the same as the instance of EntityPlayer from Minecraft#thePlayer.

 

Am I doing things the right way, or is there a better way to do this? This is all the relevant code:

 

PlayerStats (IExtendedEntityProperties):

public final class PlayerStats implements IExtendedEntityProperties
{
private static final String PLAYER_STATS = Reference.MOD_ID + "PlayerStat";
private static int maxLevel = 100, maxEXP = 1000000, minEXP = 100;
private static final ImmutableMap<Integer, Integer> XP_TO_LEVEL_UP_MAP = ImmutableMap.copyOf(initLevelMap());

private final EntityPlayer player;
private int level, exp;

private PlayerStats(EntityPlayer player)
{
	this.player = player;
	this.level = 1;
	this.exp = 0;
}


@Override
public void saveNBTData(NBTTagCompound compound)
{
	compound.setInteger(LEVEL, this.level);
	compound.setInteger(EXP, this.exp);
}

@Override
public void loadNBTData(NBTTagCompound compound)
{
	this.level = compound.getInteger(LEVEL);
	this.exp = compound.getInteger(EXP);
}

public void copy(PlayerStats oldStats)
{
	this.level = oldStats.level;
	this.exp = oldStats.exp;
}

public void copy(PlayerStatSync message)
{
	this.level = message.level;
	this.exp = message.exp;
}
public static final void register(EntityPlayer player)
{
	if(player.getExtendedProperties(PLAYER_STATS) == null)
	{
		player.registerExtendedProperties(PLAYER_STATS, new PlayerStats(player));
	}
	else
	{
		LogHelper.warn("Tried to register PlayerStats to a player twice.");
	}
}

public static PlayerStats get(EntityPlayer player)
{
	if(player.getExtendedProperties(PLAYER_STATS) == null)
	{
		register(player);
	}
	return (PlayerStats) player.getExtendedProperties(PLAYER_STATS);
}
}

 

PlayerStatHandler:

@SubscribeEvent
public void onPlayerTick(LivingEvent.LivingUpdateEvent event)
{
if(event.entityLiving instanceof EntityPlayer)
{
	EntityPlayer player = (EntityPlayer) event.entityLiving;
	PlayerStats stats = PlayerStats.get(player);
	System.out.println(String.format("Level: %s, Experience: %s, Side:%s", stats.getLevel(), stats.getEXP(), RPGMod.getSide()));
}
}

@SubscribeEvent
public void onPlayerClone(PlayerEvent.Clone event)
{
if(event.wasDeath)
{
	PlayerStats.get(event.entityPlayer).copy(PlayerStats.get(event.original));
	PacketHandler.sendPlayerStatSyncToPlayer(event.entityPlayer);
}
}

 

PacketHandler:

public final class PacketHandler
{
private PacketHandler(){}

private static final SimpleNetworkWrapper NETWORK = new SimpleNetworkWrapper(Reference.MOD_ID);

public static void init()
{
	int discriminator = 0;
	NETWORK.registerMessage(PlayerStatSync.Handler.class, PlayerStatSync.class, discriminator++, Side.CLIENT);
}

public static void sendPlayerStatSyncToPlayer(EntityPlayer player)
{
	if(RPGMod.isServer())
	{
		PlayerStatSync packet = new PlayerStatSync(PlayerStats.get(player));
		LogHelper.packetSent(packet);
		NETWORK.sendTo(packet, (EntityPlayerMP) player);
	}
	else
	{
		LogHelper.error("PacketHandler attempted to send a PlayerStatSync packet from the client!"
				+ Reference.LINE_SEPERATOR + "	This is bad, report it to the mod author with the latest log!");
		LogHelper.printStackTrace();
	}
}
}

 

Client Proxy:

public final class ClientProxy extends CommonProxy
{
@Override
public void handlePlayerStatSync(PlayerStatSync message, MessageContext ctx)
{
	PlayerStats stats = PlayerStats.get(FMLClientHandler.instance().getClientPlayerEntity());
	stats.copy(message);
}
}

 

Message Class, and Message Handler Class:

public final class PlayerStatSync implements IMessage
{
public int level, exp;

public PlayerStatSync(){}

public PlayerStatSync(PlayerStats stats)
{
	this.level = stats.getLevel();
	this.exp = stats.getEXP();
}

@Override
public void fromBytes(ByteBuf buf)
{
	this.level = buf.readInt();
	this.exp = buf.readInt();
}

@Override
public void toBytes(ByteBuf buf)
{
	buf.writeInt(this.level);
	buf.writeInt(this.exp);
}

@Override
public String toString()
{
	return String.format(
			"PlayerStatSync - Level: %s, EXP: %s",
			this.level, this.exp);
}

public static final class Handler implements IMessageHandler<PlayerStatSync, IMessage>
{

	@Override
	public IMessage onMessage(PlayerStatSync message, MessageContext ctx)
	{
		LogHelper.packetRecieved(message);
		RPGMod.proxy.handlePlayerStatSync(message, ctx);
		return null;
	}

}

}

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Posted

I am testing this on Single Player, so it couldn't be other players.

 

When I print out the level and the exp fields in the event method, along with FMLCommonHandler.instance().getEffectiveSide(), the Server one is right, and the client one is never updated from the original Level 1, Exp 0.

 

The handle method for the packet is definitely being called, too (if I print out the stats from there, they're right).

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Posted

I've been testing using the /kill command to see if it works. That should trigger the Clone event, shouldn't it?

 

Edit: Changed to player TickEvent, still not syncing properly.

 

Edit 2: Okay, this is really weird. The ClientProxy is definitely receiving the right values, and it's definitely setting them right. However in the PlayerTickEvent, the stats aren't right, even if I do this:

if(event.side.isClient())
{
PlayerStats client = PlayerStats.get(cpw.mods.fml.client.FMLClientHandler.instance().getClientPlayerEntity());
System.out.println("Client Stats: level: " + client.getLevel() + ", exp: " + client.getEXP());
}

 

That and the entity being used to sync in the client in the proxy are gotten through identical methods (FMLClientHandler.instance().getClientPlayerEntity()).

BEFORE ASKING FOR HELP READ THE EAQ!

 

I'll help if I can. Apologies if I do something obviously stupid. :D

 

If you don't know basic Java yet, go and follow these tutorials.

Guest
This topic is now closed to further replies.

Announcements



×
×
  • Create New...

Important Information

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