3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-19 14:30:17 +01:00

Move to CustomBlockRegistryPopulator

Dieser Commit ist enthalten in:
Joshua Castle 2022-12-29 22:54:04 -08:00
Ursprung 7988882f91
Commit e696972c67
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: F674F38216C35D5D
3 geänderte Dateien mit 247 neuen und 204 gelöschten Zeilen

Datei anzeigen

@ -32,29 +32,20 @@ import com.nukkitx.nbt.*;
import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
import com.nukkitx.protocol.bedrock.v544.Bedrock_v544;
import com.nukkitx.protocol.bedrock.v560.Bedrock_v560;
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.*;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
import org.geysermc.geyser.api.block.custom.component.MaterialInstance;
import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty;
import org.geysermc.geyser.api.block.custom.property.PropertyType;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomBlocksEvent;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.GeyserCustomBlockState;
import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.registry.type.BlockMappings;
import org.geysermc.geyser.registry.type.CustomSkull;
import org.geysermc.geyser.util.BlockUtils;
import java.io.DataInputStream;
@ -75,122 +66,12 @@ public final class BlockRegistryPopulator {
public static void populate() {
registerJavaBlocks();
registerCustomBedrockBlocks();
CustomBlockRegistryPopulator.registerCustomBedrockBlocks();
registerBedrockBlocks();
BLOCKS_JSON = null;
}
private static void registerCustomBedrockBlocks() {
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
return;
}
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()) {
customBlocks.add(customSkull.getCustomBlockData());
}
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) {
int totalPermutations = 1;
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
totalPermutations *= property.values().size();
}
for (int i = 0; i < totalPermutations; i++) {
NbtMapBuilder statesBuilder = NbtMap.builder();
int permIndex = i;
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
statesBuilder.put(property.name(), property.values().get(permIndex % property.values().size()));
permIndex /= property.values().size();
}
NbtMap states = statesBuilder.build();
blockStates.add(NbtMap.builder()
.putString("name", customBlock.identifier())
.putInt("version", stateVersion)
.putCompound("states", states)
.build());
customExtBlockStates.add(new GeyserCustomBlockState(customBlock, states));
}
}
@SuppressWarnings("unchecked")
private static BlockPropertyData generateBlockPropertyData(CustomBlockData customBlock, int protocolVersion) {
List<NbtMap> permutations = new ArrayList<>();
for (CustomBlockPermutation permutation : customBlock.permutations()) {
permutations.add(NbtMap.builder()
.putCompound("components", convertComponents(permutation.components(), protocolVersion))
.putString("condition", permutation.condition())
.build());
}
// The order that properties are defined influences the order that block states are generated
List<NbtMap> properties = new ArrayList<>();
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
NbtMapBuilder propertyBuilder = NbtMap.builder()
.putString("name", property.name());
if (property.type() == PropertyType.BOOLEAN) {
propertyBuilder.putList("enum", NbtType.BYTE, List.of((byte) 0, (byte) 1));
} else if (property.type() == PropertyType.INTEGER) {
propertyBuilder.putList("enum", NbtType.INT, (List<Integer>) property.values());
} else if (property.type() == PropertyType.STRING) {
propertyBuilder.putList("enum", NbtType.STRING, (List<String>) property.values());
}
properties.add(propertyBuilder.build());
}
NbtMap propertyTag = NbtMap.builder()
.putCompound("components", convertComponents(customBlock.components(), protocolVersion))
.putCompound("menu_category", NbtMap.builder()
.putString("category", "none")
.putString("group", "")
.putBoolean("is_hidden_in_commands", false)
.build())
.putInt("molangVersion", 1)
.putList("permutations", NbtType.COMPOUND, permutations)
.putList("properties", NbtType.COMPOUND, properties)
.build();
return new BlockPropertyData(customBlock.identifier(), propertyTag);
}
private static void registerBedrockBlocks() {
BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null;
ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
@ -218,8 +99,8 @@ public final class BlockRegistryPopulator {
int[] remappedVanillaIds = new int[0];
if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) {
for (CustomBlockData customBlock : BlockRegistries.CUSTOM_BLOCKS.get()) {
customBlockProperties.add(generateBlockPropertyData(customBlock, protocolVersion));
generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates, stateVersion);
customBlockProperties.add(CustomBlockRegistryPopulator.generateBlockPropertyData(customBlock, protocolVersion));
CustomBlockRegistryPopulator.generateCustomBlockStates(customBlock, customBlockStates, customExtBlockStates, stateVersion);
}
blockStates.addAll(customBlockStates);
GeyserImpl.getInstance().getLogger().debug("Added " + customBlockStates.size() + " custom block states to v" + protocolVersion + " palette.");
@ -364,69 +245,7 @@ public final class BlockRegistryPopulator {
}
}
private static NbtMap convertComponents(CustomBlockComponents components, int protocolVersion) {
if (components == null) {
return NbtMap.EMPTY;
}
NbtMapBuilder builder = NbtMap.builder();
if (components.selectionBox() != null) {
builder.putCompound("minecraft:selection_box", convertBox(components.selectionBox()));
}
if (components.collisionBox() != null) {
builder.putCompound("minecraft:collision_box", convertBox(components.collisionBox()));
}
if (components.geometry() != null) {
builder.putCompound("minecraft:geometry", NbtMap.builder()
.putString("value", components.geometry())
.build());
}
if (!components.materialInstances().isEmpty()) {
NbtMapBuilder materialsBuilder = NbtMap.builder();
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
MaterialInstance materialInstance = entry.getValue();
materialsBuilder.putCompound(entry.getKey(), NbtMap.builder()
.putString("texture", materialInstance.texture())
.putString("render_method", materialInstance.renderMethod())
.putBoolean("face_dimming", materialInstance.faceDimming())
.putBoolean("ambient_occlusion", materialInstance.faceDimming())
.build());
}
builder.putCompound("minecraft:material_instances", NbtMap.builder()
.putCompound("mappings", NbtMap.EMPTY)
.putCompound("materials", materialsBuilder.build())
.build());
}
if (components.destroyTime() != null) {
builder.putCompound("minecraft:destructible_by_mining", NbtMap.builder()
.putFloat("value", components.destroyTime())
.build());
}
if (components.friction() != null) {
builder.putCompound("minecraft:friction", NbtMap.builder()
.putFloat("value", components.friction())
.build());
}
if (components.lightEmission() != null) {
builder.putCompound("minecraft:light_emission", NbtMap.builder()
.putInt("value", components.lightEmission())
.build());
}
if (components.lightDampening() != null) {
builder.putCompound("minecraft:block_light_filter", NbtMap.builder()
.putByte("value", components.lightDampening().byteValue())
.build());
}
if (components.rotation() != null) {
builder.putCompound("minecraft:rotation", NbtMap.builder()
.putFloat("x", components.rotation().x())
.putFloat("y", components.rotation().y())
.putFloat("z", components.rotation().z())
.build());
}
return builder.build();
}
private static NbtMap convertBox(BoxComponent boxComponent) {
static NbtMap convertBox(BoxComponent boxComponent) {
return NbtMap.builder()
.putBoolean("enabled", !boxComponent.isEmpty())
.putList("origin", NbtType.FLOAT, boxComponent.originX(), boxComponent.originY(), boxComponent.originZ())

Datei anzeigen

@ -0,0 +1,205 @@
package org.geysermc.geyser.registry.populator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
import org.geysermc.geyser.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.component.CustomBlockComponents;
import org.geysermc.geyser.api.block.custom.component.MaterialInstance;
import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty;
import org.geysermc.geyser.api.block.custom.property.PropertyType;
import org.geysermc.geyser.api.event.lifecycle.GeyserDefineCustomBlocksEvent;
import org.geysermc.geyser.level.block.GeyserCustomBlockState;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.CustomSkull;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class CustomBlockRegistryPopulator {
static void registerCustomBedrockBlocks() {
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
return;
}
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()) {
customBlocks.add(customSkull.getCustomBlockData());
}
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.");
}
static void generateCustomBlockStates(CustomBlockData customBlock, List<NbtMap> blockStates, List<CustomBlockState> customExtBlockStates, int stateVersion) {
int totalPermutations = 1;
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
totalPermutations *= property.values().size();
}
for (int i = 0; i < totalPermutations; i++) {
NbtMapBuilder statesBuilder = NbtMap.builder();
int permIndex = i;
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
statesBuilder.put(property.name(), property.values().get(permIndex % property.values().size()));
permIndex /= property.values().size();
}
NbtMap states = statesBuilder.build();
blockStates.add(NbtMap.builder()
.putString("name", customBlock.identifier())
.putInt("version", stateVersion)
.putCompound("states", states)
.build());
customExtBlockStates.add(new GeyserCustomBlockState(customBlock, states));
}
}
@SuppressWarnings("unchecked")
static BlockPropertyData generateBlockPropertyData(CustomBlockData customBlock, int protocolVersion) {
List<NbtMap> permutations = new ArrayList<>();
for (CustomBlockPermutation permutation : customBlock.permutations()) {
permutations.add(NbtMap.builder()
.putCompound("components", CustomBlockRegistryPopulator.convertComponents(permutation.components(), protocolVersion))
.putString("condition", permutation.condition())
.build());
}
// The order that properties are defined influences the order that block states are generated
List<NbtMap> properties = new ArrayList<>();
for (CustomBlockProperty<?> property : customBlock.properties().values()) {
NbtMapBuilder propertyBuilder = NbtMap.builder()
.putString("name", property.name());
if (property.type() == PropertyType.BOOLEAN) {
propertyBuilder.putList("enum", NbtType.BYTE, List.of((byte) 0, (byte) 1));
} else if (property.type() == PropertyType.INTEGER) {
propertyBuilder.putList("enum", NbtType.INT, (List<Integer>) property.values());
} else if (property.type() == PropertyType.STRING) {
propertyBuilder.putList("enum", NbtType.STRING, (List<String>) property.values());
}
properties.add(propertyBuilder.build());
}
NbtMap propertyTag = NbtMap.builder()
.putCompound("components", CustomBlockRegistryPopulator.convertComponents(customBlock.components(), protocolVersion))
.putCompound("menu_category", NbtMap.builder()
.putString("category", "none")
.putString("group", "")
.putBoolean("is_hidden_in_commands", false)
.build())
.putInt("molangVersion", 1)
.putList("permutations", NbtType.COMPOUND, permutations)
.putList("properties", NbtType.COMPOUND, properties)
.build();
return new BlockPropertyData(customBlock.identifier(), propertyTag);
}
static NbtMap convertComponents(CustomBlockComponents components, int protocolVersion) {
if (components == null) {
return NbtMap.EMPTY;
}
NbtMapBuilder builder = NbtMap.builder();
if (components.selectionBox() != null) {
builder.putCompound("minecraft:selection_box", BlockRegistryPopulator.convertBox(components.selectionBox()));
}
if (components.collisionBox() != null) {
builder.putCompound("minecraft:collision_box", BlockRegistryPopulator.convertBox(components.collisionBox()));
}
if (components.geometry() != null) {
builder.putCompound("minecraft:geometry", NbtMap.builder()
.putString("value", components.geometry())
.build());
}
if (!components.materialInstances().isEmpty()) {
NbtMapBuilder materialsBuilder = NbtMap.builder();
for (Map.Entry<String, MaterialInstance> entry : components.materialInstances().entrySet()) {
MaterialInstance materialInstance = entry.getValue();
materialsBuilder.putCompound(entry.getKey(), NbtMap.builder()
.putString("texture", materialInstance.texture())
.putString("render_method", materialInstance.renderMethod())
.putBoolean("face_dimming", materialInstance.faceDimming())
.putBoolean("ambient_occlusion", materialInstance.faceDimming())
.build());
}
builder.putCompound("minecraft:material_instances", NbtMap.builder()
.putCompound("mappings", NbtMap.EMPTY)
.putCompound("materials", materialsBuilder.build())
.build());
}
if (components.destroyTime() != null) {
builder.putCompound("minecraft:destructible_by_mining", NbtMap.builder()
.putFloat("value", components.destroyTime())
.build());
}
if (components.friction() != null) {
builder.putCompound("minecraft:friction", NbtMap.builder()
.putFloat("value", components.friction())
.build());
}
if (components.lightEmission() != null) {
builder.putCompound("minecraft:light_emission", NbtMap.builder()
.putInt("value", components.lightEmission())
.build());
}
if (components.lightDampening() != null) {
builder.putCompound("minecraft:block_light_filter", NbtMap.builder()
.putByte("value", components.lightDampening().byteValue())
.build());
}
if (components.rotation() != null) {
builder.putCompound("minecraft:rotation", NbtMap.builder()
.putFloat("x", components.rotation().x())
.putFloat("y", components.rotation().y())
.putFloat("z", components.rotation().z())
.build());
}
return builder.build();
}
}

Datei anzeigen

@ -25,21 +25,18 @@
package org.geysermc.geyser.translator.inventory.item;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.*;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.api.util.TriState;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.CustomSkull;
@ -51,10 +48,30 @@ import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.FileUtils;
import javax.annotation.Nonnull;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.stream.Collectors;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag;
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.DoubleTag;
import com.github.steveice10.opennbt.tag.builtin.FloatTag;
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
import com.github.steveice10.opennbt.tag.builtin.LongTag;
import com.github.steveice10.opennbt.tag.builtin.ShortTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public abstract class ItemTranslator {
private static final Int2ObjectMap<ItemTranslator> ITEM_STACK_TRANSLATORS = new Int2ObjectOpenHashMap<>();
@ -560,4 +577,6 @@ public abstract class ItemTranslator {
}
}
// TODO: Add translator for generic custom blocks
}