3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-10-02 08:00:07 +02:00

Initial framework for extended collision boxes

Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
Dieser Commit ist enthalten in:
Joshua Castle 2023-03-06 22:24:53 -08:00
Ursprung f1bd04a71d
Commit 4002c1df8d
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: F674F38216C35D5D
5 geänderte Dateien mit 58 neuen und 5 gelöschten Zeilen

Datei anzeigen

@ -51,6 +51,13 @@ public interface CustomBlockComponents {
*/ */
BoxComponent collisionBox(); BoxComponent collisionBox();
/**
* Gets the extended collision box
* Places an invisible collision block above the block to prevent players from jumping on top of it, if defined
* @return The extended collision box.
*/
BoxComponent extendedCollisionBox();
/** /**
* Gets the display name component * Gets the display name component
* Equivalent to "minecraft:display_name" * Equivalent to "minecraft:display_name"
@ -153,6 +160,8 @@ public interface CustomBlockComponents {
Builder collisionBox(BoxComponent collisionBox); Builder collisionBox(BoxComponent collisionBox);
Builder extendedCollisionBox(BoxComponent extendedCollisionBox);
Builder displayName(String displayName); Builder displayName(String displayName);
Builder geometry(String geometry); Builder geometry(String geometry);

Datei anzeigen

@ -47,6 +47,7 @@ import java.util.Set;
public class GeyserCustomBlockComponents implements CustomBlockComponents { public class GeyserCustomBlockComponents implements CustomBlockComponents {
BoxComponent selectionBox; BoxComponent selectionBox;
BoxComponent collisionBox; BoxComponent collisionBox;
BoxComponent extendedCollisionBox;
String displayName; String displayName;
String geometry; String geometry;
Map<String, MaterialInstance> materialInstances; Map<String, MaterialInstance> materialInstances;
@ -63,6 +64,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) { private GeyserCustomBlockComponents(CustomBlockComponentsBuilder builder) {
this.selectionBox = builder.selectionBox; this.selectionBox = builder.selectionBox;
this.collisionBox = builder.collisionBox; this.collisionBox = builder.collisionBox;
this.extendedCollisionBox = builder.extendedCollisionBox;
this.displayName = builder.displayName; this.displayName = builder.displayName;
this.geometry = builder.geometry; this.geometry = builder.geometry;
if (builder.materialInstances.isEmpty()) { if (builder.materialInstances.isEmpty()) {
@ -95,6 +97,11 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
return collisionBox; return collisionBox;
} }
@Override
public BoxComponent extendedCollisionBox() {
return extendedCollisionBox;
}
@Override @Override
public String displayName() { public String displayName() {
return displayName; return displayName;
@ -158,6 +165,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
public static class CustomBlockComponentsBuilder implements Builder { public static class CustomBlockComponentsBuilder implements Builder {
protected BoxComponent selectionBox; protected BoxComponent selectionBox;
protected BoxComponent collisionBox; protected BoxComponent collisionBox;
protected BoxComponent extendedCollisionBox;
protected String displayName; protected String displayName;
protected String geometry; protected String geometry;
protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>(); protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>();
@ -203,6 +211,13 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
return this; return this;
} }
@Override
public Builder extendedCollisionBox(BoxComponent extendedCollisionBox) {
validateBox(extendedCollisionBox);
this.extendedCollisionBox = extendedCollisionBox;
return this;
}
@Override @Override
public Builder displayName(String displayName) { public Builder displayName(String displayName) {
this.displayName = displayName; this.displayName = displayName;

Datei anzeigen

@ -33,6 +33,7 @@ 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.api.block.custom.CustomBlockState;
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
import org.geysermc.geyser.registry.loader.CollisionRegistryLoader; import org.geysermc.geyser.registry.loader.CollisionRegistryLoader;
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;
@ -111,6 +112,11 @@ public class BlockRegistries {
*/ */
public static final SimpleMappedRegistry<String, CustomBlockData> CUSTOM_BLOCK_ITEM_OVERRIDES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<String, CustomBlockData> CUSTOM_BLOCK_ITEM_OVERRIDES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
/**
* A registry which stores Java Ids and the extended collision box that should be placed above.
*/
public static final SimpleMappedRegistry<Integer, BoxComponent> CUSTOM_BLOCK_EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::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

@ -294,10 +294,12 @@ public class MappingsReader_v1 extends MappingsReader {
private CustomBlockComponents createCustomBlockComponents(JsonNode node, String stateKey, String name) { private CustomBlockComponents createCustomBlockComponents(JsonNode node, String stateKey, String name) {
// This is needed to find the correct selection box for the given block // This is needed to find the correct selection box for the given block
int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(stateKey, -1); int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(stateKey, -1);
BoxComponent boxComponent = createBoxComponent(id); BoxComponent boxComponent = createBoxComponent(id, 0, 16, 0);
BoxComponent extendedboxComponent = createBoxComponent(id, 16, 32, -16);
CustomBlockComponents.Builder builder = new CustomBlockComponentsBuilder() CustomBlockComponents.Builder builder = new CustomBlockComponentsBuilder()
.collisionBox(boxComponent) .collisionBox(boxComponent)
.selectionBox(boxComponent); .selectionBox(boxComponent)
.extendedCollisionBox(extendedboxComponent);
if (node == null) { if (node == null) {
// No other components were defined // No other components were defined
@ -312,6 +314,11 @@ public class MappingsReader_v1 extends MappingsReader {
if (collisionBox != null) { if (collisionBox != null) {
builder.collisionBox(collisionBox); builder.collisionBox(collisionBox);
} }
BoxComponent extendedCollisionBox = createBoxComponent(node.get("extended_collision_box"));
if (extendedCollisionBox != null) {
builder.extendedCollisionBox(extendedCollisionBox);
}
// We set this to max value by default so that we may dictate the correct destroy time ourselves // We set this to max value by default so that we may dictate the correct destroy time ourselves
float destructibleByMining = Float.MAX_VALUE; float destructibleByMining = Float.MAX_VALUE;
@ -404,9 +411,12 @@ public class MappingsReader_v1 extends MappingsReader {
/** /**
* Creates a {@link BoxComponent} based on a Java block's collision * Creates a {@link BoxComponent} based on a Java block's collision
* @param javaId the block's Java ID * @param javaId the block's Java ID
* @param minHeight the minimum height of the box
* @param maxHeight the maximum height of the box
* @param heightTranslation the height translation of the box
* @return the {@link BoxComponent} * @return the {@link BoxComponent}
*/ */
private BoxComponent createBoxComponent(int javaId) { private BoxComponent createBoxComponent(int javaId, float minHeight, float maxHeight, float heightTranslation) {
// Some blocks (e.g. plants) have no collision box // Some blocks (e.g. plants) have no collision box
BlockCollision blockCollision = BlockUtils.getCollision(javaId); BlockCollision blockCollision = BlockUtils.getCollision(javaId);
if (blockCollision == null) { if (blockCollision == null) {
@ -425,11 +435,11 @@ public class MappingsReader_v1 extends MappingsReader {
// These could be placed above the block when a custom block exceeds this limit // These could be placed above the block when a custom block exceeds this limit
// I am hopeful this will be extended slightly since the geometry of blocks can be 1.875^3 // I am hopeful this will be extended slightly since the geometry of blocks can be 1.875^3
float cornerX = MathUtils.clamp((float) boundingBox.getMiddleX() * 16 - 8 - offsetX, -8, 8); float cornerX = MathUtils.clamp((float) boundingBox.getMiddleX() * 16 - 8 - offsetX, -8, 8);
float cornerY = MathUtils.clamp((float) boundingBox.getMiddleY() * 16 - offsetY, 0, 16); float cornerY = MathUtils.clamp((float) boundingBox.getMiddleY() * 16 - offsetY + heightTranslation, minHeight, maxHeight);
float cornerZ = MathUtils.clamp((float) boundingBox.getMiddleZ() * 16 - 8 - offsetZ, -8, 8); float cornerZ = MathUtils.clamp((float) boundingBox.getMiddleZ() * 16 - 8 - offsetZ, -8, 8);
float sizeX = MathUtils.clamp((float) boundingBox.getSizeX() * 16, 0, 16); float sizeX = MathUtils.clamp((float) boundingBox.getSizeX() * 16, 0, 16);
float sizeY = MathUtils.clamp((float) boundingBox.getSizeY() * 16, 0, 16); float sizeY = MathUtils.clamp((float) boundingBox.getSizeY() * 16 + heightTranslation, minHeight, maxHeight);
float sizeZ = MathUtils.clamp((float) boundingBox.getSizeZ() * 16, 0, 16); float sizeZ = MathUtils.clamp((float) boundingBox.getSizeZ() * 16, 0, 16);
return new BoxComponent(cornerX, cornerY, cornerZ, sizeX, sizeY, sizeZ); return new BoxComponent(cornerX, cornerY, cornerZ, sizeX, sizeY, sizeZ);

Datei anzeigen

@ -44,6 +44,8 @@ public class CustomBlockRegistryPopulator {
Set<CustomBlockData> customBlocks = new ObjectOpenHashSet<>(); Set<CustomBlockData> customBlocks = new ObjectOpenHashSet<>();
Int2ObjectMap<CustomBlockState> blockStateOverrides = new Int2ObjectOpenHashMap<>(); Int2ObjectMap<CustomBlockState> blockStateOverrides = new Int2ObjectOpenHashMap<>();
Map<String, CustomBlockData> customBlockItemOverrides = new HashMap<>(); Map<String, CustomBlockData> customBlockItemOverrides = new HashMap<>();
Map<Integer, BoxComponent> extendedCollisionBoxes = new HashMap<>();
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) {
@ -69,6 +71,10 @@ public class CustomBlockRegistryPopulator {
throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name()); throw new IllegalArgumentException("Custom block is unregistered. Name: " + customBlockState.name());
} }
CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState); CustomBlockState oldBlockState = blockStateOverrides.put(id, customBlockState);
BoxComponent extendedCollisionBox = customBlockState.block().components().extendedCollisionBox();
if (extendedCollisionBox != null) {
extendedCollisionBoxes.put(id, extendedCollisionBox);
}
if (oldBlockState != null) { if (oldBlockState != null) {
GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " + GeyserImpl.getInstance().getLogger().debug("Duplicate block state override for Java Identifier: " +
javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name()); javaIdentifier + " Old override: " + oldBlockState.name() + " New override: " + customBlockState.name());
@ -97,6 +103,10 @@ public class CustomBlockRegistryPopulator {
block.states().forEach((javaIdentifier, customBlockState) -> { block.states().forEach((javaIdentifier, customBlockState) -> {
int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(javaIdentifier, -1); int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(javaIdentifier, -1);
blockStateOverrides.put(id, customBlockState); blockStateOverrides.put(id, customBlockState);
BoxComponent extendedCollisionBox = customBlockState.block().components().extendedCollisionBox();
if (extendedCollisionBox != null) {
extendedCollisionBoxes.put(id, extendedCollisionBox);
}
}); });
}); });
@ -108,6 +118,9 @@ public class CustomBlockRegistryPopulator {
BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides); BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides);
GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides."); GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides.");
BlockRegistries.CUSTOM_BLOCK_EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes);
GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes.");
} }
/** /**