SpongeAPI icon indicating copy to clipboard operation
SpongeAPI copied to clipboard

Manipulate blocks send to the client?

Open thomas15v opened this issue 8 years ago • 10 comments

The idea is to manipulate the chunks/blocks send to the client. So that we can hide or fake certain types of blocks.

I am aware that we can send blocks to the player with the ´Viewer´ object. But if your trying to make something that prevents cheating (xray), It might be better to not send the blocks in the first place.

thomas15v avatar Jun 04 '16 13:06 thomas15v

We should add a kind of ChunkTranformer that would edit the chunk data when the chunk is going to be sent to the client (without loading it ?)

Yeregorix avatar Jul 30 '17 10:07 Yeregorix

Well it's possible, slightly buggy tho.

thomas15v avatar Jul 31 '17 11:07 thomas15v

Yes but you're using mixin, it would be nice if the API would allow us to edit chunks when packets are generated. I've also seen you got a performance issue because you're loading a lot of unloaded chunks, to avoid loading them, the API should provide us a kind of raw data of the unloaded chunks being sent

Yeregorix avatar Jul 31 '17 21:07 Yeregorix

Yeah, and so will Sponge 😉. Although the chunk issues are caused by the way I calculate the obfuscated blocks.

I think the neatest thing that should be in the API in some sort of "Player World" (this is about the same what my api in noxray does). So we could do the following for example:

//pseudocode
void onPlayerMove(event){
  player.getNetworkWorld().setBlock(Blocks.Gold, player.getPosition().translate(0,-1,0);
  player.getWorld().getGlobalNetworkWorld().setBlock(Blocks.Diamond, player.getPosition().translate(0,-1,0);
  //update blocks after modification to limit network traffic (bulk update)
  player.getGlobalNetworkWorld().update(p -> !p.getName().equals(player.getName()))
  player.getNetWorkWorld().update()
}

Also with have the following events:

  • NetworkBlockSendEvent: Sends a block to a certain location
  • NetworkChunkSendEvent: Sends a chunk to the client/player
  • NetworkWorldSendEvent: Sends a collection of chunks to player (on join/teleport/fast travel)

These events will basicly be fired upon sending and will also populate the NetworkWorld.

One problem with this is that this does increase the memory footprint a lot. Since you basically hold a copy of the "viewable" world for each player. It's also important that it's a copy, if you for example wanna spoof the chest content you don't wanna edit the chest in the world. To make sure we don't hurt other servers that don't wanna use this the api would have to need some sort of Enable function, that plugins can call upon using.

Another problem is that the events are being send from the players network thread. What means that you are somewhat limited in things you can call during that event. We also will need safeguards sending blocks during those events since that will cause a deadlock.

thomas15v avatar Aug 01 '17 08:08 thomas15v

Nice work! It would be nice if a similar API could be added in SpongeAPI. It could be a ClientBlockVolume, a ClientEntityUniverse, and many others client side stuffs, also, it might be related or an alternative to Contexts and Contextual data #1046 However, is the copy of the viewable chunk a copy of the whole chunk or only the modified blocks ? Is it really necessary to keep this copy ?

Yeregorix avatar Aug 02 '17 19:08 Yeregorix

Maybe it shouldn't be. But upon modifying this "NetworkWorld" it's important that the blocks in the world (world data) remain unchanged. Problem with have some sort of link with the core blocks to avoid copying, will modify them if you call the method. Unless sponge has some sort of immutable class that can pass for a block, I don't think this would be a good idea.

untitled diagram 2

thomas15v avatar Aug 03 '17 07:08 thomas15v

Try BlockStates for the block storage, and EntitySnapshots and TileEntitySnapshots for the entities and tile entities.

JBYoshi avatar Aug 04 '17 14:08 JBYoshi

I'm really interested in this so I could port NonEuclid from Spigot to Sponge. In NonEuclid, depending on a player's location, I want them to see one of two possible hallways (neither of which actually exist in the world). Using sendBlockChange() doesn't cut it because anything that causes the real block or chunk to be resent to the client causes the fake hallway to disappear. NonEuclid currently addresses this in Spigot by using ProtocolLib to modify block change packets and detect chunk packets. (I'm also interested in https://github.com/SpongePowered/SpongeAPI/pull/1046 so I can make it so a player who sees hallway A can't see a player inside it who sees hallway B.)

Is any of this idea affected by changes proposed in https://github.com/SpongePowered/SpongeAPI/pull/1046 or https://github.com/SpongePowered/SpongeAPI/issues/1614?

Macil avatar Jul 16 '18 10:07 Macil

You might want to look at https://github.com/Yeregorix/Mirage I think it uses the same concept I explained here (since the plugin is based on my old NoXray plugin).

Pinging @Yeregorix.

thomas15v avatar Jul 18 '18 09:07 thomas15v

Since the view will be different for each player I think the best solution is to mixin in PlayerChunkMapEntry to listen for block changes or packet sending and to modify these packets. However it's not very simple, you can also wait for an API but you may wait a very long time.

Yeregorix avatar Jul 18 '18 10:07 Yeregorix