Address @davchoo's review

Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
This commit is contained in:
Joshua Castle 2023-01-29 13:44:05 -08:00
parent d71d9c142b
commit 57c90da15b
No known key found for this signature in database
GPG key ID: F674F38216C35D5D
9 changed files with 91 additions and 96 deletions

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.api.block.custom.component;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.block.custom.component.placementfilter.PlacementFilter;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -78,11 +78,11 @@ public interface CustomBlockComponents {
/**
* Gets the placement filter component
* Equivalent to "minecraft:material_instances"
* Equivalent to "minecraft:placement_filter"
*
* @return The placement filter.
*/
PlacementFilter placementFilter();
List<PlacementConditions> placementFilter();
/**
* Gets the destructible by mining component
@ -159,7 +159,7 @@ public interface CustomBlockComponents {
Builder materialInstance(@NonNull String name, @NonNull MaterialInstance materialInstance);
Builder placementFilter(PlacementFilter placementFilter);
Builder placementFilter(List<PlacementConditions> placementConditions);
Builder destructibleByMining(Float destructibleByMining);

View file

@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.geyser.api.block.custom.component.placementfilter;
package org.geysermc.geyser.api.block.custom.component;
import java.util.LinkedHashMap;
import java.util.Set;
@ -33,7 +33,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
/*
* This class is used to store conditions for a placement filter for a custom block.
*/
public record Conditions(@NonNull Set<Face> allowedFaces, @NonNull LinkedHashMap<String, BlockFilterType> blockFilters) {
public record PlacementConditions(@NonNull Set<Face> allowedFaces, @NonNull LinkedHashMap<String, BlockFilterType> blockFilters) {
public enum Face {
DOWN(1),
UP(2),
@ -42,14 +42,8 @@ public record Conditions(@NonNull Set<Face> allowedFaces, @NonNull LinkedHashMap
WEST(16),
EAST(32);
private final byte value;
Face(int value) {
this.value = (byte) value;
}
public byte getValue() {
return value;
value = (byte) value;
}
}
public enum BlockFilterType {

View file

@ -1,36 +0,0 @@
/*
* Copyright (c) 2019-2022 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.api.block.custom.component.placementfilter;
import java.util.List;
import org.checkerframework.checker.nullness.qual.NonNull;
/*
* This class is used to store a placement filter for a custom block.
*/
public record PlacementFilter(@NonNull List<Conditions> conditions) {
}

View file

@ -35,7 +35,7 @@ public class PropertyType {
private final Class<?> typeClass;
public Class<?> getTypeClass() {
public Class<?> typeClass() {
return typeClass;
}

View file

@ -1,6 +1,6 @@
package org.geysermc.geyser.api.event.lifecycle;
import lombok.NonNull;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.event.Event;
/**

View file

@ -43,7 +43,7 @@ public final class Constants {
public static final String GEYSER_NAMESPACE = "geyser_custom";
public static final String MINECRAFT_SKIN_SERVER_URL = "http://textures.minecraft.net/texture/";
public static final String MINECRAFT_SKIN_SERVER_URL = "https://textures.minecraft.net/texture/";
static {
URI wsUri = null;

View file

@ -34,11 +34,12 @@ import org.checkerframework.checker.nullness.qual.NonNull;
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.component.PlacementConditions;
import org.geysermc.geyser.api.block.custom.component.RotationComponent;
import org.geysermc.geyser.api.block.custom.component.placementfilter.PlacementFilter;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -49,7 +50,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
String displayName;
String geometry;
Map<String, MaterialInstance> materialInstances;
PlacementFilter placementFilter;
List<PlacementConditions> placementFilter;
Float destructibleByMining;
Float friction;
Integer lightEmission;
@ -110,7 +111,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
}
@Override
public PlacementFilter placementFilter() {
public List<PlacementConditions> placementFilter() {
return placementFilter;
}
@ -160,7 +161,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
protected String displayName;
protected String geometry;
protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>();
protected PlacementFilter placementFilter;
protected List<PlacementConditions> placementFilter;
protected Float destructibleByMining;
protected Float friction;
protected Integer lightEmission;
@ -221,7 +222,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
}
@Override
public Builder placementFilter(PlacementFilter placementFilter) {
public Builder placementFilter(List<PlacementConditions> placementFilter) {
this.placementFilter = placementFilter;
return this;
}

View file

@ -35,13 +35,12 @@ 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.PlacementConditions;
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.component.RotationComponent;
import org.geysermc.geyser.api.block.custom.component.placementfilter.Conditions;
import org.geysermc.geyser.api.block.custom.component.placementfilter.PlacementFilter;
import org.geysermc.geyser.api.block.custom.component.placementfilter.Conditions.BlockFilterType;
import org.geysermc.geyser.api.block.custom.component.placementfilter.Conditions.Face;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions.BlockFilterType;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face;
import org.geysermc.geyser.api.item.custom.CustomItemData;
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException;
@ -53,7 +52,9 @@ import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.mappings.util.BlockPropertyTypeMaps;
import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping;
import org.geysermc.geyser.registry.type.BlockMapping;
import org.geysermc.geyser.translator.collision.BlockCollision;
import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.MathUtils;
import java.nio.file.Path;
import java.util.ArrayList;
@ -419,10 +420,50 @@ public class MappingsReader_v1 extends MappingsReader {
private CustomBlockComponents createCustomBlockComponents(JsonNode node, String stateKey, String name) {
// This is needed to find the correct selection box for the given block
int id = BlockRegistries.JAVA_IDENTIFIERS.getOrDefault(stateKey, -1);
CustomBlockComponentsBuilder builder = new CustomBlockComponentsBuilder();
BoxComponent boxComponent = createBoxComponent(id);
builder.selectionBox(boxComponent).collisionBox(boxComponent);
BoxComponent selectionBox = boxComponent;
if (node.has("selection_box")) {
JsonNode selectionBoxNode = node.get("selection_box");
if (selectionBoxNode.isObject()) {
if (selectionBoxNode.has("origin") && selectionBoxNode.has("size")) {
JsonNode origin = selectionBoxNode.get("origin");
int originX = origin.get(0).intValue();
int originY = origin.get(1).intValue();
int originZ = origin.get(2).intValue();
JsonNode size = selectionBoxNode.get("size");
int sizeX = size.get(0).intValue();
int sizeY = size.get(1).intValue();
int sizeZ = size.get(2).intValue();
selectionBox = new BoxComponent(originX, originY, originZ, sizeX, sizeY, sizeZ);
}
}
}
builder.selectionBox(selectionBox);
BoxComponent collisionBox = boxComponent;
if (node.has("collision_box")) {
JsonNode collisionBoxNode = node.get("collision_box");
if (collisionBoxNode.isObject()) {
if (collisionBoxNode.has("origin") && collisionBoxNode.has("size")) {
JsonNode origin = collisionBoxNode.get("origin");
int originX = origin.get(0).intValue();
int originY = origin.get(1).intValue();
int originZ = origin.get(2).intValue();
JsonNode size = collisionBoxNode.get("size");
int sizeX = size.get(0).intValue();
int sizeY = size.get(1).intValue();
int sizeZ = size.get(2).intValue();
collisionBox = new BoxComponent(originX, originY, originZ, sizeX, sizeY, sizeZ);
}
}
}
builder.collisionBox(collisionBox);
// Ideally we would just be able to calculate the right value for this, but it seems that hardness value on bedrock does not follow Java
// As such this might as well just be configured for now if people so choose
@ -492,7 +533,7 @@ public class MappingsReader_v1 extends MappingsReader {
if (placementFilter.has("conditions")) {
JsonNode conditions = placementFilter.get("conditions");
if (conditions.isArray()) {
PlacementFilter filter = createPlacementFilterComponent(conditions);
List<PlacementConditions> filter = createPlacementFilterComponent(conditions);
builder.placementFilter(filter);
}
}
@ -525,7 +566,13 @@ public class MappingsReader_v1 extends MappingsReader {
* @return the {@link BoxComponent}
*/
private BoxComponent createBoxComponent(int id) {
BoundingBox boundingBox = BlockUtils.getCollision(id).getBoundingBoxes()[0];
// Some blocks (e.g. plants) have no collision box
BlockCollision blockCollision = BlockUtils.getCollision(id);
if (blockCollision == null) {
return new BoxComponent(0, 0, 0, 0, 0, 0);
}
BoundingBox boundingBox = blockCollision.getBoundingBoxes()[0];
float offsetX = (float) boundingBox.getSizeX() * 8;
float offsetY = (float) boundingBox.getSizeY() * 8;
@ -536,13 +583,13 @@ public class MappingsReader_v1 extends MappingsReader {
// One possible solution would be to create invisible blocks that we use only for collision box
// 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
float cornerX = clamp((float) boundingBox.getMiddleX() * 16 - 8 - offsetX, -8, 8);
float cornerY = clamp((float) boundingBox.getMiddleY() * 16 - offsetY, 0, 16);
float cornerZ = clamp((float) boundingBox.getMiddleZ() * 16 - 8 - offsetZ, -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 cornerZ = MathUtils.clamp((float) boundingBox.getMiddleZ() * 16 - 8 - offsetZ, -8, 8);
float sizeX = clamp((float) boundingBox.getSizeX() * 16, 0, 16);
float sizeY = clamp((float) boundingBox.getSizeY() * 16, 0, 16);
float sizeZ = clamp((float) boundingBox.getSizeZ() * 16, 0, 16);
float sizeX = MathUtils.clamp((float) boundingBox.getSizeX() * 16, 0, 16);
float sizeY = MathUtils.clamp((float) boundingBox.getSizeY() * 16, 0, 16);
float sizeZ = MathUtils.clamp((float) boundingBox.getSizeZ() * 16, 0, 16);
BoxComponent boxComponent = new BoxComponent(cornerX, cornerY, cornerZ, sizeX, sizeY, sizeZ);
@ -563,17 +610,17 @@ public class MappingsReader_v1 extends MappingsReader {
texture = node.get("texture").asText();
}
String renderMethod = "alpha_test";
String renderMethod = "opaque";
if (node.has("render_method")) {
renderMethod = node.get("render_method").asText();
}
boolean faceDimming = false;
boolean faceDimming = true;
if (node.has("face_dimming")) {
faceDimming = node.get("face_dimming").asBoolean();
}
boolean ambientOcclusion = false;
boolean ambientOcclusion = true;
if (node.has("ambient_occlusion")) {
ambientOcclusion = node.get("ambient_occlusion").asBoolean();
}
@ -582,12 +629,12 @@ public class MappingsReader_v1 extends MappingsReader {
}
/**
* Creates the {@link PlacementFilter} for the passed conditions node
* Creates the list of {@link PlacementConditions} for the passed conditions node
* @param node the conditions node
* @return the {@link PlacementFilter}
* @return the list of {@link PlacementConditions}
*/
private PlacementFilter createPlacementFilterComponent(JsonNode node) {
List<Conditions> conditions = new ArrayList<>();
private List<PlacementConditions> createPlacementFilterComponent(JsonNode node) {
List<PlacementConditions> conditions = new ArrayList<>();
// The structure of the placement filter component is the most complex of the current components
// Each condition effectively seperated into an two arrays: one of allowed faces, and one of blocks/block molang queries
@ -619,10 +666,10 @@ public class MappingsReader_v1 extends MappingsReader {
}
}
conditions.add(new Conditions(faces, blockFilters));
conditions.add(new PlacementConditions(faces, blockFilters));
});
return new PlacementFilter(conditions);
return conditions;
}
/**
@ -672,15 +719,4 @@ public class MappingsReader_v1 extends MappingsReader {
return pairs;
}
/**
* Clamps the given value between the given min and max
* @param value the value to clamp
* @param min the minimum value
* @param max the maximum value
* @return the clamped value
*/
private float clamp(float value, float min, float max) {
return Math.max(min, Math.min(max, value));
}
}

View file

@ -15,8 +15,8 @@ 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.component.placementfilter.Conditions.Face;
import org.geysermc.geyser.api.block.custom.component.placementfilter.PlacementFilter;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions;
import org.geysermc.geyser.api.block.custom.component.PlacementConditions.Face;
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;
@ -304,15 +304,15 @@ public class CustomBlockRegistryPopulator {
* @param placementFilter the placement filter to convert
* @return the NBT representation of the provided placement filter
*/
private static List<NbtMap> convertPlacementFilter(PlacementFilter placementFilter) {
private static List<NbtMap> convertPlacementFilter(List<PlacementConditions> placementFilter) {
List<NbtMap> conditions = new ArrayList<>();
placementFilter.conditions().forEach((condition) -> {
placementFilter.forEach((condition) -> {
NbtMapBuilder conditionBuilder = NbtMap.builder();
// allowed_faces on the network is represented by 6 bits for the 6 possible faces
// the enum has the proper values for that face only, so we just bitwise OR them together
byte allowedFaces = 0;
for (Face face : condition.allowedFaces()) { allowedFaces |= face.getValue(); }
for (Face face : condition.allowedFaces()) { allowedFaces |= (1 << face.ordinal()); }
conditionBuilder.putByte("allowed_faces", allowedFaces);
// block_filters is a list of either blocks or queries for block tags