Paper icon indicating copy to clipboard operation
Paper copied to clipboard

disguise api

Open yannicklamprecht opened this issue 1 year ago • 13 comments

relates to https://github.com/PaperMC/Paper/discussions/10584

Adds a simple disguise api that also makes sure that invalid entity data, not belonging to the type that is faked, is filtered. It also adds a server generator module to reduce maintenance of the entity data filter.

tldr; The API provides a way to disguise any entity as another or a player with having the possibility to interact with the entity like with any others. The big advantage is that you've the whole vanilla logic and Mob Goal and Pathfinding included without hassle.

Testing the changes can be done using the following snippet: https://gist.github.com/yannicklamprecht/639acba127a54f5617e1281f099b7aff

TODO:

  • [x] Add JavaDoc
  • [x] remove test plugin code
  • [x] comment paper-server-generator
  • [x] ~~figure out how to get teams working with real teams, client side ones worked in my fork~~ Non issue just use the Entity#getName() instead of the Entity#getScoreboardEntryName()
  • [x] remove player profile if player disguise on ServerEntiry#removePairing(player) to avoid client disconnects when moving away and approaching again. see https://github.com/PaperMC/Paper/pull/10478#issuecomment-2105299573
  • [x] wait until dev/1.21 is merged into master
  • [x] When player is disguised as entity his attributes are propagated to the client, which isn't supported by certain entities
  • [x] When player is disguised as entity that has no ability to interact/build, the server should not propagate the players action to the rest of the players. Otherwise the other player gets kicked.
  • [x] When changing disguise while in visible range from e.g. Boat to a Living entity disguise, attributes will be sent again. -> on disguise change => auto hide and show entity to players.

Effective loc:

  • 600 loc in patches
  • 3k+ loc generated filter classe
  • 400 loc generator code copied from api-generator
  • 100 loc for generating the filter class.

yannicklamprecht avatar Apr 28 '24 16:04 yannicklamprecht

Tested with: https://gist.github.com/yannicklamprecht/639acba127a54f5617e1281f099b7aff

Only open part is the discussion for a common generator module

yannicklamprecht avatar May 04 '24 14:05 yannicklamprecht

We should probably move the common generator classes into a separate module to reduce duplications.

yannicklamprecht avatar May 04 '24 16:05 yannicklamprecht

this is complicated enough that we prolly want a lil docs page with an example, but that can wait till after its merged and we know the final api design

MiniDigger avatar May 04 '24 17:05 MiniDigger

this is complicated enough that we prolly want a lil docs page with an example, but that can wait till after its merged and we know the final api design

Thought of adding a Java 18+ snippet to the javadoc but a docs page will be better.

EDIT: Or do you mean regarding code generation?

yannicklamprecht avatar May 04 '24 18:05 yannicklamprecht

I meant the api itself

MiniDigger avatar May 05 '24 08:05 MiniDigger

Addressed issue with experience orbs by filtering them out. Mentioned that exclusion in the JavaDoc.

Additionally found an issue with ElderGuardian when disguising them as a Player on the client side. That happens only when the ElderGuardian is in the water. First thought is the ElderGuardian stream sucking health from other entities. To be sure I need to deobf the client stacktrace.

Failed to handle packet adm@395c0068
java.lang.ClassCastException: class gct cannot be cast to class ckb (gct and ckb are in unnamed module of loader 'app')
	at fxy.a(SourceFile:1068)
	at adm.a(SourceFile:41)
	at adm.a(SourceFile:13)
	at zz.a(SourceFile:25)
	at bpm.d(SourceFile:162)
	at bpq.d(SourceFile:23)
	at bpm.A(SourceFile:136)
	at bpm.bA(SourceFile:121)
	at ffh.c(SourceFile:1275)
	at ffh.f(SourceFile:888)
	at net.minecraft.client.main.Main.main(SourceFile:265)

yannicklamprecht avatar May 10 '24 17:05 yannicklamprecht

That's ClientPacketListener handleEntityEvent, Player can't be cast to Guardian

kennytv avatar May 10 '24 18:05 kennytv

That's ClientPacketListener handleEntityEvent, Player can't be cast to Guardian

Found the reason why. I basically moved away from the entity, the chunk or at least the entities got unloaded. Due to the state that the disguise data is not persisted on the entity, when loading the entity again it published itself to the client without the disguise info. The client knows the entity uuid only as the disguised type but gets the original one.

I updated the test plugin snippet to reflect the needed change - cache cleaning on death excluded.

It would be way better to persist the disguise data in NBT to avoid manual caching per plugin.

yannicklamprecht avatar May 10 '24 21:05 yannicklamprecht

Addressed the last known issue by removing the profile info for a player disguised entity on ServerEntity#removePairing(player). https://github.com/PaperMC/Paper/pull/10478/files#diff-1b00ff7ef0678fae6f893a77a2ed93bece7dbbd375a03115590b25304423ab1fR161-R170

https://github.com/PaperMC/Paper/pull/10478/files#diff-1b00ff7ef0678fae6f893a77a2ed93bece7dbbd375a03115590b25304423ab1fR252

yannicklamprecht avatar Jun 01 '24 21:06 yannicklamprecht

Update to 1.21. Now we need to wait until dev/1.21 is merged into master.

yannicklamprecht avatar Jun 14 '24 20:06 yannicklamprecht

good job!

XxGoldenbluexX avatar Aug 15 '24 09:08 XxGoldenbluexX