Jump to content

[1.7.10] How to properly sync entity from server to client [Solved]


qb_cakes

Recommended Posts

Hello, been trying to learn recently and network has been stalling my progress for some time now. I've been avoiding it but I don't think I can much more

Anyway, basically, when any entity dies, the server will listen to that event and change a value inside an entity, this value should then be updated to the client

Maybe, probably, the problem isn't really in the network code. But I'd appreciate feedback on it since I'm not sure if I'm doing it properly

 

This is the intended workflow:

 

1. A player spawns an entity in the world, EntityBank

2. A death event occurs - onEntityLivingDeath(LivingDeathEvent event) is called

2.1 Inside the method for the event, (which I noticed is only called in the server), the server checks for entities inside a radius around the position where the death occurred, and if it finds an instance of EntityBank, it calls the method entityBank.add(x);

3. The method entityBank.add(int i) increments a value inside EntityBank called storage. (this value is saved/loaded to nbt)

4. So far it's all good, everything happened well on the server side, but now the client is supposed to know about all this, I made Message and MessageHandler classes to communicate the change to all players, and I believe the issue is here.

 

Cleaned up code: (to show what is relevant)

 

EntityBank:

public class EntityBank extends EntityFlying {

private int stored;

public EntityBank(World world) {
	super(world);
	setSize(0.5f, 0.5f);
}

public void add(int inc) {
	stored += inc;

	System.out.println("~~~ storage was increased by " + inc);
}

public void updateClients() {
	NBTTagCompound ntc = new NBTTagCompound();
	ntc.setInteger("s", stored);
	ntc.setInteger("e", getEntityId());
	StorageMessage message = new StorageMessage(ntc);

	System.out.println("Sending message to clients.");
	MyMod.networkWrapper.sendToAll(message);
}


@Override
protected boolean interact(EntityPlayer player) {
	System.out.println(stored); // server prints the correct value, client doesn't (after restarting the server/world)
	return false;
}

@Override
public void readEntityFromNBT(NBTTagCompound ntc) {
	super.readEntityFromNBT(ntc);

	stored = ntc.getInteger("stored");
}

@Override
public void writeEntityToNBT(NBTTagCompound ntc) {
	super.writeEntityToNBT(ntc);

	ntc.setInteger("stored", stored);
}
}

 

The EventHandler:

public class EventHandler {

private static final float DEATH_RANGE = 10f;

@SubscribeEvent
public void onEntityLivingDeath(LivingDeathEvent event) {
	Entity entity = event.entity;

	if (entity instanceof EntityLiving) {
		int inc = 10; // ...

		if (inc > 0) {
			AxisAlignedBB radiusBB = AxisAlignedBB.getBoundingBox
					(entity.posX - DEATH_RANGE, entity.posY - DEATH_RANGE, entity.posZ - DEATH_RANGE,
							entity.posX + DEATH_RANGE, entity.posY + DEATH_RANGE, entity.posZ + DEATH_RANGE);

			Entity closestEntity = Utils.selectNearestEntityWithinAABB(entity.worldObj, Entity.class, radiusBB, entity,
					(ent) -> ent instanceof EntityBank);

			if (closestEntity != null) {
				System.out.println("Found an EntityBank nearby... adding to storage: " + inc);

				((EntityBank) closestEntity).add(inc);
				((EntityBank) closestEntity).updateClients();
			}
		}
	}
}

}

 

StorageMessage (probably not important?)

public class StorageMessage implements IMessage {

public NBTTagCompound stackTagCompound;

public StorageMessage() {

}

public StorageMessage(NBTTagCompound stackTagCompound) {
	this.stackTagCompound = stackTagCompound;
}

@Override
public void fromBytes(ByteBuf buf) {
	stackTagCompound = ByteBufUtils.readTag(buf);
}

@Override
public void toBytes(ByteBuf buf) {
	ByteBufUtils.writeTag(buf, stackTagCompound);
}
}

 

StorageMessageHandler

public class StorageMessageHandler implements IMessageHandler<StorageMessage, IMessage> {

@Override
public IMessage onMessage(StorageMessage message, MessageContext ctx) {
	NBTTagCompound ntc = message.stackTagCompound;
	int id = ntc.getInteger("e");

	System.out.println("Received storage message!"); // this gets printed

	for (Object obj : Minecraft.getMinecraft().theWorld.loadedEntityList) {
		Entity ent = (Entity) obj;

		if (id == ent.getEntityId()) {
			System.out.println("Entity found! Updating storage..."); // all good here too
			((EntityBank) ent).add(ntc.getInteger("s"));
			break;
		}
	}

	return null;
}
}

 

The network message/handler etc is all registered.

The client does receive the message, the entity gets update (if I interact with the entity, it shows the correct stored value)

but as soons as I leave the world (shutting down the server) and re-enter it again, the information on the client side is no longer in accordance to the server.

I'm probably missing something really stupid, just have no idea what it is, have only got to modding recently too.

Why does the value on the client side reset when I rejoin? Shouldn't things that are loaded on NBT be passed back to the client when he joins the world so he gets the updated information on an entity? What should happen here?

 

And lastly, what do you think of my network code? It looks a bit network intensive/inneficient to me

 

Any help is appreciated

Link to comment
Share on other sites

Keeping it very short.

Facts:

1. Data:

- NBT loading/saving is server side.

- If you want to have ANY data on client, you need to send it.

 

2. Existance of entities:

- Server knows about all currently loaded entities.

- Client knows only about entities (creates them) that server tells it to spawn, simplier:

* Client has only one world (in which player is in).

* Client has only entities that are visible for given player in this world.

 

3. When synchronization (of entities) occurs:

3.1. Server tells client to spawn some entitiy that will be mirror of server's one.

3.2. Server changes values and sends them to players that are currently tracking entity.

 

How? Where? (important points)

 

1. When entity is spawned (spawn packet is sent to client) and it implements IEntityAdditionalSpawnData you can send additional data within spawn packet.

 

2. There is this thing called EntityTracker, in simple words: it keeps track of which player watches which entity. (or other way around, which entity is watched by which players, those are internals, don't matter)

2.1. Whenever a player starts tracking new entity (meaning his client should be notified about entity's existance) - PlayerEvent.StartTracking event is called. It allows you to send additional data that cannot be placed in spawn packed (e.g for vanilla mobs).

2.2. Whenever something about your data changes you also need to notify clients. You do that with mentioned EntityTracker:

EntityTracker et = ((WorldServer) entity.worldObj).getEntityTracker(); // You get EntityTracker of world in which there is entity you want to synchronize
et.func_151248_b(entity, SimpleNetworkWrapper#getInstance().getPacketFrom(new SomeDataPacket()); // You need SNW instance, the method might vari between versions. The method itself says "send this packet to everyone who is tracking this "entity".

Code above will result in packet about "entity" being sent to all clients (players) that are currently "seeing" it (tracking).

Do note that if "entity" is EntityPlayer, the player himself will also be notified (player tracks himself), unless you use other method that is provided in EntityTracker (idk the name).

 

3. SimpleNetworkWrapper methods - there are things like sendTo(player, packed), etc. Those will be used if you want only specific clients to know stuff about entity. Can be used when data is private.

 

That is all you will need, there are also DataWatchers (for simple data only), but I never liked them, so let's skip them.

 

Setting up network is nothing more than making IMessage and Hanlder + SimpleNetworkWrapper.

http://www.minecraftforum.net/forums/mapping-and-modding/mapping-and-modding-tutorials/2137055-1-7-2-customizing-packet-handling-with

 

EDIT

Edited, recommeded to re-read.

 

EDIT EDIT

For god's sake - UPDATE to 1.8+ ! And then:

http://greyminecraftcoder.blogspot.com.au/2015/01/thread-safety-with-network-messages.html

 

Also: 1.8 is better with dynamic updating, scheluding takes care of very annoying data-losses if you are working with (very) dynamic synchronizations.

(E.g: You send packet, but client doesn't have entity constructed yet, boom - data is lost).

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

Link to comment
Share on other sites

Wow, thanks a lot for the information!

So I already have a SimpleNetworkManager instance to use

But I don't understand where will the client listen to these packets

I mean, how will it read the packet and assign the needed values from the packet and assign to the entity?

I'm reading on how to construct the packet yet, but I already have an IMessage implementation (code in the original post), will I be passing data around with NBTs too? I already have done message passing/handling in the original code above, is that what I use to send the packet?

 

And I can't update to 1.8 due to compatibility with other mods that still haven't done so unfortunately  :P

 

Edit: Now I got what you meant with the EntityTracket code section! I just reused the same Message I was using and it worked well

Thanks !

 

Edit2: Implemented IEntityAdditionalSpawnData and it worked exactly as intended

	@Override
public void writeSpawnData(ByteBuf buffer) {
	NBTTagCompound ntc = new NBTTagCompound();
	ntc.setInteger("stored", stored);
	ByteBufUtils.writeTag(buffer, ntc);

	// this should be faster instead
	//buffer.writeInt(stored);
}

@Override
public void readSpawnData(ByteBuf additionalData) {
	NBTTagCompound ntc = ByteBufUtils.readTag(additionalData);
	stored = ntc.getInteger("stored");

	// this should be faster instead
	//stored = additionalData.readInt();
}

you really saved me with all this wizardry

 

Renaming thread to solved

Link to comment
Share on other sites

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • As a seasoned investor, I’ve learned that the financial world can be exciting and treacherous. My experiences with investments have taught me the importance of diligence and thorough research, particularly when dealing with newer and high-risk assets like Bitcoin. Unfortunately, my journey with Bitcoin was marred by a painful lesson in the form of a scam, which I hope to share to help others avoid similar pitfalls. My introduction to Bitcoin investing seemed promising. The allure of high returns and the buzz surrounding cryptocurrency were captivating. I was drawn to several Bitcoin investment platforms that promised substantial profits. These platforms presented themselves with professional websites, attractive promotions, and genuine testimonials. I was led to believe that these sites were reliable and that I was making a sound investment. However, this trust proved to be misplaced. The platform I initially invested in showcased fake success stories and substantial profits to entice investors. They used these fabricated examples to build credibility and persuade new investors like me to commit more funds. Their tactics were sophisticated; they knew exactly how to create an illusion of success and security. I, too, was lured by their promises and gradually invested a considerable amount of money, totaling 68,000 USD.The initial investments went smoothly. My account appeared to grow with impressive returns, and I felt a sense of validation in my investment strategy. But things took a drastic turn when I decided to make a more significant investment, believing that the returns would only get better. Once I deposited a substantial sum, the platform’s behavior changed abruptly. My account was frozen without warning, and I was faced with a barrage of demands for additional payments before I could access my funds or the supposed profits. The situation was both distressing and bewildering. I was met with excuses and obstructions at every turn. It became clear that I was dealing with a fraudulent company that had no intention of honoring its commitments. The realization that I had been deceived was crushing. The emotional and financial toll of the situation was overwhelming. Determined to recover my funds, I reached out to Trust Geeks Hack Expert, a service recommended by a trusted friend who had faced a similar ordeal. My initial skepticism was tempered by desperation and hope. Trust Geeks Hack Expert took immediate action. Their team worked tirelessly to investigate the fraudulent platform and recover my lost funds. Their dedication and expertise were evident throughout the process. In just a few weeks, Trust Geeks Hack Expert managed to successfully retrieve the full amount of 68,000 USD. Their assistance was thorough and professional, and they kept me informed every step of the way. Their efforts not only resulted in the recovery of my funds but also provided me with invaluable insights into how these scams operate. This. This experience has been a harsh lesson in the importance of conducting thorough research before investing in any platform, particularly in the cryptocurrency space. The allure of high returns can be overwhelming, but it’s crucial to approach such investments with caution. Verify the legitimacy of the platform, seek out reviews from reliable sources, and ensure that any investment opportunity has a track record of transparency and reliability. To anyone who finds themselves in a similar predicament, I cannot recommend Trust Geeks Hack Expert  enough. Their professionalism and commitment to recovering my funds were exemplary:: E>mail: trustgeekshackexpert {@} fastservice{.}com -----> Tele>gram : Trustgeekshackexpert, And also  What's>App   + 1-7-1-9-4-9-2-2-6-9-3
    • As a seasoned investor, I’ve learned that the financial world can be exciting and treacherous. My experiences with investments have taught me the importance of diligence and thorough research, particularly when dealing with newer and high-risk assets like Bitcoin. Unfortunately, my journey with Bitcoin was marred by a painful lesson in the form of a scam, which I hope to share to help others avoid similar pitfalls. My introduction to Bitcoin investing seemed promising. The allure of high returns and the buzz surrounding cryptocurrency were captivating. I was drawn to several Bitcoin investment platforms that promised substantial profits. These platforms presented themselves with professional websites, attractive promotions, and genuine testimonials. I was led to believe that these sites were reliable and that I was making a sound investment. However, this trust proved to be misplaced. The platform I initially invested in showcased fake success stories and substantial profits to entice investors. They used these fabricated examples to build credibility and persuade new investors like me to commit more funds. Their tactics were sophisticated; they knew exactly how to create an illusion of success and security. I, too, was lured by their promises and gradually invested a considerable amount of money, totaling 68,000 USD.The initial investments went smoothly. My account appeared to grow with impressive returns, and I felt a sense of validation in my investment strategy. But things took a drastic turn when I decided to make a more significant investment, believing that the returns would only get better. Once I deposited a substantial sum, the platform’s behavior changed abruptly. My account was frozen without warning, and I was faced with a barrage of demands for additional payments before I could access my funds or the supposed profits. The situation was both distressing and bewildering. I was met with excuses and obstructions at every turn. It became clear that I was dealing with a fraudulent company that had no intention of honoring its commitments. The realization that I had been deceived was crushing. The emotional and financial toll of the situation was overwhelming. Determined to recover my funds, I reached out to Trust Geeks Hack Expert, a service recommended by a trusted friend who had faced a similar ordeal. My initial skepticism was tempered by desperation and hope. Trust Geeks Hack Expert took immediate action. Their team worked tirelessly to investigate the fraudulent platform and recover my lost funds. Their dedication and expertise were evident throughout the process. In just a few weeks, Trust Geeks Hack Expert managed to successfully retrieve the full amount of 68,000 USD. Their assistance was thorough and professional, and they kept me informed every step of the way. Their efforts not only resulted in the recovery of my funds but also provided me with invaluable insights into how these scams operate. This. This experience has been a harsh lesson in the importance of conducting thorough research before investing in any platform, particularly in the cryptocurrency space. The allure of high returns can be overwhelming, but it’s crucial to approach such investments with caution. Verify the legitimacy of the platform, seek out reviews from reliable sources, and ensure that any investment opportunity has a track record of transparency and reliability. To anyone who finds themselves in a similar predicament, I cannot recommend Trust Geeks Hack Expert  enough. Their professionalism and commitment to recovering my funds were exemplary:: E>mail: trustgeekshackexpert{@}fastservice{.}com -----> Tele>gram : Trustgeekshackexpert, And also  What's>App   + 1-7-1-9-4-9-2-2-6-9-3
    • I've been playing it for only 1 day and it doesn't want to go into the game anymore. I've tried reinstalling the game and repairing the game files (on curseforge) but it still doesn't work. Whenever i try to click on the Singleplayer icon, it just flickers into the world creation page and flickers back 
    • https://gist.github.com/RealMangoBot/03ce10d60ce10f126dcf2c033c3a4f46  
  • Topics

×
×
  • Create New...

Important Information

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