Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-25 15:50:14 +01:00
Add validation custom block components and s/lightFilter/lightDampening/
Also validate custom block names
Dieser Commit ist enthalten in:
Ursprung
bc7564f82a
Commit
f495c8522d
@ -63,7 +63,7 @@ public interface CustomBlockComponents {
|
|||||||
|
|
||||||
Builder lightEmission(Integer lightEmission);
|
Builder lightEmission(Integer lightEmission);
|
||||||
|
|
||||||
Builder lightFilter(Integer lightFilter);
|
Builder lightDampening(Integer lightDampening);
|
||||||
|
|
||||||
Builder rotation(RotationComponent rotation);
|
Builder rotation(RotationComponent rotation);
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
package org.geysermc.geyser.level.block;
|
package org.geysermc.geyser.level.block;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps;
|
||||||
@ -38,6 +39,7 @@ import org.geysermc.geyser.api.block.custom.component.RotationComponent;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Value
|
@Value
|
||||||
public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
||||||
@ -63,7 +65,7 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||||||
this.destroyTime = builder.destroyTime;
|
this.destroyTime = builder.destroyTime;
|
||||||
this.friction = builder.friction;
|
this.friction = builder.friction;
|
||||||
this.lightEmission = builder.lightEmission;
|
this.lightEmission = builder.lightEmission;
|
||||||
this.lightDampening = builder.lightFilter;
|
this.lightDampening = builder.lightDampening;
|
||||||
this.rotation = builder.rotation;
|
this.rotation = builder.rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,22 +117,45 @@ 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 String displayName;
|
||||||
protected String geometry;
|
protected String geometry;
|
||||||
protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>();
|
protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>();
|
||||||
protected Float destroyTime;
|
protected Float destroyTime;
|
||||||
protected Float friction;
|
protected Float friction;
|
||||||
protected Integer lightEmission;
|
protected Integer lightEmission;
|
||||||
protected Integer lightFilter;
|
protected Integer lightDampening;
|
||||||
protected RotationComponent rotation;
|
protected RotationComponent rotation;
|
||||||
|
|
||||||
|
private static final Set<String> VALID_MATERIAL_INSTANCE_NAMES = ImmutableSet.of("*", "up", "down", "north", "south", "west", "east");
|
||||||
|
|
||||||
|
private void validateBox(BoxComponent box) {
|
||||||
|
if (box == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (box.sizeX() < 0 || box.sizeY() < 0 || box.sizeZ() < 0) {
|
||||||
|
throw new IllegalArgumentException("Box size must be non-negative.");
|
||||||
|
}
|
||||||
|
float minX = box.originX() + 8;
|
||||||
|
float minY = box.originY();
|
||||||
|
float minZ = box.originZ() + 8;
|
||||||
|
float maxX = minX + box.sizeX();
|
||||||
|
float maxY = minY + box.sizeY();
|
||||||
|
float maxZ = minZ + box.sizeZ();
|
||||||
|
if (minX < 0 || minY < 0 || minZ < 0 || maxX > 16 || maxY > 16 || maxZ > 16) {
|
||||||
|
throw new IllegalArgumentException("Box bounds must be within (0, 0, 0) and (16, 16, 16)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder selectionBox(BoxComponent selectionBox) {
|
public Builder selectionBox(BoxComponent selectionBox) {
|
||||||
|
validateBox(selectionBox);
|
||||||
this.selectionBox = selectionBox;
|
this.selectionBox = selectionBox;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder collisionBox(BoxComponent collisionBox) {
|
public Builder collisionBox(BoxComponent collisionBox) {
|
||||||
|
validateBox(collisionBox);
|
||||||
this.collisionBox = collisionBox;
|
this.collisionBox = collisionBox;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -143,36 +168,60 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder materialInstance(@NotNull String name, @NotNull MaterialInstance materialInstance) {
|
public Builder materialInstance(@NotNull String name, @NotNull MaterialInstance materialInstance) {
|
||||||
|
if (!VALID_MATERIAL_INSTANCE_NAMES.contains(name)) {
|
||||||
|
throw new IllegalArgumentException("Material instance name must be one of " + VALID_MATERIAL_INSTANCE_NAMES);
|
||||||
|
}
|
||||||
this.materialInstances.put(name, materialInstance);
|
this.materialInstances.put(name, materialInstance);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder destroyTime(Float destroyTime) {
|
public Builder destroyTime(Float destroyTime) {
|
||||||
|
if (destroyTime != null && destroyTime < 0) {
|
||||||
|
throw new IllegalArgumentException("Destroy time must be non-negative");
|
||||||
|
}
|
||||||
this.destroyTime = destroyTime;
|
this.destroyTime = destroyTime;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder friction(Float friction) {
|
public Builder friction(Float friction) {
|
||||||
|
if (friction != null) {
|
||||||
|
if (friction < 0 || friction > 1) {
|
||||||
|
throw new IllegalArgumentException("Friction must be in the range 0-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
this.friction = friction;
|
this.friction = friction;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder lightEmission(Integer lightEmission) {
|
public Builder lightEmission(Integer lightEmission) {
|
||||||
|
if (lightEmission != null) {
|
||||||
|
if (lightEmission < 0 || lightEmission > 15) {
|
||||||
|
throw new IllegalArgumentException("Light emission must be in the range 0-15");
|
||||||
|
}
|
||||||
|
}
|
||||||
this.lightEmission = lightEmission;
|
this.lightEmission = lightEmission;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder lightFilter(Integer lightFilter) {
|
public Builder lightDampening(Integer lightDampening) {
|
||||||
this.lightFilter = lightFilter;
|
if (lightDampening != null) {
|
||||||
|
if (lightDampening < 0 || lightDampening > 15) {
|
||||||
|
throw new IllegalArgumentException("Light dampening must be in the range 0-15");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.lightDampening = lightDampening;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder rotation(RotationComponent rotation) {
|
public Builder rotation(RotationComponent rotation) {
|
||||||
|
if (rotation.x() % 90 != 0 || rotation.y() % 90 != 0 || rotation.z() % 90 != 0) {
|
||||||
|
throw new IllegalArgumentException("Rotation must be a multiple of 90 degrees.");
|
||||||
|
}
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -250,14 +250,6 @@ public final class BlockRegistryPopulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NbtMap convertBox(BoxComponent boxComponent) {
|
|
||||||
return NbtMap.builder()
|
|
||||||
.putBoolean("enabled", !boxComponent.isEmpty())
|
|
||||||
.putList("origin", NbtType.FLOAT, boxComponent.originX(), boxComponent.originY(), boxComponent.originZ())
|
|
||||||
.putList("size", NbtType.FLOAT, boxComponent.sizeX(), boxComponent.sizeY(), boxComponent.sizeZ())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void registerJavaBlocks() {
|
private static void registerJavaBlocks() {
|
||||||
JsonNode blocksJson;
|
JsonNode blocksJson;
|
||||||
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/blocks.json")) {
|
try (InputStream stream = GeyserImpl.getInstance().getBootstrap().getResource("mappings/blocks.json")) {
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package org.geysermc.geyser.registry.populator;
|
package org.geysermc.geyser.registry.populator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||||
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
|
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
|
||||||
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.api.block.custom.component.CustomBlockComponents;
|
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.MaterialInstance;
|
||||||
import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty;
|
import org.geysermc.geyser.api.block.custom.property.CustomBlockProperty;
|
||||||
@ -34,17 +35,21 @@ public class CustomBlockRegistryPopulator {
|
|||||||
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
|
if (!GeyserImpl.getInstance().getConfig().isAddCustomBlocks()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Set<String> customBlockNames = new HashSet<>();
|
Set<String> customBlockNames = new ObjectOpenHashSet<>();
|
||||||
Set<CustomBlockData> customBlocks = new HashSet<>();
|
Set<CustomBlockData> customBlocks = new ObjectOpenHashSet<>();
|
||||||
Int2ObjectMap<CustomBlockState> blockStateOverrides = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<CustomBlockState> blockStateOverrides = new Int2ObjectOpenHashMap<>();
|
||||||
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) {
|
||||||
|
if (customBlockData.name().length() == 0) {
|
||||||
|
throw new IllegalArgumentException("Custom block name must have at least 1 character.");
|
||||||
|
}
|
||||||
if (!customBlockNames.add(customBlockData.name())) {
|
if (!customBlockNames.add(customBlockData.name())) {
|
||||||
throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name());
|
throw new IllegalArgumentException("Another custom block was already registered under the name: " + customBlockData.name());
|
||||||
}
|
}
|
||||||
// TODO validate collision+selection box bounds
|
if (Character.isDigit(customBlockData.name().charAt(0))) {
|
||||||
// TODO validate names
|
throw new IllegalArgumentException("Custom block can not start with a digit. Name: " + customBlockData.name());
|
||||||
|
}
|
||||||
customBlocks.add(customBlockData);
|
customBlocks.add(customBlockData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,10 +151,10 @@ public class CustomBlockRegistryPopulator {
|
|||||||
}
|
}
|
||||||
NbtMapBuilder builder = NbtMap.builder();
|
NbtMapBuilder builder = NbtMap.builder();
|
||||||
if (components.selectionBox() != null) {
|
if (components.selectionBox() != null) {
|
||||||
builder.putCompound("minecraft:selection_box", BlockRegistryPopulator.convertBox(components.selectionBox()));
|
builder.putCompound("minecraft:selection_box", convertBox(components.selectionBox()));
|
||||||
}
|
}
|
||||||
if (components.collisionBox() != null) {
|
if (components.collisionBox() != null) {
|
||||||
builder.putCompound("minecraft:collision_box", BlockRegistryPopulator.convertBox(components.collisionBox()));
|
builder.putCompound("minecraft:collision_box", convertBox(components.collisionBox()));
|
||||||
}
|
}
|
||||||
if (components.geometry() != null) {
|
if (components.geometry() != null) {
|
||||||
builder.putCompound("minecraft:geometry", NbtMap.builder()
|
builder.putCompound("minecraft:geometry", NbtMap.builder()
|
||||||
@ -202,4 +207,11 @@ public class CustomBlockRegistryPopulator {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static NbtMap convertBox(BoxComponent boxComponent) {
|
||||||
|
return NbtMap.builder()
|
||||||
|
.putBoolean("enabled", !boxComponent.isEmpty())
|
||||||
|
.putList("origin", NbtType.FLOAT, boxComponent.originX(), boxComponent.originY(), boxComponent.originZ())
|
||||||
|
.putList("size", NbtType.FLOAT, boxComponent.sizeX(), boxComponent.sizeY(), boxComponent.sizeZ())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ public class CustomSkull {
|
|||||||
CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder()
|
CustomBlockComponents components = new GeyserCustomBlockComponents.CustomBlockComponentsBuilder()
|
||||||
.destroyTime(1.5f)
|
.destroyTime(1.5f)
|
||||||
.materialInstance("*", new MaterialInstance("geyser." + skinHash + "_player_skin", "alpha_test", true, true))
|
.materialInstance("*", new MaterialInstance("geyser." + skinHash + "_player_skin", "alpha_test", true, true))
|
||||||
.lightFilter(0)
|
.lightDampening(0)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
List<CustomBlockPermutation> permutations = new ArrayList<>();
|
List<CustomBlockPermutation> permutations = new ArrayList<>();
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren