mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Actually implement adventure mode predicates, kind of.
If it's just block IDs, it'll work.
This commit is contained in:
parent
d85549c38d
commit
1b075badce
7 changed files with 71 additions and 58 deletions
|
@ -66,11 +66,6 @@ public class BlockRegistries {
|
|||
*/
|
||||
public static final ListRegistry<BlockState> BLOCK_STATES = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
|
||||
|
||||
/**
|
||||
* A mapped registry which stores Java to Bedrock block identifiers.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, String> JAVA_TO_BEDROCK_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
/**
|
||||
* A mapped registry containing which holds block IDs to its {@link BlockCollision}.
|
||||
*/
|
||||
|
@ -89,6 +84,9 @@ public class BlockRegistries {
|
|||
|
||||
/**
|
||||
* A registry containing all the waterlogged blockstates.
|
||||
* Properties.WATERLOGGED should not be relied on for two reasons:
|
||||
* - Custom blocks
|
||||
* - Seagrass, kelp, and bubble columns are assumed waterlogged and don't have a waterlogged property
|
||||
*/
|
||||
public static final SimpleRegistry<BitSet> WATERLOGGED = SimpleRegistry.create(RegistryLoaders.empty(BitSet::new));
|
||||
|
||||
|
@ -144,7 +142,6 @@ public class BlockRegistries {
|
|||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT);
|
||||
System.out.println("Block registries loaded");
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
|
|
@ -204,6 +204,5 @@ public final class Registries {
|
|||
biomesNbt.put(key, value.build());
|
||||
}
|
||||
BIOMES_NBT.set(biomesNbt.build());
|
||||
System.out.println("Registries loaded");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -236,6 +236,10 @@ public final class BlockRegistryPopulator {
|
|||
GeyserBedrockBlock[] javaToBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
|
||||
GeyserBedrockBlock[] javaToVanillaBedrockBlocks = new GeyserBedrockBlock[JAVA_BLOCKS_SIZE];
|
||||
|
||||
//List<String> javaToBedrockIdentifiers = new ArrayList<>(BlockRegistries.JAVA_BLOCKS.get().size());
|
||||
var javaToBedrockIdentifiers = new Int2ObjectOpenHashMap<String>();
|
||||
Block lastBlockSeen = null;
|
||||
|
||||
// Stream isn't ideal.
|
||||
List<Block> javaPottable = BlockRegistries.JAVA_BLOCKS.get()
|
||||
.parallelStream()
|
||||
|
@ -291,27 +295,35 @@ public final class BlockRegistryPopulator {
|
|||
case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition;
|
||||
}
|
||||
|
||||
if (blockState.block() == Blocks.JIGSAW) {
|
||||
Block block = blockState.block();
|
||||
if (block != lastBlockSeen) {
|
||||
lastBlockSeen = block;
|
||||
String bedrockName = bedrockDefinition.getState().getString("name");
|
||||
if (!block.javaIdentifier().toString().equals(bedrockName)) {
|
||||
javaToBedrockIdentifiers.put(block.javaId(), bedrockName.substring("minecraft:".length()).intern());
|
||||
}
|
||||
}
|
||||
|
||||
if (block == Blocks.JIGSAW) {
|
||||
jigsawDefinitions.add(bedrockDefinition);
|
||||
}
|
||||
|
||||
if (blockState.block() == Blocks.STRUCTURE_BLOCK) {
|
||||
if (block == Blocks.STRUCTURE_BLOCK) {
|
||||
String mode = blockState.getValue(Properties.STRUCTUREBLOCK_MODE);
|
||||
structureBlockDefinitions.put(mode.toUpperCase(Locale.ROOT), bedrockDefinition);
|
||||
}
|
||||
|
||||
boolean waterlogged = blockState.getValue(Properties.WATERLOGGED, false)
|
||||
|| blockState.block() == Blocks.BUBBLE_COLUMN || blockState.block() == Blocks.KELP || blockState.block() == Blocks.SEAGRASS;
|
||||
|| block == Blocks.BUBBLE_COLUMN || block == Blocks.KELP || block == Blocks.SEAGRASS;
|
||||
|
||||
if (waterlogged) {
|
||||
int finalJavaRuntimeId = javaRuntimeId;
|
||||
BlockRegistries.WATERLOGGED.register(set -> set.set(finalJavaRuntimeId));
|
||||
BlockRegistries.WATERLOGGED.get().set(javaRuntimeId);
|
||||
}
|
||||
|
||||
// Get the tag needed for non-empty flower pots
|
||||
if (javaPottable.contains(blockState.block())) {
|
||||
if (javaPottable.contains(block)) {
|
||||
// Specifically NOT putIfAbsent - mangrove propagule breaks otherwise
|
||||
flowerPotBlocks.put(blockState.block(), blockStates.get(bedrockDefinition.getRuntimeId()));
|
||||
flowerPotBlocks.put(block, blockStates.get(bedrockDefinition.getRuntimeId()));
|
||||
}
|
||||
|
||||
javaToVanillaBedrockBlocks[javaRuntimeId] = vanillaBedrockDefinition;
|
||||
|
@ -367,9 +379,12 @@ public final class BlockRegistryPopulator {
|
|||
|
||||
javaToVanillaBedrockBlocks[stateRuntimeId] = bedrockDefinition; // TODO: Check this?
|
||||
javaToBedrockBlocks[stateRuntimeId] = bedrockDefinition;
|
||||
javaToBedrockIdentifiers.put(entry.getKey().stateGroupId(), entry.getValue().block().identifier());
|
||||
}
|
||||
}
|
||||
|
||||
javaToBedrockIdentifiers.trim();
|
||||
|
||||
// Loop around again to find all item frame runtime IDs
|
||||
Object2ObjectMaps.fastForEach(blockStateOrderedMap, entry -> {
|
||||
String name = entry.getKey().getString("name");
|
||||
|
@ -381,6 +396,7 @@ public final class BlockRegistryPopulator {
|
|||
BlockRegistries.BLOCKS.register(palette.valueInt(), builder.bedrockRuntimeMap(bedrockRuntimeMap)
|
||||
.javaToBedrockBlocks(javaToBedrockBlocks)
|
||||
.javaToVanillaBedrockBlocks(javaToVanillaBedrockBlocks)
|
||||
.javaToBedrockIdentifiers(javaToBedrockIdentifiers)
|
||||
.stateDefinitionMap(blockStateOrderedMap)
|
||||
.itemFrames(itemFrames)
|
||||
.flowerPotBlocks(flowerPotBlocks)
|
||||
|
@ -484,15 +500,9 @@ public final class BlockRegistryPopulator {
|
|||
};
|
||||
block.setJavaId(javaBlockState.stateGroupId());
|
||||
|
||||
String bedrockIdentifier = customBlockState.block().identifier();
|
||||
|
||||
BlockRegistries.JAVA_BLOCKS.get().add(javaBlockState.stateGroupId(), block); //TODO don't allow duplicates, allow blanks
|
||||
BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, stateRuntimeId);
|
||||
BlockRegistries.BLOCK_STATES.register(stateRuntimeId, new BlockState(block, stateRuntimeId));
|
||||
|
||||
// Keeping this here since this is currently unchanged between versions
|
||||
// It's possible to only have this store differences in names, but the key set of all Java names is used in sending command suggestions
|
||||
BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.register(cleanJavaIdentifier.intern(), bedrockIdentifier.intern());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,12 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
|||
GeyserBedrockBlock[] javaToBedrockBlocks;
|
||||
GeyserBedrockBlock[] javaToVanillaBedrockBlocks;
|
||||
|
||||
/**
|
||||
* Java block ID -> Bedrock block ID (without minecraft:), IF they are different
|
||||
* While Bedrock is progressing slowly through their flattening, some Bedrock identifiers may differ.
|
||||
*/
|
||||
Int2ObjectMap<String> javaToBedrockIdentifiers;
|
||||
|
||||
Map<NbtMap, GeyserBedrockBlock> stateDefinitionMap;
|
||||
GeyserBedrockBlock[] bedrockRuntimeMap;
|
||||
int[] remappedVanillaIds;
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
|||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.level.block.type.Block;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.CustomSkull;
|
||||
|
@ -52,20 +53,12 @@ import org.geysermc.geyser.text.ChatColor;
|
|||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.Identifier;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.AdventureModePredicate;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemAttributeModifiers;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.*;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public final class ItemTranslator {
|
||||
|
||||
|
@ -185,11 +178,11 @@ public final class ItemTranslator {
|
|||
translateCustomItem(components, builder, bedrockItem);
|
||||
|
||||
if (components != null) {
|
||||
// Translate the canDestroy and canPlaceOn Java NBT
|
||||
// Translate the canDestroy and canPlaceOn Java components
|
||||
AdventureModePredicate canDestroy = components.get(DataComponentType.CAN_BREAK);
|
||||
AdventureModePredicate canPlaceOn = components.get(DataComponentType.CAN_PLACE_ON);
|
||||
String[] canBreak = getCanModify(canDestroy);
|
||||
String[] canPlace = getCanModify(canPlaceOn);
|
||||
String[] canBreak = getCanModify(session, canDestroy);
|
||||
String[] canPlace = getCanModify(session, canPlaceOn);
|
||||
if (canBreak != null) {
|
||||
builder.canBreak(canBreak);
|
||||
}
|
||||
|
@ -325,27 +318,42 @@ public final class ItemTranslator {
|
|||
* @param canModifyJava the list of items in Java
|
||||
* @return the new list of items in Bedrock
|
||||
*/
|
||||
// TODO this is now more complicated in 1.20.5. Yippee!
|
||||
private static String @Nullable [] getCanModify(@Nullable AdventureModePredicate canModifyJava) {
|
||||
// TODO blocks by tag, maybe NBT, maybe properties
|
||||
// Blocks by tag will be easy enough, most likely, we just need to... save all block tags.
|
||||
// Probably do that with Guava interning around sessions
|
||||
private static String @Nullable [] getCanModify(GeyserSession session, @Nullable AdventureModePredicate canModifyJava) {
|
||||
if (canModifyJava == null) {
|
||||
return null;
|
||||
}
|
||||
List<AdventureModePredicate.BlockPredicate> predicates = canModifyJava.getPredicates();
|
||||
if (predicates.size() > 0) {
|
||||
String[] canModifyBedrock = new String[predicates.size()];
|
||||
for (int i = 0; i < canModifyBedrock.length; i++) {
|
||||
// Get the Java identifier of the block that can be placed
|
||||
String location = predicates.get(i).getLocation();
|
||||
if (location == null) {
|
||||
canModifyBedrock[i] = ""; // So it'll serialize
|
||||
continue; // ???
|
||||
if (!predicates.isEmpty()) {
|
||||
List<String> canModifyBedrock = new ArrayList<>(); // This used to be an array, but we need to be flexible with what blocks can be supported
|
||||
for (int i = 0; i < predicates.size(); i++) {
|
||||
HolderSet holderSet = predicates.get(i).getBlocks();
|
||||
if (holderSet == null) {
|
||||
continue;
|
||||
}
|
||||
int[] holders = holderSet.getHolders();
|
||||
if (holders == null) {
|
||||
continue;
|
||||
}
|
||||
// Holders is an int state of Java block IDs (not block states)
|
||||
for (int blockId : holders) {
|
||||
// Get the Bedrock identifier of the item
|
||||
// This will unfortunately be limited - for example, beds and banners will be translated weirdly
|
||||
Block block = BlockRegistries.JAVA_BLOCKS.get(blockId);
|
||||
if (block == null) {
|
||||
continue;
|
||||
}
|
||||
String identifier = session.getBlockMappings().getJavaToBedrockIdentifiers().get(block.javaId());
|
||||
if (identifier == null) {
|
||||
canModifyBedrock.add(block.javaIdentifier().value());
|
||||
} else {
|
||||
canModifyBedrock.add(identifier);
|
||||
}
|
||||
}
|
||||
String block = Identifier.formalize(location);
|
||||
// Get the Bedrock identifier of the item and replace it.
|
||||
// This will unfortunately be limited - for example, beds and banners will be translated weirdly
|
||||
canModifyBedrock[i] = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.getOrDefault(block, block).replace("minecraft:", "");
|
||||
}
|
||||
return canModifyBedrock;
|
||||
return canModifyBedrock.toArray(new String[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ import java.util.*;
|
|||
@Translator(packet = ClientboundCommandsPacket.class)
|
||||
public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommandsPacket> {
|
||||
|
||||
private static final String[] ALL_BLOCK_NAMES = BlockRegistries.JAVA_BLOCKS.get().stream().map(block -> block.javaIdentifier().toString()).toArray(String[]::new);
|
||||
private static final String[] ALL_EFFECT_IDENTIFIERS = EntityUtils.getAllEffectIdentifiers();
|
||||
private static final String[] ATTRIBUTES = AttributeType.Builtin.BUILTIN.values().stream().map(AttributeType::getIdentifier).toList().toArray(new String[0]);
|
||||
private static final String[] ENUM_BOOLEAN = {"true", "false"};
|
||||
|
@ -246,7 +247,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
case RESOURCE_LOCATION, FUNCTION -> CommandParam.FILE_PATH;
|
||||
case BOOL -> ENUM_BOOLEAN;
|
||||
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
|
||||
case BLOCK_STATE -> context.getBlockStates();
|
||||
case BLOCK_STATE -> ALL_BLOCK_NAMES;
|
||||
case ITEM_STACK -> context.getItemNames();
|
||||
case COLOR -> VALID_COLORS;
|
||||
case SCOREBOARD_SLOT -> VALID_SCOREBOARD_SLOTS;
|
||||
|
@ -286,7 +287,6 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
private final GeyserSession session;
|
||||
private Object biomesWithTags;
|
||||
private Object biomesNoTags;
|
||||
private String[] blockStates;
|
||||
private String[] entityTypes;
|
||||
private String[] itemNames;
|
||||
private CommandEnumData teams;
|
||||
|
@ -313,13 +313,6 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
|||
return (biomesWithTags = identifiers != null ? identifiers : CommandParam.STRING);
|
||||
}
|
||||
|
||||
private String[] getBlockStates() {
|
||||
if (blockStates != null) {
|
||||
return blockStates;
|
||||
}
|
||||
return (blockStates = BlockRegistries.JAVA_TO_BEDROCK_IDENTIFIERS.get().keySet().toArray(new String[0]));
|
||||
}
|
||||
|
||||
private String[] getEntityTypes() {
|
||||
if (entityTypes != null) {
|
||||
return entityTypes;
|
||||
|
|
|
@ -15,7 +15,7 @@ protocol-connection = "3.0.0.Beta1-20240411.165033-128"
|
|||
raknet = "1.0.0.CR3-20240416.144209-1"
|
||||
blockstateupdater="1.20.80-20240411.142413-1"
|
||||
mcauthlib = "e5b0bcc"
|
||||
mcprotocollib = "1.20.6-2-20240515.051848-2" # Revert from jitpack after release
|
||||
mcprotocollib = "1.20.6-2-20240520.030045-8"
|
||||
adventure = "4.14.0"
|
||||
adventure-platform = "4.3.0"
|
||||
junit = "5.9.2"
|
||||
|
|
Loading…
Reference in a new issue