mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 19:47:44 +01:00
Make Material an interface
This commit is contained in:
parent
5b044a2d38
commit
d685a7b136
@ -164,7 +164,7 @@ dependencies {
|
||||
}
|
||||
|
||||
api "com.github.Minestom:DependencyGetter:v1.0.1"
|
||||
implementation 'com.github.Minestom:MinestomDataGenerator:386c3ef9c0'
|
||||
implementation 'com.github.Minestom:MinestomDataGenerator:9f8b6a3748'
|
||||
|
||||
// Adventure, for user-interface
|
||||
api "net.kyori:adventure-api:$adventureVersion"
|
||||
|
@ -50,7 +50,7 @@ public final class BlockGenerator extends MinestomCodeGenerator {
|
||||
FieldSpec.builder(blockCN, constantName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.initializer(
|
||||
// Blocks.STONE = Block.fromNamespaceId("minecraft:stone")
|
||||
// Block.STONE = Block.fromNamespaceId("minecraft:stone")
|
||||
"$T.fromNamespaceId($S)",
|
||||
blockCN,
|
||||
namespace
|
||||
|
@ -1,7 +1,5 @@
|
||||
package net.minestom.codegen.item;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.javapoet.*;
|
||||
import net.minestom.codegen.MinestomCodeGenerator;
|
||||
@ -14,8 +12,8 @@ import javax.lang.model.element.Modifier;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class MaterialGenerator extends MinestomCodeGenerator {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MaterialGenerator.class);
|
||||
@ -34,308 +32,35 @@ public final class MaterialGenerator extends MinestomCodeGenerator {
|
||||
LOGGER.error("Stopped code generation for items.");
|
||||
return;
|
||||
}
|
||||
if (!outputFolder.exists() && !outputFolder.mkdirs()) {
|
||||
LOGGER.error("Output folder for code generation does not exist and could not be created.");
|
||||
return;
|
||||
}
|
||||
// Important classes we use alot
|
||||
ClassName namespaceIDClassName = ClassName.get("net.minestom.server.utils", "NamespaceID");
|
||||
ClassName blockClassName = ClassName.get("net.minestom.server.instance.block", "Block");
|
||||
ClassName registriesClassName = ClassName.get("net.minestom.server.registry", "Registries");
|
||||
ClassName blockCN = ClassName.get("net.minestom.server.instance.block", "Block");
|
||||
ParameterizedTypeName blocksCNSupplier = ParameterizedTypeName.get(ClassName.get(Supplier.class), blockCN);
|
||||
ClassName materialCN = ClassName.get("net.minestom.server.item", "Material");
|
||||
|
||||
JsonObject items = GSON.fromJson(new InputStreamReader(itemsFile), JsonObject.class);
|
||||
ClassName itemClassName = ClassName.get("net.minestom.server.item", "Material");
|
||||
|
||||
// Item
|
||||
TypeSpec.Builder itemClass = TypeSpec.enumBuilder(itemClassName)
|
||||
.addSuperinterface(ClassName.get("net.kyori.adventure.key", "Keyed"))
|
||||
.addModifiers(Modifier.PUBLIC).addJavadoc("AUTOGENERATED by " + getClass().getSimpleName());
|
||||
|
||||
itemClass.addField(
|
||||
FieldSpec.builder(namespaceIDClassName, "id")
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.FINAL).addAnnotation(NotNull.class).build()
|
||||
);
|
||||
itemClass.addField(
|
||||
FieldSpec.builder(TypeName.BYTE, "maxDefaultStackSize")
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()
|
||||
);
|
||||
itemClass.addField(
|
||||
FieldSpec.builder(blocksCNSupplier, "correspondingBlockSupplier")
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.FINAL).build()
|
||||
);
|
||||
// static field
|
||||
itemClass.addField(
|
||||
FieldSpec.builder(ArrayTypeName.of(itemClassName), "VALUES")
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
|
||||
.initializer("values()")
|
||||
.build()
|
||||
);
|
||||
itemClass.addMethod(
|
||||
MethodSpec.constructorBuilder()
|
||||
.addParameter(ParameterSpec.builder(namespaceIDClassName, "id").addAnnotation(NotNull.class).build())
|
||||
.addParameter(TypeName.BYTE, "maxDefaultStackSize")
|
||||
.addParameter(ParameterSpec.builder(blocksCNSupplier, "correspondingBlockSupplier").addAnnotation(NotNull.class).build())
|
||||
.addStatement("this.id = id")
|
||||
.addStatement("this.maxDefaultStackSize = maxDefaultStackSize")
|
||||
.addStatement("this.correspondingBlockSupplier = correspondingBlockSupplier")
|
||||
.addStatement("$T.materials.put(id, this)", registriesClassName)
|
||||
.build()
|
||||
);
|
||||
// Override key method (adventure)
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("key")
|
||||
.returns(ClassName.get("net.kyori.adventure.key", "Key"))
|
||||
.addAnnotation(Override.class)
|
||||
.addAnnotation(NotNull.class)
|
||||
.addStatement("return this.id")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// getId method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("getId")
|
||||
.returns(TypeName.SHORT)
|
||||
.addStatement("return (short) ordinal()")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// getNamespaceID method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("getNamespaceID")
|
||||
.returns(namespaceIDClassName)
|
||||
.addAnnotation(NotNull.class)
|
||||
.addStatement("return this.id")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// getName method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("getName")
|
||||
.addAnnotation(NotNull.class)
|
||||
.returns(ClassName.get(String.class))
|
||||
.addStatement("return this.id.asString()")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// getMaxDefaultStackSize
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("getMaxDefaultStackSize")
|
||||
.returns(TypeName.BYTE)
|
||||
.addStatement("return this.maxDefaultStackSize")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// fromId Method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("fromId")
|
||||
.returns(itemClassName)
|
||||
.addAnnotation(Nullable.class)
|
||||
.addParameter(TypeName.SHORT, "id")
|
||||
.beginControlFlow("if(id >= 0 && id < VALUES.length)")
|
||||
.addStatement("return VALUES[id]")
|
||||
.endControlFlow()
|
||||
.addStatement("return null")
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
|
||||
.build()
|
||||
);
|
||||
// isFood method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isFood")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// hasState method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("hasState")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.beginControlFlow("if (this == BOW || this == TRIDENT || this == CROSSBOW || this == SHIELD)")
|
||||
.addStatement("return true")
|
||||
.nextControlFlow("else")
|
||||
.addStatement("return isFood()")
|
||||
.endControlFlow()
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isBlock method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isBlock")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement(
|
||||
"return this.correspondingBlockSupplier.get() != null && this.correspondingBlockSupplier.get() != $T.AIR",
|
||||
blockCN
|
||||
)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isArmor method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isArmor")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isHelmet method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isHelmet")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isChestplate method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isChestplate")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isLeggings method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isLeggings")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// isBoots method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("isBoots")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addStatement("return false")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// getBlock method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("getBlock")
|
||||
.addAnnotation(Nullable.class)
|
||||
.returns(blockCN)
|
||||
.addStatement("return this.correspondingBlockSupplier.get()")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
// toString method
|
||||
itemClass.addMethod(
|
||||
MethodSpec.methodBuilder("toString")
|
||||
.addAnnotation(NotNull.class)
|
||||
.addAnnotation(Override.class)
|
||||
.returns(String.class)
|
||||
// this resolves to [Namespace]
|
||||
.addStatement("return \"[\" + this.id + \"]\"")
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.build()
|
||||
);
|
||||
JsonObject items;
|
||||
items = GSON.fromJson(new InputStreamReader(itemsFile), JsonObject.class);
|
||||
ClassName materialsCN = ClassName.get("net.minestom.server.item", "MaterialConstants");
|
||||
// BlockConstants class
|
||||
TypeSpec.Builder blockConstantsClass = TypeSpec.interfaceBuilder(materialsCN)
|
||||
// Add @SuppressWarnings("unused")
|
||||
.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unused").build())
|
||||
.addJavadoc("AUTOGENERATED by " + getClass().getSimpleName());
|
||||
|
||||
// Use data
|
||||
items.entrySet().forEach(entry -> {
|
||||
final String itemNamespace = entry.getKey();
|
||||
final String itemConstant = toConstant(itemNamespace);
|
||||
|
||||
JsonObject item = entry.getValue().getAsJsonObject();
|
||||
|
||||
TypeSpec.Builder enumConst;
|
||||
if (!(item.get("blockId").getAsString().equals("minecraft:air"))) {
|
||||
enumConst = TypeSpec.anonymousClassBuilder(
|
||||
"$T.from($S), (byte) $L, () -> $T.$L",
|
||||
namespaceIDClassName,
|
||||
itemNamespace,
|
||||
item.get("maxStackSize").getAsInt(),
|
||||
// Supplier
|
||||
blockClassName,
|
||||
toConstant(item.get("blockId").getAsString())
|
||||
);
|
||||
} else {
|
||||
enumConst = TypeSpec.anonymousClassBuilder(
|
||||
"$T.from($S), (byte) $L, () -> null",
|
||||
namespaceIDClassName,
|
||||
itemNamespace,
|
||||
item.get("maxStackSize").getAsInt()
|
||||
);
|
||||
}
|
||||
if (item.get("edible").getAsBoolean()) {
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isFood")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
}
|
||||
if (item.get("armorProperties") != null) {
|
||||
JsonObject ap = item.get("armorProperties").getAsJsonObject();
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isArmor")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
if (ap.get("slot") != null) {
|
||||
switch (ap.get("slot").getAsString()) {
|
||||
case "head": {
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isHelmet")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "chest": {
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isChestplate")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "legs": {
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isLeggings")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "feet": {
|
||||
enumConst.addMethod(
|
||||
MethodSpec.methodBuilder("isBoots")
|
||||
.returns(TypeName.BOOLEAN)
|
||||
.addAnnotation(Override.class)
|
||||
.addModifiers(Modifier.PUBLIC)
|
||||
.addStatement("return true")
|
||||
.build()
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
itemClass.addEnumConstant(itemConstant, enumConst.build());
|
||||
items.keySet().forEach(namespace -> {
|
||||
final String constantName = namespace.replace("minecraft:", "").toUpperCase(Locale.ROOT);
|
||||
blockConstantsClass.addField(
|
||||
FieldSpec.builder(materialCN, constantName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.initializer(
|
||||
// Material.STONE = Material.fromNamespaceId("minecraft:stone")
|
||||
"$T.fromNamespaceId($S)",
|
||||
materialCN,
|
||||
namespace
|
||||
)
|
||||
.build()
|
||||
);
|
||||
});
|
||||
|
||||
// Write files to outputFolder
|
||||
writeFiles(
|
||||
Collections.singletonList(
|
||||
JavaFile.builder("net.minestom.server.item", itemClass.build())
|
||||
List.of(
|
||||
JavaFile.builder("net.minestom.server.item", blockConstantsClass.build())
|
||||
.indent(" ")
|
||||
.skipJavaLangImports(true)
|
||||
.build()
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
package net.minestom.server.entity;
|
||||
|
||||
import net.minestom.server.event.item.EntityEquipEvent;
|
||||
import net.minestom.server.item.attribute.AttributeSlot;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -20,8 +19,7 @@ public enum EquipmentSlot {
|
||||
return !isHand();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static EquipmentSlot fromAttributeSlot(AttributeSlot attributeSlot) {
|
||||
public static EquipmentSlot fromAttributeSlot(@NotNull AttributeSlot attributeSlot) {
|
||||
switch (attributeSlot) {
|
||||
case MAINHAND:
|
||||
return MAIN_HAND;
|
||||
@ -38,5 +36,4 @@ public enum EquipmentSlot {
|
||||
}
|
||||
throw new IllegalStateException("Something weird happened");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* Loads {@link Block blocks} from file.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
class BlockLoader {
|
||||
final class BlockLoader {
|
||||
|
||||
// Maps do not need to be thread-safe as they are fully populated
|
||||
// in the static initializer, should not be modified during runtime
|
||||
@ -39,11 +39,11 @@ class BlockLoader {
|
||||
return NAMESPACE_MAP.get(namespace);
|
||||
}
|
||||
|
||||
static @Nullable Block getId(int id) {
|
||||
static Block getId(int id) {
|
||||
return BLOCK_ID_MAP.get(id);
|
||||
}
|
||||
|
||||
static @Nullable Block getState(int stateId) {
|
||||
static Block getState(int stateId) {
|
||||
return BLOCK_STATE_MAP.get(stateId);
|
||||
}
|
||||
|
||||
@ -59,23 +59,23 @@ class BlockLoader {
|
||||
final JsonObject blockObject = entry.getValue().getAsJsonObject();
|
||||
final JsonObject stateObject = blockObject.remove("states").getAsJsonObject();
|
||||
|
||||
retrieveState(blockObject, stateObject);
|
||||
retrieveState(blockNamespace, blockObject, stateObject);
|
||||
final int defaultState = blockObject.get("defaultStateId").getAsInt();
|
||||
final Block defaultBlock = getState(defaultState);
|
||||
final int id = blockObject.get("id").getAsInt();
|
||||
BLOCK_ID_MAP.put(id, defaultBlock);
|
||||
BLOCK_ID_MAP.put(defaultBlock.id(), defaultBlock);
|
||||
NAMESPACE_MAP.put(blockNamespace, defaultBlock);
|
||||
});
|
||||
}
|
||||
|
||||
private static void retrieveState(JsonObject object, JsonObject stateObject) {
|
||||
private static void retrieveState(String namespace, JsonObject object, JsonObject stateObject) {
|
||||
PropertyEntry propertyEntry = new PropertyEntry();
|
||||
stateObject.entrySet().forEach(stateEntry -> {
|
||||
final String query = stateEntry.getKey();
|
||||
JsonObject stateOverride = stateEntry.getValue().getAsJsonObject();
|
||||
final int stateId = stateOverride.get("stateId").getAsInt();
|
||||
final var propertyMap = BlockUtils.parseProperties(query);
|
||||
final Block block = new BlockImpl(Registry.block(object, stateOverride), propertyEntry, propertyMap, null, null);
|
||||
final Block block = new BlockImpl(Registry.block(namespace, object, stateOverride),
|
||||
propertyEntry, propertyMap, null, null);
|
||||
BLOCK_STATE_MAP.put(stateId, block);
|
||||
propertyEntry.map.put(propertyMap, block);
|
||||
});
|
||||
|
75
src/main/java/net/minestom/server/item/Material.java
Normal file
75
src/main/java/net/minestom/server/item/Material.java
Normal file
@ -0,0 +1,75 @@
|
||||
package net.minestom.server.item;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface Material extends ProtocolObject, MaterialConstants {
|
||||
/**
|
||||
* Returns the material registry.
|
||||
*
|
||||
* @return the material registry
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@NotNull Registry.MaterialEntry registry();
|
||||
|
||||
@Override
|
||||
default @NotNull NamespaceID namespace() {
|
||||
return registry().namespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
default int id() {
|
||||
return registry().id();
|
||||
}
|
||||
|
||||
default int maxStackSize() {
|
||||
return registry().maxStackSize();
|
||||
}
|
||||
|
||||
default boolean isFood() {
|
||||
return registry().isFood();
|
||||
}
|
||||
|
||||
default boolean isBlock() {
|
||||
return registry().block() != null;
|
||||
}
|
||||
|
||||
default Block block() {
|
||||
return registry().block();
|
||||
}
|
||||
|
||||
default boolean isArmor() {
|
||||
return registry().isArmor();
|
||||
}
|
||||
|
||||
default boolean hasState() {
|
||||
if (this == BOW || this == TRIDENT || this == CROSSBOW || this == SHIELD) {
|
||||
return true;
|
||||
} else {
|
||||
return isFood();
|
||||
}
|
||||
}
|
||||
|
||||
static @NotNull Collection<@NotNull Material> values() {
|
||||
return MaterialLoader.values();
|
||||
}
|
||||
|
||||
static Material fromNamespaceId(@NotNull String namespaceID) {
|
||||
return MaterialLoader.get(namespaceID);
|
||||
}
|
||||
|
||||
static Material fromNamespaceId(@NotNull NamespaceID namespaceID) {
|
||||
return fromNamespaceId(namespaceID.asString());
|
||||
}
|
||||
|
||||
static @Nullable Material fromId(int id) {
|
||||
return MaterialLoader.getId(id);
|
||||
}
|
||||
}
|
17
src/main/java/net/minestom/server/item/MaterialImpl.java
Normal file
17
src/main/java/net/minestom/server/item/MaterialImpl.java
Normal file
@ -0,0 +1,17 @@
|
||||
package net.minestom.server.item;
|
||||
|
||||
import net.minestom.server.registry.Registry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
final class MaterialImpl implements Material {
|
||||
private final Registry.MaterialEntry registry;
|
||||
|
||||
MaterialImpl(Registry.MaterialEntry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Registry.MaterialEntry registry() {
|
||||
return registry;
|
||||
}
|
||||
}
|
58
src/main/java/net/minestom/server/item/MaterialLoader.java
Normal file
58
src/main/java/net/minestom/server/item/MaterialLoader.java
Normal file
@ -0,0 +1,58 @@
|
||||
package net.minestom.server.item;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Loads {@link net.minestom.server.item.Material materials} from file.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
final class MaterialLoader {
|
||||
|
||||
// Maps do not need to be thread-safe as they are fully populated
|
||||
// in the static initializer, should not be modified during runtime
|
||||
|
||||
// Block namespace -> registry data
|
||||
private static final Map<String, Material> NAMESPACE_MAP = new HashMap<>();
|
||||
// Block id -> registry data
|
||||
private static final Int2ObjectMap<Material> MATERIAL_ID_MAP = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static @Nullable Material get(@NotNull String namespace) {
|
||||
if (namespace.indexOf(':') == -1) {
|
||||
// Default to minecraft namespace
|
||||
namespace = "minecraft:" + namespace;
|
||||
}
|
||||
return NAMESPACE_MAP.get(namespace);
|
||||
}
|
||||
|
||||
static Material getId(int id) {
|
||||
return MATERIAL_ID_MAP.get(id);
|
||||
}
|
||||
|
||||
static Collection<Material> values() {
|
||||
return Collections.unmodifiableCollection(NAMESPACE_MAP.values());
|
||||
}
|
||||
|
||||
static {
|
||||
// Load data from file
|
||||
JsonObject blocks = Registry.load(Registry.Resource.ITEM);
|
||||
blocks.entrySet().forEach(entry -> {
|
||||
final String namespace = entry.getKey();
|
||||
final JsonObject materialObject = entry.getValue().getAsJsonObject();
|
||||
|
||||
final Material material = new MaterialImpl(Registry.material(namespace, materialObject, null));
|
||||
MATERIAL_ID_MAP.put(material.id(), material);
|
||||
NAMESPACE_MAP.put(namespace, material);
|
||||
});
|
||||
}
|
||||
}
|
@ -181,7 +181,7 @@ public class CrossbowMeta extends ItemMeta implements ItemMetaBuilder.Provider<S
|
||||
private @NotNull NBTCompound getItemCompound(@NotNull ItemStack itemStack) {
|
||||
NBTCompound compound = itemStack.getMeta().toNBT();
|
||||
compound.setByte("Count", (byte) itemStack.getAmount());
|
||||
compound.setString("id", itemStack.getMaterial().getName());
|
||||
compound.setString("id", itemStack.getMaterial().name());
|
||||
return compound;
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class VanillaStackingRule implements StackingRule {
|
||||
|
||||
@Override
|
||||
public int getMaxSize(@NotNull ItemStack itemStack) {
|
||||
return itemStack.getMaterial().getMaxDefaultStackSize();
|
||||
return itemStack.getMaterial().maxStackSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -109,7 +109,7 @@ public class BlockPlacementListener {
|
||||
return;
|
||||
}
|
||||
|
||||
final Block placedBlock = useMaterial.getBlock();
|
||||
final Block placedBlock = useMaterial.block();
|
||||
final Set<Entity> entities = instance.getChunkEntities(chunk);
|
||||
// Check if the player is trying to place a block in an entity
|
||||
boolean intersect = player.getBoundingBox().intersectWithBlock(placementPosition);
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.minestom.server.listener;
|
||||
|
||||
import net.minestom.server.entity.EquipmentSlot;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.player.PlayerItemAnimationEvent;
|
||||
@ -30,21 +31,10 @@ public class UseItemListener {
|
||||
final Material material = itemStack.getMaterial();
|
||||
|
||||
// Equip armor with right click
|
||||
if (material.isArmor()) {
|
||||
ItemStack currentlyEquipped;
|
||||
if (material.isHelmet()) {
|
||||
currentlyEquipped = playerInventory.getHelmet();
|
||||
playerInventory.setHelmet(itemStack);
|
||||
} else if (material.isChestplate()) {
|
||||
currentlyEquipped = playerInventory.getChestplate();
|
||||
playerInventory.setChestplate(itemStack);
|
||||
} else if (material.isLeggings()) {
|
||||
currentlyEquipped = playerInventory.getLeggings();
|
||||
playerInventory.setLeggings(itemStack);
|
||||
} else {
|
||||
currentlyEquipped = playerInventory.getBoots();
|
||||
playerInventory.setBoots(itemStack);
|
||||
}
|
||||
final EquipmentSlot equipmentSlot = material.registry().equipmentSlot();
|
||||
if (equipmentSlot != null) {
|
||||
final ItemStack currentlyEquipped = playerInventory.getEquipment(equipmentSlot);
|
||||
playerInventory.setEquipment(equipmentSlot, itemStack);
|
||||
playerInventory.setItemInHand(hand, currentlyEquipped);
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ public class TagsPacket implements ServerPacket {
|
||||
writer.writeVarInt(values.size());
|
||||
// entries
|
||||
for (NamespaceID name : values) {
|
||||
writer.writeVarInt(Registries.getMaterial(name).ordinal());
|
||||
writer.writeVarInt(Registries.getMaterial(name).id());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -4,6 +4,8 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minestom.server.entity.EquipmentSlot;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@ -17,8 +19,12 @@ import java.util.function.Supplier;
|
||||
public class Registry {
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
|
||||
public static BlockEntry block(@NotNull JsonObject jsonObject, JsonObject override) {
|
||||
return new BlockEntry(jsonObject, override);
|
||||
public static BlockEntry block(String namespace, @NotNull JsonObject jsonObject, JsonObject override) {
|
||||
return new BlockEntry(namespace, jsonObject, override);
|
||||
}
|
||||
|
||||
public static MaterialEntry material(String namespace, @NotNull JsonObject jsonObject, JsonObject override) {
|
||||
return new MaterialEntry(namespace, jsonObject, override);
|
||||
}
|
||||
|
||||
public static JsonObject load(Resource resource) {
|
||||
@ -28,7 +34,8 @@ public class Registry {
|
||||
}
|
||||
|
||||
public enum Resource {
|
||||
BLOCK("blocks");
|
||||
BLOCK("blocks"),
|
||||
ITEM("items");
|
||||
|
||||
private final String name;
|
||||
|
||||
@ -52,9 +59,9 @@ public class Registry {
|
||||
private final String blockEntity;
|
||||
private final Supplier<Material> materialSupplier;
|
||||
|
||||
private BlockEntry(JsonObject main, JsonObject override) {
|
||||
private BlockEntry(String namespace, JsonObject main, JsonObject override) {
|
||||
super(main, override);
|
||||
this.namespace = NamespaceID.from(getString("namespaceId"));
|
||||
this.namespace = NamespaceID.from(namespace);
|
||||
this.id = getInt("id");
|
||||
this.stateId = getInt("stateId");
|
||||
this.hardness = getDouble("hardness");
|
||||
@ -129,6 +136,81 @@ public class Registry {
|
||||
}
|
||||
}
|
||||
|
||||
public static class MaterialEntry extends Entry {
|
||||
private final NamespaceID namespace;
|
||||
private final int id;
|
||||
private final int maxStackSize;
|
||||
private final boolean isFood;
|
||||
private final Supplier<Block> blockSupplier;
|
||||
private final EquipmentSlot equipmentSlot;
|
||||
|
||||
private MaterialEntry(String namespace, JsonObject main, JsonObject override) {
|
||||
super(main, override);
|
||||
this.namespace = NamespaceID.from(namespace);
|
||||
this.id = getInt("id");
|
||||
this.maxStackSize = getInt("maxStackSize", 64);
|
||||
this.isFood = getBoolean("edible", false);
|
||||
{
|
||||
final String blockNamespace = getString("correspondingBlock", null);
|
||||
this.blockSupplier = blockNamespace != null ? () -> Block.fromNamespaceId(blockNamespace) : () -> null;
|
||||
}
|
||||
|
||||
{
|
||||
final var armorProperties = element("armorProperties");
|
||||
if (armorProperties != null) {
|
||||
final String slot = armorProperties.getAsJsonObject().get("slot").getAsString();
|
||||
switch (slot) {
|
||||
case "feet":
|
||||
this.equipmentSlot = EquipmentSlot.BOOTS;
|
||||
break;
|
||||
case "legs":
|
||||
this.equipmentSlot = EquipmentSlot.LEGGINGS;
|
||||
break;
|
||||
case "chest":
|
||||
this.equipmentSlot = EquipmentSlot.CHESTPLATE;
|
||||
break;
|
||||
case "head":
|
||||
this.equipmentSlot = EquipmentSlot.HELMET;
|
||||
break;
|
||||
default:
|
||||
this.equipmentSlot = null;
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
this.equipmentSlot = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public @NotNull NamespaceID namespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int maxStackSize() {
|
||||
return maxStackSize;
|
||||
}
|
||||
|
||||
public boolean isFood() {
|
||||
return isFood;
|
||||
}
|
||||
|
||||
public @Nullable Block block() {
|
||||
return blockSupplier.get();
|
||||
}
|
||||
|
||||
public boolean isArmor() {
|
||||
return equipmentSlot != null;
|
||||
}
|
||||
|
||||
public @Nullable EquipmentSlot equipmentSlot() {
|
||||
return equipmentSlot;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entry {
|
||||
private final JsonObject main, override;
|
||||
|
||||
@ -174,7 +256,7 @@ public class Registry {
|
||||
}
|
||||
|
||||
protected JsonElement element(String name) {
|
||||
if (override.has(name)) {
|
||||
if (override != null && override.has(name)) {
|
||||
return override.get(name);
|
||||
}
|
||||
return main.get(name);
|
||||
|
@ -93,7 +93,7 @@ public final class NBTUtils {
|
||||
nbt.set("tag", tag);
|
||||
nbt.setByte("Slot", (byte) i);
|
||||
nbt.setByte("Count", (byte) stack.getAmount());
|
||||
nbt.setString("id", stack.getMaterial().getName());
|
||||
nbt.setString("id", stack.getMaterial().name());
|
||||
|
||||
list.add(nbt);
|
||||
}
|
||||
|
@ -269,7 +269,7 @@ public class BinaryWriter extends OutputStream {
|
||||
writeBoolean(false);
|
||||
} else {
|
||||
writeBoolean(true);
|
||||
writeVarInt(itemStack.getMaterial().getId());
|
||||
writeVarInt(itemStack.getMaterial().id());
|
||||
writeByte((byte) itemStack.getAmount());
|
||||
write(itemStack.getMeta());
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class CampfireHandler implements BlockHandler {
|
||||
NBTCompound compound = new NBTCompound()
|
||||
.setByte("Count", (byte) item.getAmount())
|
||||
.setByte("Slot", (byte) 1)
|
||||
.setString("id", item.getMaterial().getNamespaceID().asString());
|
||||
.setString("id", item.getMaterial().name());
|
||||
items.add(compound);
|
||||
}
|
||||
writer.setTag(internal, items);
|
||||
|
Loading…
Reference in New Issue
Block a user