mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Implement all remaining block components
This commit is contained in:
parent
3d1d51d198
commit
bfdebadacc
6 changed files with 249 additions and 1 deletions
|
@ -26,6 +26,7 @@
|
|||
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.Map;
|
||||
import java.util.Set;
|
||||
|
@ -74,6 +75,15 @@ public interface CustomBlockComponents {
|
|||
*/
|
||||
@NonNull Map<String, MaterialInstance> materialInstances();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the placement filter component
|
||||
* Equivalent to "minecraft:material_instances"
|
||||
*
|
||||
* @return The placement filter.
|
||||
*/
|
||||
PlacementFilter placementFilter();
|
||||
|
||||
/**
|
||||
* Gets the destructible by mining component
|
||||
* Equivalent to "minecraft:destructible_by_mining"
|
||||
|
@ -114,6 +124,14 @@ public interface CustomBlockComponents {
|
|||
*/
|
||||
RotationComponent rotation();
|
||||
|
||||
/**
|
||||
* Gets the unit cube component
|
||||
* Equivalent to "minecraft:unit_cube"
|
||||
*
|
||||
* @return The rotation.
|
||||
*/
|
||||
boolean unitCube();
|
||||
|
||||
/**
|
||||
* Gets if the block should place only air
|
||||
* Equivalent to setting a dummy event to run on "minecraft:on_player_placing"
|
||||
|
@ -141,6 +159,8 @@ public interface CustomBlockComponents {
|
|||
|
||||
Builder materialInstance(@NonNull String name, @NonNull MaterialInstance materialInstance);
|
||||
|
||||
Builder placementFilter(PlacementFilter placementFilter);
|
||||
|
||||
Builder destructibleByMining(Float destructibleByMining);
|
||||
|
||||
Builder friction(Float friction);
|
||||
|
@ -151,6 +171,8 @@ public interface CustomBlockComponents {
|
|||
|
||||
Builder rotation(RotationComponent rotation);
|
||||
|
||||
Builder unitCube(boolean unitCube);
|
||||
|
||||
Builder placeAir(boolean placeAir);
|
||||
|
||||
Builder tags(Set<String> tags);
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
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 enum Face {
|
||||
DOWN(1),
|
||||
UP(2),
|
||||
NORTH(4),
|
||||
SOUTH(8),
|
||||
WEST(16),
|
||||
EAST(32);
|
||||
|
||||
private final byte value;
|
||||
|
||||
Face(int value) {
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
public enum BlockFilterType {
|
||||
BLOCK,
|
||||
TAG
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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) {
|
||||
|
||||
}
|
|
@ -34,6 +34,7 @@ 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.RotationComponent;
|
||||
import org.geysermc.geyser.api.block.custom.component.placementfilter.PlacementFilter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||
|
@ -49,11 +50,13 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
String displayName;
|
||||
String geometry;
|
||||
Map<String, MaterialInstance> materialInstances;
|
||||
PlacementFilter placementFilter;
|
||||
Float destructibleByMining;
|
||||
Float friction;
|
||||
Integer lightEmission;
|
||||
Integer lightDampening;
|
||||
RotationComponent rotation;
|
||||
boolean unitCube;
|
||||
boolean placeAir;
|
||||
Set<String> tags;
|
||||
|
||||
|
@ -67,11 +70,13 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
} else {
|
||||
this.materialInstances = Object2ObjectMaps.unmodifiable(new Object2ObjectArrayMap<>(builder.materialInstances));
|
||||
}
|
||||
this.placementFilter = builder.placementFilter;
|
||||
this.destructibleByMining = builder.destructibleByMining;
|
||||
this.friction = builder.friction;
|
||||
this.lightEmission = builder.lightEmission;
|
||||
this.lightDampening = builder.lightDampening;
|
||||
this.rotation = builder.rotation;
|
||||
this.unitCube = builder.unitCube;
|
||||
this.placeAir = builder.placeAir;
|
||||
if (builder.tags.isEmpty()) {
|
||||
this.tags = Set.of();
|
||||
|
@ -105,6 +110,11 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
return materialInstances;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementFilter placementFilter() {
|
||||
return placementFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float destructibleByMining() {
|
||||
return destructibleByMining;
|
||||
|
@ -130,6 +140,11 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
return rotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unitCube() {
|
||||
return unitCube;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean placeAir() {
|
||||
return placeAir;
|
||||
|
@ -146,11 +161,13 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
protected String displayName;
|
||||
protected String geometry;
|
||||
protected final Object2ObjectMap<String, MaterialInstance> materialInstances = new Object2ObjectOpenHashMap<>();
|
||||
protected PlacementFilter placementFilter;
|
||||
protected Float destructibleByMining;
|
||||
protected Float friction;
|
||||
protected Integer lightEmission;
|
||||
protected Integer lightDampening;
|
||||
protected RotationComponent rotation;
|
||||
protected boolean unitCube = false;
|
||||
protected boolean placeAir = false;
|
||||
protected final Set<String> tags = new HashSet<>();
|
||||
|
||||
|
@ -204,6 +221,12 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder placementFilter(PlacementFilter placementFilter) {
|
||||
this.placementFilter = placementFilter;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder destructibleByMining(Float destructibleByMining) {
|
||||
if (destructibleByMining != null && destructibleByMining < 0) {
|
||||
|
@ -255,6 +278,12 @@ public class GeyserCustomBlockComponents implements CustomBlockComponents {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder unitCube(boolean unitCube) {
|
||||
this.unitCube = unitCube;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder placeAir(boolean placeAir) {
|
||||
this.placeAir = placeAir;
|
||||
|
|
|
@ -37,6 +37,10 @@ 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.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.item.custom.CustomItemData;
|
||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||
import org.geysermc.geyser.item.exception.InvalidCustomMappingsFileException;
|
||||
|
@ -56,6 +60,7 @@ import java.util.Collections;
|
|||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -347,9 +352,11 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
builder.geometry(node.get("geometry").asText());
|
||||
}
|
||||
|
||||
String displayName = name;
|
||||
if (node.has("display_name")) {
|
||||
builder.displayName(node.get("display_name").asText());
|
||||
displayName = node.get("display_name").asText();
|
||||
}
|
||||
builder.displayName(displayName);
|
||||
|
||||
if (node.has("light_emission")) {
|
||||
builder.lightEmission(node.get("light_emission").asInt());
|
||||
|
@ -373,6 +380,10 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
builder.rotation(new RotationComponent(rotationX, rotationY, rotationZ));
|
||||
}
|
||||
|
||||
if (node.has("unit_cube")) {
|
||||
builder.unitCube(node.get("unit_cube").asBoolean());
|
||||
}
|
||||
|
||||
if (node.has("material_instances")) {
|
||||
JsonNode materialInstances = node.get("material_instances");
|
||||
if (materialInstances.isObject()) {
|
||||
|
@ -387,6 +398,19 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
}
|
||||
}
|
||||
|
||||
if (node.has("placement_filter")) {
|
||||
JsonNode placementFilter = node.get("placement_filter");
|
||||
if (placementFilter.isObject()) {
|
||||
if (placementFilter.has("conditions")) {
|
||||
JsonNode conditions = placementFilter.get("conditions");
|
||||
if (conditions.isArray()) {
|
||||
PlacementFilter filter = createPlacementFilterComponent(conditions);
|
||||
builder.placementFilter(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (node.has("tags")) {
|
||||
JsonNode tags = node.get("tags");
|
||||
if (tags.isArray()) {
|
||||
|
@ -446,6 +470,43 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||
return new MaterialInstance(texture, renderMethod, faceDimming, ambientOcclusion);
|
||||
}
|
||||
|
||||
private PlacementFilter createPlacementFilterComponent(JsonNode node) {
|
||||
List<Conditions> conditions = new ArrayList<>();
|
||||
|
||||
node.forEach(condition -> {
|
||||
Set<Face> faces = new HashSet<>();
|
||||
if (condition.has("allowed_faces")) {
|
||||
JsonNode allowedFaces = condition.get("allowed_faces");
|
||||
if (allowedFaces.isArray()) {
|
||||
allowedFaces.forEach(face -> {
|
||||
faces.add(Face.valueOf(face.asText().toUpperCase()));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LinkedHashMap<String, BlockFilterType> blockFilters = new LinkedHashMap<>();
|
||||
if (condition.has("block_filter")) {
|
||||
JsonNode blockFilter = condition.get("block_filter");
|
||||
if (blockFilter.isArray()) {
|
||||
blockFilter.forEach(filter -> {
|
||||
if (filter.isObject()) {
|
||||
if (filter.has("tags")) {
|
||||
JsonNode tags = filter.get("tags");
|
||||
blockFilters.put(tags.asText(), BlockFilterType.TAG);
|
||||
}
|
||||
} else if (filter.isTextual()) {
|
||||
blockFilters.put(filter.asText(), BlockFilterType.BLOCK);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
conditions.add(new Conditions(faces, blockFilters));
|
||||
});
|
||||
|
||||
return new PlacementFilter(conditions);
|
||||
}
|
||||
|
||||
private String createCustomBlockPropertyQuery(String state) {
|
||||
String[] conditions = splitStateString(state);
|
||||
String[] queries = new String[conditions.length];
|
||||
|
|
|
@ -15,6 +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.PlacementFilter;
|
||||
import org.geysermc.geyser.api.block.custom.component.placementfilter.Conditions.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;
|
||||
|
@ -176,6 +178,11 @@ public class CustomBlockRegistryPopulator {
|
|||
return NbtMap.EMPTY;
|
||||
}
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
if (components.displayName() != null) {
|
||||
builder.putCompound("minecraft:display_name", NbtMap.builder()
|
||||
.putString("value", components.displayName())
|
||||
.build());
|
||||
}
|
||||
if (components.selectionBox() != null) {
|
||||
builder.putCompound("minecraft:selection_box", convertBox(components.selectionBox()));
|
||||
}
|
||||
|
@ -203,6 +210,11 @@ public class CustomBlockRegistryPopulator {
|
|||
.putCompound("materials", materialsBuilder.build())
|
||||
.build());
|
||||
}
|
||||
if (components.placementFilter() != null) {
|
||||
builder.putCompound("minecraft:placement_filter", NbtMap.builder()
|
||||
.putList("conditions", NbtType.COMPOUND, convertPlacementFilter(components.placementFilter()))
|
||||
.build());
|
||||
}
|
||||
if (components.destructibleByMining() != null) {
|
||||
builder.putCompound("minecraft:destructible_by_mining", NbtMap.builder()
|
||||
.putFloat("value", components.destructibleByMining())
|
||||
|
@ -230,6 +242,9 @@ public class CustomBlockRegistryPopulator {
|
|||
.putFloat("z", components.rotation().z())
|
||||
.build());
|
||||
}
|
||||
if (components.unitCube()) {
|
||||
builder.putCompound("minecraft:unit_cube", NbtMap.EMPTY);
|
||||
}
|
||||
if (components.placeAir()) {
|
||||
builder.putCompound("minecraft:on_player_placing", NbtMap.builder()
|
||||
.putString("triggerType", "geyser:place_event")
|
||||
|
@ -248,4 +263,29 @@ public class CustomBlockRegistryPopulator {
|
|||
.putList("size", NbtType.FLOAT, boxComponent.sizeX(), boxComponent.sizeY(), boxComponent.sizeZ())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static List<NbtMap> convertPlacementFilter(PlacementFilter placementFilter) {
|
||||
List<NbtMap> conditions = new ArrayList<>();
|
||||
placementFilter.conditions().forEach((condition) -> {
|
||||
NbtMapBuilder conditionBuilder = NbtMap.builder();
|
||||
|
||||
byte allowedFaces = 0;
|
||||
for (Face face : condition.allowedFaces()) { allowedFaces |= face.getValue(); }
|
||||
conditionBuilder.putByte("allowed_faces", allowedFaces);
|
||||
|
||||
List <NbtMap> blockFilters = new ArrayList<>();
|
||||
condition.blockFilters().forEach((value, type) -> {
|
||||
NbtMapBuilder blockFilterBuilder = NbtMap.builder();
|
||||
switch (type) {
|
||||
case BLOCK -> blockFilterBuilder.putString("name", value);
|
||||
case TAG -> blockFilterBuilder.putString("tags", value).putInt("tags_version", 6);
|
||||
}
|
||||
blockFilters.add(blockFilterBuilder.build());
|
||||
});
|
||||
conditionBuilder.putList("block_filters", NbtType.COMPOUND, blockFilters);
|
||||
conditions.add(conditionBuilder.build());
|
||||
});
|
||||
|
||||
return conditions;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue