Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-25 15:50:14 +01:00
Add basis for overriding Bedrock block states
Fix missing providers when used in GeyserDefineCustomBlocksEvent
Dieser Commit ist enthalten in:
Ursprung
d00886e12a
Commit
42fdbeb647
@ -27,10 +27,12 @@ package org.geysermc.geyser.api.event.lifecycle;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||
import org.geysermc.geyser.api.event.Event;
|
||||
|
||||
public abstract class GeyserDefineCustomBlocksEvent implements Event {
|
||||
|
||||
public abstract void registerCustomBlock(@NonNull CustomBlockData customBlockData);
|
||||
|
||||
public abstract void registerBlockStateOverride(@NonNull String javaIdentifier, @NonNull CustomBlockState customBlockState);
|
||||
}
|
||||
|
@ -25,11 +25,13 @@
|
||||
|
||||
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.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
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.populator.BlockRegistryPopulator;
|
||||
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[] {}));
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -64,6 +64,12 @@ import java.util.*;
|
||||
* Holds all the common registries in Geyser.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -136,11 +142,6 @@ public final class Registries {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -32,6 +32,8 @@ import com.nukkitx.nbt.*;
|
||||
import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
|
||||
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
|
||||
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.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
@ -94,12 +96,36 @@ public class BlockRegistryPopulator {
|
||||
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
|
||||
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() {
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@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()) {
|
||||
@ -108,6 +134,9 @@ public class BlockRegistryPopulator {
|
||||
|
||||
BlockRegistries.CUSTOM_BLOCKS.set(customBlocks.toArray(new CustomBlockData[0]));
|
||||
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) {
|
||||
@ -247,10 +276,20 @@ public class BlockRegistryPopulator {
|
||||
Map.Entry<String, JsonNode> entry = blocksIterator.next();
|
||||
String javaId = entry.getKey();
|
||||
|
||||
int 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));
|
||||
int bedrockRuntimeId;
|
||||
CustomBlockState blockStateOverride = BlockRegistries.CUSTOM_BLOCK_STATE_OVERRIDES.get(javaRuntimeId);
|
||||
if (blockStateOverride == null) {
|
||||
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) {
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren