3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-10-03 08:21:06 +02: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
Dieser Commit ist enthalten in:
chris 2023-12-01 10:27:42 +01:00 committet von GitHub
Ursprung 0f50a3cbe6
Commit 11945db7a0
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
6 geänderte Dateien mit 47 neuen und 7 gelöschten Zeilen

Datei anzeigen

@ -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");
}

Datei anzeigen

@ -54,6 +54,7 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
int[] remappedVanillaIds;
BlockDefinition commandBlock;
BlockDefinition mobSpawnerBlock;
Map<NbtMap, BlockDefinition> itemFrames;
Map<String, NbtMap> flowerPotBlocks;

Datei anzeigen

@ -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();

Datei anzeigen

@ -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);

Datei anzeigen

@ -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());
}

Datei anzeigen

@ -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")) {