mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-31 16:41:02 +01:00
Clear mob spawners if the Java server so requests (#4232)
* Clear mob spawners if the Java server so requests * Empty spawners by replacing the spawner block with a new one instead of adding an invalid identifier to them. Unfortunately, sending one UpdateBlockPacket that replaces the spawner does not work, we need to set the spawner to air first. Cool. But at least we don't summon particles for all empty spawners now * store position vector (address review by @konicai) * remove empty line
This commit is contained in:
parent
0f50a3cbe6
commit
11945db7a0
6 changed files with 47 additions and 7 deletions
|
@ -221,6 +221,7 @@ public final class BlockRegistryPopulator {
|
|||
|
||||
GeyserBedrockBlock airDefinition = null;
|
||||
BlockDefinition commandBlockDefinition = null;
|
||||
BlockDefinition mobSpawnerBlockDefinition = null;
|
||||
BlockDefinition waterDefinition = null;
|
||||
BlockDefinition movingBlockDefinition = null;
|
||||
Iterator<Map.Entry<String, JsonNode>> blocksIterator = BLOCKS_JSON.fields();
|
||||
|
@ -269,6 +270,7 @@ public final class BlockRegistryPopulator {
|
|||
case "minecraft:air" -> airDefinition = bedrockDefinition;
|
||||
case "minecraft:water[level=0]" -> waterDefinition = bedrockDefinition;
|
||||
case "minecraft:command_block[conditional=false,facing=north]" -> commandBlockDefinition = bedrockDefinition;
|
||||
case "minecraft:spawner" -> mobSpawnerBlockDefinition = bedrockDefinition;
|
||||
case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition;
|
||||
}
|
||||
|
||||
|
@ -298,9 +300,13 @@ public final class BlockRegistryPopulator {
|
|||
if (commandBlockDefinition == null) {
|
||||
throw new AssertionError("Unable to find command block in palette");
|
||||
}
|
||||
|
||||
builder.commandBlock(commandBlockDefinition);
|
||||
|
||||
if (mobSpawnerBlockDefinition == null) {
|
||||
throw new AssertionError("Unable to find mob spawner block in palette");
|
||||
}
|
||||
builder.mobSpawnerBlock(mobSpawnerBlockDefinition);
|
||||
|
||||
if (waterDefinition == null) {
|
||||
throw new AssertionError("Unable to find water in palette");
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
|||
int[] remappedVanillaIds;
|
||||
|
||||
BlockDefinition commandBlock;
|
||||
BlockDefinition mobSpawnerBlock;
|
||||
|
||||
Map<NbtMap, BlockDefinition> itemFrames;
|
||||
Map<String, NbtMap> flowerPotBlocks;
|
||||
|
|
|
@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||
|
||||
/**
|
||||
|
@ -41,7 +42,7 @@ public abstract class BlockEntityTranslator {
|
|||
|
||||
public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState);
|
||||
|
||||
public NbtMap getBlockEntityTag(BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
|
||||
translateTag(tagBuilder, tag, blockState);
|
||||
return tagBuilder.build();
|
||||
|
|
|
@ -29,12 +29,44 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
|||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
@BlockEntity(type = BlockEntityType.MOB_SPAWNER)
|
||||
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||
// Sending an empty EntityIdentifier to empty the spawner is ignored by the client, so we send a whole new spawner!
|
||||
// Fixes https://github.com/GeyserMC/Geyser/issues/4214
|
||||
CompoundTag spawnData = tag.get("SpawnData");
|
||||
if (spawnData != null) {
|
||||
CompoundTag entityTag = spawnData.get("entity");
|
||||
if (entityTag.isEmpty()) {
|
||||
Vector3i position = Vector3i.from(x, y, z);
|
||||
// Set to air and back to reset the spawner - "just" updating the spawner doesn't work
|
||||
UpdateBlockPacket emptyBlockPacket = new UpdateBlockPacket();
|
||||
emptyBlockPacket.setDataLayer(0);
|
||||
emptyBlockPacket.setBlockPosition(position);
|
||||
emptyBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir());
|
||||
session.sendUpstreamPacket(emptyBlockPacket);
|
||||
|
||||
UpdateBlockPacket spawnerBlockPacket = new UpdateBlockPacket();
|
||||
spawnerBlockPacket.setDataLayer(0);
|
||||
spawnerBlockPacket.setBlockPosition(position);
|
||||
spawnerBlockPacket.setDefinition(session.getBlockMappings().getMobSpawnerBlock());
|
||||
session.sendUpstreamPacket(spawnerBlockPacket);
|
||||
}
|
||||
}
|
||||
|
||||
return super.getBlockEntityTag(session, type, x, y, z, tag, blockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
||||
Tag current;
|
||||
|
@ -69,8 +101,8 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
|||
|
||||
CompoundTag spawnData = tag.get("SpawnData");
|
||||
if (spawnData != null) {
|
||||
StringTag idTag = ((CompoundTag) spawnData.get("entity")).get("id");
|
||||
if (idTag != null) {
|
||||
CompoundTag entityTag = spawnData.get("entity");
|
||||
if (entityTag.get("id") instanceof StringTag idTag) {
|
||||
// As of 1.19.3, spawners can be empty
|
||||
String entityId = idTag.getValue();
|
||||
builder.put("EntityIdentifier", entityId);
|
||||
|
|
|
@ -62,7 +62,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||
}
|
||||
|
||||
Vector3i position = packet.getPosition();
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(),
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(session, type, position.getX(), position.getY(), position.getZ(),
|
||||
packet.getNbt(), blockState), packet.getPosition());
|
||||
// Check for custom skulls.
|
||||
boolean hasCustomHeadBlock = false;
|
||||
|
@ -80,7 +80,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||
}
|
||||
}
|
||||
if (!hasCustomHeadBlock) {
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(),
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(session, type, position.getX(), position.getY(), position.getZ(),
|
||||
packet.getNbt(), blockState), packet.getPosition());
|
||||
}
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||
}
|
||||
|
||||
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||
|
||||
// Check for custom skulls
|
||||
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) {
|
||||
|
|
Loading…
Reference in a new issue