Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-19 22:40:18 +01:00
Extended collision boxes actually work
Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
Dieser Commit ist enthalten in:
Ursprung
550a4725ef
Commit
7f85e909b8
@ -51,13 +51,6 @@ 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"
|
||||||
@ -160,8 +153,6 @@ 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);
|
||||||
|
@ -42,7 +42,6 @@ public final class Constants {
|
|||||||
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
|
static final String SAVED_REFRESH_TOKEN_FILE = "saved-refresh-tokens.json";
|
||||||
|
|
||||||
public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom";
|
public static final String GEYSER_CUSTOM_NAMESPACE = "geyser_custom";
|
||||||
public static final String GEYSER_NAMESPACE = "geyser";
|
|
||||||
|
|
||||||
public static final String MINECRAFT_SKIN_SERVER_URL = "https://textures.minecraft.net/texture/";
|
public static final String MINECRAFT_SKIN_SERVER_URL = "https://textures.minecraft.net/texture/";
|
||||||
|
|
||||||
|
@ -47,7 +47,6 @@ 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;
|
||||||
@ -64,7 +63,6 @@ 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()) {
|
||||||
@ -97,11 +95,6 @@ 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;
|
||||||
@ -165,7 +158,6 @@ 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<>();
|
||||||
@ -211,13 +203,6 @@ 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;
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.registry.mappings.util;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
public record CustomBlockComponentsMapping(@NonNull CustomBlockComponents components, BoxComponent extendedCollisionBox) {
|
||||||
|
}
|
@ -29,12 +29,11 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
import org.geysermc.geyser.api.block.custom.CustomBlockData;
|
||||||
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to store a custom block mappings, which contain all of the
|
* This class is used to store a custom block mappings, which contain all of the
|
||||||
* data required to register a custom block that overrides a group of java block
|
* data required to register a custom block that overrides a group of java block
|
||||||
* states.
|
* states.
|
||||||
*/
|
*/
|
||||||
public record CustomBlockMapping(@NonNull CustomBlockData data, @NonNull Map<String, CustomBlockState> states, @NonNull String javaIdentifier, boolean overrideItem) {
|
public record CustomBlockMapping(@NonNull CustomBlockData data, @NonNull Map<String, CustomBlockStateMapping> states, @NonNull String javaIdentifier, boolean overrideItem) {
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* 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.registry.mappings.util;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||||
|
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public record CustomBlockStateBuilderMapping(@NonNull Function<CustomBlockState.Builder, CustomBlockState> builder, BoxComponent extendedCollisionBox) {
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* 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.registry.mappings.util;
|
||||||
|
|
||||||
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
import org.geysermc.geyser.api.block.custom.CustomBlockState;
|
||||||
|
import org.geysermc.geyser.api.block.custom.component.BoxComponent;
|
||||||
|
|
||||||
|
public record CustomBlockStateMapping(@NonNull CustomBlockState state, BoxComponent extendedCollisionBox) {
|
||||||
|
}
|
@ -44,7 +44,10 @@ import org.geysermc.geyser.level.block.GeyserCustomBlockComponents.CustomBlockCo
|
|||||||
import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder;
|
import org.geysermc.geyser.level.block.GeyserCustomBlockData.CustomBlockDataBuilder;
|
||||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
|
import org.geysermc.geyser.registry.mappings.util.CustomBlockComponentsMapping;
|
||||||
import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping;
|
import org.geysermc.geyser.registry.mappings.util.CustomBlockMapping;
|
||||||
|
import org.geysermc.geyser.registry.mappings.util.CustomBlockStateBuilderMapping;
|
||||||
|
import org.geysermc.geyser.registry.mappings.util.CustomBlockStateMapping;
|
||||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||||
import org.geysermc.geyser.util.BlockUtils;
|
import org.geysermc.geyser.util.BlockUtils;
|
||||||
import org.geysermc.geyser.util.MathUtils;
|
import org.geysermc.geyser.util.MathUtils;
|
||||||
@ -194,13 +197,14 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
|
|
||||||
if (BlockRegistries.JAVA_IDENTIFIERS.get().containsKey(identifier)) {
|
if (BlockRegistries.JAVA_IDENTIFIERS.get().containsKey(identifier)) {
|
||||||
// There is only one Java block state to override
|
// There is only one Java block state to override
|
||||||
|
CustomBlockComponentsMapping componentsMapping = createCustomBlockComponentsMapping(node, identifier, name);
|
||||||
CustomBlockData blockData = customBlockDataBuilder
|
CustomBlockData blockData = customBlockDataBuilder
|
||||||
.components(createCustomBlockComponents(node, identifier, name))
|
.components(componentsMapping.components())
|
||||||
.build();
|
.build();
|
||||||
return new CustomBlockMapping(blockData, Map.of(identifier, blockData.defaultBlockState()), identifier, !onlyOverrideStates);
|
return new CustomBlockMapping(blockData, Map.of(identifier, new CustomBlockStateMapping(blockData.defaultBlockState(), componentsMapping.extendedCollisionBox())), identifier, !onlyOverrideStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, CustomBlockComponents> componentsMap = new LinkedHashMap<>();
|
Map<String, CustomBlockComponentsMapping> componentsMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
JsonNode stateOverrides = node.get("state_overrides");
|
JsonNode stateOverrides = node.get("state_overrides");
|
||||||
if (stateOverrides != null && stateOverrides.isObject()) {
|
if (stateOverrides != null && stateOverrides.isObject()) {
|
||||||
@ -212,7 +216,7 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
if (!BlockRegistries.JAVA_IDENTIFIERS.get().containsKey(state)) {
|
if (!BlockRegistries.JAVA_IDENTIFIERS.get().containsKey(state)) {
|
||||||
throw new InvalidCustomMappingsFileException("Unknown Java block state: " + state + " for state_overrides.");
|
throw new InvalidCustomMappingsFileException("Unknown Java block state: " + state + " for state_overrides.");
|
||||||
}
|
}
|
||||||
componentsMap.put(state, createCustomBlockComponents(overrideEntry.getValue(), state, name));
|
componentsMap.put(state, createCustomBlockComponentsMapping(overrideEntry.getValue(), state, name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (componentsMap.isEmpty() && onlyOverrideStates) {
|
if (componentsMap.isEmpty() && onlyOverrideStates) {
|
||||||
@ -225,7 +229,7 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
.stream()
|
.stream()
|
||||||
.filter(s -> s.startsWith(identifier + "["))
|
.filter(s -> s.startsWith(identifier + "["))
|
||||||
.filter(Predicate.not(componentsMap::containsKey))
|
.filter(Predicate.not(componentsMap::containsKey))
|
||||||
.forEach(state -> componentsMap.put(state, createCustomBlockComponents(null, state, name)));
|
.forEach(state -> componentsMap.put(state, createCustomBlockComponentsMapping(null, state, name)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (componentsMap.isEmpty()) {
|
if (componentsMap.isEmpty()) {
|
||||||
@ -235,20 +239,21 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
// We pass in the first state and just use the hitbox from that as the default
|
// We pass in the first state and just use the hitbox from that as the default
|
||||||
// Each state will have its own so this is fine
|
// Each state will have its own so this is fine
|
||||||
String firstState = componentsMap.keySet().iterator().next();
|
String firstState = componentsMap.keySet().iterator().next();
|
||||||
customBlockDataBuilder.components(createCustomBlockComponents(node, firstState, name));
|
CustomBlockComponentsMapping firstComponentsMapping = createCustomBlockComponentsMapping(node, firstState, name);
|
||||||
|
customBlockDataBuilder.components(firstComponentsMapping.components());
|
||||||
|
|
||||||
return createCustomBlockMapping(customBlockDataBuilder, componentsMap, identifier, !onlyOverrideStates);
|
return createCustomBlockMapping(customBlockDataBuilder, componentsMap, identifier, !onlyOverrideStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CustomBlockMapping createCustomBlockMapping(CustomBlockData.Builder customBlockDataBuilder, Map<String, CustomBlockComponents> componentsMap, String identifier, boolean overrideItem) {
|
private CustomBlockMapping createCustomBlockMapping(CustomBlockData.Builder customBlockDataBuilder, Map<String, CustomBlockComponentsMapping> componentsMap, String identifier, boolean overrideItem) {
|
||||||
Map<String, LinkedHashSet<String>> valuesMap = new Object2ObjectOpenHashMap<>();
|
Map<String, LinkedHashSet<String>> valuesMap = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
List<CustomBlockPermutation> permutations = new ArrayList<>();
|
List<CustomBlockPermutation> permutations = new ArrayList<>();
|
||||||
Map<String, Function<CustomBlockState.Builder, CustomBlockState>> blockStateBuilders = new Object2ObjectOpenHashMap<>();
|
Map<String, CustomBlockStateBuilderMapping> blockStateBuilders = new Object2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
// For each Java block state, extract the property values, create a CustomBlockPermutation,
|
// For each Java block state, extract the property values, create a CustomBlockPermutation,
|
||||||
// and a CustomBlockState builder
|
// and a CustomBlockState builder
|
||||||
for (Map.Entry<String, CustomBlockComponents> entry : componentsMap.entrySet()) {
|
for (Map.Entry<String, CustomBlockComponentsMapping> entry : componentsMap.entrySet()) {
|
||||||
String state = entry.getKey();
|
String state = entry.getKey();
|
||||||
String[] pairs = splitStateString(state);
|
String[] pairs = splitStateString(state);
|
||||||
|
|
||||||
@ -267,8 +272,8 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
blockStateBuilder = blockStateBuilder.andThen(builder -> builder.stringProperty(property, value));
|
blockStateBuilder = blockStateBuilder.andThen(builder -> builder.stringProperty(property, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
permutations.add(new CustomBlockPermutation(entry.getValue(), String.join(" && ", conditions)));
|
permutations.add(new CustomBlockPermutation(entry.getValue().components(), String.join(" && ", conditions)));
|
||||||
blockStateBuilders.put(state, blockStateBuilder.andThen(CustomBlockState.Builder::build));
|
blockStateBuilders.put(state, new CustomBlockStateBuilderMapping(blockStateBuilder.andThen(CustomBlockState.Builder::build), entry.getValue().extendedCollisionBox()));
|
||||||
}
|
}
|
||||||
|
|
||||||
valuesMap.forEach((key, value) -> customBlockDataBuilder.stringProperty(key, new ArrayList<>(value)));
|
valuesMap.forEach((key, value) -> customBlockDataBuilder.stringProperty(key, new ArrayList<>(value)));
|
||||||
@ -277,8 +282,8 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
.permutations(permutations)
|
.permutations(permutations)
|
||||||
.build();
|
.build();
|
||||||
// Build CustomBlockStates for each Java block state we wish to override
|
// Build CustomBlockStates for each Java block state we wish to override
|
||||||
Map<String, CustomBlockState> states = blockStateBuilders.entrySet().stream()
|
Map<String, CustomBlockStateMapping> states = blockStateBuilders.entrySet().stream()
|
||||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().apply(customBlockData.blockStateBuilder())));
|
.collect(Collectors.toMap(Map.Entry::getKey, e -> new CustomBlockStateMapping(e.getValue().builder().apply(customBlockData.blockStateBuilder()), e.getValue().extendedCollisionBox())));
|
||||||
|
|
||||||
return new CustomBlockMapping(customBlockData, states, identifier, overrideItem);
|
return new CustomBlockMapping(customBlockData, states, identifier, overrideItem);
|
||||||
}
|
}
|
||||||
@ -290,19 +295,18 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
* @param name the name of the custom block
|
* @param name the name of the custom block
|
||||||
* @return the {@link CustomBlockComponents} object
|
* @return the {@link CustomBlockComponents} object
|
||||||
*/
|
*/
|
||||||
private CustomBlockComponents createCustomBlockComponents(JsonNode node, String stateKey, String name) {
|
private CustomBlockComponentsMapping createCustomBlockComponentsMapping(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, 0, 16, 0);
|
BoxComponent boxComponent = createBoxComponent(id);
|
||||||
BoxComponent extendedBoxComponent = createBoxComponent(id, 16, 32, -16);
|
BoxComponent extendedBoxComponent = createExtendedBoxComponent(id);
|
||||||
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
|
||||||
return builder.build();
|
return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
BoxComponent selectionBox = createBoxComponent(node.get("selection_box"));
|
BoxComponent selectionBox = createBoxComponent(node.get("selection_box"));
|
||||||
@ -315,7 +319,7 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
}
|
}
|
||||||
BoxComponent extendedCollisionBox = createBoxComponent(node.get("extended_collision_box"));
|
BoxComponent extendedCollisionBox = createBoxComponent(node.get("extended_collision_box"));
|
||||||
if (extendedCollisionBox != null) {
|
if (extendedCollisionBox != null) {
|
||||||
builder.extendedCollisionBox(extendedCollisionBox);
|
extendedBoxComponent = extendedCollisionBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -404,11 +408,11 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
builder.tags(tagsSet);
|
builder.tags(tagsSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return new CustomBlockComponentsMapping(builder.build(), extendedBoxComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BoxComponent} based on a Java block's collision
|
* Creates a {@link BoxComponent} based on a Java block's collision with provided bounds and offsets
|
||||||
* @param javaId the block's Java ID
|
* @param javaId the block's Java ID
|
||||||
* @param minHeight the minimum height of the box
|
* @param minHeight the minimum height of the box
|
||||||
* @param maxHeight the maximum height of the box
|
* @param maxHeight the maximum height of the box
|
||||||
@ -428,11 +432,6 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
float offsetY = (float) boundingBox.getSizeY() * 8;
|
float offsetY = (float) boundingBox.getSizeY() * 8;
|
||||||
float offsetZ = (float) boundingBox.getSizeZ() * 8;
|
float offsetZ = (float) boundingBox.getSizeZ() * 8;
|
||||||
|
|
||||||
// Unfortunately we need to clamp the values here to an effective size of one block
|
|
||||||
// This is quite a pain for anything like fences, as the player can just jump over them
|
|
||||||
// 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 = 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, minHeight, maxHeight);
|
float cornerY = MathUtils.clamp((float) boundingBox.getMiddleY() * 16 - offsetY, 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);
|
||||||
@ -444,6 +443,35 @@ public class MappingsReader_v1 extends MappingsReader {
|
|||||||
return new BoxComponent(cornerX, cornerY + heightTranslation, cornerZ, sizeX, sizeY + heightTranslation, sizeZ);
|
return new BoxComponent(cornerX, cornerY + heightTranslation, cornerZ, sizeX, sizeY + heightTranslation, sizeZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link BoxComponent} based on a Java block's collision
|
||||||
|
* @param javaId the block's Java ID
|
||||||
|
* @return the {@link BoxComponent}
|
||||||
|
*/
|
||||||
|
private BoxComponent createBoxComponent(int javaId) {
|
||||||
|
return createBoxComponent(javaId, 0, 16, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link BoxComponent} for an extended collision box based on a Java block's collision
|
||||||
|
* @param javaId the block's Java ID
|
||||||
|
* @return the {@link BoxComponent} or null if the block's collision box would not exceed 16 y units
|
||||||
|
*/
|
||||||
|
private BoxComponent createExtendedBoxComponent(int javaId) {
|
||||||
|
BlockCollision blockCollision = BlockUtils.getCollision(javaId);
|
||||||
|
if (blockCollision == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
BoundingBox boundingBox = blockCollision.getBoundingBoxes()[0];
|
||||||
|
float offsetY = (float) boundingBox.getSizeY() * 8;
|
||||||
|
float cornerY = (float) boundingBox.getMiddleY() * 16 - offsetY;
|
||||||
|
float sizeY = (float) boundingBox.getSizeY() * 16;
|
||||||
|
if (cornerY > 16 || sizeY > 16) {
|
||||||
|
return createBoxComponent(javaId, 16, 32, -16);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link BoxComponent} from a JSON Node
|
* Creates a {@link BoxComponent} from a JSON Node
|
||||||
* @param node the JSON node
|
* @param node the JSON node
|
||||||
|
@ -48,9 +48,6 @@ 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<CustomBlockData, Set<Integer>> extendedCollisionBoxes = new HashMap<>();
|
|
||||||
Map<BoxComponent, CustomBlockData> extendedCollisionBoxSet = new HashMap<>();
|
|
||||||
int[] extendedCollisionIndex = {0};
|
|
||||||
|
|
||||||
GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() {
|
GeyserImpl.getInstance().getEventBus().fire(new GeyserDefineCustomBlocksEvent() {
|
||||||
@Override
|
@Override
|
||||||
@ -77,20 +74,6 @@ 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) {
|
|
||||||
CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.getOrDefault(extendedCollisionBox, null);
|
|
||||||
if (extendedCollisionBlock == null) {
|
|
||||||
extendedCollisionBlock = createExtendedCollisionBlock(extendedCollisionBox, extendedCollisionIndex[0]++);
|
|
||||||
extendedCollisionBoxes.put(extendedCollisionBlock, new HashSet<>(id));
|
|
||||||
customBlocks.add(extendedCollisionBlock);
|
|
||||||
extendedCollisionBoxSet.put(extendedCollisionBox, extendedCollisionBlock);
|
|
||||||
} else {
|
|
||||||
Set<Integer> existingJavaIds = extendedCollisionBoxes.getOrDefault(extendedCollisionBlock, new HashSet<>());
|
|
||||||
existingJavaIds.add(id);
|
|
||||||
extendedCollisionBoxes.put(extendedCollisionBlock, existingJavaIds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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());
|
||||||
@ -110,6 +93,9 @@ public class CustomBlockRegistryPopulator {
|
|||||||
customBlocks.add(customSkull.getCustomBlockData());
|
customBlocks.add(customSkull.getCustomBlockData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<CustomBlockData, Set<Integer>> extendedCollisionBoxes = new HashMap<>();
|
||||||
|
Map<BoxComponent, CustomBlockData> extendedCollisionBoxSet = new HashMap<>();
|
||||||
|
int[] extendedCollisionIndex = {0};
|
||||||
MappingsConfigReader mappingsConfigReader = new MappingsConfigReader();
|
MappingsConfigReader mappingsConfigReader = new MappingsConfigReader();
|
||||||
mappingsConfigReader.loadBlockMappingsFromJson((key, block) -> {
|
mappingsConfigReader.loadBlockMappingsFromJson((key, block) -> {
|
||||||
customBlocks.add(block.data());
|
customBlocks.add(block.data());
|
||||||
@ -118,13 +104,13 @@ 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.state());
|
||||||
BoxComponent extendedCollisionBox = customBlockState.block().components().extendedCollisionBox();
|
BoxComponent extendedCollisionBox = customBlockState.extendedCollisionBox();
|
||||||
if (extendedCollisionBox != null) {
|
if (extendedCollisionBox != null) {
|
||||||
CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.getOrDefault(extendedCollisionBox, null);
|
CustomBlockData extendedCollisionBlock = extendedCollisionBoxSet.getOrDefault(extendedCollisionBox, null);
|
||||||
if (extendedCollisionBlock == null) {
|
if (extendedCollisionBlock == null) {
|
||||||
extendedCollisionBlock = createExtendedCollisionBlock(extendedCollisionBox, extendedCollisionIndex[0]++);
|
extendedCollisionBlock = createExtendedCollisionBlock(extendedCollisionBox, extendedCollisionIndex[0]++);
|
||||||
extendedCollisionBoxes.put(extendedCollisionBlock, new HashSet<>(id));
|
extendedCollisionBoxes.computeIfAbsent(extendedCollisionBlock, k -> new HashSet<>()).add(id);
|
||||||
customBlocks.add(extendedCollisionBlock);
|
customBlocks.add(extendedCollisionBlock);
|
||||||
extendedCollisionBoxSet.put(extendedCollisionBox, extendedCollisionBlock);
|
extendedCollisionBoxSet.put(extendedCollisionBox, extendedCollisionBlock);
|
||||||
} else {
|
} else {
|
||||||
@ -375,11 +361,14 @@ public class CustomBlockRegistryPopulator {
|
|||||||
|
|
||||||
private static CustomBlockData createExtendedCollisionBlock(BoxComponent boxComponent, int extendedCollisionBlock) {
|
private static CustomBlockData createExtendedCollisionBlock(BoxComponent boxComponent, int extendedCollisionBlock) {
|
||||||
CustomBlockData customBlockData = new CustomBlockDataBuilder()
|
CustomBlockData customBlockData = new CustomBlockDataBuilder()
|
||||||
.name(Constants.GEYSER_NAMESPACE + ":extended_collision_" + extendedCollisionBlock)
|
.name("extended_collision_" + extendedCollisionBlock)
|
||||||
.components(
|
.components(
|
||||||
new CustomBlockComponentsBuilder()
|
new CustomBlockComponentsBuilder()
|
||||||
.collisionBox(boxComponent)
|
.collisionBox(boxComponent)
|
||||||
.selectionBox(new BoxComponent(0, 0, 0, 0, 0, 0))
|
.selectionBox(BoxComponent.EMPTY_BOX)
|
||||||
|
.materialInstance("*", new MaterialInstance("glass", "alpha_test", false, false))
|
||||||
|
.lightDampening(0)
|
||||||
|
.geometry("geometry.invisible")
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
return customBlockData;
|
return customBlockData;
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren