mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-13 10:51:44 +01:00
feat: first pass of standardizing dynamic registries
This commit is contained in:
parent
5fb5c82192
commit
aa697a4f94
@ -23,6 +23,7 @@ allprojects {
|
||||
description = shortDescription
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
maven(url = "https://jitpack.io")
|
||||
}
|
||||
|
@ -69,6 +69,49 @@ public class CodeGenerator {
|
||||
outputFolder);
|
||||
}
|
||||
|
||||
public void generateKeys(InputStream resourceFile, String packageName, String typeName, String generatedName) {
|
||||
if (resourceFile == null) {
|
||||
LOGGER.error("Failed to find resource file for " + typeName);
|
||||
return;
|
||||
}
|
||||
ClassName typeClass = ClassName.get(packageName, typeName);
|
||||
ClassName namespaceIdClass = ClassName.get("net.minestom.server.utils", "NamespaceID");
|
||||
|
||||
JsonObject json;
|
||||
json = GSON.fromJson(new InputStreamReader(resourceFile), JsonObject.class);
|
||||
ClassName materialsCN = ClassName.get(packageName, generatedName);
|
||||
// BlockConstants class
|
||||
TypeSpec.Builder blockConstantsClass = TypeSpec.interfaceBuilder(materialsCN)
|
||||
// Add @SuppressWarnings("unused")
|
||||
.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class).addMember("value", "$S", "unused").build())
|
||||
.addJavadoc("Code autogenerated, do not edit!");
|
||||
|
||||
// Use data
|
||||
json.keySet().forEach(namespace -> {
|
||||
final String constantName = namespace
|
||||
.replace("minecraft:", "")
|
||||
.replace(".", "_")
|
||||
.toUpperCase(Locale.ROOT);
|
||||
blockConstantsClass.addField(
|
||||
FieldSpec.builder(namespaceIdClass, constantName)
|
||||
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
|
||||
.initializer(
|
||||
// TypeClass.STONE = NamespaceID.from("minecraft:stone")
|
||||
"$T.from($S)",
|
||||
namespaceIdClass,
|
||||
namespace
|
||||
)
|
||||
.build()
|
||||
);
|
||||
});
|
||||
writeFiles(
|
||||
List.of(JavaFile.builder(packageName, blockConstantsClass.build())
|
||||
.indent(" ")
|
||||
.skipJavaLangImports(true)
|
||||
.build()),
|
||||
outputFolder);
|
||||
}
|
||||
|
||||
private void writeFiles(@NotNull List<JavaFile> fileList, File outputFolder) {
|
||||
for (JavaFile javaFile : fileList) {
|
||||
try {
|
||||
|
@ -23,23 +23,30 @@ public class Generators {
|
||||
new DyeColorGenerator(resource("dye_colors.json"), outputFolder).generate();
|
||||
new RecipeTypeGenerator(resource("recipe_types.json"), outputFolder).generate();
|
||||
|
||||
// Generic protocol object
|
||||
var generator = new CodeGenerator(outputFolder);
|
||||
|
||||
// Static registries
|
||||
generator.generate(resource("blocks.json"), "net.minestom.server.instance.block", "Block", "BlockImpl", "Blocks");
|
||||
generator.generate(resource("items.json"), "net.minestom.server.item", "Material", "MaterialImpl", "Materials");
|
||||
generator.generate(resource("entities.json"), "net.minestom.server.entity", "EntityType", "EntityTypeImpl", "EntityTypes");
|
||||
generator.generate(resource("biomes.json"), "net.minestom.server.world.biomes", "Biome", "BiomeImpl", "Biomes");
|
||||
generator.generate(resource("enchantments.json"), "net.minestom.server.item.enchant", "Enchantment", "EnchantmentImpl", "Enchantments");
|
||||
generator.generate(resource("potion_effects.json"), "net.minestom.server.potion", "PotionEffect", "PotionEffectImpl", "PotionEffects");
|
||||
generator.generate(resource("potions.json"), "net.minestom.server.potion", "PotionType", "PotionTypeImpl", "PotionTypes");
|
||||
generator.generate(resource("particles.json"), "net.minestom.server.particle", "Particle", "ParticleImpl", "Particles");
|
||||
generator.generate(resource("sounds.json"), "net.minestom.server.sound", "SoundEvent", "BuiltinSoundEvent", "SoundEvents");
|
||||
generator.generate(resource("custom_statistics.json"), "net.minestom.server.statistic", "StatisticType", "StatisticTypeImpl", "StatisticTypes");
|
||||
generator.generate(resource("damage_types.json"), "net.minestom.server.entity.damage", "DamageType", "DamageTypeImpl", "DamageTypes");
|
||||
generator.generate(resource("trim_materials.json"), "net.minestom.server.item.armor", "TrimMaterial", "TrimMaterialImpl", "TrimMaterials");
|
||||
generator.generate(resource("trim_patterns.json"), "net.minestom.server.item.armor", "TrimPattern", "TrimPatternImpl", "TrimPatterns");
|
||||
generator.generate(resource("attributes.json"), "net.minestom.server.entity.attribute", "Attribute", "AttributeImpl", "Attributes");
|
||||
|
||||
// Dynamic registries
|
||||
generator.generateKeys(resource("chat_types.json"), "net.minestom.server.message", "ChatType", "ChatTypes");
|
||||
generator.generateKeys(resource("dimension_types.json"), "net.minestom.server.world", "DimensionType", "DimensionTypes");
|
||||
generator.generateKeys(resource("biomes.json"), "net.minestom.server.world.biome", "Biome", "Biomes");
|
||||
generator.generateKeys(resource("damage_types.json"), "net.minestom.server.entity.damage", "DamageType", "DamageTypes");
|
||||
generator.generateKeys(resource("trim_materials.json"), "net.minestom.server.item.armor", "TrimMaterial", "TrimMaterials");
|
||||
generator.generateKeys(resource("trim_patterns.json"), "net.minestom.server.item.armor", "TrimPattern", "TrimPatterns");
|
||||
generator.generateKeys(resource("banner_patterns.json"), "net.minestom.server.instance.block.banner", "BannerPattern", "BannerPatterns");
|
||||
generator.generateKeys(resource("wolf_variants.json"), "net.minestom.server.entity.metadata.animal.tameable", "Wolf$Variant", "WolfVariants");
|
||||
|
||||
// Generate fluids
|
||||
new FluidGenerator(resource("fluids.json"), outputFolder).generate();
|
||||
|
||||
|
@ -37,7 +37,7 @@ public final class FluidGenerator extends MinestomCodeGenerator {
|
||||
}
|
||||
// Important classes we use alot
|
||||
ClassName namespaceIDClassName = ClassName.get("net.minestom.server.utils", "NamespaceID");
|
||||
ClassName registriesClassName = ClassName.get("net.minestom.server.registry", "Registries");
|
||||
ClassName registriesClassName = ClassName.get("net.minestom.server.registry", "FluidRegistries");
|
||||
|
||||
JsonObject fluids = GSON.fromJson(new InputStreamReader(fluidsFile), JsonObject.class);
|
||||
ClassName fluidClassName = ClassName.get("net.minestom.server.fluid", "Fluid");
|
||||
|
@ -39,7 +39,6 @@ public class Main {
|
||||
MinecraftServer.setCompressionThreshold(0);
|
||||
|
||||
MinecraftServer minecraftServer = MinecraftServer.init();
|
||||
MinecraftServer.getBiomeManager().loadVanillaBiomes();
|
||||
|
||||
BlockManager blockManager = MinecraftServer.getBlockManager();
|
||||
blockManager.registerBlockPlacementRule(new DripstonePlacementRule());
|
||||
|
@ -42,7 +42,6 @@ import net.minestom.server.potion.CustomPotionEffect;
|
||||
import net.minestom.server.potion.PotionEffect;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.time.TimeUnit;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
@ -181,7 +180,7 @@ public class PlayerInit {
|
||||
static {
|
||||
InstanceManager instanceManager = MinecraftServer.getInstanceManager();
|
||||
|
||||
InstanceContainer instanceContainer = instanceManager.createInstanceContainer(DimensionType.OVERWORLD);
|
||||
InstanceContainer instanceContainer = instanceManager.createInstanceContainer();
|
||||
instanceContainer.setGenerator(unit -> {
|
||||
unit.modifier().fillHeight(0, 40, Block.STONE);
|
||||
|
||||
|
@ -3,12 +3,9 @@ metadata.format.version = "1.1"
|
||||
[versions]
|
||||
|
||||
# Important dependencies
|
||||
data = "1.20.5-rv1"
|
||||
data = "1.20.5-dev"
|
||||
adventure = "4.16.0"
|
||||
kotlin = "1.7.22"
|
||||
dependencyGetter = "v1.0.1"
|
||||
hydrazine = "1.7.2"
|
||||
hephaistos = "2.6.1"
|
||||
jetbrainsAnnotations = "23.0.0"
|
||||
slf4j = "2.0.7"
|
||||
|
||||
|
@ -1,97 +1,99 @@
|
||||
package net.minestom.server.entity.damage;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface DamageTypes {
|
||||
DamageType WITHER = DamageTypeImpl.get("minecraft:wither");
|
||||
NamespaceID WITHER = NamespaceID.from("minecraft:wither");
|
||||
|
||||
DamageType SONIC_BOOM = DamageTypeImpl.get("minecraft:sonic_boom");
|
||||
NamespaceID SONIC_BOOM = NamespaceID.from("minecraft:sonic_boom");
|
||||
|
||||
DamageType WITHER_SKULL = DamageTypeImpl.get("minecraft:wither_skull");
|
||||
NamespaceID WITHER_SKULL = NamespaceID.from("minecraft:wither_skull");
|
||||
|
||||
DamageType DRY_OUT = DamageTypeImpl.get("minecraft:dry_out");
|
||||
NamespaceID DRY_OUT = NamespaceID.from("minecraft:dry_out");
|
||||
|
||||
DamageType TRIDENT = DamageTypeImpl.get("minecraft:trident");
|
||||
NamespaceID TRIDENT = NamespaceID.from("minecraft:trident");
|
||||
|
||||
DamageType ON_FIRE = DamageTypeImpl.get("minecraft:on_fire");
|
||||
NamespaceID ON_FIRE = NamespaceID.from("minecraft:on_fire");
|
||||
|
||||
DamageType FALL = DamageTypeImpl.get("minecraft:fall");
|
||||
NamespaceID FALL = NamespaceID.from("minecraft:fall");
|
||||
|
||||
DamageType MOB_ATTACK = DamageTypeImpl.get("minecraft:mob_attack");
|
||||
NamespaceID MOB_ATTACK = NamespaceID.from("minecraft:mob_attack");
|
||||
|
||||
DamageType MOB_PROJECTILE = DamageTypeImpl.get("minecraft:mob_projectile");
|
||||
NamespaceID MOB_PROJECTILE = NamespaceID.from("minecraft:mob_projectile");
|
||||
|
||||
DamageType THROWN = DamageTypeImpl.get("minecraft:thrown");
|
||||
NamespaceID THROWN = NamespaceID.from("minecraft:thrown");
|
||||
|
||||
DamageType FALLING_STALACTITE = DamageTypeImpl.get("minecraft:falling_stalactite");
|
||||
NamespaceID FALLING_STALACTITE = NamespaceID.from("minecraft:falling_stalactite");
|
||||
|
||||
DamageType FIREBALL = DamageTypeImpl.get("minecraft:fireball");
|
||||
NamespaceID FIREBALL = NamespaceID.from("minecraft:fireball");
|
||||
|
||||
DamageType FALLING_BLOCK = DamageTypeImpl.get("minecraft:falling_block");
|
||||
NamespaceID FALLING_BLOCK = NamespaceID.from("minecraft:falling_block");
|
||||
|
||||
DamageType PLAYER_EXPLOSION = DamageTypeImpl.get("minecraft:player_explosion");
|
||||
NamespaceID PLAYER_EXPLOSION = NamespaceID.from("minecraft:player_explosion");
|
||||
|
||||
DamageType SPIT = DamageTypeImpl.get("minecraft:spit");
|
||||
NamespaceID SPIT = NamespaceID.from("minecraft:spit");
|
||||
|
||||
DamageType STING = DamageTypeImpl.get("minecraft:sting");
|
||||
NamespaceID STING = NamespaceID.from("minecraft:sting");
|
||||
|
||||
DamageType UNATTRIBUTED_FIREBALL = DamageTypeImpl.get("minecraft:unattributed_fireball");
|
||||
NamespaceID UNATTRIBUTED_FIREBALL = NamespaceID.from("minecraft:unattributed_fireball");
|
||||
|
||||
DamageType IN_WALL = DamageTypeImpl.get("minecraft:in_wall");
|
||||
NamespaceID IN_WALL = NamespaceID.from("minecraft:in_wall");
|
||||
|
||||
DamageType IN_FIRE = DamageTypeImpl.get("minecraft:in_fire");
|
||||
NamespaceID IN_FIRE = NamespaceID.from("minecraft:in_fire");
|
||||
|
||||
DamageType ARROW = DamageTypeImpl.get("minecraft:arrow");
|
||||
NamespaceID ARROW = NamespaceID.from("minecraft:arrow");
|
||||
|
||||
DamageType HOT_FLOOR = DamageTypeImpl.get("minecraft:hot_floor");
|
||||
NamespaceID HOT_FLOOR = NamespaceID.from("minecraft:hot_floor");
|
||||
|
||||
DamageType DROWN = DamageTypeImpl.get("minecraft:drown");
|
||||
NamespaceID DROWN = NamespaceID.from("minecraft:drown");
|
||||
|
||||
DamageType STARVE = DamageTypeImpl.get("minecraft:starve");
|
||||
NamespaceID STARVE = NamespaceID.from("minecraft:starve");
|
||||
|
||||
DamageType GENERIC_KILL = DamageTypeImpl.get("minecraft:generic_kill");
|
||||
NamespaceID GENERIC_KILL = NamespaceID.from("minecraft:generic_kill");
|
||||
|
||||
DamageType DRAGON_BREATH = DamageTypeImpl.get("minecraft:dragon_breath");
|
||||
NamespaceID DRAGON_BREATH = NamespaceID.from("minecraft:dragon_breath");
|
||||
|
||||
DamageType MOB_ATTACK_NO_AGGRO = DamageTypeImpl.get("minecraft:mob_attack_no_aggro");
|
||||
NamespaceID MOB_ATTACK_NO_AGGRO = NamespaceID.from("minecraft:mob_attack_no_aggro");
|
||||
|
||||
DamageType LAVA = DamageTypeImpl.get("minecraft:lava");
|
||||
NamespaceID LAVA = NamespaceID.from("minecraft:lava");
|
||||
|
||||
DamageType OUTSIDE_BORDER = DamageTypeImpl.get("minecraft:outside_border");
|
||||
NamespaceID OUTSIDE_BORDER = NamespaceID.from("minecraft:outside_border");
|
||||
|
||||
DamageType FLY_INTO_WALL = DamageTypeImpl.get("minecraft:fly_into_wall");
|
||||
NamespaceID FLY_INTO_WALL = NamespaceID.from("minecraft:fly_into_wall");
|
||||
|
||||
DamageType LIGHTNING_BOLT = DamageTypeImpl.get("minecraft:lightning_bolt");
|
||||
NamespaceID LIGHTNING_BOLT = NamespaceID.from("minecraft:lightning_bolt");
|
||||
|
||||
DamageType PLAYER_ATTACK = DamageTypeImpl.get("minecraft:player_attack");
|
||||
NamespaceID PLAYER_ATTACK = NamespaceID.from("minecraft:player_attack");
|
||||
|
||||
DamageType FREEZE = DamageTypeImpl.get("minecraft:freeze");
|
||||
NamespaceID FREEZE = NamespaceID.from("minecraft:freeze");
|
||||
|
||||
DamageType FALLING_ANVIL = DamageTypeImpl.get("minecraft:falling_anvil");
|
||||
NamespaceID FALLING_ANVIL = NamespaceID.from("minecraft:falling_anvil");
|
||||
|
||||
DamageType OUT_OF_WORLD = DamageTypeImpl.get("minecraft:out_of_world");
|
||||
NamespaceID OUT_OF_WORLD = NamespaceID.from("minecraft:out_of_world");
|
||||
|
||||
DamageType MAGIC = DamageTypeImpl.get("minecraft:magic");
|
||||
NamespaceID MAGIC = NamespaceID.from("minecraft:magic");
|
||||
|
||||
DamageType SWEET_BERRY_BUSH = DamageTypeImpl.get("minecraft:sweet_berry_bush");
|
||||
NamespaceID SWEET_BERRY_BUSH = NamespaceID.from("minecraft:sweet_berry_bush");
|
||||
|
||||
DamageType FIREWORKS = DamageTypeImpl.get("minecraft:fireworks");
|
||||
NamespaceID FIREWORKS = NamespaceID.from("minecraft:fireworks");
|
||||
|
||||
DamageType EXPLOSION = DamageTypeImpl.get("minecraft:explosion");
|
||||
NamespaceID EXPLOSION = NamespaceID.from("minecraft:explosion");
|
||||
|
||||
DamageType BAD_RESPAWN_POINT = DamageTypeImpl.get("minecraft:bad_respawn_point");
|
||||
NamespaceID BAD_RESPAWN_POINT = NamespaceID.from("minecraft:bad_respawn_point");
|
||||
|
||||
DamageType STALAGMITE = DamageTypeImpl.get("minecraft:stalagmite");
|
||||
NamespaceID STALAGMITE = NamespaceID.from("minecraft:stalagmite");
|
||||
|
||||
DamageType THORNS = DamageTypeImpl.get("minecraft:thorns");
|
||||
NamespaceID THORNS = NamespaceID.from("minecraft:thorns");
|
||||
|
||||
DamageType INDIRECT_MAGIC = DamageTypeImpl.get("minecraft:indirect_magic");
|
||||
NamespaceID INDIRECT_MAGIC = NamespaceID.from("minecraft:indirect_magic");
|
||||
|
||||
DamageType CRAMMING = DamageTypeImpl.get("minecraft:cramming");
|
||||
NamespaceID CRAMMING = NamespaceID.from("minecraft:cramming");
|
||||
|
||||
DamageType CACTUS = DamageTypeImpl.get("minecraft:cactus");
|
||||
NamespaceID CACTUS = NamespaceID.from("minecraft:cactus");
|
||||
|
||||
DamageType GENERIC = DamageTypeImpl.get("minecraft:generic");
|
||||
NamespaceID GENERIC = NamespaceID.from("minecraft:generic");
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
package net.minestom.server.entity.metadata.animal.tameable;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface WolfVariants {
|
||||
NamespaceID BLACK = NamespaceID.from("minecraft:black");
|
||||
|
||||
NamespaceID CHESTNUT = NamespaceID.from("minecraft:chestnut");
|
||||
|
||||
NamespaceID SNOWY = NamespaceID.from("minecraft:snowy");
|
||||
|
||||
NamespaceID STRIPED = NamespaceID.from("minecraft:striped");
|
||||
|
||||
NamespaceID ASHEN = NamespaceID.from("minecraft:ashen");
|
||||
|
||||
NamespaceID SPOTTED = NamespaceID.from("minecraft:spotted");
|
||||
|
||||
NamespaceID RUSTY = NamespaceID.from("minecraft:rusty");
|
||||
|
||||
NamespaceID WOODS = NamespaceID.from("minecraft:woods");
|
||||
|
||||
NamespaceID PALE = NamespaceID.from("minecraft:pale");
|
||||
}
|
@ -2,7 +2,7 @@ package net.minestom.server.fluid;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.registry.FluidRegistries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -28,7 +28,7 @@ public enum Fluid implements Keyed {
|
||||
|
||||
Fluid(@NotNull NamespaceID id) {
|
||||
this.id = id;
|
||||
Registries.fluids.put(id, this);
|
||||
FluidRegistries.fluids.put(id, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,91 @@
|
||||
package net.minestom.server.instance.block.banner;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface BannerPatterns {
|
||||
NamespaceID BORDER = NamespaceID.from("minecraft:border");
|
||||
|
||||
NamespaceID SQUARE_BOTTOM_RIGHT = NamespaceID.from("minecraft:square_bottom_right");
|
||||
|
||||
NamespaceID STRIPE_RIGHT = NamespaceID.from("minecraft:stripe_right");
|
||||
|
||||
NamespaceID RHOMBUS = NamespaceID.from("minecraft:rhombus");
|
||||
|
||||
NamespaceID TRIANGLES_TOP = NamespaceID.from("minecraft:triangles_top");
|
||||
|
||||
NamespaceID GRADIENT = NamespaceID.from("minecraft:gradient");
|
||||
|
||||
NamespaceID GLOBE = NamespaceID.from("minecraft:globe");
|
||||
|
||||
NamespaceID MOJANG = NamespaceID.from("minecraft:mojang");
|
||||
|
||||
NamespaceID STRIPE_BOTTOM = NamespaceID.from("minecraft:stripe_bottom");
|
||||
|
||||
NamespaceID STRIPE_MIDDLE = NamespaceID.from("minecraft:stripe_middle");
|
||||
|
||||
NamespaceID FLOWER = NamespaceID.from("minecraft:flower");
|
||||
|
||||
NamespaceID DIAGONAL_UP_RIGHT = NamespaceID.from("minecraft:diagonal_up_right");
|
||||
|
||||
NamespaceID CIRCLE = NamespaceID.from("minecraft:circle");
|
||||
|
||||
NamespaceID HALF_HORIZONTAL = NamespaceID.from("minecraft:half_horizontal");
|
||||
|
||||
NamespaceID BRICKS = NamespaceID.from("minecraft:bricks");
|
||||
|
||||
NamespaceID TRIANGLE_BOTTOM = NamespaceID.from("minecraft:triangle_bottom");
|
||||
|
||||
NamespaceID CURLY_BORDER = NamespaceID.from("minecraft:curly_border");
|
||||
|
||||
NamespaceID BASE = NamespaceID.from("minecraft:base");
|
||||
|
||||
NamespaceID PIGLIN = NamespaceID.from("minecraft:piglin");
|
||||
|
||||
NamespaceID STRIPE_CENTER = NamespaceID.from("minecraft:stripe_center");
|
||||
|
||||
NamespaceID SQUARE_BOTTOM_LEFT = NamespaceID.from("minecraft:square_bottom_left");
|
||||
|
||||
NamespaceID SQUARE_TOP_RIGHT = NamespaceID.from("minecraft:square_top_right");
|
||||
|
||||
NamespaceID STRIPE_DOWNRIGHT = NamespaceID.from("minecraft:stripe_downright");
|
||||
|
||||
NamespaceID GRADIENT_UP = NamespaceID.from("minecraft:gradient_up");
|
||||
|
||||
NamespaceID DIAGONAL_RIGHT = NamespaceID.from("minecraft:diagonal_right");
|
||||
|
||||
NamespaceID HALF_VERTICAL_RIGHT = NamespaceID.from("minecraft:half_vertical_right");
|
||||
|
||||
NamespaceID SMALL_STRIPES = NamespaceID.from("minecraft:small_stripes");
|
||||
|
||||
NamespaceID CROSS = NamespaceID.from("minecraft:cross");
|
||||
|
||||
NamespaceID DIAGONAL_LEFT = NamespaceID.from("minecraft:diagonal_left");
|
||||
|
||||
NamespaceID SKULL = NamespaceID.from("minecraft:skull");
|
||||
|
||||
NamespaceID STRIPE_DOWNLEFT = NamespaceID.from("minecraft:stripe_downleft");
|
||||
|
||||
NamespaceID DIAGONAL_UP_LEFT = NamespaceID.from("minecraft:diagonal_up_left");
|
||||
|
||||
NamespaceID HALF_VERTICAL = NamespaceID.from("minecraft:half_vertical");
|
||||
|
||||
NamespaceID TRIANGLE_TOP = NamespaceID.from("minecraft:triangle_top");
|
||||
|
||||
NamespaceID HALF_HORIZONTAL_BOTTOM = NamespaceID.from("minecraft:half_horizontal_bottom");
|
||||
|
||||
NamespaceID SQUARE_TOP_LEFT = NamespaceID.from("minecraft:square_top_left");
|
||||
|
||||
NamespaceID STRIPE_TOP = NamespaceID.from("minecraft:stripe_top");
|
||||
|
||||
NamespaceID CREEPER = NamespaceID.from("minecraft:creeper");
|
||||
|
||||
NamespaceID STRIPE_LEFT = NamespaceID.from("minecraft:stripe_left");
|
||||
|
||||
NamespaceID TRIANGLES_BOTTOM = NamespaceID.from("minecraft:triangles_bottom");
|
||||
|
||||
NamespaceID STRAIGHT_CROSS = NamespaceID.from("minecraft:straight_cross");
|
||||
}
|
@ -1,27 +1,29 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface TrimMaterials {
|
||||
TrimMaterial LAPIS = TrimMaterialImpl.get("minecraft:lapis");
|
||||
NamespaceID LAPIS = NamespaceID.from("minecraft:lapis");
|
||||
|
||||
TrimMaterial IRON = TrimMaterialImpl.get("minecraft:iron");
|
||||
NamespaceID IRON = NamespaceID.from("minecraft:iron");
|
||||
|
||||
TrimMaterial DIAMOND = TrimMaterialImpl.get("minecraft:diamond");
|
||||
NamespaceID DIAMOND = NamespaceID.from("minecraft:diamond");
|
||||
|
||||
TrimMaterial AMETHYST = TrimMaterialImpl.get("minecraft:amethyst");
|
||||
NamespaceID AMETHYST = NamespaceID.from("minecraft:amethyst");
|
||||
|
||||
TrimMaterial COPPER = TrimMaterialImpl.get("minecraft:copper");
|
||||
NamespaceID COPPER = NamespaceID.from("minecraft:copper");
|
||||
|
||||
TrimMaterial QUARTZ = TrimMaterialImpl.get("minecraft:quartz");
|
||||
NamespaceID QUARTZ = NamespaceID.from("minecraft:quartz");
|
||||
|
||||
TrimMaterial EMERALD = TrimMaterialImpl.get("minecraft:emerald");
|
||||
NamespaceID EMERALD = NamespaceID.from("minecraft:emerald");
|
||||
|
||||
TrimMaterial REDSTONE = TrimMaterialImpl.get("minecraft:redstone");
|
||||
NamespaceID REDSTONE = NamespaceID.from("minecraft:redstone");
|
||||
|
||||
TrimMaterial GOLD = TrimMaterialImpl.get("minecraft:gold");
|
||||
NamespaceID GOLD = NamespaceID.from("minecraft:gold");
|
||||
|
||||
TrimMaterial NETHERITE = TrimMaterialImpl.get("minecraft:netherite");
|
||||
NamespaceID NETHERITE = NamespaceID.from("minecraft:netherite");
|
||||
}
|
||||
|
@ -1,39 +1,41 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface TrimPatterns {
|
||||
TrimPattern TIDE = TrimPatternImpl.get("minecraft:tide");
|
||||
NamespaceID TIDE = NamespaceID.from("minecraft:tide");
|
||||
|
||||
TrimPattern RIB = TrimPatternImpl.get("minecraft:rib");
|
||||
NamespaceID RIB = NamespaceID.from("minecraft:rib");
|
||||
|
||||
TrimPattern HOST = TrimPatternImpl.get("minecraft:host");
|
||||
NamespaceID HOST = NamespaceID.from("minecraft:host");
|
||||
|
||||
TrimPattern SILENCE = TrimPatternImpl.get("minecraft:silence");
|
||||
NamespaceID SILENCE = NamespaceID.from("minecraft:silence");
|
||||
|
||||
TrimPattern WILD = TrimPatternImpl.get("minecraft:wild");
|
||||
NamespaceID WILD = NamespaceID.from("minecraft:wild");
|
||||
|
||||
TrimPattern WAYFINDER = TrimPatternImpl.get("minecraft:wayfinder");
|
||||
NamespaceID WAYFINDER = NamespaceID.from("minecraft:wayfinder");
|
||||
|
||||
TrimPattern DUNE = TrimPatternImpl.get("minecraft:dune");
|
||||
NamespaceID DUNE = NamespaceID.from("minecraft:dune");
|
||||
|
||||
TrimPattern RAISER = TrimPatternImpl.get("minecraft:raiser");
|
||||
NamespaceID RAISER = NamespaceID.from("minecraft:raiser");
|
||||
|
||||
TrimPattern SNOUT = TrimPatternImpl.get("minecraft:snout");
|
||||
NamespaceID SNOUT = NamespaceID.from("minecraft:snout");
|
||||
|
||||
TrimPattern VEX = TrimPatternImpl.get("minecraft:vex");
|
||||
NamespaceID VEX = NamespaceID.from("minecraft:vex");
|
||||
|
||||
TrimPattern SPIRE = TrimPatternImpl.get("minecraft:spire");
|
||||
NamespaceID SPIRE = NamespaceID.from("minecraft:spire");
|
||||
|
||||
TrimPattern SENTRY = TrimPatternImpl.get("minecraft:sentry");
|
||||
NamespaceID SENTRY = NamespaceID.from("minecraft:sentry");
|
||||
|
||||
TrimPattern EYE = TrimPatternImpl.get("minecraft:eye");
|
||||
NamespaceID EYE = NamespaceID.from("minecraft:eye");
|
||||
|
||||
TrimPattern WARD = TrimPatternImpl.get("minecraft:ward");
|
||||
NamespaceID WARD = NamespaceID.from("minecraft:ward");
|
||||
|
||||
TrimPattern COAST = TrimPatternImpl.get("minecraft:coast");
|
||||
NamespaceID COAST = NamespaceID.from("minecraft:coast");
|
||||
|
||||
TrimPattern SHAPER = TrimPatternImpl.get("minecraft:shaper");
|
||||
NamespaceID SHAPER = NamespaceID.from("minecraft:shaper");
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package net.minestom.server.message;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface ChatTypes {
|
||||
NamespaceID EMOTE_COMMAND = NamespaceID.from("minecraft:emote_command");
|
||||
|
||||
NamespaceID TEAM_MSG_COMMAND_INCOMING = NamespaceID.from("minecraft:team_msg_command_incoming");
|
||||
|
||||
NamespaceID TEAM_MSG_COMMAND_OUTGOING = NamespaceID.from("minecraft:team_msg_command_outgoing");
|
||||
|
||||
NamespaceID CHAT = NamespaceID.from("minecraft:chat");
|
||||
|
||||
NamespaceID MSG_COMMAND_INCOMING = NamespaceID.from("minecraft:msg_command_incoming");
|
||||
|
||||
NamespaceID MSG_COMMAND_OUTGOING = NamespaceID.from("minecraft:msg_command_outgoing");
|
||||
|
||||
NamespaceID SAY_COMMAND = NamespaceID.from("minecraft:say_command");
|
||||
}
|
@ -11,7 +11,7 @@ import java.util.HashMap;
|
||||
/**
|
||||
* AUTOGENERATED
|
||||
*/
|
||||
public final class Registries {
|
||||
public final class FluidRegistries {
|
||||
|
||||
/**
|
||||
* Should only be used for internal code, please use the get* methods.
|
@ -0,0 +1,17 @@
|
||||
package net.minestom.server.world;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface DimensionTypes {
|
||||
NamespaceID THE_END = NamespaceID.from("minecraft:the_end");
|
||||
|
||||
NamespaceID OVERWORLD_CAVES = NamespaceID.from("minecraft:overworld_caves");
|
||||
|
||||
NamespaceID THE_NETHER = NamespaceID.from("minecraft:the_nether");
|
||||
|
||||
NamespaceID OVERWORLD = NamespaceID.from("minecraft:overworld");
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
package net.minestom.server.world.biome;
|
||||
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface Biomes {
|
||||
NamespaceID SNOWY_SLOPES = NamespaceID.from("minecraft:snowy_slopes");
|
||||
|
||||
NamespaceID OLD_GROWTH_PINE_TAIGA = NamespaceID.from("minecraft:old_growth_pine_taiga");
|
||||
|
||||
NamespaceID MUSHROOM_FIELDS = NamespaceID.from("minecraft:mushroom_fields");
|
||||
|
||||
NamespaceID TAIGA = NamespaceID.from("minecraft:taiga");
|
||||
|
||||
NamespaceID DEEP_OCEAN = NamespaceID.from("minecraft:deep_ocean");
|
||||
|
||||
NamespaceID ERODED_BADLANDS = NamespaceID.from("minecraft:eroded_badlands");
|
||||
|
||||
NamespaceID FROZEN_RIVER = NamespaceID.from("minecraft:frozen_river");
|
||||
|
||||
NamespaceID END_HIGHLANDS = NamespaceID.from("minecraft:end_highlands");
|
||||
|
||||
NamespaceID CHERRY_GROVE = NamespaceID.from("minecraft:cherry_grove");
|
||||
|
||||
NamespaceID SUNFLOWER_PLAINS = NamespaceID.from("minecraft:sunflower_plains");
|
||||
|
||||
NamespaceID BIRCH_FOREST = NamespaceID.from("minecraft:birch_forest");
|
||||
|
||||
NamespaceID WINDSWEPT_HILLS = NamespaceID.from("minecraft:windswept_hills");
|
||||
|
||||
NamespaceID BAMBOO_JUNGLE = NamespaceID.from("minecraft:bamboo_jungle");
|
||||
|
||||
NamespaceID WOODED_BADLANDS = NamespaceID.from("minecraft:wooded_badlands");
|
||||
|
||||
NamespaceID BADLANDS = NamespaceID.from("minecraft:badlands");
|
||||
|
||||
NamespaceID SAVANNA_PLATEAU = NamespaceID.from("minecraft:savanna_plateau");
|
||||
|
||||
NamespaceID BEACH = NamespaceID.from("minecraft:beach");
|
||||
|
||||
NamespaceID DARK_FOREST = NamespaceID.from("minecraft:dark_forest");
|
||||
|
||||
NamespaceID STONY_PEAKS = NamespaceID.from("minecraft:stony_peaks");
|
||||
|
||||
NamespaceID MANGROVE_SWAMP = NamespaceID.from("minecraft:mangrove_swamp");
|
||||
|
||||
NamespaceID SPARSE_JUNGLE = NamespaceID.from("minecraft:sparse_jungle");
|
||||
|
||||
NamespaceID LUKEWARM_OCEAN = NamespaceID.from("minecraft:lukewarm_ocean");
|
||||
|
||||
NamespaceID RIVER = NamespaceID.from("minecraft:river");
|
||||
|
||||
NamespaceID STONY_SHORE = NamespaceID.from("minecraft:stony_shore");
|
||||
|
||||
NamespaceID WARPED_FOREST = NamespaceID.from("minecraft:warped_forest");
|
||||
|
||||
NamespaceID SNOWY_PLAINS = NamespaceID.from("minecraft:snowy_plains");
|
||||
|
||||
NamespaceID DRIPSTONE_CAVES = NamespaceID.from("minecraft:dripstone_caves");
|
||||
|
||||
NamespaceID SNOWY_TAIGA = NamespaceID.from("minecraft:snowy_taiga");
|
||||
|
||||
NamespaceID GROVE = NamespaceID.from("minecraft:grove");
|
||||
|
||||
NamespaceID SWAMP = NamespaceID.from("minecraft:swamp");
|
||||
|
||||
NamespaceID JAGGED_PEAKS = NamespaceID.from("minecraft:jagged_peaks");
|
||||
|
||||
NamespaceID COLD_OCEAN = NamespaceID.from("minecraft:cold_ocean");
|
||||
|
||||
NamespaceID FOREST = NamespaceID.from("minecraft:forest");
|
||||
|
||||
NamespaceID LUSH_CAVES = NamespaceID.from("minecraft:lush_caves");
|
||||
|
||||
NamespaceID BASALT_DELTAS = NamespaceID.from("minecraft:basalt_deltas");
|
||||
|
||||
NamespaceID DEEP_COLD_OCEAN = NamespaceID.from("minecraft:deep_cold_ocean");
|
||||
|
||||
NamespaceID ICE_SPIKES = NamespaceID.from("minecraft:ice_spikes");
|
||||
|
||||
NamespaceID END_MIDLANDS = NamespaceID.from("minecraft:end_midlands");
|
||||
|
||||
NamespaceID FROZEN_OCEAN = NamespaceID.from("minecraft:frozen_ocean");
|
||||
|
||||
NamespaceID DESERT = NamespaceID.from("minecraft:desert");
|
||||
|
||||
NamespaceID DEEP_FROZEN_OCEAN = NamespaceID.from("minecraft:deep_frozen_ocean");
|
||||
|
||||
NamespaceID WINDSWEPT_FOREST = NamespaceID.from("minecraft:windswept_forest");
|
||||
|
||||
NamespaceID JUNGLE = NamespaceID.from("minecraft:jungle");
|
||||
|
||||
NamespaceID OCEAN = NamespaceID.from("minecraft:ocean");
|
||||
|
||||
NamespaceID OLD_GROWTH_SPRUCE_TAIGA = NamespaceID.from("minecraft:old_growth_spruce_taiga");
|
||||
|
||||
NamespaceID SNOWY_BEACH = NamespaceID.from("minecraft:snowy_beach");
|
||||
|
||||
NamespaceID WINDSWEPT_SAVANNA = NamespaceID.from("minecraft:windswept_savanna");
|
||||
|
||||
NamespaceID END_BARRENS = NamespaceID.from("minecraft:end_barrens");
|
||||
|
||||
NamespaceID WARM_OCEAN = NamespaceID.from("minecraft:warm_ocean");
|
||||
|
||||
NamespaceID DEEP_LUKEWARM_OCEAN = NamespaceID.from("minecraft:deep_lukewarm_ocean");
|
||||
|
||||
NamespaceID FLOWER_FOREST = NamespaceID.from("minecraft:flower_forest");
|
||||
|
||||
NamespaceID SOUL_SAND_VALLEY = NamespaceID.from("minecraft:soul_sand_valley");
|
||||
|
||||
NamespaceID NETHER_WASTES = NamespaceID.from("minecraft:nether_wastes");
|
||||
|
||||
NamespaceID FROZEN_PEAKS = NamespaceID.from("minecraft:frozen_peaks");
|
||||
|
||||
NamespaceID THE_END = NamespaceID.from("minecraft:the_end");
|
||||
|
||||
NamespaceID SMALL_END_ISLANDS = NamespaceID.from("minecraft:small_end_islands");
|
||||
|
||||
NamespaceID OLD_GROWTH_BIRCH_FOREST = NamespaceID.from("minecraft:old_growth_birch_forest");
|
||||
|
||||
NamespaceID CRIMSON_FOREST = NamespaceID.from("minecraft:crimson_forest");
|
||||
|
||||
NamespaceID THE_VOID = NamespaceID.from("minecraft:the_void");
|
||||
|
||||
NamespaceID DEEP_DARK = NamespaceID.from("minecraft:deep_dark");
|
||||
|
||||
NamespaceID MEADOW = NamespaceID.from("minecraft:meadow");
|
||||
|
||||
NamespaceID WINDSWEPT_GRAVELLY_HILLS = NamespaceID.from("minecraft:windswept_gravelly_hills");
|
||||
|
||||
NamespaceID SAVANNA = NamespaceID.from("minecraft:savanna");
|
||||
|
||||
NamespaceID PLAINS = NamespaceID.from("minecraft:plains");
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
|
||||
/**
|
||||
* Code autogenerated, do not edit!
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
interface Biomes {
|
||||
Biome SNOWY_SLOPES = BiomeImpl.get("minecraft:snowy_slopes");
|
||||
|
||||
Biome OLD_GROWTH_PINE_TAIGA = BiomeImpl.get("minecraft:old_growth_pine_taiga");
|
||||
|
||||
Biome MUSHROOM_FIELDS = BiomeImpl.get("minecraft:mushroom_fields");
|
||||
|
||||
Biome TAIGA = BiomeImpl.get("minecraft:taiga");
|
||||
|
||||
Biome DEEP_OCEAN = BiomeImpl.get("minecraft:deep_ocean");
|
||||
|
||||
Biome ERODED_BADLANDS = BiomeImpl.get("minecraft:eroded_badlands");
|
||||
|
||||
Biome FROZEN_RIVER = BiomeImpl.get("minecraft:frozen_river");
|
||||
|
||||
Biome END_HIGHLANDS = BiomeImpl.get("minecraft:end_highlands");
|
||||
|
||||
Biome CHERRY_GROVE = BiomeImpl.get("minecraft:cherry_grove");
|
||||
|
||||
Biome SUNFLOWER_PLAINS = BiomeImpl.get("minecraft:sunflower_plains");
|
||||
|
||||
Biome BIRCH_FOREST = BiomeImpl.get("minecraft:birch_forest");
|
||||
|
||||
Biome WINDSWEPT_HILLS = BiomeImpl.get("minecraft:windswept_hills");
|
||||
|
||||
Biome BAMBOO_JUNGLE = BiomeImpl.get("minecraft:bamboo_jungle");
|
||||
|
||||
Biome WOODED_BADLANDS = BiomeImpl.get("minecraft:wooded_badlands");
|
||||
|
||||
Biome BADLANDS = BiomeImpl.get("minecraft:badlands");
|
||||
|
||||
Biome SAVANNA_PLATEAU = BiomeImpl.get("minecraft:savanna_plateau");
|
||||
|
||||
Biome BEACH = BiomeImpl.get("minecraft:beach");
|
||||
|
||||
Biome DARK_FOREST = BiomeImpl.get("minecraft:dark_forest");
|
||||
|
||||
Biome STONY_PEAKS = BiomeImpl.get("minecraft:stony_peaks");
|
||||
|
||||
Biome MANGROVE_SWAMP = BiomeImpl.get("minecraft:mangrove_swamp");
|
||||
|
||||
Biome SPARSE_JUNGLE = BiomeImpl.get("minecraft:sparse_jungle");
|
||||
|
||||
Biome LUKEWARM_OCEAN = BiomeImpl.get("minecraft:lukewarm_ocean");
|
||||
|
||||
Biome RIVER = BiomeImpl.get("minecraft:river");
|
||||
|
||||
Biome STONY_SHORE = BiomeImpl.get("minecraft:stony_shore");
|
||||
|
||||
Biome WARPED_FOREST = BiomeImpl.get("minecraft:warped_forest");
|
||||
|
||||
Biome SNOWY_PLAINS = BiomeImpl.get("minecraft:snowy_plains");
|
||||
|
||||
Biome DRIPSTONE_CAVES = BiomeImpl.get("minecraft:dripstone_caves");
|
||||
|
||||
Biome SNOWY_TAIGA = BiomeImpl.get("minecraft:snowy_taiga");
|
||||
|
||||
Biome GROVE = BiomeImpl.get("minecraft:grove");
|
||||
|
||||
Biome SWAMP = BiomeImpl.get("minecraft:swamp");
|
||||
|
||||
Biome JAGGED_PEAKS = BiomeImpl.get("minecraft:jagged_peaks");
|
||||
|
||||
Biome COLD_OCEAN = BiomeImpl.get("minecraft:cold_ocean");
|
||||
|
||||
Biome FOREST = BiomeImpl.get("minecraft:forest");
|
||||
|
||||
Biome LUSH_CAVES = BiomeImpl.get("minecraft:lush_caves");
|
||||
|
||||
Biome BASALT_DELTAS = BiomeImpl.get("minecraft:basalt_deltas");
|
||||
|
||||
Biome DEEP_COLD_OCEAN = BiomeImpl.get("minecraft:deep_cold_ocean");
|
||||
|
||||
Biome ICE_SPIKES = BiomeImpl.get("minecraft:ice_spikes");
|
||||
|
||||
Biome END_MIDLANDS = BiomeImpl.get("minecraft:end_midlands");
|
||||
|
||||
Biome FROZEN_OCEAN = BiomeImpl.get("minecraft:frozen_ocean");
|
||||
|
||||
Biome DESERT = BiomeImpl.get("minecraft:desert");
|
||||
|
||||
Biome DEEP_FROZEN_OCEAN = BiomeImpl.get("minecraft:deep_frozen_ocean");
|
||||
|
||||
Biome WINDSWEPT_FOREST = BiomeImpl.get("minecraft:windswept_forest");
|
||||
|
||||
Biome JUNGLE = BiomeImpl.get("minecraft:jungle");
|
||||
|
||||
Biome OCEAN = BiomeImpl.get("minecraft:ocean");
|
||||
|
||||
Biome OLD_GROWTH_SPRUCE_TAIGA = BiomeImpl.get("minecraft:old_growth_spruce_taiga");
|
||||
|
||||
Biome SNOWY_BEACH = BiomeImpl.get("minecraft:snowy_beach");
|
||||
|
||||
Biome WINDSWEPT_SAVANNA = BiomeImpl.get("minecraft:windswept_savanna");
|
||||
|
||||
Biome END_BARRENS = BiomeImpl.get("minecraft:end_barrens");
|
||||
|
||||
Biome WARM_OCEAN = BiomeImpl.get("minecraft:warm_ocean");
|
||||
|
||||
Biome DEEP_LUKEWARM_OCEAN = BiomeImpl.get("minecraft:deep_lukewarm_ocean");
|
||||
|
||||
Biome FLOWER_FOREST = BiomeImpl.get("minecraft:flower_forest");
|
||||
|
||||
Biome SOUL_SAND_VALLEY = BiomeImpl.get("minecraft:soul_sand_valley");
|
||||
|
||||
Biome NETHER_WASTES = BiomeImpl.get("minecraft:nether_wastes");
|
||||
|
||||
Biome FROZEN_PEAKS = BiomeImpl.get("minecraft:frozen_peaks");
|
||||
|
||||
Biome THE_END = BiomeImpl.get("minecraft:the_end");
|
||||
|
||||
Biome SMALL_END_ISLANDS = BiomeImpl.get("minecraft:small_end_islands");
|
||||
|
||||
Biome OLD_GROWTH_BIRCH_FOREST = BiomeImpl.get("minecraft:old_growth_birch_forest");
|
||||
|
||||
Biome CRIMSON_FOREST = BiomeImpl.get("minecraft:crimson_forest");
|
||||
|
||||
Biome THE_VOID = BiomeImpl.get("minecraft:the_void");
|
||||
|
||||
Biome DEEP_DARK = BiomeImpl.get("minecraft:deep_dark");
|
||||
|
||||
Biome MEADOW = BiomeImpl.get("minecraft:meadow");
|
||||
|
||||
Biome WINDSWEPT_GRAVELLY_HILLS = BiomeImpl.get("minecraft:windswept_gravelly_hills");
|
||||
|
||||
Biome SAVANNA = BiomeImpl.get("minecraft:savanna");
|
||||
|
||||
Biome PLAINS = BiomeImpl.get("minecraft:plains");
|
||||
}
|
@ -4,13 +4,18 @@ import net.kyori.adventure.text.logger.slf4j.ComponentLogger;
|
||||
import net.minestom.server.advancements.AdvancementManager;
|
||||
import net.minestom.server.adventure.bossbar.BossBarManager;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
|
||||
import net.minestom.server.event.GlobalEventHandler;
|
||||
import net.minestom.server.exception.ExceptionManager;
|
||||
import net.minestom.server.gamedata.tags.TagManager;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.BlockManager;
|
||||
import net.minestom.server.item.armor.TrimManager;
|
||||
import net.minestom.server.instance.block.banner.BannerPattern;
|
||||
import net.minestom.server.item.armor.TrimMaterial;
|
||||
import net.minestom.server.item.armor.TrimPattern;
|
||||
import net.minestom.server.listener.manager.PacketListenerManager;
|
||||
import net.minestom.server.message.ChatType;
|
||||
import net.minestom.server.monitoring.BenchmarkManager;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.PacketProcessor;
|
||||
@ -18,14 +23,15 @@ import net.minestom.server.network.packet.server.common.PluginMessagePacket;
|
||||
import net.minestom.server.network.packet.server.play.ServerDifficultyPacket;
|
||||
import net.minestom.server.network.socket.Server;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.scoreboard.TeamManager;
|
||||
import net.minestom.server.thread.TickSchedulerThread;
|
||||
import net.minestom.server.timer.SchedulerManager;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.Difficulty;
|
||||
import net.minestom.server.world.DimensionTypeManager;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
@ -241,14 +247,6 @@ public final class MinecraftServer {
|
||||
MinecraftServer.compressionThreshold = compressionThreshold;
|
||||
}
|
||||
|
||||
public static DimensionTypeManager getDimensionTypeManager() {
|
||||
return serverProcess.dimension();
|
||||
}
|
||||
|
||||
public static BiomeManager getBiomeManager() {
|
||||
return serverProcess.biome();
|
||||
}
|
||||
|
||||
public static AdvancementManager getAdvancementManager() {
|
||||
return serverProcess.advancement();
|
||||
}
|
||||
@ -257,8 +255,36 @@ public final class MinecraftServer {
|
||||
return serverProcess.tag();
|
||||
}
|
||||
|
||||
public static TrimManager getTrimManager() {
|
||||
return serverProcess.trim();
|
||||
public static @NotNull DynamicRegistry<ChatType> getChatTypeRegistry() {
|
||||
return serverProcess.chatType();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<DimensionType> getDimensionTypeRegistry() {
|
||||
return serverProcess.dimensionType();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<Biome> getBiomeRegistry() {
|
||||
return serverProcess.biome();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<DamageType> getDamageTypeRegistry() {
|
||||
return serverProcess.damageType();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<TrimMaterial> getTrimMaterialRegistry() {
|
||||
return serverProcess.trimMaterial();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<TrimPattern> getTrimPatternRegistry() {
|
||||
return serverProcess.trimPattern();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<BannerPattern> getBannerPatternRegistry() {
|
||||
return serverProcess.bannerPattern();
|
||||
}
|
||||
|
||||
public static @NotNull DynamicRegistry<WolfMeta.Variant> getWolfVariantRegistry() {
|
||||
return serverProcess.wolfVariant();
|
||||
}
|
||||
|
||||
public static Server getServer() {
|
||||
|
@ -49,6 +49,7 @@ public final class ServerFlag {
|
||||
public static final @Nullable String MAP_RGB_REDUCTION = System.getProperty("minestom.map.rgbreduction"); // Only used if rgb mapping is "approximate"
|
||||
|
||||
// Experimental/Unstable
|
||||
public static final boolean REGISTRY_UNSAFE_REMOVE = Boolean.getBoolean("minestom.registry.unsafe-remove");
|
||||
public static final boolean EVENT_NODE_ALLOW_MULTIPLE_PARENTS = Boolean.getBoolean("minestom.event.multiple-parents");
|
||||
|
||||
private ServerFlag() {}
|
||||
|
@ -10,19 +10,17 @@ import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.BlockManager;
|
||||
import net.minestom.server.instance.block.rule.BlockPlacementRule;
|
||||
import net.minestom.server.item.armor.TrimManager;
|
||||
import net.minestom.server.listener.manager.PacketListenerManager;
|
||||
import net.minestom.server.monitoring.BenchmarkManager;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.PacketProcessor;
|
||||
import net.minestom.server.network.socket.Server;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.scoreboard.TeamManager;
|
||||
import net.minestom.server.snapshot.Snapshotable;
|
||||
import net.minestom.server.thread.ThreadDispatcher;
|
||||
import net.minestom.server.timer.SchedulerManager;
|
||||
import net.minestom.server.world.DimensionTypeManager;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -30,7 +28,7 @@ import java.net.SocketAddress;
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@ApiStatus.NonExtendable
|
||||
public interface ServerProcess extends Snapshotable {
|
||||
public interface ServerProcess extends Registries, Snapshotable {
|
||||
/**
|
||||
* Handles incoming connections/players.
|
||||
*/
|
||||
@ -76,16 +74,6 @@ public interface ServerProcess extends Snapshotable {
|
||||
|
||||
@NotNull BenchmarkManager benchmark();
|
||||
|
||||
/**
|
||||
* Handles registered dimensions.
|
||||
*/
|
||||
@NotNull DimensionTypeManager dimension();
|
||||
|
||||
/**
|
||||
* Handles registered biomes.
|
||||
*/
|
||||
@NotNull BiomeManager biome();
|
||||
|
||||
/**
|
||||
* Handles registered advancements.
|
||||
*/
|
||||
@ -101,8 +89,6 @@ public interface ServerProcess extends Snapshotable {
|
||||
*/
|
||||
@NotNull TagManager tag();
|
||||
|
||||
@NotNull TrimManager trim();
|
||||
|
||||
/**
|
||||
* Handles all thrown exceptions from the server.
|
||||
*/
|
||||
|
@ -5,6 +5,8 @@ import net.minestom.server.advancements.AdvancementManager;
|
||||
import net.minestom.server.adventure.bossbar.BossBarManager;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
|
||||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.GlobalEventHandler;
|
||||
import net.minestom.server.event.server.ServerTickMonitorEvent;
|
||||
@ -14,14 +16,18 @@ import net.minestom.server.instance.Chunk;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.instance.block.BlockManager;
|
||||
import net.minestom.server.item.armor.TrimManager;
|
||||
import net.minestom.server.instance.block.banner.BannerPattern;
|
||||
import net.minestom.server.item.armor.TrimMaterial;
|
||||
import net.minestom.server.item.armor.TrimPattern;
|
||||
import net.minestom.server.listener.manager.PacketListenerManager;
|
||||
import net.minestom.server.message.ChatType;
|
||||
import net.minestom.server.monitoring.BenchmarkManager;
|
||||
import net.minestom.server.monitoring.TickMonitor;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.PacketProcessor;
|
||||
import net.minestom.server.network.socket.Server;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.scoreboard.TeamManager;
|
||||
import net.minestom.server.snapshot.*;
|
||||
import net.minestom.server.thread.Acquirable;
|
||||
@ -30,8 +36,8 @@ import net.minestom.server.timer.SchedulerManager;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.PropertyUtils;
|
||||
import net.minestom.server.utils.collection.MappedCollection;
|
||||
import net.minestom.server.world.DimensionTypeManager;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -59,12 +65,19 @@ final class ServerProcessImpl implements ServerProcess {
|
||||
private final GlobalEventHandler eventHandler;
|
||||
private final SchedulerManager scheduler;
|
||||
private final BenchmarkManager benchmark;
|
||||
private final DimensionTypeManager dimension;
|
||||
private final BiomeManager biome;
|
||||
private final AdvancementManager advancement;
|
||||
private final BossBarManager bossBar;
|
||||
private final TagManager tag;
|
||||
private final TrimManager trim;
|
||||
|
||||
private final DynamicRegistry<ChatType> chatType;
|
||||
private final DynamicRegistry<DimensionType> dimensionType;
|
||||
private final DynamicRegistry<Biome> biome;
|
||||
private final DynamicRegistry<DamageType> damageType;
|
||||
private final DynamicRegistry<TrimMaterial> trimMaterial;
|
||||
private final DynamicRegistry<TrimPattern> trimPattern;
|
||||
private final DynamicRegistry<BannerPattern> bannerPattern;
|
||||
private final DynamicRegistry<WolfMeta.Variant> wolfVariant;
|
||||
|
||||
private final Server server;
|
||||
|
||||
private final ThreadDispatcher<Chunk> dispatcher;
|
||||
@ -86,12 +99,19 @@ final class ServerProcessImpl implements ServerProcess {
|
||||
this.eventHandler = new GlobalEventHandler();
|
||||
this.scheduler = new SchedulerManager();
|
||||
this.benchmark = new BenchmarkManager();
|
||||
this.dimension = new DimensionTypeManager();
|
||||
this.biome = new BiomeManager();
|
||||
this.advancement = new AdvancementManager();
|
||||
this.bossBar = new BossBarManager();
|
||||
this.tag = new TagManager();
|
||||
this.trim = new TrimManager();
|
||||
|
||||
this.chatType = ChatType.createDefaultRegistry();
|
||||
this.dimensionType = DimensionType.createDefaultRegistry();
|
||||
this.biome = Biome.createDefaultRegistry();
|
||||
this.damageType = DamageType.createDefaultRegistry();
|
||||
this.trimMaterial = TrimMaterial.createDefaultRegistry();
|
||||
this.trimPattern = TrimPattern.createDefaultRegistry();
|
||||
this.bannerPattern = BannerPattern.createDefaultRegistry();
|
||||
this.wolfVariant = WolfMeta.Variant.createDefaultRegistry();
|
||||
|
||||
this.server = new Server(packetProcessor);
|
||||
|
||||
this.dispatcher = ThreadDispatcher.singleThread();
|
||||
@ -143,16 +163,6 @@ final class ServerProcessImpl implements ServerProcess {
|
||||
return benchmark;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DimensionTypeManager dimension() {
|
||||
return dimension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BiomeManager biome() {
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AdvancementManager advancement() {
|
||||
return advancement;
|
||||
@ -169,8 +179,43 @@ final class ServerProcessImpl implements ServerProcess {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TrimManager trim() {
|
||||
return trim;
|
||||
public @NotNull DynamicRegistry<ChatType> chatType() {
|
||||
return chatType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<DimensionType> dimensionType() {
|
||||
return dimensionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<Biome> biome() {
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<DamageType> damageType() {
|
||||
return damageType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<TrimMaterial> trimMaterial() {
|
||||
return trimMaterial;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<TrimPattern> trimPattern() {
|
||||
return trimPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<BannerPattern> bannerPattern() {
|
||||
return bannerPattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DynamicRegistry<WolfMeta.Variant> wolfVariant() {
|
||||
return wolfVariant;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,9 @@
|
||||
package net.minestom.server.adventure.serializer.nbt;
|
||||
|
||||
import net.kyori.adventure.nbt.BinaryTag;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.serializer.ComponentSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@ -9,4 +11,8 @@ public interface NbtComponentSerializer extends ComponentSerializer<Component, C
|
||||
static @NotNull NbtComponentSerializer nbt() {
|
||||
return NbtComponentSerializerImpl.INSTANCE;
|
||||
}
|
||||
|
||||
@NotNull Style deserializeStyle(@NotNull BinaryTag tag);
|
||||
|
||||
@NotNull CompoundBinaryTag serializeStyle(@NotNull Style style);
|
||||
}
|
||||
|
@ -96,6 +96,17 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||
}
|
||||
|
||||
// Formatting
|
||||
builder.style(deserializeStyle(compound));
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Style deserializeStyle(@NotNull BinaryTag tag) {
|
||||
if (!(tag instanceof CompoundBinaryTag compound)) {
|
||||
return Style.empty();
|
||||
}
|
||||
|
||||
var style = Style.style();
|
||||
var color = compound.getString("color");
|
||||
if (!color.isEmpty()) {
|
||||
@ -128,17 +139,16 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||
BinaryTag obfuscated = compound.get("obfuscated");
|
||||
if (obfuscated instanceof ByteBinaryTag b)
|
||||
style.decoration(TextDecoration.OBFUSCATED, b.value() == 1 ? TextDecoration.State.TRUE : TextDecoration.State.FALSE);
|
||||
builder.style(style.build());
|
||||
|
||||
// Interactivity
|
||||
var insertion = compound.getString("insertion");
|
||||
if (!insertion.isEmpty()) builder.insertion(insertion);
|
||||
if (!insertion.isEmpty()) style.insertion(insertion);
|
||||
var clickEvent = compound.getCompound("clickEvent");
|
||||
if (clickEvent.size() > 0) builder.clickEvent(deserializeClickEvent(clickEvent));
|
||||
if (clickEvent.size() > 0) style.clickEvent(deserializeClickEvent(clickEvent));
|
||||
var hoverEvent = compound.getCompound("hoverEvent");
|
||||
if (hoverEvent.size() > 0) builder.hoverEvent(deserializeHoverEvent(hoverEvent));
|
||||
if (hoverEvent.size() > 0) style.hoverEvent(deserializeHoverEvent(hoverEvent));
|
||||
|
||||
return builder.build();
|
||||
return style.build();
|
||||
}
|
||||
|
||||
private @NotNull ComponentBuilder<?, ?> deserializeTextComponent(@NotNull CompoundBinaryTag compound) {
|
||||
@ -289,8 +299,16 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||
compound.put("extra", children.build());
|
||||
}
|
||||
|
||||
// Formatting
|
||||
var style = component.style();
|
||||
// Formatting/Interactivity
|
||||
compound.put(serializeStyle(component.style()));
|
||||
|
||||
return compound.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompoundBinaryTag serializeStyle(@NotNull Style style) {
|
||||
CompoundBinaryTag.Builder compound = CompoundBinaryTag.builder();
|
||||
|
||||
var color = style.color();
|
||||
if (color != null) {
|
||||
if (color instanceof NamedTextColor named) {
|
||||
@ -318,12 +336,11 @@ final class NbtComponentSerializerImpl implements NbtComponentSerializer {
|
||||
if (obfuscated != TextDecoration.State.NOT_SET)
|
||||
compound.putBoolean("obfuscated", obfuscated == TextDecoration.State.TRUE);
|
||||
|
||||
// Interactivity
|
||||
var insertion = component.insertion();
|
||||
var insertion = style.insertion();
|
||||
if (insertion != null) compound.putString("insertion", insertion);
|
||||
var clickEvent = component.clickEvent();
|
||||
var clickEvent = style.clickEvent();
|
||||
if (clickEvent != null) compound.put("clickEvent", serializeClickEvent(clickEvent));
|
||||
var hoverEvent = component.hoverEvent();
|
||||
var hoverEvent = style.hoverEvent();
|
||||
if (hoverEvent != null) compound.put("hoverEvent", serializeHoverEvent(hoverEvent));
|
||||
|
||||
return compound.build();
|
||||
|
@ -20,7 +20,10 @@ import net.minestom.server.inventory.EquipmentHandler;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.server.LazyPacket;
|
||||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.packet.server.play.CollectItemPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityAnimationPacket;
|
||||
import net.minestom.server.network.packet.server.play.EntityAttributesPacket;
|
||||
import net.minestom.server.network.packet.server.play.SoundEffectPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
@ -336,7 +339,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
sendPacketToViewersAndSelf(new EntityAnimationPacket(getEntityId(), EntityAnimationPacket.Animation.TAKE_DAMAGE));
|
||||
}
|
||||
|
||||
sendPacketToViewersAndSelf(new DamageEventPacket(getEntityId(), damage.getType().id(), 0, 0, null));
|
||||
//todo
|
||||
// sendPacketToViewersAndSelf(new DamageEventPacket(getEntityId(), damage.getType().id(), 0, 0, null));
|
||||
|
||||
// Additional hearts support
|
||||
if (this instanceof Player player) {
|
||||
|
@ -72,6 +72,7 @@ import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.network.player.PlayerSocketConnection;
|
||||
import net.minestom.server.recipe.Recipe;
|
||||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.scoreboard.BelowNameTag;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.snapshot.EntitySnapshot;
|
||||
@ -120,6 +121,8 @@ import java.util.function.UnaryOperator;
|
||||
public class Player extends LivingEntity implements CommandSender, Localizable, HoverEventSource<ShowEntity>, Identified, NamedAndIdentified {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Player.class);
|
||||
|
||||
private static final DynamicRegistry<DimensionType> DIMENSION_TYPE_REGISTRY = MinecraftServer.getDimensionTypeRegistry();
|
||||
|
||||
private static final Component REMOVE_MESSAGE = Component.text("You have been removed from the server without reason.", NamedTextColor.RED);
|
||||
|
||||
private static final float MIN_CHUNKS_PER_TICK = PropertyUtils.getFloat("minestom.chunk-queue.min-per-tick", 0.01f);
|
||||
@ -144,7 +147,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
private PlayerSkin skin;
|
||||
|
||||
private Instance pendingInstance = null;
|
||||
private DimensionType dimensionType;
|
||||
private int dimensionTypeId;
|
||||
private GameMode gameMode;
|
||||
private WorldPos deathLocation;
|
||||
|
||||
@ -249,7 +252,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
refreshAnswerKeepAlive(true);
|
||||
|
||||
this.gameMode = GameMode.SURVIVAL;
|
||||
this.dimensionType = DimensionType.OVERWORLD; // Default dimension
|
||||
this.dimensionTypeId = DIMENSION_TYPE_REGISTRY.getId(DimensionType.OVERWORLD); // Default dimension
|
||||
this.levelFlat = true;
|
||||
getAttribute(Attribute.GENERIC_MOVEMENT_SPEED).setBaseValue(0.1);
|
||||
|
||||
@ -288,12 +291,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
this.pendingInstance = null;
|
||||
|
||||
this.removed = false;
|
||||
this.dimensionType = spawnInstance.getDimensionType();
|
||||
this.dimensionTypeId = DIMENSION_TYPE_REGISTRY.getId(spawnInstance.getDimensionType().namespace());
|
||||
|
||||
final JoinGamePacket joinGamePacket = new JoinGamePacket(
|
||||
getEntityId(), this.hardcore, List.of(), 0,
|
||||
ServerFlag.CHUNK_VIEW_DISTANCE, ServerFlag.CHUNK_VIEW_DISTANCE,
|
||||
false, true, false, dimensionType.getId(), spawnInstance.getDimensionName(),
|
||||
false, true, false, dimensionTypeId, spawnInstance.getDimensionName(),
|
||||
0, gameMode, null, false, levelFlat, deathLocation, portalCooldown, true);
|
||||
sendPacket(joinGamePacket);
|
||||
|
||||
@ -520,7 +523,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
setOnFire(false);
|
||||
refreshHealth();
|
||||
|
||||
sendPacket(new RespawnPacket(getDimensionType().getId(), instance.getDimensionName(),
|
||||
sendPacket(new RespawnPacket(DIMENSION_TYPE_REGISTRY.getId(getDimensionType().namespace()), instance.getDimensionName(),
|
||||
0, gameMode, gameMode, false, levelFlat, deathLocation, portalCooldown, RespawnPacket.COPY_ALL));
|
||||
refreshClientStateAfterRespawn();
|
||||
|
||||
@ -1034,7 +1037,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
@Override
|
||||
public boolean isImmune(@NotNull DamageType type) {
|
||||
if (!getGameMode().canTakeDamage()) {
|
||||
return type != DamageType.OUT_OF_WORLD;
|
||||
return !DamageType.OUT_OF_WORLD.equals(type.namespace());
|
||||
}
|
||||
return super.isImmune(type);
|
||||
}
|
||||
@ -1196,7 +1199,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
final PlayerInfoRemovePacket removePlayerPacket = getRemovePlayerToList();
|
||||
final PlayerInfoUpdatePacket addPlayerPacket = getAddPlayerToList();
|
||||
|
||||
RespawnPacket respawnPacket = new RespawnPacket(getDimensionType().getId(), instance.getDimensionName(),
|
||||
RespawnPacket respawnPacket = new RespawnPacket(dimensionTypeId, instance.getDimensionName(),
|
||||
0, gameMode, gameMode, false, levelFlat, deathLocation, portalCooldown, RespawnPacket.COPY_ALL);
|
||||
|
||||
sendPacket(removePlayerPacket);
|
||||
@ -1220,7 +1223,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
}
|
||||
|
||||
public void setDeathLocation(@NotNull DimensionType type, @NotNull Pos position) {
|
||||
this.deathLocation = new WorldPos(type.getName().asString(), position);
|
||||
this.deathLocation = new WorldPos(type.name(), position);
|
||||
}
|
||||
|
||||
public @Nullable WorldPos getDeathLocation() {
|
||||
@ -1543,7 +1546,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
* @return the player current dimension
|
||||
*/
|
||||
public DimensionType getDimensionType() {
|
||||
return dimensionType;
|
||||
return DIMENSION_TYPE_REGISTRY.get(dimensionTypeId);
|
||||
}
|
||||
|
||||
public @NotNull PlayerInventory getInventory() {
|
||||
@ -1646,8 +1649,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
|
||||
protected void sendDimension(@NotNull DimensionType dimensionType, @NotNull String dimensionName) {
|
||||
Check.argCondition(instance.getDimensionName().equals(dimensionName),
|
||||
"The dimension needs to be different than the current one!");
|
||||
this.dimensionType = dimensionType;
|
||||
sendPacket(new RespawnPacket(dimensionType.getId(), dimensionName,
|
||||
this.dimensionTypeId = DIMENSION_TYPE_REGISTRY.getId(dimensionType.namespace());
|
||||
sendPacket(new RespawnPacket(dimensionTypeId, dimensionName,
|
||||
0, gameMode, gameMode, false, levelFlat,
|
||||
deathLocation, portalCooldown, RespawnPacket.COPY_ALL));
|
||||
refreshClientStateAfterRespawn();
|
||||
|
@ -160,7 +160,7 @@ public class Damage implements Taggable {
|
||||
}
|
||||
|
||||
protected SoundEvent getPlayerSound(@NotNull Player player) {
|
||||
if (type == DamageType.ON_FIRE) return SoundEvent.ENTITY_PLAYER_HURT_ON_FIRE;
|
||||
if (DamageType.ON_FIRE.equals(type.namespace())) return SoundEvent.ENTITY_PLAYER_HURT_ON_FIRE;
|
||||
return SoundEvent.ENTITY_PLAYER_HURT;
|
||||
}
|
||||
|
||||
|
@ -1,60 +1,84 @@
|
||||
package net.minestom.server.entity.damage;
|
||||
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.registry.StaticProtocolObject;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
public sealed interface DamageType extends ProtocolObject, DamageTypes permits DamageTypeImpl {
|
||||
@NotNull BinaryTagSerializer<DamageType> NBT_TYPE = DamageTypeImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull DamageType create(
|
||||
@NotNull NamespaceID namespace,
|
||||
float exhaustion,
|
||||
@NotNull String messageId,
|
||||
@NotNull String scaling
|
||||
) {
|
||||
return new DamageTypeImpl(namespace, exhaustion, messageId, scaling, null);
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
public sealed interface DamageType extends StaticProtocolObject, DamageTypes permits DamageTypeImpl {
|
||||
/**
|
||||
* Returns the damage type registry.
|
||||
* <p>Creates a new registry for damage types, loading the vanilla damage types.</p>
|
||||
*
|
||||
* @return the damage type registry
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@NotNull Registry.DamageTypeEntry registry();
|
||||
|
||||
@Override
|
||||
default @NotNull NamespaceID namespace() {
|
||||
return registry().namespace();
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<DamageType> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:damage_type", NBT_TYPE, Registry.Resource.DAMAGE_TYPES,
|
||||
(namespace, props) -> new DamageTypeImpl(Registry.damageType(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
default double exhaustion() {
|
||||
return registry().exhaustion();
|
||||
float exhaustion();
|
||||
|
||||
@NotNull String messageId();
|
||||
|
||||
@NotNull String scaling();
|
||||
|
||||
@Nullable Registry.DamageTypeEntry registry();
|
||||
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private float exhaustion = 0f;
|
||||
private String messageId;
|
||||
private String scaling;
|
||||
|
||||
public Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public @NotNull Builder exhaustion(float exhaustion) {
|
||||
this.exhaustion = exhaustion;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder messageId(@NotNull String messageId) {
|
||||
this.messageId = messageId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder scaling(@NotNull String scaling) {
|
||||
this.scaling = scaling;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull DamageType build() {
|
||||
return new DamageTypeImpl(namespace, exhaustion, messageId, scaling, null);
|
||||
}
|
||||
}
|
||||
|
||||
default String messageId() {
|
||||
return registry().messageId();
|
||||
}
|
||||
|
||||
default String scaling() {
|
||||
return registry().scaling();
|
||||
}
|
||||
|
||||
@NotNull RegistryDataPacket.Entry toRegistryEntry();
|
||||
|
||||
static @NotNull Collection<@NotNull DamageType> values() {
|
||||
return DamageTypeImpl.values();
|
||||
}
|
||||
|
||||
static DamageType fromNamespaceId(@NotNull String namespaceID) {
|
||||
return DamageTypeImpl.getSafe(namespaceID);
|
||||
}
|
||||
|
||||
static DamageType fromNamespaceId(@NotNull NamespaceID namespaceID) {
|
||||
return fromNamespaceId(namespaceID.asString());
|
||||
}
|
||||
|
||||
static @Nullable DamageType fromId(int id) {
|
||||
return DamageTypeImpl.getId(id);
|
||||
}
|
||||
|
||||
static @NotNull RegistryDataPacket registryDataPacket() {
|
||||
return DamageTypeImpl.registryDataPacket();
|
||||
}
|
||||
}
|
@ -1,67 +1,41 @@
|
||||
package net.minestom.server.entity.damage;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
record DamageTypeImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
float exhaustion,
|
||||
@NotNull String messageId,
|
||||
@NotNull String scaling,
|
||||
@Nullable Registry.DamageTypeEntry registry
|
||||
) implements DamageType {
|
||||
|
||||
record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements DamageType {
|
||||
private static final Registry.Container<DamageType> CONTAINER;
|
||||
static final BinaryTagSerializer<DamageType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("DamageType is read-only");
|
||||
},
|
||||
damageType -> CompoundBinaryTag.builder()
|
||||
.putFloat("exhaustion", damageType.exhaustion())
|
||||
.putString("message_id", damageType.messageId())
|
||||
.putString("scaling", damageType.scaling())
|
||||
.build()
|
||||
);
|
||||
|
||||
static {
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
CONTAINER = Registry.createStaticContainer(Registry.Resource.DAMAGE_TYPES,
|
||||
(namespace, properties) -> new DamageTypeImpl(Registry.damageType(namespace, properties), i.getAndIncrement()));
|
||||
@SuppressWarnings("ConstantValue") // The builder can violate the nullability constraints
|
||||
DamageTypeImpl {
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.argCondition(messageId == null || messageId.isEmpty(), "missing message id: {0}", namespace);
|
||||
Check.argCondition(scaling == null || scaling.isEmpty(), "missing scaling: {0}", namespace);
|
||||
}
|
||||
|
||||
static DamageType get(@NotNull String namespace) {
|
||||
return CONTAINER.get(namespace);
|
||||
DamageTypeImpl(@NotNull Registry.DamageTypeEntry registry) {
|
||||
this(registry.namespace(), registry.exhaustion(), registry.messageId(), registry.scaling(), registry);
|
||||
}
|
||||
|
||||
static DamageType getSafe(@NotNull String namespace) {
|
||||
return CONTAINER.getSafe(namespace);
|
||||
}
|
||||
|
||||
static DamageType getId(int id) {
|
||||
return CONTAINER.getId(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public @NotNull RegistryDataPacket.Entry toRegistryEntry() {
|
||||
return new RegistryDataPacket.Entry(name(), CompoundBinaryTag.builder()
|
||||
.putFloat("exhaustion", registry.exhaustion())
|
||||
.putString("message_id", registry.messageId())
|
||||
.putString("scaling", registry.scaling())
|
||||
.build());
|
||||
}
|
||||
|
||||
static Collection<DamageType> values() {
|
||||
return CONTAINER.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
private static RegistryDataPacket lazyRegistryDataPacket = null;
|
||||
|
||||
static @NotNull RegistryDataPacket registryDataPacket() {
|
||||
if (lazyRegistryDataPacket != null) return lazyRegistryDataPacket;
|
||||
return lazyRegistryDataPacket = new RegistryDataPacket(
|
||||
"minecraft:damage_type",
|
||||
values().stream()
|
||||
.map(DamageType::toRegistryEntry)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,15 +1,21 @@
|
||||
package net.minestom.server.entity.damage;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents damage inflicted by an {@link Entity}.
|
||||
*/
|
||||
public class EntityDamage extends Damage {
|
||||
private static final DynamicRegistry<DamageType> DAMAGE_TYPES = MinecraftServer.getDamageTypeRegistry();
|
||||
|
||||
public EntityDamage(@NotNull Entity source, float amount) {
|
||||
super(DamageType.MOB_ATTACK, source, source, null, amount);
|
||||
super(Objects.requireNonNull(DAMAGE_TYPES.get(DamageType.MOB_ATTACK)),
|
||||
source, source, null, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,16 +1,21 @@
|
||||
package net.minestom.server.entity.damage;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Represents damage inflicted by an entity, via a projectile.
|
||||
*/
|
||||
public class EntityProjectileDamage extends Damage {
|
||||
private static final DynamicRegistry<DamageType> DAMAGE_TYPES = MinecraftServer.getDamageTypeRegistry();
|
||||
|
||||
public EntityProjectileDamage(@Nullable Entity shooter, @NotNull Entity projectile, float amount) {
|
||||
super(DamageType.MOB_PROJECTILE, projectile, shooter, null, amount);
|
||||
super(Objects.requireNonNull(DAMAGE_TYPES.get(DamageType.MOB_PROJECTILE)), projectile, shooter, null, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,22 @@
|
||||
package net.minestom.server.entity.metadata.animal.tameable;
|
||||
|
||||
import net.kyori.adventure.nbt.BinaryTag;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.StringBinaryTag;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Metadata;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WolfMeta extends TameableAnimalMeta {
|
||||
public static final byte OFFSET = TameableAnimalMeta.MAX_OFFSET;
|
||||
@ -38,4 +52,136 @@ public class WolfMeta extends TameableAnimalMeta {
|
||||
super.metadata.setIndex(OFFSET + 2, Metadata.VarInt(value));
|
||||
}
|
||||
|
||||
public sealed interface Variant extends ProtocolObject, WolfVariants permits VariantImpl {
|
||||
@NotNull BinaryTagSerializer<Variant> NBT_TYPE = VariantImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull Variant create(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID wildTexture,
|
||||
@NotNull NamespaceID tameTexture,
|
||||
@NotNull NamespaceID angryTexture,
|
||||
@NotNull String biome
|
||||
) {
|
||||
return new VariantImpl(namespace, wildTexture, tameTexture, angryTexture, List.of(biome), null);
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new registry for wolf variants, loading the vanilla wolf variants.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<Variant> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:wolf_variant", NBT_TYPE, Registry.Resource.WOLF_VARIANTS,
|
||||
(namespace, props) -> new WolfMeta.VariantImpl(Registry.wolfVariant(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull NamespaceID wildTexture();
|
||||
|
||||
@NotNull NamespaceID tameTexture();
|
||||
|
||||
@NotNull NamespaceID angryTexture();
|
||||
|
||||
@NotNull List<String> biomes();
|
||||
|
||||
@Override
|
||||
@Nullable Registry.WolfVariantEntry registry();
|
||||
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private NamespaceID wildTexture;
|
||||
private NamespaceID tameTexture;
|
||||
private NamespaceID angryTexture;
|
||||
private List<String> biomes;
|
||||
|
||||
private Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public @NotNull Builder wildTexture(@NotNull NamespaceID wildTexture) {
|
||||
this.wildTexture = wildTexture;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder tameTexture(@NotNull NamespaceID tameTexture) {
|
||||
this.tameTexture = tameTexture;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder angryTexture(@NotNull NamespaceID angryTexture) {
|
||||
this.angryTexture = angryTexture;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder biome(@NotNull String biome) {
|
||||
this.biomes = List.of(biome);
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Builder biomes(@NotNull List<String> biomes) {
|
||||
this.biomes = biomes;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull Variant build() {
|
||||
return new VariantImpl(namespace, wildTexture, tameTexture, angryTexture, biomes, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
record VariantImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID wildTexture,
|
||||
@NotNull NamespaceID tameTexture,
|
||||
@NotNull NamespaceID angryTexture,
|
||||
@NotNull List<String> biomes,
|
||||
@Nullable Registry.WolfVariantEntry registry
|
||||
) implements Variant {
|
||||
|
||||
private static final BinaryTagSerializer<List<String>> BIOMES_NBT_TYPE = BinaryTagSerializer.STRING.list();
|
||||
static final BinaryTagSerializer<Variant> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("WolfVariant is read-only");
|
||||
},
|
||||
wolfVariant -> {
|
||||
BinaryTag biomes;
|
||||
if (wolfVariant.biomes().size() == 1) {
|
||||
biomes = StringBinaryTag.stringBinaryTag(wolfVariant.biomes().getFirst());
|
||||
} else {
|
||||
biomes = BIOMES_NBT_TYPE.write(wolfVariant.biomes());
|
||||
}
|
||||
return CompoundBinaryTag.builder()
|
||||
.putString("wild_texture", wolfVariant.wildTexture().asString())
|
||||
.putString("tame_texture", wolfVariant.tameTexture().asString())
|
||||
.putString("angry_texture", wolfVariant.angryTexture().asString())
|
||||
.put("biomes", biomes)
|
||||
.build();
|
||||
}
|
||||
);
|
||||
|
||||
VariantImpl {
|
||||
// The builder can violate the nullability constraints
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.notNull(wildTexture, "missing wild texture: {0}", namespace);
|
||||
Check.notNull(tameTexture, "missing tame texture: {0}", namespace);
|
||||
Check.notNull(angryTexture, "missing angry texture: {0}", namespace);
|
||||
Check.notNull(biomes, "missing biomes: {0}", namespace);
|
||||
}
|
||||
|
||||
VariantImpl(@NotNull Registry.WolfVariantEntry registry) {
|
||||
this(registry.namespace(), registry.wildTexture(), registry.tameTexture(),
|
||||
registry.angryTexture(), registry.biomes(), registry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.registry.FluidRegistries;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -78,11 +78,11 @@ public final class Tag implements ProtocolObject {
|
||||
ITEMS("minecraft:item", Registry.Resource.ITEM_TAGS,
|
||||
name -> Objects.requireNonNull(Material.fromNamespaceId(name)).id()),
|
||||
FLUIDS("minecraft:fluid", Registry.Resource.FLUID_TAGS,
|
||||
name -> Registries.getFluid(name).ordinal()),
|
||||
name -> FluidRegistries.getFluid(name).ordinal()),
|
||||
ENTITY_TYPES("minecraft:entity_type", Registry.Resource.ENTITY_TYPE_TAGS,
|
||||
name -> Objects.requireNonNull(EntityType.fromNamespaceId(name)).id()),
|
||||
GAME_EVENTS("minecraft:game_event", Registry.Resource.GAMEPLAY_TAGS,
|
||||
name -> Registries.getFluid(name).ordinal());
|
||||
name -> FluidRegistries.getFluid(name).ordinal());
|
||||
|
||||
private final static BasicType[] VALUES = values();
|
||||
private final String identifier;
|
||||
|
@ -18,7 +18,7 @@ import net.minestom.server.tag.TagHandler;
|
||||
import net.minestom.server.tag.Taggable;
|
||||
import net.minestom.server.utils.chunk.ChunkSupplier;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -70,8 +70,8 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
|
||||
this.chunkX = chunkX;
|
||||
this.chunkZ = chunkZ;
|
||||
this.shouldGenerate = shouldGenerate;
|
||||
this.minSection = instance.getDimensionType().getMinY() / CHUNK_SECTION_SIZE;
|
||||
this.maxSection = (instance.getDimensionType().getMinY() + instance.getDimensionType().getHeight()) / CHUNK_SECTION_SIZE;
|
||||
this.minSection = instance.getDimensionType().minY() / CHUNK_SECTION_SIZE;
|
||||
this.maxSection = (instance.getDimensionType().minY() + instance.getDimensionType().height()) / CHUNK_SECTION_SIZE;
|
||||
final List<SharedInstance> shared = instance instanceof InstanceContainer instanceContainer ?
|
||||
instanceContainer.getSharedInstances() : List.of();
|
||||
this.viewable = instance.getEntityTracker().viewable(shared, chunkX, chunkZ);
|
||||
|
@ -21,13 +21,13 @@ import net.minestom.server.network.packet.server.play.ChunkDataPacket;
|
||||
import net.minestom.server.network.packet.server.play.UpdateLightPacket;
|
||||
import net.minestom.server.network.packet.server.play.data.ChunkData;
|
||||
import net.minestom.server.network.packet.server.play.data.LightData;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.snapshot.ChunkSnapshot;
|
||||
import net.minestom.server.snapshot.SnapshotImpl;
|
||||
import net.minestom.server.snapshot.SnapshotUpdater;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@ -58,7 +58,7 @@ public class DynamicChunk extends Chunk {
|
||||
|
||||
private long lastChange;
|
||||
final CachedPacket chunkCache = new CachedPacket(this::createChunkPacket);
|
||||
private static final BiomeManager BIOME_MANAGER = MinecraftServer.getBiomeManager();
|
||||
private static final DynamicRegistry<Biome> BIOME_REGISTRY = MinecraftServer.getBiomeRegistry();
|
||||
|
||||
public DynamicChunk(@NotNull Instance instance, int chunkX, int chunkZ) {
|
||||
super(instance, chunkX, chunkZ, true);
|
||||
@ -71,9 +71,9 @@ public class DynamicChunk extends Chunk {
|
||||
public void setBlock(int x, int y, int z, @NotNull Block block,
|
||||
@Nullable BlockHandler.Placement placement,
|
||||
@Nullable BlockHandler.Destroy destroy) {
|
||||
if(y >= instance.getDimensionType().getMaxY() || y < instance.getDimensionType().getMinY()) {
|
||||
if(y >= instance.getDimensionType().maxY() || y < instance.getDimensionType().minY()) {
|
||||
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}",
|
||||
instance.getDimensionType().getMinY(), instance.getDimensionType().getMaxY(), y);
|
||||
instance.getDimensionType().minY(), instance.getDimensionType().maxY(), y);
|
||||
return;
|
||||
}
|
||||
assertLock();
|
||||
@ -141,7 +141,7 @@ public class DynamicChunk extends Chunk {
|
||||
this.chunkCache.invalidate();
|
||||
Section section = getSectionAt(y);
|
||||
|
||||
var id = BIOME_MANAGER.getId(biome);
|
||||
var id = BIOME_REGISTRY.getId(biome.namespace());
|
||||
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace());
|
||||
|
||||
section.biomePalette().set(
|
||||
@ -222,7 +222,7 @@ public class DynamicChunk extends Chunk {
|
||||
final int id = section.biomePalette()
|
||||
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
|
||||
|
||||
Biome biome = BIOME_MANAGER.getById(id);
|
||||
Biome biome = BIOME_REGISTRY.get(id);
|
||||
if (biome == null) {
|
||||
throw new IllegalStateException("Biome with id " + id + " is not registered");
|
||||
}
|
||||
|
@ -9,8 +9,8 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.generator.GenerationUnit;
|
||||
import net.minestom.server.instance.generator.UnitModifier;
|
||||
import net.minestom.server.instance.palette.Palette;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@ -23,7 +23,7 @@ import static net.minestom.server.utils.chunk.ChunkUtils.*;
|
||||
|
||||
final class GeneratorImpl {
|
||||
private static final Vec SECTION_SIZE = new Vec(16);
|
||||
private static final BiomeManager BIOME_MANAGER = MinecraftServer.getBiomeManager();
|
||||
private static final DynamicRegistry<Biome> BIOME_MANAGER = MinecraftServer.getBiomeRegistry();
|
||||
|
||||
static GenerationUnit section(Section section, int sectionX, int sectionY, int sectionZ,
|
||||
boolean fork) {
|
||||
@ -217,10 +217,15 @@ final class GeneratorImpl {
|
||||
record SectionModifierImpl(Point size, Point start, Point end,
|
||||
Palette blockPalette, Palette biomePalette,
|
||||
Int2ObjectMap<Block> cache, boolean fork) implements GenericModifier {
|
||||
|
||||
SectionModifierImpl {
|
||||
biomePalette.fill(BIOME_MANAGER.getId(Biome.PLAINS));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int y, int z, @NotNull Biome biome) {
|
||||
if (fork) throw new IllegalStateException("Cannot modify biomes of a fork");
|
||||
var id = BIOME_MANAGER.getId(biome);
|
||||
var id = BIOME_MANAGER.getId(biome.namespace());
|
||||
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace());
|
||||
|
||||
this.biomePalette.set(
|
||||
@ -270,7 +275,7 @@ final class GeneratorImpl {
|
||||
@Override
|
||||
public void fillBiome(@NotNull Biome biome) {
|
||||
if (fork) throw new IllegalStateException("Cannot modify biomes of a fork");
|
||||
var id = MinecraftServer.getBiomeManager().getId(biome);
|
||||
var id = BIOME_MANAGER.getId(biome.namespace());
|
||||
if (id == -1) throw new IllegalStateException("Biome has not been registered: " + biome.namespace());
|
||||
this.biomePalette.fill(id);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ import net.minestom.server.instance.generator.Generator;
|
||||
import net.minestom.server.instance.light.Light;
|
||||
import net.minestom.server.network.packet.server.play.BlockActionPacket;
|
||||
import net.minestom.server.network.packet.server.play.TimeUpdatePacket;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.snapshot.*;
|
||||
import net.minestom.server.tag.TagHandler;
|
||||
import net.minestom.server.tag.Taggable;
|
||||
@ -67,9 +68,12 @@ import java.util.stream.Collectors;
|
||||
public abstract class Instance implements Block.Getter, Block.Setter,
|
||||
Tickable, Schedulable, Snapshotable, EventHandler<InstanceEvent>, Taggable, PacketGroupingAudience {
|
||||
|
||||
private static final DynamicRegistry<DimensionType> DIMENSION_REGISTRY = MinecraftServer.getDimensionTypeRegistry();
|
||||
|
||||
private boolean registered;
|
||||
|
||||
private final DimensionType dimensionType;
|
||||
private final int dimensionTypeId;
|
||||
private final DimensionType cachedDimensionType;
|
||||
private final String dimensionName;
|
||||
|
||||
private final WorldBorder worldBorder;
|
||||
@ -120,7 +124,7 @@ public abstract class Instance implements Block.Getter, Block.Setter,
|
||||
* @param dimensionType the {@link DimensionType} of the instance
|
||||
*/
|
||||
public Instance(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType) {
|
||||
this(uniqueId, dimensionType, dimensionType.getName());
|
||||
this(uniqueId, dimensionType, dimensionType.namespace());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -130,10 +134,10 @@ public abstract class Instance implements Block.Getter, Block.Setter,
|
||||
* @param dimensionType the {@link DimensionType} of the instance
|
||||
*/
|
||||
public Instance(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @NotNull NamespaceID dimensionName) {
|
||||
Check.argCondition(!dimensionType.isRegistered(),
|
||||
"The dimension " + dimensionType.getName() + " is not registered! Please use DimensionTypeManager#addDimension");
|
||||
this.uniqueId = uniqueId;
|
||||
this.dimensionType = dimensionType;
|
||||
this.dimensionTypeId = DIMENSION_REGISTRY.getId(dimensionType.namespace());
|
||||
Check.argCondition(this.dimensionTypeId == -1, "The dimension " + dimensionType.name() + " is not registered! Please add it to the registry (`MinecraftServer.getDimensionTypeRegistry().registry(dimensionType)`).");
|
||||
this.cachedDimensionType = dimensionType;
|
||||
this.dimensionName = dimensionName.asString();
|
||||
|
||||
this.worldBorder = new WorldBorder(this);
|
||||
@ -396,7 +400,7 @@ public abstract class Instance implements Block.Getter, Block.Setter,
|
||||
* @return the dimension of the instance
|
||||
*/
|
||||
public DimensionType getDimensionType() {
|
||||
return dimensionType;
|
||||
return cachedDimensionType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,6 @@ import net.minestom.server.utils.chunk.ChunkSupplier;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@ -89,19 +88,17 @@ public class InstanceContainer extends Instance {
|
||||
private long lastBlockChangeTime; // Time at which the last block change happened (#setBlock)
|
||||
|
||||
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType) {
|
||||
this(uniqueId, dimensionType, null, dimensionType.getName());
|
||||
this(uniqueId, dimensionType, null, dimensionType.namespace());
|
||||
}
|
||||
|
||||
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @NotNull NamespaceID dimensionName) {
|
||||
this(uniqueId, dimensionType, null, dimensionName);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @Nullable IChunkLoader loader) {
|
||||
this(uniqueId, dimensionType, loader, dimensionType.getName());
|
||||
this(uniqueId, dimensionType, loader, dimensionType.namespace());
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public InstanceContainer(@NotNull UUID uniqueId, @NotNull DimensionType dimensionType, @Nullable IChunkLoader loader, @NotNull NamespaceID dimensionName) {
|
||||
super(uniqueId, dimensionType, dimensionName);
|
||||
setChunkSupplier(DynamicChunk::new);
|
||||
@ -135,8 +132,8 @@ public class InstanceContainer extends Instance {
|
||||
@Nullable BlockHandler.Placement placement, @Nullable BlockHandler.Destroy destroy,
|
||||
boolean doBlockUpdates, int updateDistance) {
|
||||
if (chunk.isReadOnly()) return;
|
||||
if(y >= getDimensionType().getMaxY() || y < getDimensionType().getMinY()) {
|
||||
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", getDimensionType().getMinY(), getDimensionType().getMaxY(), y);
|
||||
if (y >= getDimensionType().maxY() || y < getDimensionType().minY()) {
|
||||
LOGGER.warn("tried to set a block outside the world bounds, should be within [{}, {}): {}", getDimensionType().minY(), getDimensionType().maxY(), y);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -441,7 +438,7 @@ public class InstanceContainer extends Instance {
|
||||
@Override
|
||||
public boolean isInVoid(@NotNull Point point) {
|
||||
// TODO: more customizable
|
||||
return point.y() < getDimensionType().getMinY() - 64;
|
||||
return point.y() < getDimensionType().minY() - 64;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -630,7 +627,7 @@ public class InstanceContainer extends Instance {
|
||||
final int neighborX = blockPosition.blockX() + direction.normalX();
|
||||
final int neighborY = blockPosition.blockY() + direction.normalY();
|
||||
final int neighborZ = blockPosition.blockZ() + direction.normalZ();
|
||||
if (neighborY < getDimensionType().getMinY() || neighborY > getDimensionType().getTotalHeight())
|
||||
if (neighborY < getDimensionType().minY() || neighborY > getDimensionType().height())
|
||||
continue;
|
||||
final Block neighborBlock = cache.getBlock(neighborX, neighborY, neighborZ, Condition.TYPE);
|
||||
if (neighborBlock == null)
|
||||
|
@ -10,10 +10,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
@ -57,7 +54,8 @@ public final class InstanceManager {
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public @NotNull InstanceContainer createInstanceContainer(@Nullable IChunkLoader loader) {
|
||||
return createInstanceContainer(DimensionType.OVERWORLD, loader);
|
||||
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD));
|
||||
return createInstanceContainer(defaultDimension, loader);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +64,8 @@ public final class InstanceManager {
|
||||
* @return the created {@link InstanceContainer}
|
||||
*/
|
||||
public @NotNull InstanceContainer createInstanceContainer() {
|
||||
return createInstanceContainer(DimensionType.OVERWORLD, null);
|
||||
DimensionType defaultDimension = Objects.requireNonNull(MinecraftServer.getDimensionTypeRegistry().get(DimensionType.OVERWORLD));
|
||||
return createInstanceContainer(defaultDimension, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -210,7 +210,7 @@ public class LightingChunk extends DynamicChunk {
|
||||
if (this.occlusionMap != null) return this.occlusionMap;
|
||||
var occlusionMap = new int[CHUNK_SIZE_X * CHUNK_SIZE_Z];
|
||||
|
||||
int minY = instance.getDimensionType().getMinY();
|
||||
int minY = instance.getDimensionType().minY();
|
||||
highestBlock = minY - 1;
|
||||
|
||||
synchronized (this) {
|
||||
@ -249,9 +249,9 @@ public class LightingChunk extends DynamicChunk {
|
||||
List<byte[]> skyLights = new ArrayList<>();
|
||||
List<byte[]> blockLights = new ArrayList<>();
|
||||
|
||||
int chunkMin = instance.getDimensionType().getMinY();
|
||||
int chunkMin = instance.getDimensionType().minY();
|
||||
|
||||
int highestNeighborBlock = instance.getDimensionType().getMinY();
|
||||
int highestNeighborBlock = instance.getDimensionType().minY();
|
||||
for (int i = -1; i <= 1; i++) {
|
||||
for (int j = -1; j <= 1; j++) {
|
||||
Chunk neighborChunk = instance.getChunk(chunkX + i, chunkZ + j);
|
||||
@ -286,7 +286,7 @@ public class LightingChunk extends DynamicChunk {
|
||||
final int sectionMinY = index * 16 + chunkMin;
|
||||
index++;
|
||||
|
||||
if ((wasUpdatedSky) && this.instance.getDimensionType().isSkylightEnabled() && sectionMinY <= (highestNeighborBlock + 16)) {
|
||||
if ((wasUpdatedSky) && this.instance.getDimensionType().hasSkylight() && sectionMinY <= (highestNeighborBlock + 16)) {
|
||||
final byte[] skyLight = section.skyLight().array();
|
||||
|
||||
if (skyLight.length != 0 && skyLight != emptyContent) {
|
||||
@ -433,7 +433,7 @@ public class LightingChunk extends DynamicChunk {
|
||||
Set<Point> collected = new HashSet<>();
|
||||
collected.add(point);
|
||||
|
||||
int highestRegionPoint = instance.getDimensionType().getMinY() - 1;
|
||||
int highestRegionPoint = instance.getDimensionType().minY() - 1;
|
||||
|
||||
for (int x = point.blockX() - 1; x <= point.blockX() + 1; x++) {
|
||||
for (int z = point.blockZ() - 1; z <= point.blockZ() + 1; z++) {
|
||||
@ -455,7 +455,7 @@ public class LightingChunk extends DynamicChunk {
|
||||
|
||||
for (int y = point.blockY() - 1; y <= point.blockY() + 1; y++) {
|
||||
Point sectionPosition = new Vec(x, y, z);
|
||||
int sectionHeight = instance.getDimensionType().getMinY() + 16 * y;
|
||||
int sectionHeight = instance.getDimensionType().minY() + 16 * y;
|
||||
if ((sectionHeight + 16) > highestRegionPoint && type == LightType.SKY) continue;
|
||||
|
||||
if (sectionPosition.blockY() < chunkCheck.getMaxSection() && sectionPosition.blockY() >= chunkCheck.getMinSection()) {
|
||||
|
@ -9,13 +9,13 @@ import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.Section;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.block.BlockHandler;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.utils.ArrayUtils;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biomes.BiomeManager;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
@ -35,8 +35,8 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
public class AnvilLoader implements IChunkLoader {
|
||||
private final static Logger LOGGER = LoggerFactory.getLogger(AnvilLoader.class);
|
||||
private static final BiomeManager BIOME_MANAGER = MinecraftServer.getBiomeManager();
|
||||
private final static Biome PLAINS = BIOME_MANAGER.getByName(NamespaceID.from("minecraft:plains"));
|
||||
private static final DynamicRegistry<Biome> BIOME_REGISTRY = MinecraftServer.getBiomeRegistry();
|
||||
private final static int PLAINS_ID = BIOME_REGISTRY.getId(NamespaceID.from("minecraft:plains"));
|
||||
|
||||
private final Map<String, RegionFile> alreadyLoaded = new ConcurrentHashMap<>();
|
||||
private final Path path;
|
||||
@ -182,12 +182,12 @@ public class AnvilLoader implements IChunkLoader {
|
||||
{ // Biomes
|
||||
final CompoundBinaryTag biomesTag = sectionData.getCompound("biomes");
|
||||
final ListBinaryTag biomePaletteTag = biomesTag.getList("palette", BinaryTagTypes.STRING);
|
||||
Biome[] convertedPalette = loadBiomePalette(biomePaletteTag);
|
||||
int[] convertedBiomePalette = loadBiomePalette(biomePaletteTag);
|
||||
|
||||
if (convertedPalette.length == 1) {
|
||||
if (convertedBiomePalette.length == 1) {
|
||||
// One solid block, no need to check the data
|
||||
section.biomePalette().fill(BIOME_MANAGER.getId(convertedPalette[0]));
|
||||
} else if (convertedPalette.length > 1) {
|
||||
section.biomePalette().fill(convertedBiomePalette[0]);
|
||||
} else if (convertedBiomePalette.length > 1) {
|
||||
final long[] packedIndices = biomesTag.getLongArray("data");
|
||||
Check.stateCondition(packedIndices.length == 0, "Missing packed biomes data");
|
||||
int[] biomeIndices = new int[64];
|
||||
@ -195,8 +195,7 @@ public class AnvilLoader implements IChunkLoader {
|
||||
|
||||
section.biomePalette().setAll((x, y, z) -> {
|
||||
final int index = x + z * 4 + y * 16;
|
||||
final Biome biome = convertedPalette[biomeIndices[index]];
|
||||
return BIOME_MANAGER.getId(biome);
|
||||
return convertedBiomePalette[biomeIndices[index]];
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -266,11 +265,13 @@ public class AnvilLoader implements IChunkLoader {
|
||||
return convertedPalette;
|
||||
}
|
||||
|
||||
private Biome[] loadBiomePalette(@NotNull ListBinaryTag paletteTag) {
|
||||
Biome[] convertedPalette = new Biome[paletteTag.size()];
|
||||
private int[] loadBiomePalette(@NotNull ListBinaryTag paletteTag) {
|
||||
int[] convertedPalette = new int[paletteTag.size()];
|
||||
for (int i = 0; i < convertedPalette.length; i++) {
|
||||
final String name = paletteTag.getString(i);
|
||||
convertedPalette[i] = Objects.requireNonNullElse(BIOME_MANAGER.getByName(name), PLAINS);
|
||||
int biomeId = BIOME_REGISTRY.getId(NamespaceID.from(name));
|
||||
if (biomeId == -1) biomeId = PLAINS_ID;
|
||||
convertedPalette[i] = biomeId;
|
||||
}
|
||||
return convertedPalette;
|
||||
}
|
||||
|
@ -0,0 +1,78 @@
|
||||
package net.minestom.server.instance.block.banner;
|
||||
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public sealed interface BannerPattern extends ProtocolObject, BannerPatterns permits BannerPatternImpl {
|
||||
@NotNull BinaryTagSerializer<BannerPattern> NBT_TYPE = BannerPatternImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull BannerPattern create(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetId,
|
||||
@NotNull String translationKey
|
||||
) {
|
||||
return new BannerPatternImpl(namespace, assetId, translationKey, null);
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new registry for banner patterns, loading the vanilla banner patterns.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<BannerPattern> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:banner_pattern", NBT_TYPE, Registry.Resource.BANNER_PATTERNS,
|
||||
(namespace, props) -> new BannerPatternImpl(Registry.bannerPattern(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull NamespaceID assetId();
|
||||
|
||||
@NotNull String translationKey();
|
||||
|
||||
@Nullable Registry.BannerPatternEntry registry();
|
||||
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private NamespaceID assetId;
|
||||
private String translationKey;
|
||||
|
||||
private Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder assetId(@NotNull NamespaceID assetId) {
|
||||
this.assetId = assetId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder translationKey(@NotNull String translationKey) {
|
||||
this.translationKey = translationKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull BannerPattern build() {
|
||||
return new BannerPatternImpl(namespace, assetId, translationKey, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package net.minestom.server.instance.block.banner;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
record BannerPatternImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetId,
|
||||
@NotNull String translationKey,
|
||||
@Nullable Registry.BannerPatternEntry registry
|
||||
) implements BannerPattern {
|
||||
|
||||
static final BinaryTagSerializer<BannerPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("BannerPattern is read-only");
|
||||
},
|
||||
bannerPattern -> CompoundBinaryTag.builder()
|
||||
.putString("asset_id", bannerPattern.assetId().asString())
|
||||
.putString("translation_key", bannerPattern.translationKey())
|
||||
.build()
|
||||
);
|
||||
|
||||
@SuppressWarnings("ConstantValue") // The builder can violate the nullability constraints
|
||||
BannerPatternImpl {
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.argCondition(assetId == null, "missing asset id: {0}", namespace);
|
||||
Check.argCondition(translationKey == null || translationKey.isEmpty(), "missing translation key: {0}", namespace);
|
||||
}
|
||||
|
||||
BannerPatternImpl(@NotNull Registry.BannerPatternEntry registry) {
|
||||
this(registry.namespace(), registry.assetId(), registry.translationKey(), registry);
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ package net.minestom.server.instance.generator;
|
||||
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface UnitModifier extends Block.Setter, Biome.Setter {
|
||||
|
@ -16,7 +16,7 @@ public abstract class Heightmap {
|
||||
|
||||
public Heightmap(Chunk chunk) {
|
||||
this.chunk = chunk;
|
||||
minHeight = chunk.getInstance().getDimensionType().getMinY() - 1;
|
||||
minHeight = chunk.getInstance().getDimensionType().minY() - 1;
|
||||
}
|
||||
|
||||
protected abstract boolean checkBlock(@NotNull Block block);
|
||||
@ -57,13 +57,13 @@ public abstract class Heightmap {
|
||||
}
|
||||
|
||||
public long[] getNBT() {
|
||||
final int dimensionHeight = chunk.getInstance().getDimensionType().getHeight();
|
||||
final int dimensionHeight = chunk.getInstance().getDimensionType().height();
|
||||
final int bitsForHeight = MathUtils.bitsToRepresent(dimensionHeight);
|
||||
return encode(heights, bitsForHeight);
|
||||
}
|
||||
|
||||
public void loadFrom(long[] data) {
|
||||
final int dimensionHeight = chunk.getInstance().getDimensionType().getHeight();
|
||||
final int dimensionHeight = chunk.getInstance().getDimensionType().height();
|
||||
final int bitsPerEntry = MathUtils.bitsToRepresent(dimensionHeight);
|
||||
|
||||
final int entriesPerLong = 64 / bitsPerEntry;
|
||||
@ -94,7 +94,7 @@ public abstract class Heightmap {
|
||||
}
|
||||
|
||||
public static int getHighestBlockSection(Chunk chunk) {
|
||||
int y = chunk.getInstance().getDimensionType().getMaxY();
|
||||
int y = chunk.getInstance().getDimensionType().maxY();
|
||||
|
||||
final int sectionsCount = chunk.getMaxSection() - chunk.getMinSection();
|
||||
for (int i = 0; i < sectionsCount; i++) {
|
||||
|
@ -52,7 +52,7 @@ final class SkyLight implements Light {
|
||||
|
||||
if (c instanceof LightingChunk lc) {
|
||||
int[] heightmap = lc.getOcclusionMap();
|
||||
int maxY = c.getInstance().getDimensionType().getMinY() + c.getInstance().getDimensionType().getHeight();
|
||||
int maxY = c.getInstance().getDimensionType().minY() + c.getInstance().getDimensionType().height();
|
||||
int sectionMaxY = (sectionY + 1) * 16 - 1;
|
||||
int sectionMinY = sectionY * 16;
|
||||
|
||||
|
@ -1,96 +0,0 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.kyori.adventure.nbt.BinaryTagTypes;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.ListBinaryTag;
|
||||
import net.minestom.server.item.Material;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TrimManager {
|
||||
private final Set<TrimMaterial> trimMaterials;
|
||||
private final Set<TrimPattern> trimPatterns;
|
||||
private CompoundBinaryTag trimMaterialCache = null;
|
||||
private CompoundBinaryTag trimPatternCache = null;
|
||||
|
||||
public TrimManager() {
|
||||
this.trimMaterials = new HashSet<>();
|
||||
this.trimPatterns = new HashSet<>();
|
||||
}
|
||||
|
||||
public @Nullable TrimMaterial fromIngredient(Material ingredient) {
|
||||
return this.trimMaterials.stream().filter(trimMaterial -> trimMaterial.ingredient().equals(ingredient)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public @Nullable TrimPattern fromTemplate(Material material) {
|
||||
return this.trimPatterns.stream().filter(trimPattern -> trimPattern.template().equals(material)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public CompoundBinaryTag getTrimMaterialNBT() {
|
||||
if (trimMaterialCache == null) {
|
||||
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||
for (TrimMaterial trimMaterial : this.trimMaterials)
|
||||
entries.add(trimMaterial.asNBT());
|
||||
trimMaterialCache = CompoundBinaryTag.builder()
|
||||
.putString("type", "minecraft:trim_material")
|
||||
.put("value", entries.build())
|
||||
.build();
|
||||
}
|
||||
return trimMaterialCache;
|
||||
}
|
||||
|
||||
public CompoundBinaryTag getTrimPatternNBT() {
|
||||
if (trimPatternCache == null) {
|
||||
ListBinaryTag.Builder<CompoundBinaryTag> entries = ListBinaryTag.builder(BinaryTagTypes.COMPOUND);
|
||||
for (TrimPattern trimPattern : this.trimPatterns)
|
||||
entries.add(trimPattern.asNBT());
|
||||
trimPatternCache = CompoundBinaryTag.builder()
|
||||
.putString("type", "minecraft:trim_pattern")
|
||||
.put("value", entries.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
return trimPatternCache;
|
||||
}
|
||||
|
||||
public Set<TrimMaterial> getTrimMaterials() {
|
||||
return Set.copyOf(this.trimMaterials);
|
||||
}
|
||||
|
||||
public Set<TrimPattern> getTrimPatterns() {
|
||||
return Set.copyOf(trimPatterns);
|
||||
}
|
||||
|
||||
public void addDefaultTrimMaterials() {
|
||||
this.trimMaterialCache = null;
|
||||
this.trimMaterials.addAll(TrimMaterial.values());
|
||||
}
|
||||
|
||||
public void addDefaultTrimPatterns() {
|
||||
this.trimPatternCache = null;
|
||||
this.trimPatterns.addAll(TrimPattern.values());
|
||||
}
|
||||
|
||||
public boolean addTrimMaterial(TrimMaterial trimMaterial) {
|
||||
this.trimMaterialCache = null;
|
||||
return this.trimMaterials.add(trimMaterial);
|
||||
}
|
||||
|
||||
public boolean removeTrimMaterial(TrimMaterial trimMaterial) {
|
||||
this.trimMaterialCache = null;
|
||||
return this.trimMaterials.remove(trimMaterial);
|
||||
}
|
||||
|
||||
public boolean addTrimPattern(TrimPattern trimPattern) {
|
||||
this.trimPatternCache = null;
|
||||
return this.trimPatterns.add(trimPattern);
|
||||
}
|
||||
|
||||
public boolean removeTrimPattern(TrimPattern trimPattern) {
|
||||
this.trimPatternCache = null;
|
||||
return this.trimPatterns.remove(trimPattern);
|
||||
}
|
||||
}
|
@ -1,98 +1,130 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.registry.StaticProtocolObject;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public interface TrimMaterial extends StaticProtocolObject {
|
||||
static @NotNull TrimMaterial create(@NotNull NamespaceID namespace,
|
||||
@NotNull String assetName,
|
||||
@NotNull Material ingredient,
|
||||
float itemModelIndex,
|
||||
@NotNull Map<String, String> overrideArmorMaterials,
|
||||
@NotNull Component description,
|
||||
Registry.Properties custom) {
|
||||
public sealed interface TrimMaterial extends ProtocolObject permits TrimMaterialImpl {
|
||||
@NotNull BinaryTagSerializer<TrimMaterial> NBT_TYPE = TrimMaterialImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull TrimMaterial create(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull String assetName,
|
||||
@NotNull Material ingredient,
|
||||
float itemModelIndex,
|
||||
@NotNull Map<String, String> overrideArmorMaterials,
|
||||
@NotNull Component description
|
||||
) {
|
||||
return new TrimMaterialImpl(
|
||||
new Registry.TrimMaterialEntry(
|
||||
namespace,
|
||||
assetName,
|
||||
ingredient,
|
||||
itemModelIndex,
|
||||
overrideArmorMaterials,
|
||||
description,
|
||||
custom
|
||||
)
|
||||
namespace, assetName, ingredient, itemModelIndex,
|
||||
overrideArmorMaterials, description, null
|
||||
);
|
||||
}
|
||||
|
||||
static @NotNull TrimMaterial create(@NotNull NamespaceID namespace,
|
||||
@NotNull String assetName,
|
||||
@NotNull Material ingredient,
|
||||
float itemModelIndex,
|
||||
@NotNull Map<String, String> overrideArmorMaterials,
|
||||
@NotNull Component description) {
|
||||
return new TrimMaterialImpl(
|
||||
new Registry.TrimMaterialEntry(
|
||||
namespace,
|
||||
assetName,
|
||||
ingredient,
|
||||
itemModelIndex,
|
||||
overrideArmorMaterials,
|
||||
description,
|
||||
null
|
||||
)
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new registry for trim materials, loading the vanilla trim materials.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<TrimMaterial> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:trim_material", NBT_TYPE, Registry.Resource.TRIM_MATERIALS,
|
||||
(namespace, props) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
static @Nullable TrimMaterial fromId(int id) {
|
||||
return TrimMaterialImpl.fromId(id);
|
||||
}
|
||||
@NotNull String assetName();
|
||||
|
||||
static @Nullable TrimMaterial fromNamespaceId(@NotNull String id) {
|
||||
return TrimMaterialImpl.fromNamespaceId(id);
|
||||
}
|
||||
@NotNull Material ingredient();
|
||||
|
||||
static Collection<TrimMaterial> values() {
|
||||
return TrimMaterialImpl.values();
|
||||
}
|
||||
float itemModelIndex();
|
||||
|
||||
@NotNull Map<String, String> overrideArmorMaterials();
|
||||
|
||||
@NotNull Component description();
|
||||
|
||||
/**
|
||||
* Returns the raw registry entry of this trim, only if the trim is a vanilla trim. Otherwise, returns null.
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@NotNull Registry.TrimMaterialEntry registry();
|
||||
@Nullable Registry.TrimMaterialEntry registry();
|
||||
|
||||
@Override
|
||||
default @NotNull NamespaceID namespace() {
|
||||
return registry().namespace();
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private String assetName;
|
||||
private Material ingredient;
|
||||
private float itemModelIndex;
|
||||
private final Map<String, String> overrideArmorMaterials = new HashMap<>();
|
||||
private Component description;
|
||||
|
||||
Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder assetName(@NotNull String assetName) {
|
||||
this.assetName = assetName;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder ingredient(@NotNull Material ingredient) {
|
||||
this.ingredient = ingredient;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder itemModelIndex(float itemModelIndex) {
|
||||
this.itemModelIndex = itemModelIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder overrideArmorMaterials(@NotNull Map<String, String> overrideArmorMaterials) {
|
||||
this.overrideArmorMaterials.putAll(overrideArmorMaterials);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_, _ -> this", pure = true)
|
||||
public @NotNull Builder overrideArmorMaterial(@NotNull String slot, @NotNull String material) {
|
||||
this.overrideArmorMaterials.put(slot, material);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder description(@NotNull Component description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull TrimMaterial build() {
|
||||
return new TrimMaterialImpl(
|
||||
namespace, assetName, ingredient, itemModelIndex,
|
||||
overrideArmorMaterials, description, null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
default @NotNull String assetName() {
|
||||
return registry().assetName();
|
||||
}
|
||||
|
||||
default @NotNull Material ingredient() {
|
||||
return registry().ingredient();
|
||||
}
|
||||
|
||||
default float itemModelIndex() {
|
||||
return registry().itemModelIndex();
|
||||
}
|
||||
|
||||
default @NotNull Map<String, String> overrideArmorMaterials() {
|
||||
return registry().overrideArmorMaterials();
|
||||
}
|
||||
|
||||
default @NotNull Component description() {
|
||||
return registry().description();
|
||||
}
|
||||
|
||||
CompoundBinaryTag asNBT();
|
||||
|
||||
}
|
||||
|
@ -1,55 +1,61 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.StringBinaryTag;
|
||||
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
record TrimMaterialImpl(Registry.TrimMaterialEntry registry, int id) implements TrimMaterial {
|
||||
static final AtomicInteger i = new AtomicInteger();
|
||||
private static final Registry.Container<TrimMaterial> CONTAINER;
|
||||
record TrimMaterialImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull String assetName,
|
||||
@NotNull Material ingredient,
|
||||
float itemModelIndex,
|
||||
@NotNull Map<String, String> overrideArmorMaterials,
|
||||
@NotNull Component description,
|
||||
@Nullable Registry.TrimMaterialEntry registry
|
||||
) implements TrimMaterial {
|
||||
|
||||
static {
|
||||
CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_MATERIALS,
|
||||
(namespace, properties) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, properties)));
|
||||
static final BinaryTagSerializer<TrimMaterial> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("TrimMaterial is read-only");
|
||||
},
|
||||
trimMaterial -> {
|
||||
CompoundBinaryTag.Builder overrideArmorMaterials = CompoundBinaryTag.builder();
|
||||
for (Map.Entry<String, String> entry : trimMaterial.overrideArmorMaterials().entrySet()) {
|
||||
overrideArmorMaterials.putString(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
return CompoundBinaryTag.builder()
|
||||
.putString("asset_name", trimMaterial.assetName())
|
||||
.put("ingredient", Material.NBT_TYPE.write(trimMaterial.ingredient()))
|
||||
.putFloat("item_model_index", trimMaterial.itemModelIndex())
|
||||
.put("override_armor_materials", overrideArmorMaterials.build())
|
||||
.put("description", BinaryTagSerializer.NBT_COMPONENT.write(trimMaterial.description()))
|
||||
.build();
|
||||
}
|
||||
);
|
||||
|
||||
@SuppressWarnings("ConstantValue") // The builder can violate the nullability constraints
|
||||
TrimMaterialImpl {
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.argCondition(assetName == null || assetName.isEmpty(), "missing asset name: {0}", namespace);
|
||||
Check.argCondition(ingredient == null, "missing ingredient: {0}", namespace);
|
||||
Check.argCondition(overrideArmorMaterials == null, "missing override armor materials: {0}", namespace);
|
||||
Check.argCondition(description == null, "missing description: {0}", namespace);
|
||||
overrideArmorMaterials = Map.copyOf(overrideArmorMaterials);
|
||||
}
|
||||
|
||||
public TrimMaterialImpl(Registry.TrimMaterialEntry registry) {
|
||||
this(registry, i.getAndIncrement());
|
||||
}
|
||||
|
||||
public static TrimMaterial get(String namespace) {
|
||||
return CONTAINER.get(namespace);
|
||||
}
|
||||
|
||||
static @Nullable TrimMaterial fromId(int id) {
|
||||
return CONTAINER.getId(id);
|
||||
}
|
||||
|
||||
static @Nullable TrimMaterial fromNamespaceId(@NotNull String id) {
|
||||
return CONTAINER.get(id);
|
||||
}
|
||||
|
||||
static Collection<TrimMaterial> values() {
|
||||
return CONTAINER.values();
|
||||
}
|
||||
|
||||
public CompoundBinaryTag asNBT() {
|
||||
return CompoundBinaryTag.builder()
|
||||
.putString("asset_name", assetName())
|
||||
.putString("ingredient", ingredient().namespace().asString())
|
||||
.putFloat("item_model_index", itemModelIndex())
|
||||
.put("override_armor_materials", CompoundBinaryTag.from(overrideArmorMaterials().entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, entry -> StringBinaryTag.stringBinaryTag(entry.getValue())))))
|
||||
.put("description", NbtComponentSerializer.nbt().serialize(description()))
|
||||
.build();
|
||||
TrimMaterialImpl(@NotNull Registry.TrimMaterialEntry registry) {
|
||||
this(registry.namespace(), registry.assetName(), registry.ingredient(),
|
||||
registry.itemModelIndex(), registry.overrideArmorMaterials(),
|
||||
registry.description(), registry);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,75 +1,106 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.registry.StaticProtocolObject;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
public sealed interface TrimPattern extends ProtocolObject permits TrimPatternImpl {
|
||||
@NotNull BinaryTagSerializer<TrimPattern> NBT_TYPE = TrimPatternImpl.NBT_TYPE;
|
||||
|
||||
public interface TrimPattern extends StaticProtocolObject {
|
||||
static @NotNull TrimPattern create(@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetID,
|
||||
@NotNull Material template,
|
||||
@NotNull Component description,
|
||||
boolean decal,
|
||||
@NotNull Registry.Properties custom) {
|
||||
return new TrimPatternImpl(
|
||||
new Registry.TrimPatternEntry(namespace, assetID, template, description, decal, custom)
|
||||
static @NotNull TrimPattern create(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetId,
|
||||
@NotNull Material template,
|
||||
@NotNull Component description,
|
||||
boolean decal
|
||||
) {
|
||||
return new TrimPatternImpl(namespace, assetId, template, description, decal, null);
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new registry for trim materials, loading the vanilla trim materials.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<TrimPattern> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:trim_pattern", NBT_TYPE, Registry.Resource.TRIM_PATTERNS,
|
||||
(namespace, props) -> new TrimPatternImpl(Registry.trimPattern(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
static @NotNull TrimPattern create(@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetID,
|
||||
@NotNull Material template,
|
||||
@NotNull Component description,
|
||||
boolean decal) {
|
||||
return new TrimPatternImpl(
|
||||
new Registry.TrimPatternEntry(namespace, assetID, template, description, decal, null)
|
||||
);
|
||||
}
|
||||
@NotNull NamespaceID assetId();
|
||||
|
||||
static @Nullable TrimPattern fromId(int id) {
|
||||
return TrimPatternImpl.fromId(id);
|
||||
}
|
||||
@NotNull Material template();
|
||||
|
||||
static @Nullable TrimPattern fromNamespaceId(@NotNull String id) {
|
||||
return TrimPatternImpl.fromNamespaceId(id);
|
||||
}
|
||||
@NotNull Component description();
|
||||
|
||||
static Collection<TrimPattern> values() {
|
||||
return TrimPatternImpl.values();
|
||||
}
|
||||
boolean isDecal();
|
||||
|
||||
@Contract(pure = true)
|
||||
@NotNull Registry.TrimPatternEntry registry();
|
||||
@Nullable Registry.TrimPatternEntry registry();
|
||||
|
||||
@Override
|
||||
default @NotNull NamespaceID namespace() {
|
||||
return registry().namespace();
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private NamespaceID assetId;
|
||||
private Material template;
|
||||
private Component description;
|
||||
private boolean decal;
|
||||
|
||||
Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder assetId(@NotNull String assetId) {
|
||||
return assetId(NamespaceID.from(assetId));
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder assetId(@NotNull NamespaceID assetId) {
|
||||
this.assetId = assetId;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder template(@NotNull Material template) {
|
||||
this.template = template;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder description(@NotNull Component description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder decal(boolean decal) {
|
||||
this.decal = decal;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull TrimPattern build() {
|
||||
return new TrimPatternImpl(namespace, assetId, template, description, decal, null);
|
||||
}
|
||||
}
|
||||
|
||||
default @NotNull NamespaceID assetID() {
|
||||
return registry().assetID();
|
||||
}
|
||||
|
||||
default @NotNull Material template() {
|
||||
return registry().template();
|
||||
}
|
||||
|
||||
default @NotNull Component description() {
|
||||
return registry().description();
|
||||
}
|
||||
|
||||
default boolean decal() {
|
||||
return registry().decal();
|
||||
}
|
||||
|
||||
CompoundBinaryTag asNBT();
|
||||
|
||||
}
|
||||
|
@ -1,48 +1,45 @@
|
||||
package net.minestom.server.item.armor;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
record TrimPatternImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull NamespaceID assetId,
|
||||
@NotNull Material template,
|
||||
@NotNull Component description,
|
||||
boolean isDecal,
|
||||
@Nullable Registry.TrimPatternEntry registry
|
||||
) implements TrimPattern {
|
||||
|
||||
record TrimPatternImpl(Registry.TrimPatternEntry registry, int id) implements TrimPattern {
|
||||
static final AtomicInteger i = new AtomicInteger();
|
||||
private static final Registry.Container<TrimPattern> CONTAINER;
|
||||
static final BinaryTagSerializer<TrimPattern> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("TrimMaterial is read-only");
|
||||
},
|
||||
trimPattern -> CompoundBinaryTag.builder()
|
||||
.putString("asset_id", trimPattern.assetId().asString())
|
||||
.put("template_item", Material.NBT_TYPE.write(trimPattern.template()))
|
||||
.put("description", BinaryTagSerializer.NBT_COMPONENT.write(trimPattern.description()))
|
||||
.putBoolean("decal", trimPattern.isDecal())
|
||||
.build()
|
||||
);
|
||||
|
||||
static {
|
||||
CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_PATTERNS,
|
||||
(namespace, properties) -> new TrimPatternImpl(Registry.trimPattern(namespace, properties)));
|
||||
TrimPatternImpl {
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.notNull(assetId, "missing asset id: {0}", namespace);
|
||||
Check.notNull(template, "missing template: {0}", namespace);
|
||||
Check.notNull(description, "missing description: {0}", namespace);
|
||||
}
|
||||
|
||||
public TrimPatternImpl(Registry.TrimPatternEntry registry) {
|
||||
this(registry, i.getAndIncrement());
|
||||
TrimPatternImpl(@NotNull Registry.TrimPatternEntry registry) {
|
||||
this(registry.namespace(), registry.assetID(), registry.template(),
|
||||
registry.description(), registry.decal(), registry);
|
||||
}
|
||||
|
||||
public static TrimPattern fromId(int id) {
|
||||
return CONTAINER.getId(id);
|
||||
}
|
||||
|
||||
public static TrimPattern fromNamespaceId(String namespace) {
|
||||
return CONTAINER.getSafe(namespace);
|
||||
}
|
||||
|
||||
public static TrimPattern get(String namespace) {
|
||||
return CONTAINER.get(namespace);
|
||||
}
|
||||
|
||||
static Collection<TrimPattern> values() {
|
||||
return CONTAINER.values();
|
||||
}
|
||||
|
||||
public CompoundBinaryTag asNBT() {
|
||||
return CompoundBinaryTag.builder()
|
||||
.putString("asset_id", assetID().asString())
|
||||
.putString("template_item", template().namespace().asString())
|
||||
.put("description", NbtComponentSerializer.nbt().serialize(description()))
|
||||
.putBoolean("decal", decal())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,32 +7,32 @@ import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public record ArmorTrim(@NotNull TrimMaterial material, @NotNull TrimPattern pattern, boolean showInTooltip) {
|
||||
|
||||
public static final NetworkBuffer.Type<ArmorTrim> NETWORK_TYPE = new NetworkBuffer.Type<>() {
|
||||
@Override
|
||||
public void write(@NotNull NetworkBuffer buffer, ArmorTrim value) {
|
||||
buffer.write(NetworkBuffer.VAR_INT, value.material.id());
|
||||
buffer.write(NetworkBuffer.VAR_INT, value.pattern.id());
|
||||
// buffer.write(NetworkBuffer.VAR_INT, value.material.id());
|
||||
// buffer.write(NetworkBuffer.VAR_INT, value.pattern.id());
|
||||
buffer.write(NetworkBuffer.BOOLEAN, value.showInTooltip);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArmorTrim read(@NotNull NetworkBuffer buffer) {
|
||||
TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim material");
|
||||
TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim pattern");
|
||||
return new ArmorTrim(material, pattern, buffer.read(NetworkBuffer.BOOLEAN));
|
||||
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim material");
|
||||
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromId(buffer.read(NetworkBuffer.VAR_INT)), "unknown trim pattern");
|
||||
// return new ArmorTrim(material, pattern, buffer.read(NetworkBuffer.BOOLEAN));
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
public static final BinaryTagSerializer<ArmorTrim> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromNamespaceId(tag.getString("material")), "unknown trim material");
|
||||
TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromNamespaceId(tag.getString("pattern")), "unknown trim pattern");
|
||||
boolean showInTooltip = tag.getBoolean("show_in_tooltip", true);
|
||||
return new ArmorTrim(material, pattern, showInTooltip);
|
||||
// TrimMaterial material = Objects.requireNonNull(TrimMaterial.fromNamespaceId(tag.getString("material")), "unknown trim material");
|
||||
// TrimPattern pattern = Objects.requireNonNull(TrimPattern.fromNamespaceId(tag.getString("pattern")), "unknown trim pattern");
|
||||
// boolean showInTooltip = tag.getBoolean("show_in_tooltip", true);
|
||||
// return new ArmorTrim(material, pattern, showInTooltip);
|
||||
throw new UnsupportedOperationException("Not implemented");
|
||||
},
|
||||
value -> CompoundBinaryTag.builder()
|
||||
.putString("material", value.material.name())
|
||||
|
@ -117,8 +117,8 @@ public class BlockPlacementListener {
|
||||
}
|
||||
}
|
||||
|
||||
if (placementPosition.y() >= instance.getDimensionType().getMaxY()
|
||||
|| placementPosition.y() < instance.getDimensionType().getMinY()) return;
|
||||
if (placementPosition.y() >= instance.getDimensionType().maxY()
|
||||
|| placementPosition.y() < instance.getDimensionType().minY()) return;
|
||||
|
||||
// Ensure that the final placement position is inside the world border.
|
||||
if (!instance.getWorldBorder().isInside(placementPosition)) {
|
||||
|
@ -13,6 +13,7 @@ import net.minestom.server.network.ConnectionState;
|
||||
import net.minestom.server.network.packet.client.ClientPacket;
|
||||
import net.minestom.server.network.packet.client.common.*;
|
||||
import net.minestom.server.network.packet.client.configuration.ClientFinishConfigurationPacket;
|
||||
import net.minestom.server.network.packet.client.configuration.ClientSelectKnownPacksPacket;
|
||||
import net.minestom.server.network.packet.client.handshake.ClientHandshakePacket;
|
||||
import net.minestom.server.network.packet.client.login.ClientEncryptionResponsePacket;
|
||||
import net.minestom.server.network.packet.client.login.ClientLoginAcknowledgedPacket;
|
||||
@ -55,6 +56,7 @@ public final class PacketListenerManager {
|
||||
setConfigurationListener(ClientKeepAlivePacket.class, KeepAliveListener::listener);
|
||||
setConfigurationListener(ClientPongPacket.class, (packet, player) -> {/* empty */});
|
||||
setConfigurationListener(ClientResourcePackStatusPacket.class, ResourcePackListener::listener);
|
||||
setConfigurationListener(ClientSelectKnownPacksPacket.class, ConfigListener::selectKnownPacks);
|
||||
setConfigurationListener(ClientFinishConfigurationPacket.class, ConfigListener::finishConfigListener);
|
||||
setListener(ConnectionState.CONFIGURATION, ClientCookieResponsePacket.class, CookieListener::handleCookieResponse);
|
||||
|
||||
|
@ -4,11 +4,16 @@ import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.ConnectionManager;
|
||||
import net.minestom.server.network.packet.client.configuration.ClientFinishConfigurationPacket;
|
||||
import net.minestom.server.network.packet.client.configuration.ClientSelectKnownPacksPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class ConfigListener {
|
||||
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
|
||||
|
||||
public static void selectKnownPacks(@NotNull ClientSelectKnownPacksPacket packet, @NotNull Player player) {
|
||||
System.out.println("SelectKnownPacksPacket: " + packet);
|
||||
}
|
||||
|
||||
public static void finishConfigListener(@NotNull ClientFinishConfigurationPacket packet, @NotNull Player player) {
|
||||
CONNECTION_MANAGER.transitionConfigToPlay(player);
|
||||
}
|
||||
|
75
src/main/java/net/minestom/server/message/ChatType.java
Normal file
75
src/main/java/net/minestom/server/message/ChatType.java
Normal file
@ -0,0 +1,75 @@
|
||||
package net.minestom.server.message;
|
||||
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public sealed interface ChatType extends ProtocolObject, ChatTypes permits ChatTypeImpl {
|
||||
@NotNull BinaryTagSerializer<ChatType> NBT_TYPE = ChatTypeImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull ChatType create(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull ChatTypeDecoration chat,
|
||||
@NotNull ChatTypeDecoration narration
|
||||
) {
|
||||
return new ChatTypeImpl(namespace, chat, narration, null);
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Creates a new registry for chat types, loading the vanilla chat types.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<ChatType> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:chat_type", NBT_TYPE, Registry.Resource.CHAT_TYPES,
|
||||
(namespace, props) -> new ChatTypeImpl(Registry.chatType(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull ChatTypeDecoration chat();
|
||||
|
||||
@NotNull ChatTypeDecoration narration();
|
||||
|
||||
@Override
|
||||
@Nullable Registry.ChatTypeEntry registry();
|
||||
|
||||
final class Builder {
|
||||
private final NamespaceID namespace;
|
||||
private ChatTypeDecoration chat;
|
||||
private ChatTypeDecoration narration;
|
||||
|
||||
public Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public Builder chat(@NotNull ChatTypeDecoration chat) {
|
||||
this.chat = chat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder narration(@NotNull ChatTypeDecoration narration) {
|
||||
this.narration = narration;
|
||||
return this;
|
||||
}
|
||||
|
||||
public @NotNull ChatType build() {
|
||||
return new ChatTypeImpl(namespace, chat, narration, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package net.minestom.server.message;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public record ChatTypeDecoration(
|
||||
@NotNull String translationKey,
|
||||
@NotNull List<Parameter> parameters,
|
||||
@NotNull Style style
|
||||
) {
|
||||
|
||||
public static final BinaryTagSerializer<ChatTypeDecoration> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
String translationKey = tag.getString("translation_key");
|
||||
List<Parameter> parameters = Parameter.LIST_NBT_TYPE.read(tag.getList("parameters"));
|
||||
Style style = Style.empty();
|
||||
if (tag.get("style") instanceof CompoundBinaryTag styleTag)
|
||||
style = BinaryTagSerializer.NBT_COMPONENT_STYLE.read(styleTag);
|
||||
return new ChatTypeDecoration(translationKey, parameters, style);
|
||||
},
|
||||
deco -> {
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||
builder.putString("translation_key", deco.translationKey());
|
||||
builder.put("parameters", Parameter.LIST_NBT_TYPE.write(deco.parameters()));
|
||||
if (!deco.style.isEmpty())
|
||||
builder.put("style", BinaryTagSerializer.NBT_COMPONENT_STYLE.write(deco.style()));
|
||||
return builder.build();
|
||||
}
|
||||
);
|
||||
|
||||
public enum Parameter {
|
||||
SENDER,
|
||||
TARGET,
|
||||
CONTENT;
|
||||
|
||||
public static final BinaryTagSerializer<Parameter> NBT_TYPE = BinaryTagSerializer.fromEnumStringable(Parameter.class);
|
||||
private static final BinaryTagSerializer<List<Parameter>> LIST_NBT_TYPE = NBT_TYPE.list();
|
||||
}
|
||||
|
||||
}
|
38
src/main/java/net/minestom/server/message/ChatTypeImpl.java
Normal file
38
src/main/java/net/minestom/server/message/ChatTypeImpl.java
Normal file
@ -0,0 +1,38 @@
|
||||
package net.minestom.server.message;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
record ChatTypeImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
@NotNull ChatTypeDecoration chat,
|
||||
@NotNull ChatTypeDecoration narration,
|
||||
@Nullable Registry.ChatTypeEntry registry
|
||||
) implements ChatType {
|
||||
|
||||
static final BinaryTagSerializer<ChatType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("ChatType is read-only");
|
||||
},
|
||||
chatType -> CompoundBinaryTag.builder()
|
||||
.put("chat", ChatTypeDecoration.NBT_TYPE.write(chatType.chat()))
|
||||
.put("narration", ChatTypeDecoration.NBT_TYPE.write(chatType.narration()))
|
||||
.build()
|
||||
);
|
||||
|
||||
ChatTypeImpl {
|
||||
Check.notNull(namespace, "Namespace cannot be null");
|
||||
Check.notNull(chat, "missing chat: {0}", namespace);
|
||||
Check.notNull(narration, "missing narration: {0}", namespace);
|
||||
}
|
||||
|
||||
ChatTypeImpl(@NotNull Registry.ChatTypeEntry registry) {
|
||||
this(registry.namespace(), registry.chat(), registry.narration(), registry);
|
||||
}
|
||||
|
||||
}
|
@ -1,19 +1,14 @@
|
||||
package net.minestom.server.message;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.TagStringIO;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.network.packet.server.play.SystemChatPacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
@ -28,38 +23,6 @@ public final class Messenger {
|
||||
private static final UUID NO_SENDER = new UUID(0, 0);
|
||||
private static final SystemChatPacket CANNOT_SEND_PACKET = new SystemChatPacket(CANNOT_SEND_MESSAGE, false);
|
||||
|
||||
private static final RegistryDataPacket REGISTRY_DATA_PACKET;
|
||||
|
||||
static {
|
||||
try {
|
||||
REGISTRY_DATA_PACKET = new RegistryDataPacket(
|
||||
"minecraft:chat_type", List.of(
|
||||
new RegistryDataPacket.Entry(
|
||||
"minecraft:chat",
|
||||
TagStringIO.get().asCompound(
|
||||
"""
|
||||
{
|
||||
"chat":{
|
||||
"translation_key":"chat.type.text",
|
||||
"parameters":["sender", "content"]
|
||||
},
|
||||
"narration":{
|
||||
"translation_key":"chat.type.text.narrate",
|
||||
"parameters":["sender", "content"]
|
||||
}
|
||||
}"""
|
||||
)
|
||||
)
|
||||
));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static @NotNull RegistryDataPacket registryDataPacket() {
|
||||
return REGISTRY_DATA_PACKET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a player, respecting their chat settings.
|
||||
*
|
||||
|
@ -5,13 +5,11 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.ServerFlag;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
import net.minestom.server.event.player.AsyncPlayerPreLoginEvent;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.listener.preplay.LoginListener;
|
||||
import net.minestom.server.message.Messenger;
|
||||
import net.minestom.server.network.packet.client.login.ClientLoginStartPacket;
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.common.KeepAlivePacket;
|
||||
@ -19,6 +17,7 @@ import net.minestom.server.network.packet.server.common.PluginMessagePacket;
|
||||
import net.minestom.server.network.packet.server.common.TagsPacket;
|
||||
import net.minestom.server.network.packet.server.configuration.FinishConfigurationPacket;
|
||||
import net.minestom.server.network.packet.server.configuration.ResetChatPacket;
|
||||
import net.minestom.server.network.packet.server.configuration.SelectKnownPacksPacket;
|
||||
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
|
||||
import net.minestom.server.network.packet.server.play.StartConfigurationPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
@ -287,14 +286,18 @@ public final class ConnectionManager {
|
||||
// Registry data (if it should be sent)
|
||||
if (event.willSendRegistryData()) {
|
||||
|
||||
// minecraft:trim_pattern, minecraft:trim_material, minecraft:wolf_variant, and minecraft:banner_pattern.
|
||||
player.sendPacket(new SelectKnownPacksPacket(List.of(SelectKnownPacksPacket.MINECRAFT_CORE)));
|
||||
|
||||
player.sendPacket(Messenger.registryDataPacket());
|
||||
player.sendPacket(MinecraftServer.getDimensionTypeManager().registryDataPacket());
|
||||
player.sendPacket(MinecraftServer.getBiomeManager().registryDataPacket());
|
||||
player.sendPacket(DamageType.registryDataPacket());
|
||||
// registry.put("minecraft:trim_material", MinecraftServer.getTrimManager().getTrimMaterialNBT());
|
||||
// registry.put("minecraft:trim_pattern", MinecraftServer.getTrimManager().getTrimPatternNBT());
|
||||
boolean excludeVanilla = false;
|
||||
var serverProcess = MinecraftServer.process();
|
||||
player.sendPacket(serverProcess.chatType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.dimensionType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.biome().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.damageType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.trimMaterial().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.trimPattern().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.bannerPattern().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.wolfVariant().registryDataPacket(excludeVanilla));
|
||||
|
||||
player.sendPacket(TagsPacket.DEFAULT_TAGS);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.minestom.server.network.packet.server.configuration;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
@ -13,6 +14,8 @@ public record SelectKnownPacksPacket(
|
||||
) implements ServerPacket.Configuration {
|
||||
private static final int MAX_ENTRIES = 64;
|
||||
|
||||
public static final Entry MINECRAFT_CORE = new Entry("minecraft", "core", MinecraftServer.VERSION_NAME);
|
||||
|
||||
public SelectKnownPacksPacket {
|
||||
Check.argCondition(entries.size() > MAX_ENTRIES, "Too many known packs: {0} > {1}", entries.size(), MAX_ENTRIES);
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package net.minestom.server.registry;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface DynamicRegistry<T extends ProtocolObject> {
|
||||
|
||||
@Nullable T get(int id);
|
||||
@Nullable T get(@NotNull NamespaceID namespace);
|
||||
|
||||
int getId(@NotNull NamespaceID id);
|
||||
|
||||
/**
|
||||
* <p>Returns the entries in this registry as an immutable list. The indices in the returned list correspond
|
||||
* to the protocol ID of each entry.</p>
|
||||
*
|
||||
* <p>Note: The returned list is not guaranteed to update with the registry,
|
||||
* it should be fetched again for updated values.</p>
|
||||
*
|
||||
* @return An immutable list of the entries in this registry.
|
||||
*/
|
||||
@NotNull List<T> values();
|
||||
|
||||
/**
|
||||
* <p>Register an object to this registry, overwriting the previous entry if any is present.</p>
|
||||
*
|
||||
* <p>Note: the new registry will not be sent to existing players. They must be returned to
|
||||
* the configuration phase to receive new registry data. See {@link Player#startConfigurationPhase()}.</p>
|
||||
*
|
||||
* @param object The entry to register
|
||||
* @return The new ID of the registered object
|
||||
*/
|
||||
int register(@NotNull T object);
|
||||
|
||||
/**
|
||||
* <p>Removes an object from this registry.</p>
|
||||
*
|
||||
* <p><b>WARNING:</b> This operation will cause all subsequent IDs to be remapped, meaning that any loaded entry
|
||||
* with existing IDs may be incorrect. For example, loading a world with 0=plains, 1=desert, 2=badlands would store
|
||||
* those IDs in the palette. If you then deleted entry 1 (desert), any desert biomes in the loaded world would
|
||||
* become badlands, and any badlands would become invalid. <b>This behavior is disabled by default, and must be
|
||||
* enabled by setting the system property <code>minestom.registry.unsafe-remove</code> to <code>true</code>.</b></p>
|
||||
*
|
||||
* <p>Note: the new registry will not be sent to existing players. They must be returned to
|
||||
* the configuration phase to receive new registry data. See {@link Player#startConfigurationPhase()}.</p>
|
||||
*
|
||||
* @param object The entry to remove
|
||||
* @return True if the object was removed, false if it was not present
|
||||
* @throws UnsupportedOperationException If the system property <code>minestom.registry.unsafe-remove</code> is not set to <code>true</code>
|
||||
*/
|
||||
boolean remove(@NotNull T object) throws UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* <p>Returns a {@link SendablePacket} potentially excluding vanilla entries if possible. It is never possible to
|
||||
* exclude vanilla entries if one has been overridden (e.g. via {@link #register(ProtocolObject)}.</p>
|
||||
*
|
||||
* @param excludeVanilla Whether to exclude vanilla entries
|
||||
* @return A {@link SendablePacket} containing the registry data
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@NotNull SendablePacket registryDataPacket(boolean excludeVanilla);
|
||||
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package net.minestom.server.registry;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.ServerFlag;
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class DynamicRegistryImpl<T extends ProtocolObject> implements DynamicRegistry<T> {
|
||||
private static final UnsupportedOperationException UNSAFE_REMOVE_EXCEPTION = new UnsupportedOperationException("Unsafe remove is disabled. Enable by setting the system property 'minestom.registry.unsafe-remove' to 'true'");
|
||||
|
||||
private final CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(true));
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(); // Protects entryById (except when used alone, it is safe), entryByName, and idByName
|
||||
private final List<T> entryById = new CopyOnWriteArrayList<>(); // We use a CopyOnWriteArrayList even with the lock above because it handles concurrent iteration
|
||||
private final Map<NamespaceID, T> entryByName = new HashMap<>();
|
||||
private final List<NamespaceID> idByName = new ArrayList<>();
|
||||
|
||||
private final String id;
|
||||
private final BinaryTagSerializer<T> nbtType;
|
||||
|
||||
public DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer<T> nbtType) {
|
||||
this.id = id;
|
||||
this.nbtType = nbtType;
|
||||
}
|
||||
|
||||
public DynamicRegistryImpl(@NotNull String id, BinaryTagSerializer<T> nbtType, @NotNull Registry.Resource resource, @NotNull Registry.Container.Loader<T> loader) {
|
||||
this(id, nbtType);
|
||||
loadStaticRegistry(resource, loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable T get(int id) {
|
||||
if (id < 0 || id >= entryById.size()) {
|
||||
return null;
|
||||
}
|
||||
return entryById.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable T get(@NotNull NamespaceID namespace) {
|
||||
lock.lock();
|
||||
try {
|
||||
return entryByName.get(namespace);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId(@NotNull NamespaceID id) {
|
||||
lock.lock();
|
||||
try {
|
||||
return idByName.indexOf(id);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull List<T> values() {
|
||||
return Collections.unmodifiableList(entryById);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int register(@NotNull T object) {
|
||||
lock.lock();
|
||||
try {
|
||||
int id = idByName.indexOf(object.namespace());
|
||||
if (id == -1) id = entryById.size();
|
||||
|
||||
entryById.add(id, object);
|
||||
entryByName.put(object.namespace(), object);
|
||||
idByName.add(object.namespace());
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
return id;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(@NotNull T object) throws UnsupportedOperationException {
|
||||
if (!ServerFlag.REGISTRY_UNSAFE_REMOVE) throw UNSAFE_REMOVE_EXCEPTION;
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
int id = idByName.indexOf(object.namespace());
|
||||
if (id == -1) return false;
|
||||
|
||||
entryById.remove(id);
|
||||
entryByName.remove(object.namespace());
|
||||
idByName.remove(id);
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SendablePacket registryDataPacket(boolean excludeVanilla) {
|
||||
// We cache the vanilla packet because that is by far the most common case. If some client claims not to have
|
||||
// the vanilla datapack we can compute the entire thing.
|
||||
return excludeVanilla ? vanillaRegistryDataPacket : createRegistryDataPacket(false);
|
||||
}
|
||||
|
||||
private @NotNull RegistryDataPacket createRegistryDataPacket(boolean excludeVanilla) {
|
||||
lock.lock();
|
||||
try {
|
||||
var entries = new ArrayList<RegistryDataPacket.Entry>(entryById.size());
|
||||
for (var entry : entryById) {
|
||||
CompoundBinaryTag data = null;
|
||||
// sorta todo, sorta just a note:
|
||||
// Right now we very much only support the minecraft:core (vanilla) 'pack'. Any entry which was not loaded
|
||||
// from static data will be treated as non vanilla and always sent completely. However, we really should
|
||||
// support arbitrary packs and associate all registry data with a datapack. Additionally, we should generate
|
||||
// all data for the experimental datapacks built in to vanilla such as the next update experimental (1.21 at
|
||||
// the time of writing). Datagen currently behaves kind of badly in that the registry inspecting generators
|
||||
// like material, block, etc generate entries which are behind feature flags, whereas the ones which inspect
|
||||
// static assets (the traditionally dynamic registries), do not generate those assets.
|
||||
if (!excludeVanilla || entry.registry() == null) {
|
||||
data = (CompoundBinaryTag) nbtType.write(entry);
|
||||
}
|
||||
entries.add(new RegistryDataPacket.Entry(entry.name(), data));
|
||||
}
|
||||
return new RegistryDataPacket(id, entries);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadStaticRegistry(@NotNull Registry.Resource resource, @NotNull Registry.Container.Loader<T> loader) {
|
||||
for (var entry : Registry.load(resource).entrySet()) {
|
||||
final String namespace = entry.getKey();
|
||||
final Registry.Properties properties = Registry.Properties.fromMap(entry.getValue());
|
||||
register(loader.get(namespace, properties));
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface ProtocolObject extends Keyed {
|
||||
|
||||
@ -21,4 +22,8 @@ public interface ProtocolObject extends Keyed {
|
||||
default @NotNull Key key() {
|
||||
return namespace();
|
||||
}
|
||||
|
||||
default @Nullable Object registry() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
34
src/main/java/net/minestom/server/registry/Registries.java
Normal file
34
src/main/java/net/minestom/server/registry/Registries.java
Normal file
@ -0,0 +1,34 @@
|
||||
package net.minestom.server.registry;
|
||||
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
|
||||
import net.minestom.server.instance.block.banner.BannerPattern;
|
||||
import net.minestom.server.item.armor.TrimMaterial;
|
||||
import net.minestom.server.item.armor.TrimPattern;
|
||||
import net.minestom.server.message.ChatType;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Provides access to all the dynamic registries.
|
||||
*/
|
||||
public interface Registries {
|
||||
|
||||
@NotNull DynamicRegistry<ChatType> chatType();
|
||||
|
||||
@NotNull DynamicRegistry<DimensionType> dimensionType();
|
||||
|
||||
@NotNull DynamicRegistry<Biome> biome();
|
||||
|
||||
@NotNull DynamicRegistry<DamageType> damageType();
|
||||
|
||||
@NotNull DynamicRegistry<TrimMaterial> trimMaterial();
|
||||
|
||||
@NotNull DynamicRegistry<TrimPattern> trimPattern();
|
||||
|
||||
@NotNull DynamicRegistry<BannerPattern> bannerPattern();
|
||||
|
||||
@NotNull DynamicRegistry<WolfMeta.Variant> wolfVariant();
|
||||
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package net.minestom.server.registry;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.ToNumberPolicy;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.kyori.adventure.nbt.BinaryTag;
|
||||
import net.kyori.adventure.nbt.TagStringIOExt;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.json.JSONComponentSerializer;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.collision.BoundingBox;
|
||||
@ -17,6 +21,7 @@ import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.entity.EquipmentSlot;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.message.ChatTypeDecoration;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.collection.ObjectArray;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
@ -42,6 +47,11 @@ public final class Registry {
|
||||
return new BlockEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static DimensionTypeEntry dimensionType(String namespace, @NotNull Properties main) {
|
||||
return new DimensionTypeEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static BiomeEntry biome(String namespace, Properties properties) {
|
||||
return new BiomeEntry(namespace, properties, null);
|
||||
@ -87,6 +97,21 @@ public final class Registry {
|
||||
return new AttributeEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static BannerPatternEntry bannerPattern(String namespace, @NotNull Properties main) {
|
||||
return new BannerPatternEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static WolfVariantEntry wolfVariant(String namespace, @NotNull Properties main) {
|
||||
return new WolfVariantEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static ChatTypeEntry chatType(String namespace, @NotNull Properties main) {
|
||||
return new ChatTypeEntry(namespace, main, null);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static Map<String, Map<String, Object>> load(Resource resource) {
|
||||
Map<String, Map<String, Object>> map = new HashMap<>();
|
||||
@ -232,8 +257,12 @@ public final class Registry {
|
||||
FLUID_TAGS("tags/fluid_tags.json"),
|
||||
GAMEPLAY_TAGS("tags/gameplay_tags.json"),
|
||||
ITEM_TAGS("tags/item_tags.json"),
|
||||
DIMENSION_TYPES("dimension_types.json"),
|
||||
BIOMES("biomes.json"),
|
||||
ATTRIBUTES("attributes.json");
|
||||
ATTRIBUTES("attributes.json"),
|
||||
BANNER_PATTERNS("banner_patterns.json"),
|
||||
WOLF_VARIANTS("wolf_variants.json"),
|
||||
CHAT_TYPES("chat_types.json");
|
||||
|
||||
private final String name;
|
||||
|
||||
@ -400,6 +429,49 @@ public final class Registry {
|
||||
}
|
||||
}
|
||||
|
||||
public record DimensionTypeEntry(
|
||||
NamespaceID namespace,
|
||||
boolean ultrawarm,
|
||||
boolean natural,
|
||||
double coordinateScale,
|
||||
boolean hasSkylight,
|
||||
boolean hasCeiling,
|
||||
float ambientLight,
|
||||
Long fixedTime,
|
||||
boolean piglinSafe,
|
||||
boolean bedWorks,
|
||||
boolean respawnAnchorWorks,
|
||||
boolean hasRaids,
|
||||
int logicalHeight,
|
||||
int minY,
|
||||
int height,
|
||||
String infiniburn,
|
||||
String effects,
|
||||
Properties custom
|
||||
) implements Entry {
|
||||
|
||||
public DimensionTypeEntry(String namespace, Properties main, Properties custom) {
|
||||
this(NamespaceID.from(namespace),
|
||||
main.getBoolean("ultrawarm"),
|
||||
main.getBoolean("natural"),
|
||||
main.getDouble("coordinate_scale"),
|
||||
main.getBoolean("has_skylight"),
|
||||
main.getBoolean("has_ceiling"),
|
||||
main.getFloat("ambient_light"),
|
||||
(Long) main.asMap().get("fixed_time"),
|
||||
main.getBoolean("piglin_safe"),
|
||||
main.getBoolean("bed_works"),
|
||||
main.getBoolean("respawn_anchor_works"),
|
||||
main.getBoolean("has_raids"),
|
||||
main.getInt("logical_height"),
|
||||
main.getInt("min_y"),
|
||||
main.getInt("height"),
|
||||
main.getString("infiniburn"),
|
||||
main.getString("effects"),
|
||||
custom);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class BiomeEntry implements Entry {
|
||||
private final Properties custom;
|
||||
private final NamespaceID namespace;
|
||||
@ -772,6 +844,89 @@ public final class Registry {
|
||||
}
|
||||
}
|
||||
|
||||
public record BannerPatternEntry(NamespaceID namespace, NamespaceID assetId, String translationKey, Properties custom) implements Entry {
|
||||
public BannerPatternEntry(String namespace, Properties main, Properties custom) {
|
||||
this(NamespaceID.from(namespace),
|
||||
NamespaceID.from(main.getString("asset_id")),
|
||||
main.getString("translation_key"),
|
||||
custom);
|
||||
}
|
||||
}
|
||||
|
||||
public record WolfVariantEntry(NamespaceID namespace, NamespaceID wildTexture, NamespaceID tameTexture, NamespaceID angryTexture, List<String> biomes, Properties custom) implements Entry {
|
||||
public WolfVariantEntry(String namespace, Properties main, Properties custom) {
|
||||
this(NamespaceID.from(namespace),
|
||||
NamespaceID.from(main.getString("wild_texture")),
|
||||
NamespaceID.from(main.getString("tame_texture")),
|
||||
NamespaceID.from(main.getString("angry_texture")),
|
||||
readBiomesList(main.asMap().get("biomes")),
|
||||
custom);
|
||||
}
|
||||
|
||||
private static @NotNull List<String> readBiomesList(Object biomes) {
|
||||
if (biomes instanceof List<?> list) {
|
||||
return list.stream().map(Object::toString).collect(Collectors.toList());
|
||||
} else if (biomes instanceof String single) {
|
||||
return List.of(single);
|
||||
} else {
|
||||
throw new IllegalArgumentException("invalid biomes entry: " + biomes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ChatTypeEntry implements Entry {
|
||||
private final NamespaceID namespace;
|
||||
private final ChatTypeDecoration chat;
|
||||
private final ChatTypeDecoration narration;
|
||||
private final Properties custom;
|
||||
|
||||
public ChatTypeEntry(String namespace, Properties main, Properties custom) {
|
||||
this.namespace = NamespaceID.from(namespace);
|
||||
this.chat = readChatTypeDecoration(main.section("chat"));
|
||||
this.narration = readChatTypeDecoration(main.section("narration"));
|
||||
this.custom = custom;
|
||||
}
|
||||
|
||||
public NamespaceID namespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public ChatTypeDecoration chat() {
|
||||
return chat;
|
||||
}
|
||||
|
||||
public ChatTypeDecoration narration() {
|
||||
return narration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties custom() {
|
||||
return custom;
|
||||
}
|
||||
|
||||
private static @NotNull ChatTypeDecoration readChatTypeDecoration(Properties properties) {
|
||||
List<ChatTypeDecoration.Parameter> parameters = new ArrayList<>();
|
||||
if (properties.asMap().get("parameters") instanceof List<?> paramList) {
|
||||
for (Object param : paramList) {
|
||||
parameters.add(ChatTypeDecoration.Parameter.valueOf(param.toString().toUpperCase(Locale.ROOT)));
|
||||
}
|
||||
}
|
||||
Style style = Style.empty();
|
||||
if (properties.containsKey("style")) {
|
||||
// This is admittedly a pretty cursed way to handle deserialization here, however I do not want to
|
||||
// write a standalone JSON style deserializer for this one use case.
|
||||
// The methodology is to just convert it to a valid text component and deserialize that, then take the style.
|
||||
Gson gson = GsonComponentSerializer.gson().serializer();
|
||||
JsonObject textComponentJson = gson.toJsonTree(properties.section("style").asMap()).getAsJsonObject();
|
||||
textComponentJson.addProperty("text", "IGNORED_VALUE");
|
||||
Component textComponent = GsonComponentSerializer.gson().deserializeFromTree(textComponentJson);
|
||||
style = textComponent.style();
|
||||
}
|
||||
return new ChatTypeDecoration(properties.getString("translation_key"), parameters, style);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public interface Entry {
|
||||
@ApiStatus.Experimental
|
||||
Properties custom();
|
||||
@ -834,6 +989,17 @@ public final class Registry {
|
||||
return ((Number) element(name)).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String name, float defaultValue) {
|
||||
var element = element(name);
|
||||
return element != null ? ((Number) element).floatValue() : defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String name) {
|
||||
return ((Number) element(name)).floatValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String name, boolean defaultValue) {
|
||||
var element = element(name);
|
||||
@ -893,6 +1059,10 @@ public final class Registry {
|
||||
|
||||
int getInt(String name);
|
||||
|
||||
float getFloat(String name, float defaultValue);
|
||||
|
||||
float getFloat(String name);
|
||||
|
||||
boolean getBoolean(String name, boolean defaultValue);
|
||||
|
||||
boolean getBoolean(String name);
|
||||
|
@ -2,7 +2,7 @@ package net.minestom.server.snapshot;
|
||||
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.tag.TagReadable;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -4,7 +4,7 @@ import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.tag.TagReadable;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.UnknownNullability;
|
||||
|
@ -13,7 +13,7 @@ import net.minestom.server.tag.TagReadable;
|
||||
import net.minestom.server.utils.collection.IntMappedArray;
|
||||
import net.minestom.server.utils.collection.MappedCollection;
|
||||
import net.minestom.server.world.DimensionType;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -103,7 +103,7 @@ public final class SnapshotImpl {
|
||||
final Section section = sections[getChunkCoordinate(y) - minSection];
|
||||
final int id = section.biomePalette()
|
||||
.get(toSectionRelativeCoordinate(x) / 4, toSectionRelativeCoordinate(y) / 4, toSectionRelativeCoordinate(z) / 4);
|
||||
return MinecraftServer.getBiomeManager().getById(id);
|
||||
return MinecraftServer.getBiomeRegistry().get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,7 +2,9 @@ package net.minestom.server.utils.nbt;
|
||||
|
||||
import net.kyori.adventure.nbt.*;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.adventure.serializer.nbt.NbtComponentSerializer;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.utils.UniqueIdUtils;
|
||||
import net.minestom.server.utils.Unit;
|
||||
@ -176,6 +178,28 @@ public interface BinaryTagSerializer<T> {
|
||||
s -> GsonComponentSerializer.gson().deserialize(s),
|
||||
c -> GsonComponentSerializer.gson().serialize(c)
|
||||
);
|
||||
BinaryTagSerializer<Component> NBT_COMPONENT = new BinaryTagSerializer<>() {
|
||||
@Override
|
||||
public @NotNull BinaryTag write(@NotNull Component value) {
|
||||
return NbtComponentSerializer.nbt().serialize(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component read(@NotNull BinaryTag tag) {
|
||||
return NbtComponentSerializer.nbt().deserialize(tag);
|
||||
}
|
||||
};
|
||||
BinaryTagSerializer<Style> NBT_COMPONENT_STYLE = new BinaryTagSerializer<>() {
|
||||
@Override
|
||||
public @NotNull BinaryTag write(@NotNull Style value) {
|
||||
return NbtComponentSerializer.nbt().serializeStyle(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Style read(@NotNull BinaryTag tag) {
|
||||
return NbtComponentSerializer.nbt().deserializeStyle(tag);
|
||||
}
|
||||
};
|
||||
BinaryTagSerializer<ItemStack> ITEM = COMPOUND.map(ItemStack::fromItemNBT, ItemStack::toItemNBT);
|
||||
|
||||
BinaryTagSerializer<UUID> UUID = new BinaryTagSerializer<>() {
|
||||
|
@ -1,361 +1,213 @@
|
||||
package net.minestom.server.world;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* https://minecraft.wiki/w/Custom_dimension
|
||||
*/
|
||||
public class DimensionType {
|
||||
public sealed interface DimensionType extends ProtocolObject, DimensionTypes permits DimensionTypeImpl {
|
||||
@NotNull BinaryTagSerializer<DimensionType> NBT_TYPE = DimensionTypeImpl.NBT_TYPE;
|
||||
|
||||
private static final AtomicInteger idCounter = new AtomicInteger(0);
|
||||
int VANILLA_MIN_Y = -64;
|
||||
int VANILLA_MAX_Y = 319;
|
||||
|
||||
private static final int VANILLA_MIN_Y = -64;
|
||||
private static final int VANILLA_MAX_Y = 319;
|
||||
|
||||
public static final DimensionType OVERWORLD = DimensionType.builder(NamespaceID.from("minecraft:overworld"))
|
||||
.ultrawarm(false)
|
||||
.natural(true)
|
||||
.piglinSafe(false)
|
||||
.respawnAnchorSafe(false)
|
||||
.bedSafe(true)
|
||||
.raidCapable(true)
|
||||
.skylightEnabled(true)
|
||||
.ceilingEnabled(false)
|
||||
.fixedTime(null)
|
||||
.ambientLight(0.0f)
|
||||
.height(384)
|
||||
.minY(-64)
|
||||
.logicalHeight(384)
|
||||
.infiniburn(NamespaceID.from("minecraft:infiniburn_overworld"))
|
||||
.build();
|
||||
|
||||
private final int id = idCounter.getAndIncrement();
|
||||
|
||||
protected volatile boolean registered;
|
||||
|
||||
private final NamespaceID name;
|
||||
private final boolean natural;
|
||||
private final float ambientLight;
|
||||
private final boolean ceilingEnabled;
|
||||
private final boolean skylightEnabled;
|
||||
|
||||
@Nullable
|
||||
private final Long fixedTime;
|
||||
|
||||
private final boolean raidCapable;
|
||||
private final boolean respawnAnchorSafe;
|
||||
private final boolean ultrawarm;
|
||||
private final boolean bedSafe;
|
||||
private final String effects;
|
||||
private final boolean piglinSafe;
|
||||
private final int minY;
|
||||
private final int height;
|
||||
private final int logicalHeight;
|
||||
private final double coordinateScale;
|
||||
private final NamespaceID infiniburn;
|
||||
|
||||
DimensionType(NamespaceID name, boolean natural, float ambientLight, boolean ceilingEnabled,
|
||||
boolean skylightEnabled, @Nullable Long fixedTime, boolean raidCapable,
|
||||
boolean respawnAnchorSafe, boolean ultrawarm, boolean bedSafe, String effects, boolean piglinSafe,
|
||||
int minY, int height, int logicalHeight, double coordinateScale, NamespaceID infiniburn) {
|
||||
this.name = name;
|
||||
this.natural = natural;
|
||||
this.ambientLight = ambientLight;
|
||||
this.ceilingEnabled = ceilingEnabled;
|
||||
this.skylightEnabled = skylightEnabled;
|
||||
this.fixedTime = fixedTime;
|
||||
this.raidCapable = raidCapable;
|
||||
this.respawnAnchorSafe = respawnAnchorSafe;
|
||||
this.ultrawarm = ultrawarm;
|
||||
this.bedSafe = bedSafe;
|
||||
this.effects = effects;
|
||||
this.piglinSafe = piglinSafe;
|
||||
this.minY = minY;
|
||||
this.height = height;
|
||||
this.logicalHeight = logicalHeight;
|
||||
this.coordinateScale = coordinateScale;
|
||||
this.infiniburn = infiniburn;
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
public static DimensionTypeBuilder builder(NamespaceID name) {
|
||||
return hiddenBuilder().name(name);
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
public static DimensionTypeBuilder hiddenBuilder() {
|
||||
return new DimensionTypeBuilder();
|
||||
/**
|
||||
* <p>Creates a new registry for dimension types, loading the vanilla dimension types.</p>
|
||||
*
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<DimensionType> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:dimension_type", NBT_TYPE, Registry.Resource.DIMENSION_TYPES,
|
||||
(namespace, props) -> new DimensionTypeImpl(Registry.dimensionType(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
public static DimensionType fromNBT(CompoundBinaryTag nbt) {
|
||||
return DimensionType.builder(NamespaceID.from(nbt.getString("name")))
|
||||
.ambientLight(nbt.getFloat("ambient_light"))
|
||||
.infiniburn(NamespaceID.from(nbt.getString("infiniburn").replaceFirst("#", "")))
|
||||
.natural(nbt.getBoolean("natural"))
|
||||
.ceilingEnabled(nbt.getBoolean("has_ceiling"))
|
||||
.skylightEnabled(nbt.getBoolean("has_skylight"))
|
||||
.ultrawarm(nbt.getBoolean("ultrawarm"))
|
||||
.raidCapable(nbt.getBoolean("has_raids"))
|
||||
.respawnAnchorSafe(nbt.getBoolean("respawn_anchor_works"))
|
||||
.bedSafe(nbt.getBoolean("bed_works"))
|
||||
.effects(nbt.getString("effects"))
|
||||
.piglinSafe(nbt.getBoolean("piglin_safe"))
|
||||
.logicalHeight(nbt.getInt("logical_height"))
|
||||
.coordinateScale(nbt.getDouble("coordinate_scale"))
|
||||
.build();
|
||||
boolean ultrawarm();
|
||||
|
||||
boolean natural();
|
||||
|
||||
double coordinateScale();
|
||||
|
||||
boolean hasSkylight();
|
||||
|
||||
boolean hasCeiling();
|
||||
|
||||
float ambientLight();
|
||||
|
||||
@Nullable Long fixedTime();
|
||||
|
||||
boolean piglinSafe();
|
||||
|
||||
boolean bedWorks();
|
||||
|
||||
boolean respawnAnchorWorks();
|
||||
|
||||
boolean hasRaids();
|
||||
|
||||
int logicalHeight();
|
||||
|
||||
int minY();
|
||||
|
||||
default int maxY() {
|
||||
return minY() + height();
|
||||
}
|
||||
|
||||
public @NotNull RegistryDataPacket.Entry toRegistryEntry() {
|
||||
return new RegistryDataPacket.Entry(name.toString(), toNBT());
|
||||
int height();
|
||||
|
||||
@NotNull NamespaceID infiniburn();
|
||||
|
||||
@NotNull String effects();
|
||||
|
||||
default int totalHeight() {
|
||||
return minY() + height();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CompoundBinaryTag toNBT() {
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder();
|
||||
builder.putFloat("ambient_light", ambientLight);
|
||||
builder.putString("infiniburn", "#" + infiniburn.toString());
|
||||
builder.putByte("natural", (byte) (natural ? 0x01 : 0x00));
|
||||
builder.putByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00));
|
||||
builder.putByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00));
|
||||
builder.putByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00));
|
||||
builder.putByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00));
|
||||
builder.putByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00));
|
||||
builder.putByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00));
|
||||
builder.putString("effects", effects);
|
||||
builder.putByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00));
|
||||
builder.putInt("min_y", minY);
|
||||
builder.putInt("height", height);
|
||||
builder.putInt("logical_height", logicalHeight);
|
||||
builder.putDouble("coordinate_scale", coordinateScale);
|
||||
builder.putString("name", name.toString());
|
||||
builder.putInt("monster_spawn_block_light_limit", 0);
|
||||
builder.putInt("monster_spawn_light_level", 11);
|
||||
if (fixedTime != null) builder.putLong("fixed_time", fixedTime);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name.toString();
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public boolean isRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public NamespaceID getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public boolean isNatural() {
|
||||
return this.natural;
|
||||
}
|
||||
|
||||
public float getAmbientLight() {
|
||||
return this.ambientLight;
|
||||
}
|
||||
|
||||
public boolean isCeilingEnabled() {
|
||||
return this.ceilingEnabled;
|
||||
}
|
||||
|
||||
public boolean isSkylightEnabled() {
|
||||
return this.skylightEnabled;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getFixedTime() {
|
||||
return this.fixedTime;
|
||||
}
|
||||
|
||||
public boolean isRaidCapable() {
|
||||
return this.raidCapable;
|
||||
}
|
||||
|
||||
public boolean isRespawnAnchorSafe() {
|
||||
return this.respawnAnchorSafe;
|
||||
}
|
||||
|
||||
public boolean isUltrawarm() {
|
||||
return this.ultrawarm;
|
||||
}
|
||||
|
||||
public boolean isBedSafe() {
|
||||
return this.bedSafe;
|
||||
}
|
||||
|
||||
public String getEffects() {
|
||||
return effects;
|
||||
}
|
||||
|
||||
public boolean isPiglinSafe() {
|
||||
return this.piglinSafe;
|
||||
}
|
||||
|
||||
public int getMinY() {
|
||||
return minY;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public int getMaxY() {
|
||||
return getMinY() + getHeight();
|
||||
}
|
||||
|
||||
public int getLogicalHeight() {
|
||||
return this.logicalHeight;
|
||||
}
|
||||
|
||||
public double getCoordinateScale() {
|
||||
return this.coordinateScale;
|
||||
}
|
||||
|
||||
public NamespaceID getInfiniburn() {
|
||||
return this.infiniburn;
|
||||
}
|
||||
|
||||
public int getTotalHeight() {
|
||||
return minY + height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
DimensionType that = (DimensionType) o;
|
||||
return id == that.id &&
|
||||
Objects.equals(name, that.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name);
|
||||
}
|
||||
|
||||
public static class DimensionTypeBuilder {
|
||||
private NamespaceID name;
|
||||
private boolean natural;
|
||||
private float ambientLight;
|
||||
private boolean ceilingEnabled;
|
||||
private boolean skylightEnabled;
|
||||
|
||||
@Nullable
|
||||
private Long fixedTime = null;
|
||||
private boolean raidCapable;
|
||||
private boolean respawnAnchorSafe;
|
||||
private boolean ultrawarm;
|
||||
private boolean bedSafe = true;
|
||||
private String effects = "minecraft:overworld";
|
||||
private boolean piglinSafe = false;
|
||||
private int minY = VANILLA_MIN_Y;
|
||||
private int logicalHeight = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||
private int height = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||
final class Builder {
|
||||
// Defaults match the vanilla overworld
|
||||
private final NamespaceID namespace;
|
||||
private boolean ultrawarm = false;
|
||||
private boolean natural = true;
|
||||
private double coordinateScale = 1.0;
|
||||
private boolean hasSkylight = true;
|
||||
private boolean hasCeiling = false;
|
||||
private float ambientLight = 0f;
|
||||
private Long fixedTime = null;
|
||||
private boolean piglinSafe = false;
|
||||
private boolean bedWorks = true;
|
||||
private boolean respawnAnchorWorks = false;
|
||||
private boolean hasRaids = true;
|
||||
private int logicalHeight = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||
private int minY = VANILLA_MIN_Y;
|
||||
private int height = VANILLA_MAX_Y - VANILLA_MIN_Y + 1;
|
||||
private NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld");
|
||||
private String effects = "minecraft:overworld";
|
||||
|
||||
DimensionTypeBuilder() {
|
||||
public Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder name(NamespaceID name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder natural(boolean natural) {
|
||||
this.natural = natural;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder ambientLight(float ambientLight) {
|
||||
this.ambientLight = ambientLight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder ceilingEnabled(boolean ceilingEnabled) {
|
||||
this.ceilingEnabled = ceilingEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder skylightEnabled(boolean skylightEnabled) {
|
||||
this.skylightEnabled = skylightEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder fixedTime(Long fixedTime) {
|
||||
this.fixedTime = fixedTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder raidCapable(boolean raidCapable) {
|
||||
this.raidCapable = raidCapable;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder respawnAnchorSafe(boolean respawnAnchorSafe) {
|
||||
this.respawnAnchorSafe = respawnAnchorSafe;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder ultrawarm(boolean ultrawarm) {
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder ultrawarm(boolean ultrawarm) {
|
||||
this.ultrawarm = ultrawarm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder bedSafe(boolean bedSafe) {
|
||||
this.bedSafe = bedSafe;
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder natural(boolean natural) {
|
||||
this.natural = natural;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder effects(String effects) {
|
||||
this.effects = effects;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder piglinSafe(boolean piglinSafe) {
|
||||
this.piglinSafe = piglinSafe;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder minY(int minY) {
|
||||
this.minY = minY;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder height(int height) {
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder logicalHeight(int logicalHeight) {
|
||||
this.logicalHeight = logicalHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder coordinateScale(double coordinateScale) {
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder coordinateScale(double coordinateScale) {
|
||||
this.coordinateScale = coordinateScale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType.DimensionTypeBuilder infiniburn(NamespaceID infiniburn) {
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder hasSkylight(boolean hasSkylight) {
|
||||
this.hasSkylight = hasSkylight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder hasCeiling(boolean hasCeiling) {
|
||||
this.hasCeiling = hasCeiling;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder ambientLight(float ambientLight) {
|
||||
this.ambientLight = ambientLight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder fixedTime(@Nullable Long fixedTime) {
|
||||
this.fixedTime = fixedTime;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder piglinSafe(boolean piglinSafe) {
|
||||
this.piglinSafe = piglinSafe;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder bedWorks(boolean bedWorks) {
|
||||
this.bedWorks = bedWorks;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder respawnAnchorWorks(boolean respawnAnchorWorks) {
|
||||
this.respawnAnchorWorks = respawnAnchorWorks;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder hasRaids(boolean hasRaids) {
|
||||
this.hasRaids = hasRaids;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder logicalHeight(int logicalHeight) {
|
||||
this.logicalHeight = logicalHeight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder minY(int minY) {
|
||||
this.minY = minY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder height(int height) {
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder infiniburn(@NotNull NamespaceID infiniburn) {
|
||||
this.infiniburn = infiniburn;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DimensionType build() {
|
||||
return new DimensionType(name, natural, ambientLight, ceilingEnabled, skylightEnabled,
|
||||
fixedTime, raidCapable, respawnAnchorSafe, ultrawarm, bedSafe, effects,
|
||||
piglinSafe, minY, height, logicalHeight, coordinateScale, infiniburn);
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder effects(@NotNull String effects) {
|
||||
this.effects = effects;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull DimensionType build() {
|
||||
return new DimensionTypeImpl(
|
||||
namespace, ultrawarm, natural, coordinateScale, hasSkylight, hasCeiling, ambientLight,
|
||||
fixedTime, piglinSafe, bedWorks, respawnAnchorWorks, hasRaids, logicalHeight, minY, height,
|
||||
infiniburn, effects, null
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
package net.minestom.server.world;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
record DimensionTypeImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
boolean ultrawarm,
|
||||
boolean natural,
|
||||
double coordinateScale,
|
||||
boolean hasSkylight,
|
||||
boolean hasCeiling,
|
||||
float ambientLight,
|
||||
@Nullable Long fixedTime,
|
||||
boolean piglinSafe,
|
||||
boolean bedWorks,
|
||||
boolean respawnAnchorWorks,
|
||||
boolean hasRaids,
|
||||
int logicalHeight,
|
||||
int minY,
|
||||
int height,
|
||||
@NotNull NamespaceID infiniburn,
|
||||
@NotNull String effects,
|
||||
@Nullable Registry.DimensionTypeEntry registry
|
||||
) implements DimensionType {
|
||||
|
||||
static final BinaryTagSerializer<DimensionType> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("DimensionType is read-only");
|
||||
},
|
||||
dimensionType -> {
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder()
|
||||
.putBoolean("ultrawarm", dimensionType.ultrawarm())
|
||||
.putBoolean("natural", dimensionType.natural())
|
||||
.putDouble("coordinate_scale", dimensionType.coordinateScale())
|
||||
.putBoolean("has_skylight", dimensionType.hasSkylight())
|
||||
.putBoolean("has_ceiling", dimensionType.hasCeiling())
|
||||
.putFloat("ambient_light", dimensionType.ambientLight())
|
||||
.putBoolean("piglin_safe", dimensionType.piglinSafe())
|
||||
.putBoolean("bed_works", dimensionType.bedWorks())
|
||||
.putBoolean("respawn_anchor_works", dimensionType.respawnAnchorWorks())
|
||||
.putBoolean("has_raids", dimensionType.hasRaids())
|
||||
.putInt("logical_height", dimensionType.logicalHeight())
|
||||
.putInt("min_y", dimensionType.minY())
|
||||
.putInt("height", dimensionType.height())
|
||||
.putString("infiniburn", dimensionType.infiniburn().toString())
|
||||
.putString("effects", dimensionType.effects())
|
||||
|
||||
//todo load these from registry
|
||||
.putInt("monster_spawn_block_light_limit", 0)
|
||||
.putInt("monster_spawn_light_level", 0);
|
||||
Long fixedTime = dimensionType.fixedTime();
|
||||
if (fixedTime != null) builder.putLong("fixed_time", fixedTime);
|
||||
return builder.build();
|
||||
}
|
||||
);
|
||||
|
||||
DimensionTypeImpl(@NotNull Registry.DimensionTypeEntry registry) {
|
||||
this(registry.namespace(), registry.ultrawarm(), registry.natural(), registry.coordinateScale(),
|
||||
registry.hasSkylight(), registry.hasCeiling(), registry.ambientLight(), registry.fixedTime(),
|
||||
registry.piglinSafe(), registry.bedWorks(), registry.respawnAnchorWorks(), registry.hasRaids(),
|
||||
registry.logicalHeight(), registry.minY(), registry.height(), NamespaceID.from(registry.infiniburn()),
|
||||
registry.effects(), registry);
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
package net.minestom.server.world;
|
||||
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* Allows servers to register custom dimensions. Also used during player login to send the list of all existing dimensions.
|
||||
* <p>
|
||||
* Contains {@link DimensionType#OVERWORLD} by default but can be removed.
|
||||
*/
|
||||
public final class DimensionTypeManager {
|
||||
|
||||
private final CachedPacket registryDataPacket = new CachedPacket(this::createRegistryDataPacket);
|
||||
private final List<DimensionType> dimensionTypes = new CopyOnWriteArrayList<>();
|
||||
|
||||
public DimensionTypeManager() {
|
||||
addDimension(DimensionType.OVERWORLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new dimension type. This does NOT send the new list to players.
|
||||
*
|
||||
* @param dimensionType the dimension to add
|
||||
*/
|
||||
public void addDimension(@NotNull DimensionType dimensionType) {
|
||||
dimensionType.registered = true;
|
||||
this.dimensionTypes.add(dimensionType);
|
||||
registryDataPacket.invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a dimension type. This does NOT send the new list to players.
|
||||
*
|
||||
* @param dimensionType the dimension to remove
|
||||
* @return if the dimension type was removed, false if it was not present before
|
||||
*/
|
||||
public boolean removeDimension(@NotNull DimensionType dimensionType) {
|
||||
dimensionType.registered = false;
|
||||
boolean removed = dimensionTypes.remove(dimensionType);
|
||||
if (removed) registryDataPacket.invalidate();
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param namespaceID The dimension name
|
||||
* @return true if the dimension is registered
|
||||
*/
|
||||
public boolean isRegistered(@NotNull NamespaceID namespaceID) {
|
||||
return isRegistered(getDimension(namespaceID));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dimensionType dimension to check if is registered
|
||||
* @return true if the dimension is registered
|
||||
*/
|
||||
public boolean isRegistered(@Nullable DimensionType dimensionType) {
|
||||
return dimensionType != null && dimensionTypes.contains(dimensionType) && dimensionType.isRegistered();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return to a @{@link DimensionType} only if present and registered
|
||||
*
|
||||
* @param namespaceID The Dimension Name
|
||||
* @return a DimensionType if it is present and registered
|
||||
*/
|
||||
public @Nullable DimensionType getDimension(@NotNull NamespaceID namespaceID) {
|
||||
return unmodifiableList().stream().filter(dimensionType -> dimensionType.getName().equals(namespaceID)).filter(DimensionType::isRegistered).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of the dimension types already registered.
|
||||
*
|
||||
* @return an unmodifiable {@link List} containing all the added dimensions
|
||||
*/
|
||||
public @NotNull List<DimensionType> unmodifiableList() {
|
||||
return Collections.unmodifiableList(dimensionTypes);
|
||||
}
|
||||
|
||||
public @NotNull SendablePacket registryDataPacket() {
|
||||
return registryDataPacket;
|
||||
}
|
||||
|
||||
private @NotNull RegistryDataPacket createRegistryDataPacket() {
|
||||
return new RegistryDataPacket(
|
||||
"minecraft:dimension_type",
|
||||
dimensionTypes.stream()
|
||||
.map(DimensionType::toRegistryEntry)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,35 +1,53 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
package net.minestom.server.world.biome;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.DynamicRegistryImpl;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
public sealed interface Biome extends Biomes, ProtocolObject permits BiomeImpl {
|
||||
@NotNull BinaryTagSerializer<Biome> NBT_TYPE = BiomeImpl.NBT_TYPE;
|
||||
|
||||
static @NotNull Builder builder(@NotNull String namespace) {
|
||||
return builder(NamespaceID.from(namespace));
|
||||
}
|
||||
|
||||
static @NotNull Builder builder(@NotNull NamespaceID namespace) {
|
||||
return new Builder(namespace);
|
||||
}
|
||||
|
||||
sealed public interface Biome extends ProtocolObject permits BiomeImpl {
|
||||
/**
|
||||
* Returns the entity registry.
|
||||
* <p>Creates a new registry for biomes, loading the vanilla trim biomes.</p>
|
||||
*
|
||||
* @return the entity registry or null if it was created with a builder
|
||||
* @see net.minestom.server.MinecraftServer to get an existing instance of the registry
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
@Nullable Registry.BiomeEntry registry();
|
||||
@ApiStatus.Internal
|
||||
static @NotNull DynamicRegistry<Biome> createDefaultRegistry() {
|
||||
return new DynamicRegistryImpl<>(
|
||||
"minecraft:worldgen/biome", NBT_TYPE, Registry.Resource.BIOMES,
|
||||
(namespace, props) -> new BiomeImpl(Registry.biome(namespace, props))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull NamespaceID namespace();
|
||||
float temperature();
|
||||
|
||||
float downfall();
|
||||
|
||||
@NotNull BiomeEffects effects();
|
||||
|
||||
@NotNull Precipitation precipitation();
|
||||
|
||||
@NotNull TemperatureModifier temperatureModifier();
|
||||
|
||||
@Nullable Registry.BiomeEntry registry();
|
||||
|
||||
enum Precipitation {
|
||||
NONE, RAIN, SNOW;
|
||||
}
|
||||
@ -54,30 +72,6 @@ sealed public interface Biome extends ProtocolObject permits BiomeImpl {
|
||||
}
|
||||
}
|
||||
|
||||
default @NotNull RegistryDataPacket.Entry toRegistryEntry() {
|
||||
return new RegistryDataPacket.Entry(namespace().toString(), toNbt());
|
||||
}
|
||||
|
||||
default @NotNull CompoundBinaryTag toNbt() {
|
||||
Check.notNull(name(), "The biome namespace cannot be null");
|
||||
Check.notNull(effects(), "The biome effects cannot be null");
|
||||
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder()
|
||||
.putFloat("temperature", temperature())
|
||||
.putFloat("downfall", downfall())
|
||||
.putByte("has_precipitation", (byte) (precipitation() == Precipitation.NONE ? 0 : 1))
|
||||
.putString("precipitation", precipitation().name().toLowerCase(Locale.ROOT));
|
||||
if (temperatureModifier() != TemperatureModifier.NONE)
|
||||
builder.putString("temperature_modifier", temperatureModifier().name().toLowerCase(Locale.ROOT));
|
||||
return builder
|
||||
.put("effects", effects().toNbt())
|
||||
.build();
|
||||
}
|
||||
|
||||
static @NotNull Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
final class Builder {
|
||||
private static final BiomeEffects DEFAULT_EFFECTS = BiomeEffects.builder()
|
||||
.fogColor(0xC0D8FF)
|
||||
@ -86,17 +80,15 @@ sealed public interface Biome extends ProtocolObject permits BiomeImpl {
|
||||
.waterFogColor(0x50533)
|
||||
.build();
|
||||
|
||||
private NamespaceID name;
|
||||
private final NamespaceID namespace;
|
||||
private float temperature = 0.25f;
|
||||
private float downfall = 0.8f;
|
||||
private BiomeEffects effects = DEFAULT_EFFECTS;
|
||||
private Precipitation precipitation = Precipitation.RAIN;
|
||||
private TemperatureModifier temperatureModifier = TemperatureModifier.NONE;
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
public @NotNull Builder name(@NotNull NamespaceID name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
Builder(@NotNull NamespaceID namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Contract(value = "_ -> this", pure = true)
|
||||
@ -131,7 +123,7 @@ sealed public interface Biome extends ProtocolObject permits BiomeImpl {
|
||||
|
||||
@Contract(pure = true)
|
||||
public @NotNull Biome build() {
|
||||
return new BiomeImpl(name, temperature, downfall, effects, precipitation, temperatureModifier);
|
||||
return new BiomeImpl(namespace, temperature, downfall, effects, precipitation, temperatureModifier, null);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
package net.minestom.server.world.biome;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.utils.NamespaceID;
|
66
src/main/java/net/minestom/server/world/biome/BiomeImpl.java
Normal file
66
src/main/java/net/minestom/server/world/biome/BiomeImpl.java
Normal file
@ -0,0 +1,66 @@
|
||||
package net.minestom.server.world.biome;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.nbt.BinaryTagSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
record BiomeImpl(
|
||||
@NotNull NamespaceID namespace,
|
||||
float temperature,
|
||||
float downfall,
|
||||
@NotNull BiomeEffects effects,
|
||||
@NotNull Precipitation precipitation,
|
||||
@NotNull TemperatureModifier temperatureModifier,
|
||||
@Nullable Registry.BiomeEntry registry
|
||||
) implements Biome {
|
||||
// https://minecraft.wiki/w/Rain
|
||||
private final static Double SNOW_TEMPERATURE = 0.15;
|
||||
|
||||
static final BinaryTagSerializer<Biome> NBT_TYPE = BinaryTagSerializer.COMPOUND.map(
|
||||
tag -> {
|
||||
throw new UnsupportedOperationException("Biome is read-only");
|
||||
},
|
||||
biome -> {
|
||||
CompoundBinaryTag.Builder builder = CompoundBinaryTag.builder()
|
||||
.putFloat("temperature", biome.temperature())
|
||||
.putFloat("downfall", biome.downfall())
|
||||
.putByte("has_precipitation", (byte) (biome.precipitation() == Precipitation.NONE ? 0 : 1))
|
||||
.putString("precipitation", biome.precipitation().name().toLowerCase(Locale.ROOT));
|
||||
if (biome.temperatureModifier() != TemperatureModifier.NONE)
|
||||
builder.putString("temperature_modifier", biome.temperatureModifier().name().toLowerCase(Locale.ROOT));
|
||||
return builder
|
||||
.put("effects", biome.effects().toNbt())
|
||||
.build();
|
||||
}
|
||||
);
|
||||
|
||||
BiomeImpl(Registry.BiomeEntry entry) {
|
||||
this(entry.namespace(), entry.temperature(), entry.downfall(), getBuilder(entry).build(),
|
||||
entry.hasPrecipitation()
|
||||
? entry.temperature() < SNOW_TEMPERATURE
|
||||
? Precipitation.SNOW
|
||||
: Precipitation.RAIN
|
||||
: Precipitation.NONE,
|
||||
entry.temperature() < SNOW_TEMPERATURE ? TemperatureModifier.FROZEN : TemperatureModifier.NONE,
|
||||
entry
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static BiomeEffects.Builder getBuilder(Registry.BiomeEntry entry) {
|
||||
BiomeEffects.Builder effectsBuilder = BiomeEffects.builder();
|
||||
if (entry.foliageColor() != null) effectsBuilder.foliageColor(entry.foliageColor());
|
||||
if (entry.grassColor() != null) effectsBuilder.grassColor(entry.grassColor());
|
||||
if (entry.skyColor() != null) effectsBuilder.skyColor(entry.skyColor());
|
||||
if (entry.waterColor() != null) effectsBuilder.waterColor(entry.waterColor());
|
||||
if (entry.waterFogColor() != null) effectsBuilder.waterFogColor(entry.waterFogColor());
|
||||
if (entry.fogColor() != null) effectsBuilder.fogColor(entry.fogColor());
|
||||
return effectsBuilder;
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
package net.minestom.server.world.biome;
|
||||
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.minestom.server.instance.block.Block;
|
@ -1,111 +0,0 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
final class BiomeImpl implements ProtocolObject, Biome {
|
||||
// https://minecraft.wiki/w/Rain
|
||||
private final static Double SNOW_TEMPERATURE = 0.15;
|
||||
|
||||
private static final Registry.DynamicContainer<BiomeImpl> CONTAINER = Registry.createDynamicContainer(Registry.Resource.BIOMES,
|
||||
(namespace, properties) -> new BiomeImpl(Registry.biome(namespace, properties)));
|
||||
|
||||
static Collection<BiomeImpl> values() {
|
||||
return CONTAINER.values();
|
||||
}
|
||||
|
||||
static BiomeImpl get(@NotNull String namespace) {
|
||||
return CONTAINER.get(namespace);
|
||||
}
|
||||
|
||||
static BiomeImpl getSafe(@NotNull String namespace) {
|
||||
return CONTAINER.getSafe(namespace);
|
||||
}
|
||||
|
||||
private Registry.BiomeEntry entry;
|
||||
@NotNull
|
||||
private final NamespaceID name;
|
||||
private final float temperature;
|
||||
private final float downfall;
|
||||
@NotNull
|
||||
private final BiomeEffects effects;
|
||||
@NotNull
|
||||
private final Precipitation precipitation;
|
||||
@NotNull
|
||||
private final TemperatureModifier temperatureModifier;
|
||||
|
||||
BiomeImpl(NamespaceID name, float temperature, float downfall, BiomeEffects effects, Precipitation precipitation, TemperatureModifier temperatureModifier) {
|
||||
this.name = name;
|
||||
this.temperature = temperature;
|
||||
this.downfall = downfall;
|
||||
this.effects = effects;
|
||||
this.precipitation = precipitation;
|
||||
this.temperatureModifier = temperatureModifier;
|
||||
}
|
||||
|
||||
BiomeImpl(Registry.BiomeEntry entry) {
|
||||
this.entry = entry;
|
||||
this.name = entry.namespace();
|
||||
this.temperature = entry.temperature();
|
||||
|
||||
BiomeEffects.Builder effectsBuilder = getBuilder(entry);
|
||||
this.effects = effectsBuilder.build();
|
||||
|
||||
this.precipitation = entry.hasPrecipitation()
|
||||
? temperature < SNOW_TEMPERATURE
|
||||
? Biome.Precipitation.SNOW
|
||||
: Biome.Precipitation.RAIN
|
||||
: Biome.Precipitation.NONE;
|
||||
|
||||
this.downfall = entry.downfall();
|
||||
this.temperatureModifier = entry.temperature() < SNOW_TEMPERATURE ? TemperatureModifier.FROZEN : TemperatureModifier.NONE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static BiomeEffects.Builder getBuilder(Registry.BiomeEntry entry) {
|
||||
BiomeEffects.Builder effectsBuilder = BiomeEffects.builder();
|
||||
if (entry.foliageColor() != null) effectsBuilder.foliageColor(entry.foliageColor());
|
||||
if (entry.grassColor() != null) effectsBuilder.grassColor(entry.grassColor());
|
||||
if (entry.skyColor() != null) effectsBuilder.skyColor(entry.skyColor());
|
||||
if (entry.waterColor() != null) effectsBuilder.waterColor(entry.waterColor());
|
||||
if (entry.waterFogColor() != null) effectsBuilder.waterFogColor(entry.waterFogColor());
|
||||
if (entry.fogColor() != null) effectsBuilder.fogColor(entry.fogColor());
|
||||
return effectsBuilder;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Registry.BiomeEntry registry() {
|
||||
return this.entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull NamespaceID namespace() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public float temperature() {
|
||||
return this.temperature;
|
||||
}
|
||||
|
||||
public float downfall() {
|
||||
return this.downfall;
|
||||
}
|
||||
|
||||
public @NotNull BiomeEffects effects() {
|
||||
return this.effects;
|
||||
}
|
||||
|
||||
public @NotNull Precipitation precipitation() {
|
||||
return this.precipitation;
|
||||
}
|
||||
|
||||
public @NotNull TemperatureModifier temperatureModifier() {
|
||||
return this.temperatureModifier;
|
||||
}
|
||||
}
|
@ -1,143 +0,0 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
import net.minestom.server.network.packet.server.SendablePacket;
|
||||
import net.minestom.server.network.packet.server.configuration.RegistryDataPacket;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions.
|
||||
*/
|
||||
public final class BiomeManager {
|
||||
private final CachedPacket registryDataPacket = new CachedPacket(this::createRegistryDataPacket);
|
||||
|
||||
private final List<Biome> biomes = new CopyOnWriteArrayList<>();
|
||||
private final Map<NamespaceID, Biome> biomesByName = new ConcurrentHashMap<>();
|
||||
private final Map<NamespaceID, Integer> idMappings = new ConcurrentHashMap<>();
|
||||
|
||||
private final AtomicInteger ID_COUNTER = new AtomicInteger(0);
|
||||
|
||||
public BiomeManager() {
|
||||
// Need to register plains for the client to work properly
|
||||
// Plains is always ID 0
|
||||
addBiome(BiomeImpl.get("minecraft:plains"));
|
||||
}
|
||||
|
||||
public void loadVanillaBiomes() {
|
||||
for (BiomeImpl biome : BiomeImpl.values()) {
|
||||
if (getByName(biome.namespace()) == null)
|
||||
addBiome(biome);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new biome. This does NOT send the new list to players.
|
||||
*
|
||||
* @param biome the biome to add
|
||||
*/
|
||||
public void addBiome(@NotNull Biome biome) {
|
||||
Check.stateCondition(getByName(biome.namespace()) != null, "The biome " + biome.namespace() + " has already been registered");
|
||||
|
||||
var id = this.biomes.size();
|
||||
this.biomes.add(biome);
|
||||
this.biomesByName.put(biome.namespace(), biome);
|
||||
this.idMappings.put(biome.namespace(), id);
|
||||
registryDataPacket.invalidate();
|
||||
}
|
||||
|
||||
//todo supporting remove is probably challenging at best since we no longer send ids explicitly, so you cannot skip an ID.
|
||||
// /**
|
||||
// * Removes a biome. This does NOT send the new list to players.
|
||||
// *
|
||||
// * @param biome the biome to remove
|
||||
// */
|
||||
// public void removeBiome(@NotNull Biome biome) {
|
||||
// var id = idMappings.get(biome.namespace());
|
||||
// if (id != null) {
|
||||
// biomes.remove(id.intValue());
|
||||
// biomesByName.remove(biome.namespace());
|
||||
// idMappings.remove(biome.namespace());
|
||||
// registryDataPacket.invalidate();
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns an immutable copy of the biomes already registered.
|
||||
*
|
||||
* @return an immutable copy of the biomes already registered
|
||||
*/
|
||||
public Collection<Biome> unmodifiableCollection() {
|
||||
return Collections.unmodifiableCollection(biomes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a biome by its id.
|
||||
*
|
||||
* @param id the id of the biome
|
||||
* @return the {@link Biome} linked to this id
|
||||
*/
|
||||
@Nullable
|
||||
public Biome getById(int id) {
|
||||
return biomes.get(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Biome getByName(@NotNull NamespaceID namespaceID) {
|
||||
return biomesByName.get(namespaceID);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Biome getByName(@NotNull String namespaceID) {
|
||||
NamespaceID namespace = NamespaceID.from(namespaceID);
|
||||
return getByName(namespace);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of a biome.
|
||||
*`
|
||||
* @param biome
|
||||
* @return the id of the biome, or -1 if the biome is not registered
|
||||
*/
|
||||
public int getId(Biome biome) {
|
||||
return idMappings.getOrDefault(biome.namespace(), -1);
|
||||
}
|
||||
//
|
||||
// public @NotNull NBTCompound toNBT() {
|
||||
// if (nbtCache != null) return nbtCache;
|
||||
// nbtCache = NBT.Compound(Map.of(
|
||||
// "type", NBT.String("minecraft:worldgen/biome"),
|
||||
// "value", NBT.List(NBTType.TAG_Compound, biomes.values().stream().map(biome -> {
|
||||
// return NBT.Compound(Map.of(
|
||||
// "id", NBT.Int(getId(biome)),
|
||||
// "name", NBT.String(biome.namespace().toString()),
|
||||
// "element", biome.toNbt()
|
||||
// ));
|
||||
// }).toList())));
|
||||
//
|
||||
// return nbtCache;
|
||||
// }
|
||||
|
||||
public @NotNull SendablePacket registryDataPacket() {
|
||||
return registryDataPacket;
|
||||
}
|
||||
|
||||
private @NotNull RegistryDataPacket createRegistryDataPacket() {
|
||||
return new RegistryDataPacket(
|
||||
"minecraft:worldgen/biome",
|
||||
biomes.stream()
|
||||
.map(Biome::toRegistryEntry)
|
||||
.toList()
|
||||
);
|
||||
}
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
package net.minestom.server.world.biomes;
|
||||
|
||||
final public class VanillaBiome implements Biomes {
|
||||
}
|
@ -3,13 +3,12 @@ package net.minestom.server.instance;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.instance.generator.Generator;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import net.minestom.testing.Env;
|
||||
import net.minestom.testing.EnvTest;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -6,10 +6,7 @@ import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.instance.generator.GenerationUnit;
|
||||
import net.minestom.server.instance.generator.Generator;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.utils.chunk.ChunkUtils;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biomes.BiomeEffects;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
@ -6,7 +6,7 @@ import net.minestom.server.instance.Section;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.network.NetworkBuffer;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import net.minestom.server.world.biomes.Biome;
|
||||
import net.minestom.server.world.biome.Biome;
|
||||
import net.minestom.testing.Env;
|
||||
import net.minestom.testing.EnvTest;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
Loading…
Reference in New Issue
Block a user