3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-19 22:40:18 +01:00

Add basis for overriding Bedrock block states

Fix missing providers when used in GeyserDefineCustomBlocksEvent
Dieser Commit ist enthalten in:
davchoo 2022-07-29 18:21:14 -04:00
Ursprung d00886e12a
Commit 42fdbeb647
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: A0168C8E45799B7D
4 geänderte Dateien mit 59 neuen und 10 gelöschten Zeilen

Datei anzeigen

@ -27,10 +27,12 @@ package org.geysermc.geyser.api.event.lifecycle;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.event.Event; import org.geysermc.geyser.api.event.Event;
public abstract class GeyserDefineCustomBlocksEvent implements Event { public abstract class GeyserDefineCustomBlocksEvent implements Event {
public abstract void registerCustomBlock(@NonNull CustomBlockData customBlockData); public abstract void registerCustomBlock(@NonNull CustomBlockData customBlockData);
public abstract void registerBlockStateOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState);
} }

Datei anzeigen

@ -25,11 +25,13 @@
package org.geysermc.geyser.registry; package org.geysermc.geyser.registry;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.registry.loader.RegistryLoaders; import org.geysermc.geyser.registry.loader.RegistryLoaders;
import org.geysermc.geyser.registry.populator.BlockRegistryPopulator; import org.geysermc.geyser.registry.populator.BlockRegistryPopulator;
import org.geysermc.geyser.registry.populator.CustomSkullRegistryPopulator; import org.geysermc.geyser.registry.populator.CustomSkullRegistryPopulator;
@ -90,6 +92,11 @@ public class BlockRegistries {
*/ */
public static final ArrayRegistry<CustomBlockData> CUSTOM_BLOCKS = ArrayRegistry.create(RegistryLoaders.empty(() -> new CustomBlockData[] {})); public static final ArrayRegistry<CustomBlockData> CUSTOM_BLOCKS = ArrayRegistry.create(RegistryLoaders.empty(() -> new CustomBlockData[] {}));
/**
* A registry which stores Java Ids and the custom block state it should be replaced with.
*/
public static final MappedRegistry<Integer, CustomBlockState, Int2ObjectMap<CustomBlockState>> CUSTOM_BLOCK_STATE_OVERRIDES = MappedRegistry.create(RegistryLoaders.empty(Int2ObjectOpenHashMap::new));
/** /**
* A registry which stores skin texture hashes to custom skull blocks. * A registry which stores skin texture hashes to custom skull blocks.
*/ */

Datei anzeigen

@ -64,6 +64,12 @@ import java.util.*;
* Holds all the common registries in Geyser. * Holds all the common registries in Geyser.
*/ */
public final class Registries { public final class Registries {
/**
* A registry holding all the providers.
* This has to be initialized first to allow extensions to access providers during other registry events.
*/
public static final SimpleMappedRegistry<Class<?>, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new);
/** /**
* A registry holding a CompoundTag of the known entity identifiers. * A registry holding a CompoundTag of the known entity identifiers.
*/ */
@ -136,11 +142,6 @@ public final class Registries {
*/ */
public static final SimpleRegistry<Set<PotionMixData>> POTION_MIXES; public static final SimpleRegistry<Set<PotionMixData>> POTION_MIXES;
/**
* A registry holding all the
*/
public static final SimpleMappedRegistry<Class<?>, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new);
/** /**
* A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value. * A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value.
*/ */

Datei anzeigen

@ -32,6 +32,8 @@ import com.nukkitx.nbt.*;
import com.nukkitx.protocol.bedrock.data.BlockPropertyData; import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527; import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
import com.nukkitx.protocol.bedrock.v534.Bedrock_v534; import com.nukkitx.protocol.bedrock.v534.Bedrock_v534;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.*; import it.unimi.dsi.fastutil.objects.*;
@ -94,12 +96,36 @@ public class BlockRegistryPopulator {
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) { if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
return; return;
} }
List<CustomBlockData> customBlocks = new ArrayList<>(); Set<String> customBlockNames = new HashSet<>();
Set<CustomBlockData> customBlocks = new HashSet<>();
Int2ObjectMap<CustomBlockState> blockStateOverrides = new Int2ObjectOpenHashMap<>();
GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() { GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() {
@Override @Override
public void registerCustomBlock(@NonNull CustomBlockData customBlockData) { public void registerCustomBlock(@NonNull CustomBlockData customBlockData) {
if (!customBlockNames.add(customBlockData.name())) {
throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name());
}
// TODO validate collision+selection box bounds
// TODO validate names
customBlocks.add(customBlockData); customBlocks.add(customBlockData);
} }
@Override
public void registerBlockStateOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState) {
int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(javaIdentifier, -1);
if (id == -1) {
throw new IllegalArgumentException("Unknown Java block state. Identifier: " + javaIdentifier);
}
if (!customBlocks.contains(customBlockState.block())) {
throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name());
}
CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState);
if (oldBlockState != null) {
// TODO should this be an error? Allow extensions to query block state overrides?
GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " +
javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name());
}
}
}); });
for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) { for (CustomSkull customSkull : BlockRegistries.CUSTOM_SKULLS.get().values()) {
@ -108,6 +134,9 @@ public class BlockRegistryPopulator {
BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0])); BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0]));
GeyserImpl.getInstance().getLogger().debug("Registered " + customBlocks.size() + " custom blocks."); GeyserImpl.getInstance().getLogger().debug("Registered " + customBlocks.size() + " custom blocks.");
BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.set(blockStateOverrides);
GeyserImpl.getInstance().getLogger().debug("Registered " + blockStateOverrides.size() + " custom block overrides.");
} }
private static void generateCustomBlockStates(CustomBlockData customBlock, List<NbtMap> blockStates, List<CustomBlockState> customExtBlockStates, int stateVersion) { private static void generateCustomBlockStates(CustomBlockData customBlock, List<NbtMap> blockStates, List<CustomBlockState> customExtBlockStates, int stateVersion) {
@ -247,10 +276,20 @@ public class BlockRegistryPopulator {
Map.Entry<String, JsonNode> entry = blocksIterator.next(); Map.Entry<String, JsonNode> entry = blocksIterator.next();
String javaId = entry.getKey(); String javaId = entry.getKey();
int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(buildBedrockState(entry.getValue(), stateVersion, stateMapper), -1); int bedrockRuntimeId;
if (bedrockRuntimeId == -1) { CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(javaRuntimeId);
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" + if (blockStateOverride == null) {
buildBedrockState(entry.getValue(), stateVersion, stateMapper)); bedrockRuntimeId = blockStateOrderedMap.getOrDefault(buildBedrockState(entry.getValue(), stateVersion, stateMapper), -1);
if (bedrockRuntimeId == -1) {
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Built NBT tag: \n" +
buildBedrockState(entry.getValue(), stateVersion, stateMapper));
}
} else {
bedrockRuntimeId = customBlockStateIds.getOrDefault(blockStateOverride, -1);
if (bedrockRuntimeId == -1) {
throw new RuntimeException("Unable to find " + javaId + " Bedrock runtime ID! Custom block override: \n" +
blockStateOverride);
}
} }
switch (javaId) { switch (javaId) {