Small optimizations and BlockStateValues reduction

This commit is contained in:
Camotoy 2024-05-20 21:26:01 -04:00
parent f489fd3b98
commit db166ad8de
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
12 changed files with 97 additions and 65 deletions

View file

@ -41,6 +41,7 @@ import org.bukkit.event.block.BlockPistonRetractEvent;
import org.cloudburstmc.math.vector.Vector3i;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.platform.spigot.world.manager.GeyserSpigotWorldManager;
@ -120,7 +121,7 @@ public class GeyserPistonListener implements Listener {
int pistonBlockId = worldManager.getBlockNetworkId(event.getBlock());
// event.getDirection() is unreliable
Direction orientation = BlockStateValues.getPistonOrientation(pistonBlockId);
Direction orientation = BlockState.of(pistonBlockId).getValue(Properties.FACING);
session.executeInEventLoop(() -> {
PistonCache pistonCache = session.getPistonCache();

View file

@ -42,7 +42,6 @@ import org.geysermc.erosion.bukkit.SchedulerUtils;
import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.GameRule;
import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.util.BlockEntityUtils;
@ -88,7 +87,7 @@ public class GeyserSpigotWorldManager extends WorldManager {
Bukkit.getRegionScheduler().execute(this.plugin, block.getLocation(), () -> blockData.complete(block.getBlockData().getAsString()));
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(blockData.join(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
}
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID);
return BlockRegistries.JAVA_IDENTIFIER_TO_ID.getOrDefault(block.getBlockData().getAsString(), org.geysermc.geyser.level.block.type.Block.JAVA_AIR_ID); // TODO could just make this a BlockState lookup?
}
@Override

View file

@ -44,6 +44,7 @@ import org.geysermc.erosion.packet.backendbound.BackendboundInitializePacket;
import org.geysermc.erosion.packet.backendbound.BackendboundPacket;
import org.geysermc.erosion.packet.geyserbound.*;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.Direction;
@ -148,7 +149,7 @@ public final class GeyserboundPacketHandlerImpl extends AbstractGeyserboundPacke
@Override
public void handlePistonEvent(GeyserboundPistonEventPacket packet) {
Direction orientation = BlockStateValues.getPistonOrientation(packet.getBlockId());
Direction orientation = BlockState.of(packet.getBlockId()).getValue(Properties.FACING);
Vector3i position = packet.getPos();
boolean isExtend = packet.isExtend();

View file

@ -25,7 +25,10 @@
package org.geysermc.geyser.level.block;
import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.geysermc.geyser.level.block.property.Properties;
@ -36,16 +39,11 @@ import org.geysermc.geyser.level.physics.Direction;
import org.geysermc.geyser.level.physics.PistonBehavior;
import org.geysermc.geyser.registry.BlockRegistries;
import java.util.Locale;
/**
* Used for block entities if the Java block state contains Bedrock block information.
*/
public final class BlockStateValues {
private static final IntSet HORIZONTAL_FACING_JIGSAWS = new IntOpenHashSet();
private static final IntSet STICKY_PISTONS = new IntOpenHashSet();
private static final Object2IntMap<Direction> PISTON_HEADS = new Object2IntOpenHashMap<>();
private static final Int2ObjectMap<Direction> PISTON_ORIENTATION = new Int2ObjectOpenHashMap<>();
private static final IntSet ALL_PISTON_HEADS = new IntOpenHashSet();
private static final Int2IntMap WATER_LEVEL = new Int2IntOpenHashMap();
@ -61,10 +59,6 @@ public final class BlockStateValues {
*/
public static void storeBlockStateValues(String javaId, int javaBlockState) {
if (javaId.contains("piston[")) { // minecraft:moving_piston, minecraft:sticky_piston, minecraft:piston
if (javaId.contains("sticky")) {
STICKY_PISTONS.add(javaBlockState);
}
PISTON_ORIENTATION.put(javaBlockState, getBlockDirection(javaId));
return;
} else if (javaId.startsWith("minecraft:piston_head")) {
ALL_PISTON_HEADS.add(javaBlockState);
@ -78,27 +72,7 @@ public final class BlockStateValues {
String strLevel = javaId.substring(javaId.lastIndexOf("level=") + 6, javaId.length() - 1);
int level = Integer.parseInt(strLevel);
WATER_LEVEL.put(javaBlockState, level);
return;
}
if (javaId.startsWith("minecraft:jigsaw[orientation=")) {
String blockStateData = javaId.substring(javaId.indexOf("orientation=") + "orientation=".length(), javaId.lastIndexOf('_'));
Direction direction = Direction.valueOf(blockStateData.toUpperCase(Locale.ROOT));
if (direction.isHorizontal()) {
HORIZONTAL_FACING_JIGSAWS.add(javaBlockState);
}
}
}
/**
* @return a set of all forward-facing jigsaws, to use as a fallback if NBT is missing.
*/
public static IntSet getHorizontalFacingJigsaws() {
return HORIZONTAL_FACING_JIGSAWS;
}
public static boolean isStickyPiston(int blockState) {
return STICKY_PISTONS.contains(blockState);
}
public static boolean isPistonHead(int state) {
@ -116,17 +90,6 @@ public final class BlockStateValues {
return PISTON_HEADS.getOrDefault(direction, Block.JAVA_AIR_ID);
}
/**
* This is used in GeyserPistonEvents.java and accepts minecraft:piston,
* minecraft:sticky_piston, and minecraft:moving_piston.
*
* @param state The block state of the piston base
* @return The direction in which the piston faces
*/
public static Direction getPistonOrientation(int state) {
return PISTON_ORIENTATION.get(state);
}
/**
* Checks if a block sticks to other blocks
* (Slime and honey blocks)

View file

@ -27,6 +27,7 @@ package org.geysermc.geyser.level.block;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.level.block.property.ChestType;
import org.geysermc.geyser.level.block.property.FrontAndTop;
import org.geysermc.geyser.level.block.type.*;
import org.geysermc.geyser.level.physics.Axis;
import org.geysermc.geyser.level.physics.Direction;
@ -2169,7 +2170,7 @@ public final class Blocks {
public static final Block STRUCTURE_BLOCK = register(new Block("structure_block", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
.enumState(STRUCTUREBLOCK_MODE, "save", "load", "corner", "data")));
public static final Block JIGSAW = register(new Block("jigsaw", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(-1.0f)
.enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up")));
.enumState(ORIENTATION, FrontAndTop.VALUES)));
public static final Block COMPOSTER = register(new Block("composter", builder().destroyTime(0.6f)
.intState(LEVEL_COMPOSTER, 0, 8)));
public static final Block TARGET = register(new Block("target", builder().destroyTime(0.5f)
@ -2799,7 +2800,7 @@ public final class Blocks {
.booleanState(WATERLOGGED)));
public static final Block CRAFTER = register(new Block("crafter", builder().setBlockEntity().destroyTime(1.5f)
.booleanState(CRAFTING)
.enumState(ORIENTATION, "down_east", "down_north", "down_south", "down_west", "up_east", "up_north", "up_south", "up_west", "west_up", "east_up", "north_up", "south_up")
.enumState(ORIENTATION, FrontAndTop.VALUES)
.booleanState(TRIGGERED)));
public static final Block TRIAL_SPAWNER = register(new Block("trial_spawner", builder().setBlockEntity().requiresCorrectToolForDrops().destroyTime(50.0f)
.booleanState(OMINOUS)

View file

@ -0,0 +1,55 @@
/*
* Copyright (c) 2024 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.level.block.property;
import org.geysermc.geyser.level.physics.Direction;
public enum FrontAndTop {
DOWN_EAST(Direction.DOWN),
DOWN_NORTH(Direction.DOWN),
DOWN_SOUTH(Direction.DOWN),
DOWN_WEST(Direction.DOWN),
UP_EAST(Direction.UP),
UP_NORTH(Direction.UP),
UP_SOUTH(Direction.UP),
UP_WEST(Direction.UP),
WEST_UP(Direction.WEST),
EAST_UP(Direction.EAST),
NORTH_UP(Direction.NORTH),
SOUTH_UP(Direction.SOUTH);
private final boolean horizontal;
FrontAndTop(Direction front) {
this.horizontal = front.isHorizontal();
}
public boolean isHorizontal() {
return horizontal;
}
public static final FrontAndTop[] VALUES = values();
}

View file

@ -74,7 +74,7 @@ public final class Properties {
public static final Property<Direction> FACING_HOPPER = Property.create("facing");
public static final Property<Direction> HORIZONTAL_FACING = Property.create("facing");
public static final Property<Integer> FLOWER_AMOUNT = Property.create("flower_amount");
public static final Property<String> ORIENTATION = Property.create("orientation");
public static final Property<FrontAndTop> ORIENTATION = Property.create("orientation");
public static final Property<String> ATTACH_FACE = Property.create("face");
public static final Property<String> BELL_ATTACHMENT = Property.create("attachment");
public static final Property<String> EAST_WALL = Property.create("east");

View file

@ -28,10 +28,13 @@ package org.geysermc.geyser.registry;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.geyser.registry.loader.RegistryLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class ListRegistry<M> extends Registry<List<M>> {
private boolean frozen = false;
/**
* Creates a new instance of this class with the given input and
* {@link RegistryLoader}. The input specified is what the registry
@ -85,9 +88,24 @@ public class ListRegistry<M> extends Registry<List<M>> {
* @return a new value into this registry with the given index.
*/
public M register(int index, M value) {
if (this.frozen) {
throw new IllegalStateException("Registry should not be modified after frozen!");
}
return this.mappings.set(index, value);
}
/**
* Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
*/
public void freeze() {
if (!this.frozen) {
this.frozen = true;
if (this.mappings instanceof ArrayList<M> arrayList) {
arrayList.trimToSize();
}
}
}
/**
* Creates a new array registry with the given {@link RegistryLoader}. The
* input type is not specified here, meaning the loader return type is either

View file

@ -77,7 +77,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
}
List<BlockState> blockStates = BlockRegistries.BLOCK_STATES.get();
List<BlockCollision> collisions = new ObjectArrayList<>(blockStates.size());
var collisions = new ObjectArrayList<BlockCollision>(blockStates.size());
// Map of unique collisions to its instance
Map<BlockCollision, BlockCollision> collisionInstances = new Object2ObjectOpenHashMap<>();
@ -102,6 +102,7 @@ public class CollisionRegistryLoader extends MultiResourceRegistryLoader<String,
collisions.add(newCollision);
}
collisions.trim();
return collisions;
}

View file

@ -440,15 +440,8 @@ public final class BlockRegistryPopulator {
BlockStateValues.storeBlockStateValues(javaId, javaRuntimeId);
//String cleanJavaIdentifier = javaBlockState.block().javaIdentifier().toString();
//String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
BlockRegistries.JAVA_IDENTIFIER_TO_ID.register(javaId, javaRuntimeId);
// 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());
if ("minecraft:water[level=0]".equals(javaId)) {
waterRuntimeId = javaRuntimeId;
}
@ -467,8 +460,6 @@ public final class BlockRegistryPopulator {
throw new RuntimeException("Duplicate runtime ID " + javaBlockState.javaId() + " for non vanilla Java block state " + javaBlockState.identifier());
}
CustomBlockState customBlockState = BlockRegistries.NON_VANILLA_BLOCK_STATE_OVERRIDES.get().get(javaBlockState);
String javaId = javaBlockState.identifier();
int stateRuntimeId = javaBlockState.javaId();
String pistonBehavior = javaBlockState.pistonBehavior();
@ -517,6 +508,8 @@ public final class BlockRegistryPopulator {
BlockRegistries.INTERACTIVE.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("always_consumes")));
BlockRegistries.INTERACTIVE_MAY_BUILD.set(toBlockStateSet((ArrayNode) blockInteractionsJson.get("requires_may_build")));
BlockRegistries.BLOCK_STATES.freeze();
}
private static BitSet toBlockStateSet(ArrayNode node) {

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType;
@ -47,7 +47,7 @@ public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator impl
} else {
// Tag is not present in at least 1.14.4 Paper
// Minecraft 1.18.1 deliberately has a fallback here, but not for any other value
bedrockNbt.putString("joint", BlockStateValues.getHorizontalFacingJigsaws().contains(blockState.javaId()) ? "aligned" : "rollable"); // TODO
bedrockNbt.putString("joint", blockState.getValue(Properties.ORIENTATION).isHorizontal() ? "aligned" : "rollable");
}
bedrockNbt.putString("name", javaNbt.getString("name"));
bedrockNbt.putString("target_pool", javaNbt.getString("target_pool"));

View file

@ -31,7 +31,7 @@ import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.BlockEventPacket;
import org.geysermc.geyser.api.util.PlatformType;
import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.level.block.property.Properties;
import org.geysermc.geyser.level.block.type.Block;
import org.geysermc.geyser.level.block.type.BlockState;
@ -78,8 +78,8 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
// Retracting sticky pistons is an exception, since the event is not called on Spigot from 1.13.2 - 1.17.1
// See https://github.com/PaperMC/Paper/blob/6fa1983e9ce177a4a412d5b950fd978620174777/patches/server/0304-Fire-BlockPistonRetractEvent-for-all-empty-pistons.patch
if (action == PistonValueType.PULLING || action == PistonValueType.CANCELLED_MID_PUSH) {
int pistonBlock = session.getGeyser().getWorldManager().getBlockAt(session, position);
if (!BlockStateValues.isStickyPiston(pistonBlock)) {
BlockState pistonBlock = session.getGeyser().getWorldManager().blockAt(session, position);
if (!pistonBlock.is(Blocks.STICKY_PISTON)) {
return;
}
if (action != PistonValueType.CANCELLED_MID_PUSH) {
@ -97,8 +97,8 @@ public class JavaBlockEventTranslator extends PacketTranslator<ClientboundBlockE
}
} else {
PistonBlockEntity blockEntity = pistonCache.getPistons().computeIfAbsent(position, pos -> {
int blockId = session.getGeyser().getWorldManager().getBlockAt(session, position);
boolean sticky = BlockStateValues.isStickyPiston(blockId);
BlockState state = session.getGeyser().getWorldManager().blockAt(session, position);
boolean sticky = state.is(Blocks.STICKY_PISTON);
boolean extended = action != PistonValueType.PUSHING;
return new PistonBlockEntity(session, pos, direction, sticky, extended);
});