mirror of https://github.com/Minestom/Minestom.git
commit
74947251fd
11
build.gradle
11
build.gradle
|
@ -165,6 +165,12 @@ dependencies {
|
|||
|
||||
api "com.github.Minestom:DependencyGetter:v1.0.1"
|
||||
|
||||
// Adventure, for user-interface
|
||||
api "net.kyori:adventure-api:$adventureVersion"
|
||||
api "net.kyori:adventure-text-serializer-gson:$adventureVersion"
|
||||
api "net.kyori:adventure-text-serializer-plain:$adventureVersion"
|
||||
api "net.kyori:adventure-text-serializer-legacy:$adventureVersion"
|
||||
|
||||
// LWJGL, for map rendering
|
||||
lwjglApi platform("org.lwjgl:lwjgl-bom:$lwjglVersion")
|
||||
|
||||
|
@ -184,6 +190,11 @@ dependencies {
|
|||
generatorsImplementation("com.squareup:javapoet:1.13.0")
|
||||
}
|
||||
|
||||
configurations.all {
|
||||
// we use jetbrains annotations
|
||||
exclude group: "org.checkerframework", module: "checker-qual"
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
asmVersion=9.0
|
||||
mixinVersion=0.8.1
|
||||
hephaistosVersion=v1.1.8
|
||||
kotlinVersion=1.4.21
|
||||
kotlinVersion=1.4.21
|
||||
adventureVersion=4.7.0
|
|
@ -1,29 +1,11 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.entity.metadata.EntityMeta;
|
||||
import net.minestom.server.entity.metadata.PlayerMeta;
|
||||
import net.minestom.server.entity.metadata.ambient.BatMeta;
|
||||
import net.minestom.server.entity.metadata.animal.BeeMeta;
|
||||
import net.minestom.server.entity.metadata.animal.ChickenMeta;
|
||||
import net.minestom.server.entity.metadata.animal.CowMeta;
|
||||
import net.minestom.server.entity.metadata.animal.DonkeyMeta;
|
||||
import net.minestom.server.entity.metadata.animal.FoxMeta;
|
||||
import net.minestom.server.entity.metadata.animal.HoglinMeta;
|
||||
import net.minestom.server.entity.metadata.animal.HorseMeta;
|
||||
import net.minestom.server.entity.metadata.animal.LlamaMeta;
|
||||
import net.minestom.server.entity.metadata.animal.MooshroomMeta;
|
||||
import net.minestom.server.entity.metadata.animal.MuleMeta;
|
||||
import net.minestom.server.entity.metadata.animal.OcelotMeta;
|
||||
import net.minestom.server.entity.metadata.animal.PandaMeta;
|
||||
import net.minestom.server.entity.metadata.animal.PigMeta;
|
||||
import net.minestom.server.entity.metadata.animal.PolarBearMeta;
|
||||
import net.minestom.server.entity.metadata.animal.RabbitMeta;
|
||||
import net.minestom.server.entity.metadata.animal.SheepMeta;
|
||||
import net.minestom.server.entity.metadata.animal.SkeletonHorseMeta;
|
||||
import net.minestom.server.entity.metadata.animal.StriderMeta;
|
||||
import net.minestom.server.entity.metadata.animal.TurtleMeta;
|
||||
import net.minestom.server.entity.metadata.animal.ZombieHorseMeta;
|
||||
import net.minestom.server.entity.metadata.animal.*;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.CatMeta;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.ParrotMeta;
|
||||
import net.minestom.server.entity.metadata.animal.tameable.WolfMeta;
|
||||
|
@ -35,73 +17,15 @@ import net.minestom.server.entity.metadata.flying.PhantomMeta;
|
|||
import net.minestom.server.entity.metadata.golem.IronGolemMeta;
|
||||
import net.minestom.server.entity.metadata.golem.ShulkerMeta;
|
||||
import net.minestom.server.entity.metadata.golem.SnowGolemMeta;
|
||||
import net.minestom.server.entity.metadata.item.EyeOfEnderMeta;
|
||||
import net.minestom.server.entity.metadata.item.FireballMeta;
|
||||
import net.minestom.server.entity.metadata.item.ItemEntityMeta;
|
||||
import net.minestom.server.entity.metadata.item.SmallFireballMeta;
|
||||
import net.minestom.server.entity.metadata.item.SnowballMeta;
|
||||
import net.minestom.server.entity.metadata.item.ThrownEggMeta;
|
||||
import net.minestom.server.entity.metadata.item.ThrownEnderPearlMeta;
|
||||
import net.minestom.server.entity.metadata.item.ThrownExperienceBottleMeta;
|
||||
import net.minestom.server.entity.metadata.item.ThrownPotionMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.ChestMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.CommandBlockMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.FurnaceMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.HopperMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.MinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.SpawnerMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.minecart.TntMinecartMeta;
|
||||
import net.minestom.server.entity.metadata.monster.BlazeMeta;
|
||||
import net.minestom.server.entity.metadata.monster.CaveSpiderMeta;
|
||||
import net.minestom.server.entity.metadata.monster.CreeperMeta;
|
||||
import net.minestom.server.entity.metadata.monster.ElderGuardianMeta;
|
||||
import net.minestom.server.entity.metadata.monster.EndermanMeta;
|
||||
import net.minestom.server.entity.metadata.monster.EndermiteMeta;
|
||||
import net.minestom.server.entity.metadata.monster.GiantMeta;
|
||||
import net.minestom.server.entity.metadata.monster.GuardianMeta;
|
||||
import net.minestom.server.entity.metadata.monster.PiglinBruteMeta;
|
||||
import net.minestom.server.entity.metadata.monster.PiglinMeta;
|
||||
import net.minestom.server.entity.metadata.monster.SilverfishMeta;
|
||||
import net.minestom.server.entity.metadata.monster.SpiderMeta;
|
||||
import net.minestom.server.entity.metadata.monster.VexMeta;
|
||||
import net.minestom.server.entity.metadata.monster.WitherMeta;
|
||||
import net.minestom.server.entity.metadata.monster.ZoglinMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.EvokerMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.IllusionerMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.PillagerMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.RavagerMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.VindicatorMeta;
|
||||
import net.minestom.server.entity.metadata.monster.raider.WitchMeta;
|
||||
import net.minestom.server.entity.metadata.item.*;
|
||||
import net.minestom.server.entity.metadata.minecart.*;
|
||||
import net.minestom.server.entity.metadata.monster.*;
|
||||
import net.minestom.server.entity.metadata.monster.raider.*;
|
||||
import net.minestom.server.entity.metadata.monster.skeleton.SkeletonMeta;
|
||||
import net.minestom.server.entity.metadata.monster.skeleton.StrayMeta;
|
||||
import net.minestom.server.entity.metadata.monster.skeleton.WitherSkeletonMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.DrownedMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.HuskMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.ZombieMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.ZombieVillagerMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.ZombifiedPiglinMeta;
|
||||
import net.minestom.server.entity.metadata.other.AreaEffectCloudMeta;
|
||||
import net.minestom.server.entity.metadata.other.ArmorStandMeta;
|
||||
import net.minestom.server.entity.metadata.other.BoatMeta;
|
||||
import net.minestom.server.entity.metadata.other.DragonFireballMeta;
|
||||
import net.minestom.server.entity.metadata.other.EndCrystalMeta;
|
||||
import net.minestom.server.entity.metadata.other.EnderDragonMeta;
|
||||
import net.minestom.server.entity.metadata.other.EvokerFangsMeta;
|
||||
import net.minestom.server.entity.metadata.other.ExperienceOrbMeta;
|
||||
import net.minestom.server.entity.metadata.other.FallingBlockMeta;
|
||||
import net.minestom.server.entity.metadata.other.FireworkRocketMeta;
|
||||
import net.minestom.server.entity.metadata.other.FishingHookMeta;
|
||||
import net.minestom.server.entity.metadata.other.ItemFrameMeta;
|
||||
import net.minestom.server.entity.metadata.other.LeashKnotMeta;
|
||||
import net.minestom.server.entity.metadata.other.LightningBoltMeta;
|
||||
import net.minestom.server.entity.metadata.other.LlamaSpitMeta;
|
||||
import net.minestom.server.entity.metadata.other.MagmaCubeMeta;
|
||||
import net.minestom.server.entity.metadata.other.PaintingMeta;
|
||||
import net.minestom.server.entity.metadata.other.PrimedTntMeta;
|
||||
import net.minestom.server.entity.metadata.other.ShulkerBulletMeta;
|
||||
import net.minestom.server.entity.metadata.other.SlimeMeta;
|
||||
import net.minestom.server.entity.metadata.other.TraderLlamaMeta;
|
||||
import net.minestom.server.entity.metadata.other.WitherSkullMeta;
|
||||
import net.minestom.server.entity.metadata.monster.zombie.*;
|
||||
import net.minestom.server.entity.metadata.other.*;
|
||||
import net.minestom.server.entity.metadata.villager.VillagerMeta;
|
||||
import net.minestom.server.entity.metadata.villager.WanderingTraderMeta;
|
||||
import net.minestom.server.entity.metadata.water.DolphinMeta;
|
||||
|
@ -114,13 +38,15 @@ import net.minestom.server.registry.Registries;
|
|||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* //==============================
|
||||
* // AUTOGENERATED BY EnumGenerator
|
||||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum EntityType {
|
||||
public enum EntityType implements Keyed {
|
||||
AREA_EFFECT_CLOUD("minecraft:area_effect_cloud", 6.0, 0.5, AreaEffectCloudMeta::new, EntitySpawnType.BASE),
|
||||
|
||||
ARMOR_STAND("minecraft:armor_stand", 0.5, 1.975, ArmorStandMeta::new, EntitySpawnType.LIVING),
|
||||
|
@ -352,6 +278,8 @@ public enum EntityType {
|
|||
@NotNull
|
||||
private final EntitySpawnType spawnType;
|
||||
|
||||
private final Key key;
|
||||
|
||||
EntityType(@NotNull String namespaceID, double width, double height,
|
||||
@NotNull BiFunction<Entity, Metadata, EntityMeta> metaConstructor,
|
||||
@NotNull EntitySpawnType spawnType) {
|
||||
|
@ -361,6 +289,7 @@ public enum EntityType {
|
|||
this.metaConstructor = metaConstructor;
|
||||
this.spawnType = spawnType;
|
||||
Registries.entityTypes.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public short getId() {
|
||||
|
@ -393,4 +322,8 @@ public enum EntityType {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.fluids;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Fluid {
|
||||
public enum Fluid implements Keyed {
|
||||
EMPTY("minecraft:empty"),
|
||||
|
||||
FLOWING_WATER("minecraft:flowing_water"),
|
||||
|
@ -20,11 +22,14 @@ public enum Fluid {
|
|||
|
||||
LAVA("minecraft:lava");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
Fluid(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.fluids.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -35,6 +40,10 @@ public enum Fluid {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static Fluid fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
|
|
|
@ -2,6 +2,8 @@ package net.minestom.server.instance.block;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.instance.block.states.AcaciaButton;
|
||||
import net.minestom.server.instance.block.states.AcaciaDoor;
|
||||
import net.minestom.server.instance.block.states.AcaciaFence;
|
||||
|
@ -481,7 +483,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Block {
|
||||
public enum Block implements Keyed {
|
||||
AIR("minecraft:air", (short) 0, 0.0, 0.0, true, false, null, true),
|
||||
|
||||
STONE("minecraft:stone", (short) 1, 1.5, 6.0, false, true, null, true),
|
||||
|
@ -2480,25 +2482,27 @@ public enum Block {
|
|||
}
|
||||
|
||||
@NotNull
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private short defaultID;
|
||||
private final short defaultID;
|
||||
|
||||
private double hardness;
|
||||
private final double hardness;
|
||||
|
||||
private double resistance;
|
||||
private final double resistance;
|
||||
|
||||
private boolean isAir;
|
||||
private final boolean isAir;
|
||||
|
||||
private boolean isSolid;
|
||||
private final boolean isSolid;
|
||||
|
||||
@Nullable
|
||||
private NamespaceID blockEntity;
|
||||
private final NamespaceID blockEntity;
|
||||
|
||||
private boolean singleState;
|
||||
private final boolean singleState;
|
||||
|
||||
private List<BlockAlternative> alternatives = new java.util.ArrayList<>();
|
||||
|
||||
private final Key key;
|
||||
|
||||
Block(@NotNull String namespaceID, short defaultID, double hardness, double resistance,
|
||||
boolean isAir, boolean isSolid, @Nullable NamespaceID blockEntity,
|
||||
boolean singleState) {
|
||||
|
@ -2514,6 +2518,7 @@ public enum Block {
|
|||
addBlockAlternative(new BlockAlternative(defaultID));
|
||||
}
|
||||
Registries.blocks.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public short getBlockId() {
|
||||
|
@ -2586,4 +2591,8 @@ public enum Block {
|
|||
public static Block fromStateId(short blockStateId) {
|
||||
return BlockArray.blocks[blockStateId];
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.item;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Enchantment {
|
||||
public enum Enchantment implements Keyed {
|
||||
PROTECTION("minecraft:protection"),
|
||||
|
||||
FIRE_PROTECTION("minecraft:fire_protection"),
|
||||
|
@ -86,11 +88,14 @@ public enum Enchantment {
|
|||
|
||||
VANISHING_CURSE("minecraft:vanishing_curse");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
Enchantment(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.enchantments.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -101,6 +106,10 @@ public enum Enchantment {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static Enchantment fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.item;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
@ -12,7 +14,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Material {
|
||||
public enum Material implements Keyed {
|
||||
AIR("minecraft:air", 64, Block.AIR),
|
||||
|
||||
STONE("minecraft:stone", 64, Block.STONE),
|
||||
|
@ -1966,12 +1968,14 @@ public enum Material {
|
|||
RESPAWN_ANCHOR("minecraft:respawn_anchor", 64, Block.RESPAWN_ANCHOR);
|
||||
|
||||
@NotNull
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private int maxDefaultStackSize;
|
||||
private final int maxDefaultStackSize;
|
||||
|
||||
@Nullable
|
||||
private Block correspondingBlock;
|
||||
private final Block correspondingBlock;
|
||||
|
||||
private final Key key;
|
||||
|
||||
Material(@NotNull String namespaceID, int maxDefaultStackSize,
|
||||
@Nullable Block correspondingBlock) {
|
||||
|
@ -1979,6 +1983,7 @@ public enum Material {
|
|||
this.maxDefaultStackSize = maxDefaultStackSize;
|
||||
this.correspondingBlock = correspondingBlock;
|
||||
Registries.materials.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public short getId() {
|
||||
|
@ -2083,4 +2088,8 @@ public enum Material {
|
|||
}
|
||||
return isFood();
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.particle;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Particle {
|
||||
public enum Particle implements Keyed {
|
||||
AMBIENT_ENTITY_EFFECT("minecraft:ambient_entity_effect"),
|
||||
|
||||
ANGRY_VILLAGER("minecraft:angry_villager"),
|
||||
|
@ -154,11 +156,14 @@ public enum Particle {
|
|||
|
||||
WHITE_ASH("minecraft:white_ash");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
Particle(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.particles.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -169,6 +174,10 @@ public enum Particle {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static Particle fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.potion;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum PotionEffect {
|
||||
public enum PotionEffect implements Keyed {
|
||||
SPEED("minecraft:speed"),
|
||||
|
||||
SLOWNESS("minecraft:slowness"),
|
||||
|
@ -74,11 +76,14 @@ public enum PotionEffect {
|
|||
|
||||
HERO_OF_THE_VILLAGE("minecraft:hero_of_the_village");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
PotionEffect(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.potionEffects.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -89,6 +94,10 @@ public enum PotionEffect {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static PotionEffect fromId(int id) {
|
||||
if (id >= 0 && id < values().length + 1) {
|
||||
return values()[id - 1];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.potion;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum PotionType {
|
||||
public enum PotionType implements Keyed {
|
||||
EMPTY("minecraft:empty"),
|
||||
|
||||
WATER("minecraft:water"),
|
||||
|
@ -96,11 +98,14 @@ public enum PotionType {
|
|||
|
||||
LONG_SLOW_FALLING("minecraft:long_slow_falling");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
PotionType(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.potionTypes.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -111,6 +116,10 @@ public enum PotionType {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static PotionType fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
package net.minestom.server.registry;
|
||||
|
||||
import java.util.HashMap;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.fluids.Fluid;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
@ -10,7 +11,7 @@ import net.minestom.server.item.Material;
|
|||
import net.minestom.server.particle.Particle;
|
||||
import net.minestom.server.potion.PotionEffect;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.stat.StatisticType;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -66,7 +67,7 @@ public final class Registries {
|
|||
* Should only be used for internal code, please use the get* methods.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final HashMap<NamespaceID, Sound> sounds = new HashMap<>();
|
||||
public static final HashMap<NamespaceID, SoundEvent> soundEvents = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Should only be used for internal code, please use the get* methods.
|
||||
|
@ -96,6 +97,14 @@ public final class Registries {
|
|||
return blocks.getOrDefault(id, Block.AIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Block matching the given key. Returns 'AIR' if none match.
|
||||
*/
|
||||
@NotNull
|
||||
public static Block getBlock(Key key) {
|
||||
return getBlock(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Material matching the given id. Returns 'AIR' if none match.
|
||||
*/
|
||||
|
@ -112,6 +121,14 @@ public final class Registries {
|
|||
return materials.getOrDefault(id, Material.AIR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Material matching the given key. Returns 'AIR' if none match.
|
||||
*/
|
||||
@NotNull
|
||||
public static Material getMaterial(Key key) {
|
||||
return getMaterial(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Enchantment matching the given id. Returns null if none match.
|
||||
*/
|
||||
|
@ -128,6 +145,14 @@ public final class Registries {
|
|||
return enchantments.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Enchantment matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static Enchantment getEnchantment(Key key) {
|
||||
return getEnchantment(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding EntityType matching the given id. Returns null if none match.
|
||||
*/
|
||||
|
@ -144,6 +169,14 @@ public final class Registries {
|
|||
return entityTypes.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding EntityType matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static EntityType getEntityType(Key key) {
|
||||
return getEntityType(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Particle matching the given id. Returns null if none match.
|
||||
*/
|
||||
|
@ -160,6 +193,14 @@ public final class Registries {
|
|||
return particles.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Particle matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static Particle getParticle(Key key) {
|
||||
return getParticle(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding PotionType matching the given id. Returns null if none match.
|
||||
*/
|
||||
|
@ -176,6 +217,14 @@ public final class Registries {
|
|||
return potionTypes.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding PotionType matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static PotionType getPotionType(Key key) {
|
||||
return getPotionType(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding PotionEffect matching the given id. Returns null if none match.
|
||||
*/
|
||||
|
@ -193,19 +242,35 @@ public final class Registries {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Sound matching the given id. Returns null if none match.
|
||||
* Returns the corresponding PotionEffect matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static Sound getSound(String id) {
|
||||
return getSound(NamespaceID.from(id));
|
||||
public static PotionEffect getPotionEffect(Key key) {
|
||||
return getPotionEffect(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Sound matching the given id. Returns null if none match.
|
||||
* Returns the corresponding SoundEvent matching the given id. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static Sound getSound(NamespaceID id) {
|
||||
return sounds.get(id);
|
||||
public static SoundEvent getSoundEvent(String id) {
|
||||
return getSoundEvent(NamespaceID.from(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding SoundEvent matching the given id. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static SoundEvent getSoundEvent(NamespaceID id) {
|
||||
return soundEvents.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding SoundEvent matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static SoundEvent getSoundEvent(Key key) {
|
||||
return getSoundEvent(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,6 +289,14 @@ public final class Registries {
|
|||
return statisticTypes.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding StatisticType matching the given key. Returns null if none match.
|
||||
*/
|
||||
@Nullable
|
||||
public static StatisticType getStatisticType(Key key) {
|
||||
return getStatisticType(NamespaceID.from(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Fluid matching the given id. Returns 'EMPTY' if none match.
|
||||
*/
|
||||
|
@ -239,4 +312,12 @@ public final class Registries {
|
|||
public static Fluid getFluid(NamespaceID id) {
|
||||
return fluids.getOrDefault(id, Fluid.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the corresponding Fluid matching the given key. Returns 'EMPTY' if none match.
|
||||
*/
|
||||
@NotNull
|
||||
public static Fluid getFluid(Key key) {
|
||||
return getFluid(NamespaceID.from(key));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package net.minestom.server.sound;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +12,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum Sound {
|
||||
public enum SoundEvent implements Keyed, Sound.Type {
|
||||
AMBIENT_CAVE("minecraft:ambient.cave"),
|
||||
|
||||
AMBIENT_BASALT_DELTAS_ADDITIONS("minecraft:ambient.basalt_deltas.additions"),
|
||||
|
@ -1994,11 +1997,14 @@ public enum Sound {
|
|||
|
||||
ENTITY_ZOMBIE_VILLAGER_STEP("minecraft:entity.zombie_villager.step");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
Sound(String namespaceID) {
|
||||
private final Key key;
|
||||
|
||||
SoundEvent(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.sounds.put(NamespaceID.from(namespaceID), this);
|
||||
Registries.soundEvents.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -2009,7 +2015,11 @@ public enum Sound {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public static Sound fromId(int id) {
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static SoundEvent fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.stat;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -9,7 +11,7 @@ import net.minestom.server.utils.NamespaceID;
|
|||
* //==============================
|
||||
*/
|
||||
@SuppressWarnings({"deprecation"})
|
||||
public enum StatisticType {
|
||||
public enum StatisticType implements Keyed {
|
||||
LEAVE_GAME("minecraft:leave_game"),
|
||||
|
||||
PLAY_ONE_MINUTE("minecraft:play_one_minute"),
|
||||
|
@ -158,11 +160,14 @@ public enum StatisticType {
|
|||
|
||||
INTERACT_WITH_SMITHING_TABLE("minecraft:interact_with_smithing_table");
|
||||
|
||||
private String namespaceID;
|
||||
private final String namespaceID;
|
||||
|
||||
private final Key key;
|
||||
|
||||
StatisticType(String namespaceID) {
|
||||
this.namespaceID = namespaceID;
|
||||
Registries.statisticTypes.put(NamespaceID.from(namespaceID), this);
|
||||
this.key = Key.key(this.namespaceID);
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
|
@ -173,6 +178,10 @@ public enum StatisticType {
|
|||
return namespaceID;
|
||||
}
|
||||
|
||||
public Key key() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public static StatisticType fromId(int id) {
|
||||
if (id >= 0 && id < values().length) {
|
||||
return values()[id];
|
||||
|
|
|
@ -3,6 +3,8 @@ package net.minestom.codegen;
|
|||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.javapoet.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
|
||||
|
@ -116,6 +118,12 @@ public abstract class BasicEnumGenerator extends MinestomEnumGenerator<BasicEnum
|
|||
generator.appendToConstructor(code -> {
|
||||
code.addStatement("$T." + CodeGenerator.decapitalize(getClassName()) + "s.put($T.from($N), this)", registriesClass, NamespaceID.class, "namespaceID");
|
||||
});
|
||||
|
||||
// implement Keyed
|
||||
generator.addSuperinterface(ClassName.get(Keyed.class));
|
||||
generator.addField(ClassName.get(Key.class), "key", true);
|
||||
generator.appendToConstructor(code -> code.addStatement("this.key = Key.key(this.namespaceID)"));
|
||||
generator.addMethod("key", new ParameterSpec[0], ClassName.get(Key.class), code -> code.addStatement("return this.key"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.codegen;
|
||||
|
||||
import com.squareup.javapoet.*;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -20,9 +21,11 @@ public class EnumGenerator implements CodeGenerator {
|
|||
|
||||
private final String enumName;
|
||||
private ParameterSpec[] parameters;
|
||||
private List<TypeName> superinterfaces = new LinkedList<>();
|
||||
private List<Method> methods = new LinkedList<>();
|
||||
private List<Field> fields = new LinkedList<>();
|
||||
private List<Field> staticFields = new LinkedList<>();
|
||||
private List<Instance> instances = new LinkedList<>();
|
||||
private List<Pair<Field, Boolean>> fields = new LinkedList<>();
|
||||
private List<Field> hardcodedFields = new LinkedList<>();
|
||||
private List<AnnotationSpec> annotations = new LinkedList<>();
|
||||
private String enumPackage;
|
||||
|
@ -35,6 +38,10 @@ public class EnumGenerator implements CodeGenerator {
|
|||
this.enumName = enumName;
|
||||
}
|
||||
|
||||
public void addSuperinterface(TypeName typeNames) {
|
||||
superinterfaces.add(typeNames);
|
||||
}
|
||||
|
||||
public void setParams(ParameterSpec... parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
@ -52,7 +59,7 @@ public class EnumGenerator implements CodeGenerator {
|
|||
}
|
||||
|
||||
public void addStaticField(TypeName type, String name, String value) {
|
||||
fields.add(new Field(type, name, value));
|
||||
staticFields.add(new Field(type, name, value));
|
||||
}
|
||||
|
||||
public void addInstance(String name, Object... parameters) {
|
||||
|
@ -86,6 +93,9 @@ public class EnumGenerator implements CodeGenerator {
|
|||
enumClass.addEnumConstant(instance.name, arguments);
|
||||
}
|
||||
|
||||
// add superinterfaces
|
||||
enumClass.addSuperinterfaces(superinterfaces);
|
||||
|
||||
if (staticBlock != null) {
|
||||
enumClass.addStaticBlock(staticBlock);
|
||||
}
|
||||
|
@ -100,7 +110,7 @@ public class EnumGenerator implements CodeGenerator {
|
|||
.build());
|
||||
}
|
||||
|
||||
for (Field field : fields) {
|
||||
for (Field field : staticFields) {
|
||||
enumClass.addField(FieldSpec.builder(field.type, field.name)
|
||||
.initializer("$L", field.value)
|
||||
.addModifiers(Modifier.PRIVATE, Modifier.FINAL, Modifier.STATIC)
|
||||
|
@ -115,6 +125,18 @@ public class EnumGenerator implements CodeGenerator {
|
|||
.build());
|
||||
}
|
||||
|
||||
// normal fields
|
||||
for (Pair<Field, Boolean> field : fields) {
|
||||
FieldSpec.Builder builder = FieldSpec.builder(field.getLeft().type, field.getLeft().name)
|
||||
.addModifiers(Modifier.PRIVATE);
|
||||
|
||||
if (field.getRight()) {
|
||||
builder.addModifiers(Modifier.FINAL);
|
||||
}
|
||||
|
||||
enumClass.addField(builder.build());
|
||||
}
|
||||
|
||||
// constructor
|
||||
MethodSpec.Builder constructorBuilder = MethodSpec.constructorBuilder();
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
|
@ -166,6 +188,10 @@ public class EnumGenerator implements CodeGenerator {
|
|||
constructorEnds.add(constructorEnding);
|
||||
}
|
||||
|
||||
public void addField(TypeName type, String name, boolean isFinal) {
|
||||
fields.add(Pair.of(new Field(type, name), isFinal));
|
||||
}
|
||||
|
||||
public void addHardcodedField(TypeName type, String name, String value) {
|
||||
hardcodedFields.add(new Field(type, name, value));
|
||||
}
|
||||
|
@ -210,6 +236,10 @@ public class EnumGenerator implements CodeGenerator {
|
|||
private String name;
|
||||
private String value;
|
||||
|
||||
public Field(TypeName type, String name) {
|
||||
this(type, name, null);
|
||||
}
|
||||
|
||||
public Field(TypeName type, String name, String value) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.codegen;
|
||||
|
||||
import com.squareup.javapoet.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.fluids.Fluid;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
|
@ -10,7 +11,7 @@ import net.minestom.server.particle.Particle;
|
|||
import net.minestom.server.potion.PotionEffect;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.registry.ResourceGatherer;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.stat.StatisticType;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
@ -44,7 +45,7 @@ public class RegistriesGenerator implements CodeGenerator {
|
|||
new ImmutablePair<>(Particle.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(PotionType.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(PotionEffect.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(Sound.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(SoundEvent.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(StatisticType.class.getCanonicalName(), null),
|
||||
new ImmutablePair<>(Fluid.class.getCanonicalName(), "EMPTY"),
|
||||
};
|
||||
|
@ -101,6 +102,7 @@ public class RegistriesGenerator implements CodeGenerator {
|
|||
|
||||
ParameterSpec namespaceIDParam = ParameterSpec.builder(ClassName.get(NamespaceID.class), "id")
|
||||
.build();
|
||||
ParameterSpec keyIDParam = ParameterSpec.builder(ClassName.get(Key.class), "key").build();
|
||||
|
||||
CodeBlock.Builder code = CodeBlock.builder();
|
||||
Class<? extends Annotation> annotation;
|
||||
|
@ -134,6 +136,16 @@ public class RegistriesGenerator implements CodeGenerator {
|
|||
.addCode(code.build())
|
||||
.addJavadoc(comment.toString())
|
||||
.build());
|
||||
|
||||
// Key variant
|
||||
registriesClass.addMethod(MethodSpec.methodBuilder("get" + simpleType)
|
||||
.returns(type)
|
||||
.addAnnotation(annotation)
|
||||
.addModifiers(Modifier.STATIC, Modifier.PUBLIC)
|
||||
.addParameter(keyIDParam)
|
||||
.addStatement("return get$N(NamespaceID.from($N))", simpleType, keyIDParam)
|
||||
.addJavadoc(comment.toString().replace(" id.", " key."))
|
||||
.build());
|
||||
}
|
||||
|
||||
JavaFile file = JavaFile.builder("net.minestom.server.registry", registriesClass.build())
|
||||
|
|
|
@ -5,6 +5,8 @@ import com.google.gson.JsonArray;
|
|||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.javapoet.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.codegen.EnumGenerator;
|
||||
import net.minestom.codegen.MinestomEnumGenerator;
|
||||
import net.minestom.codegen.PrismarinePaths;
|
||||
|
@ -298,6 +300,12 @@ public class BlockEnumGenerator extends MinestomEnumGenerator<BlockContainer> {
|
|||
.endControlFlow()
|
||||
.addStatement("$T.blocks.put($T.from(namespaceID), this)", Registries.class, NamespaceID.class);
|
||||
});
|
||||
|
||||
// implement Keyed
|
||||
generator.addSuperinterface(ClassName.get(Keyed.class));
|
||||
generator.addField(ClassName.get(Key.class), "key", true);
|
||||
generator.appendToConstructor(code -> code.addStatement("this.key = Key.key(this.namespaceID)"));
|
||||
generator.addMethod("key", new ParameterSpec[0], ClassName.get(Key.class), code -> code.addStatement("return this.key"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.javapoet.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.codegen.ConstructorLambda;
|
||||
import net.minestom.codegen.EnumGenerator;
|
||||
import net.minestom.codegen.MinestomEnumGenerator;
|
||||
|
@ -177,6 +179,12 @@ public class EntityTypeEnumGenerator extends MinestomEnumGenerator<EntityTypeCon
|
|||
.endControlFlow()
|
||||
.addStatement("return null");
|
||||
});
|
||||
|
||||
// implement Keyed
|
||||
generator.addSuperinterface(ClassName.get(Keyed.class));
|
||||
generator.addField(ClassName.get(Key.class), "key", true);
|
||||
generator.appendToConstructor(code -> code.addStatement("this.key = Key.key(this.namespaceID)"));
|
||||
generator.addMethod("key", new ParameterSpec[0], ClassName.get(Key.class), code -> code.addStatement("return this.key"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.squareup.javapoet.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.codegen.EnumGenerator;
|
||||
import net.minestom.codegen.MinestomEnumGenerator;
|
||||
import net.minestom.codegen.PrismarinePaths;
|
||||
|
@ -218,6 +220,12 @@ public class ItemEnumGenerator extends MinestomEnumGenerator<ItemContainer> {
|
|||
.endControlFlow()
|
||||
.addStatement("return isFood()");
|
||||
});
|
||||
|
||||
// implement Keyed
|
||||
generator.addSuperinterface(ClassName.get(Keyed.class));
|
||||
generator.addField(ClassName.get(Key.class), "key", true);
|
||||
generator.appendToConstructor(code -> code.addStatement("this.key = Key.key(this.namespaceID)"));
|
||||
generator.addMethod("key", new ParameterSpec[0], ClassName.get(Key.class), code -> code.addStatement("return this.key"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package net.minestom.codegen.sounds;
|
||||
|
||||
import com.squareup.javapoet.ClassName;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.minestom.codegen.BasicEnumGenerator;
|
||||
import net.minestom.codegen.stats.StatsEnumGenerator;
|
||||
import net.minestom.codegen.EnumGenerator;
|
||||
import net.minestom.server.registry.ResourceGatherer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -45,6 +47,14 @@ public class SoundEnumGenerator extends BasicEnumGenerator {
|
|||
super(targetFolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void prepare(EnumGenerator generator) {
|
||||
super.prepare(generator);
|
||||
|
||||
// implement type as well
|
||||
generator.addSuperinterface(ClassName.get(Sound.Type.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCategoryID() {
|
||||
return "minecraft:sound_event";
|
||||
|
@ -57,7 +67,7 @@ public class SoundEnumGenerator extends BasicEnumGenerator {
|
|||
|
||||
@Override
|
||||
public String getClassName() {
|
||||
return "Sound";
|
||||
return "SoundEvent";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package net.minestom.server;
|
||||
|
||||
import net.minestom.server.advancements.AdvancementManager;
|
||||
import net.minestom.server.adventure.bossbar.BossBarManager;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.adventure.audience.Audiences;
|
||||
import net.minestom.server.benchmark.BenchmarkManager;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.data.DataManager;
|
||||
|
@ -37,7 +40,7 @@ import net.minestom.server.potion.PotionType;
|
|||
import net.minestom.server.recipe.RecipeManager;
|
||||
import net.minestom.server.registry.ResourceGatherer;
|
||||
import net.minestom.server.scoreboard.TeamManager;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.stat.StatisticType;
|
||||
import net.minestom.server.storage.StorageLocation;
|
||||
import net.minestom.server.storage.StorageManager;
|
||||
|
@ -115,6 +118,8 @@ public final class MinecraftServer {
|
|||
private static DimensionTypeManager dimensionTypeManager;
|
||||
private static BiomeManager biomeManager;
|
||||
private static AdvancementManager advancementManager;
|
||||
private static BossBarManager bossBarManager;
|
||||
private static Audiences audiences;
|
||||
|
||||
private static ExtensionManager extensionManager;
|
||||
|
||||
|
@ -158,7 +163,7 @@ public final class MinecraftServer {
|
|||
PotionEffect.values();
|
||||
Enchantment.values();
|
||||
EntityType.values();
|
||||
Sound.values();
|
||||
SoundEvent.values();
|
||||
Particle.values();
|
||||
StatisticType.values();
|
||||
Fluid.values();
|
||||
|
@ -180,6 +185,8 @@ public final class MinecraftServer {
|
|||
dimensionTypeManager = new DimensionTypeManager();
|
||||
biomeManager = new BiomeManager();
|
||||
advancementManager = new AdvancementManager();
|
||||
bossBarManager = new BossBarManager();
|
||||
audiences = new Audiences();
|
||||
|
||||
updateManager = new UpdateManager();
|
||||
|
||||
|
@ -427,6 +434,26 @@ public final class MinecraftServer {
|
|||
return connectionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the boss bar manager.
|
||||
*
|
||||
* @return the boss bar manager
|
||||
*/
|
||||
public static BossBarManager getBossBarManager() {
|
||||
checkInitStatus(bossBarManager);
|
||||
return bossBarManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the audiences instance.
|
||||
*
|
||||
* @return the audiences instance
|
||||
*/
|
||||
public static Audiences getAudiences() {
|
||||
checkInitStatus(audiences);
|
||||
return audiences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the object handling the client packets processing.
|
||||
* <p>
|
||||
|
@ -802,5 +829,4 @@ public final class MinecraftServer {
|
|||
"You cannot access the manager before MinecraftServer#init, " +
|
||||
"if you are developing an extension be sure to retrieve them at least after Extension#preInitialize");*/
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package net.minestom.server;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.minestom.server.adventure.audience.PacketGroupingAudience;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
|
@ -82,4 +85,23 @@ public interface Viewable {
|
|||
default void sendPacketToViewersAndSelf(@NotNull ServerPacket packet) {
|
||||
sendPacketToViewers(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result of {@link #getViewers()} as an Adventure Audience.
|
||||
*
|
||||
* @return the audience
|
||||
*/
|
||||
default @NotNull Audience getViewersAsAudience() {
|
||||
return PacketGroupingAudience.of(this.getViewers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result of {@link #getViewers()} as an {@link Iterable} of Adventure
|
||||
* {@link Audience}s.
|
||||
*
|
||||
* @return the audiences
|
||||
*/
|
||||
default @NotNull Iterable<? extends Audience> getViewersAsAudiences() {
|
||||
return this.getViewers();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.advancements;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
|
@ -23,8 +24,8 @@ public class Advancement {
|
|||
|
||||
private boolean achieved;
|
||||
|
||||
private JsonMessage title;
|
||||
private JsonMessage description;
|
||||
private Component title;
|
||||
private Component description;
|
||||
|
||||
private ItemStack icon;
|
||||
|
||||
|
@ -42,9 +43,29 @@ public class Advancement {
|
|||
// Packet
|
||||
private AdvancementsPacket.Criteria criteria;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #Advancement(Component, Component, ItemStack, FrameType, float, float)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Advancement(@NotNull JsonMessage title, JsonMessage description,
|
||||
@NotNull ItemStack icon, @NotNull FrameType frameType,
|
||||
float x, float y) {
|
||||
this(title.asComponent(), description.asComponent(), icon, frameType, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #Advancement(Component, Component, Material, FrameType, float, float)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Advancement(@NotNull JsonMessage title, @NotNull JsonMessage description,
|
||||
@NotNull Material icon, @NotNull FrameType frameType,
|
||||
float x, float y) {
|
||||
this(title, description, new ItemStack(icon, (byte) 1), frameType, x, y);
|
||||
}
|
||||
|
||||
public Advancement(@NotNull Component title, Component description,
|
||||
@NotNull ItemStack icon, @NotNull FrameType frameType,
|
||||
float x, float y) {
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
this.icon = icon;
|
||||
|
@ -53,7 +74,7 @@ public class Advancement {
|
|||
this.y = y;
|
||||
}
|
||||
|
||||
public Advancement(@NotNull JsonMessage title, @NotNull JsonMessage description,
|
||||
public Advancement(@NotNull Component title, @NotNull Component description,
|
||||
@NotNull Material icon, @NotNull FrameType frameType,
|
||||
float x, float y) {
|
||||
this(title, description, new ItemStack(icon, (byte) 1), frameType, x, y);
|
||||
|
@ -94,14 +115,25 @@ public class Advancement {
|
|||
this.tab = tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the title of the advancement.
|
||||
*
|
||||
* @return the title
|
||||
*/
|
||||
public Component getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the title of the advancement.
|
||||
*
|
||||
* @return the advancement title
|
||||
* @deprecated Use {@link #getTitle()}
|
||||
*/
|
||||
@NotNull
|
||||
public JsonMessage getTitle() {
|
||||
return title;
|
||||
@Deprecated
|
||||
public JsonMessage getTitleJson() {
|
||||
return JsonMessage.fromComponent(title);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,31 +141,67 @@ public class Advancement {
|
|||
*
|
||||
* @param title the new title
|
||||
*/
|
||||
public void setTitle(@NotNull JsonMessage title) {
|
||||
public void setTitle(@NotNull Component title) {
|
||||
this.title = title;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the advancement title.
|
||||
*
|
||||
* @param title the new title
|
||||
* @deprecated Use {@link #setTitle(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setTitle(@NotNull JsonMessage title) {
|
||||
this.title = title.asComponent();
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the advancement.
|
||||
*
|
||||
* @return the description title
|
||||
*/
|
||||
@NotNull
|
||||
public JsonMessage getDescription() {
|
||||
public Component getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the advancement.
|
||||
*
|
||||
* @return the description title
|
||||
* @deprecated Use {@link #getDescription()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public JsonMessage getDescriptionJson() {
|
||||
return JsonMessage.fromComponent(description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the description title.
|
||||
*
|
||||
* @param description the new description
|
||||
*/
|
||||
public void setDescription(@NotNull JsonMessage description) {
|
||||
public void setDescription(@NotNull Component description) {
|
||||
this.description = description;
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the description title.
|
||||
*
|
||||
* @param description the new description
|
||||
* @deprecated Use {@link #setDescription(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDescription(@NotNull JsonMessage description) {
|
||||
this.description = description.asComponent();
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the advancement icon.
|
||||
*
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.advancements;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
|
@ -15,6 +16,10 @@ import org.jetbrains.annotations.Nullable;
|
|||
*/
|
||||
public class AdvancementRoot extends Advancement {
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #AdvancementRoot(Component, Component, ItemStack, FrameType, float, float, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public AdvancementRoot(@NotNull JsonMessage title, @NotNull JsonMessage description,
|
||||
@NotNull ItemStack icon, @NotNull FrameType frameType,
|
||||
float x, float y,
|
||||
|
@ -23,6 +28,10 @@ public class AdvancementRoot extends Advancement {
|
|||
setBackground(background);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #AdvancementRoot(Component, Component, Material, FrameType, float, float, String)}
|
||||
*/
|
||||
@Deprecated
|
||||
public AdvancementRoot(@NotNull JsonMessage title, @NotNull JsonMessage description,
|
||||
@NotNull Material icon, FrameType frameType,
|
||||
float x, float y,
|
||||
|
@ -31,4 +40,20 @@ public class AdvancementRoot extends Advancement {
|
|||
setBackground(background);
|
||||
}
|
||||
|
||||
public AdvancementRoot(@NotNull Component title, @NotNull Component description,
|
||||
@NotNull ItemStack icon, @NotNull FrameType frameType,
|
||||
float x, float y,
|
||||
@Nullable String background) {
|
||||
super(title, description, icon, frameType, x, y);
|
||||
setBackground(background);
|
||||
}
|
||||
|
||||
public AdvancementRoot(@NotNull Component title, @NotNull Component description,
|
||||
@NotNull Material icon, FrameType frameType,
|
||||
float x, float y,
|
||||
@Nullable String background) {
|
||||
super(title, description, icon, frameType, x, y);
|
||||
setBackground(background);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.advancements.notifications;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.advancements.FrameType;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
|
@ -11,20 +12,47 @@ import org.jetbrains.annotations.NotNull;
|
|||
*/
|
||||
public class Notification {
|
||||
|
||||
private final JsonMessage title;
|
||||
private final Component title;
|
||||
private final FrameType frameType;
|
||||
private final ItemStack icon;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #Notification(Component, FrameType, ItemStack)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Notification(@NotNull JsonMessage title, @NotNull FrameType frameType, @NotNull ItemStack icon) {
|
||||
this(title.asComponent(), frameType, icon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #Notification(Component, FrameType, Material)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Notification(@NotNull JsonMessage title, @NotNull FrameType frameType, @NotNull Material icon) {
|
||||
this(title.asComponent(), frameType, icon);
|
||||
}
|
||||
|
||||
public Notification(@NotNull Component title, @NotNull FrameType frameType, @NotNull Material icon) {
|
||||
this(title, frameType, new ItemStack(icon, (byte) 1));
|
||||
}
|
||||
|
||||
public Notification(@NotNull Component title, @NotNull FrameType frameType, @NotNull ItemStack icon) {
|
||||
this.title = title;
|
||||
this.frameType = frameType;
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public Notification(@NotNull JsonMessage title, @NotNull FrameType frameType, @NotNull Material icon) {
|
||||
this.title = title;
|
||||
this.frameType = frameType;
|
||||
this.icon = new ItemStack(icon, (byte) 1);
|
||||
/**
|
||||
* Gets the title of the notification.
|
||||
*
|
||||
* @return the notification title
|
||||
*
|
||||
* @deprecated Use {@link #getTitle()}
|
||||
*/
|
||||
@NotNull
|
||||
@Deprecated
|
||||
public JsonMessage getTitleJson() {
|
||||
return JsonMessage.fromComponent(title);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -32,8 +60,7 @@ public class Notification {
|
|||
*
|
||||
* @return the notification title
|
||||
*/
|
||||
@NotNull
|
||||
public JsonMessage getTitle() {
|
||||
public Component getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package net.minestom.server.advancements.notifications;
|
||||
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.AdvancementsPacket;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
|
@ -84,7 +84,7 @@ public class NotificationCenter {
|
|||
{
|
||||
displayData.title = notification.getTitle();
|
||||
// Description is required, but never shown/seen so, small Easter egg.
|
||||
displayData.description = ColoredText.of("Articdive was here. #Minestom");
|
||||
displayData.description = Component.text("Articdive was here. #Minestom");
|
||||
displayData.icon = notification.getIcon();
|
||||
displayData.frameType = notification.getFrameType();
|
||||
displayData.flags = 0x6;
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
package net.minestom.server.adventure;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import net.kyori.adventure.audience.MessageType;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.kyori.adventure.sound.SoundStop;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.play.NamedSoundEffectPacket;
|
||||
import net.minestom.server.network.packet.server.play.SoundEffectPacket;
|
||||
import net.minestom.server.network.packet.server.play.StopSoundPacket;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Utility methods to convert adventure enums to their packet values.
|
||||
*/
|
||||
public class AdventurePacketConvertor {
|
||||
private static final Object2IntMap<NamedTextColor> NAMED_TEXT_COLOR_ID_MAP = new Object2IntArrayMap<>(16);
|
||||
static {
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.BLACK, 0);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_BLUE, 1);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_GREEN, 2);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_AQUA, 3);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_RED, 4);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_PURPLE, 5);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.GOLD, 6);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.GRAY, 7);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.DARK_GRAY, 8);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.BLUE, 9);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.GREEN, 10);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.AQUA, 11);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.RED, 12);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.LIGHT_PURPLE, 13);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.YELLOW, 14);
|
||||
NAMED_TEXT_COLOR_ID_MAP.put(NamedTextColor.WHITE, 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the int value of a boss bar overlay.
|
||||
* @param overlay the overlay
|
||||
* @return the value
|
||||
*/
|
||||
public static int getBossBarOverlayValue(@NotNull BossBar.Overlay overlay) {
|
||||
return overlay.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the byte value of a collection of boss bar flags.
|
||||
* @param flags the flags
|
||||
* @return the value
|
||||
*/
|
||||
public static byte getBossBarFlagValue(@NotNull Collection<BossBar.Flag> flags) {
|
||||
byte val = 0x0;
|
||||
for (BossBar.Flag flag : flags) {
|
||||
val |= flag.ordinal();
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the int value of a boss bar color.
|
||||
* @param color the color
|
||||
* @return the value
|
||||
*/
|
||||
public static int getBossBarColorValue(@NotNull BossBar.Color color) {
|
||||
return color.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the int value of a sound source.
|
||||
* @param source the source
|
||||
* @return the value
|
||||
*/
|
||||
public static int getSoundSourceValue(@NotNull Sound.Source source) {
|
||||
return source.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the int value from a named text color.
|
||||
* @param color the color
|
||||
* @return the int value
|
||||
*/
|
||||
public static int getNamedTextColorValue(@NotNull NamedTextColor color) {
|
||||
return NAMED_TEXT_COLOR_ID_MAP.getInt(color);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sound packet from a sound and a location.
|
||||
* @param sound the sound
|
||||
* @param x the x coordinate
|
||||
* @param y the y coordinate
|
||||
* @param z the z coordinate
|
||||
* @return the sound packet
|
||||
*/
|
||||
public static ServerPacket createSoundPacket(@NotNull Sound sound, double x, double y, double z) {
|
||||
SoundEvent minestomSound = Registries.getSoundEvent(sound.name());
|
||||
|
||||
if (minestomSound == null) {
|
||||
NamedSoundEffectPacket packet = new NamedSoundEffectPacket();
|
||||
packet.soundName = sound.name().asString();
|
||||
packet.soundSource = sound.source();
|
||||
packet.x = (int) x;
|
||||
packet.y = (int) y;
|
||||
packet.z = (int) z;
|
||||
packet.volume = sound.volume();
|
||||
packet.pitch = sound.pitch();
|
||||
return packet;
|
||||
} else {
|
||||
SoundEffectPacket packet = new SoundEffectPacket();
|
||||
packet.soundId = minestomSound.getId();
|
||||
packet.soundSource = sound.source();
|
||||
packet.x = (int) x;
|
||||
packet.y = (int) y;
|
||||
packet.z = (int) z;
|
||||
packet.volume = sound.volume();
|
||||
packet.pitch = sound.pitch();
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a sound stop packet from a sound stop.
|
||||
* @param stop the sound stop
|
||||
* @return the sound stop packet
|
||||
*/
|
||||
public static ServerPacket createSoundStopPacket(@NotNull SoundStop stop) {
|
||||
StopSoundPacket packet = new StopSoundPacket();
|
||||
packet.flags = 0x0;
|
||||
|
||||
if (stop.source() != null) {
|
||||
packet.flags |= 0x1;
|
||||
packet.source = AdventurePacketConvertor.getSoundSourceValue(stop.source());
|
||||
}
|
||||
|
||||
if (stop.sound() != null) {
|
||||
packet.flags |= 0x2;
|
||||
packet.sound = stop.sound().asString();
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
package net.minestom.server.adventure;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.translation.GlobalTranslator;
|
||||
import net.kyori.adventure.translation.TranslationRegistry;
|
||||
import net.kyori.adventure.translation.Translator;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Manager class for handling Adventure serialization. By default AdventureSerializer will simply
|
||||
* serialize components to Strings using {@link GsonComponentSerializer}. However, AdventureSerializer
|
||||
* class can be used to change the way text is serialized. For example, a pre-JSON
|
||||
* implementation of Minestom could change AdventureSerializer to the plain component serializer.
|
||||
* <br><br>
|
||||
* This manager also performs translation on all messages and the {@code serialize}
|
||||
* method should be used when converting {@link Component}s into strings. This allows for
|
||||
* messages with {@link TranslatableComponent} to be automatically translated into the locale
|
||||
* of specific players, or other elements which implement {@link Localizable}. To add your
|
||||
* own translations, use {@link GlobalTranslator#addSource(Translator)} with a
|
||||
* {@link TranslationRegistry} or your own implementation of {@link Translator}.
|
||||
*/
|
||||
public class AdventureSerializer {
|
||||
/**
|
||||
* If components should be automatically translated in outgoing packets.
|
||||
*/
|
||||
public static final boolean AUTOMATIC_COMPONENT_TRANSLATION = false;
|
||||
|
||||
protected static final Localizable NULL_LOCALIZABLE = () -> null;
|
||||
|
||||
private static Function<Component, String> serializer = component -> GsonComponentSerializer.gson().serialize(component);
|
||||
private static Locale defaultLocale = Locale.US;
|
||||
|
||||
private AdventureSerializer() {}
|
||||
|
||||
/**
|
||||
* Gets the root serializer that is used to convert components into strings.
|
||||
*
|
||||
* @return the serializer
|
||||
*/
|
||||
public static @NotNull Function<Component, String> getSerializer() {
|
||||
return AdventureSerializer.serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the root serializer that is used to convert components into strings.
|
||||
*
|
||||
* @param serializer the serializer
|
||||
*/
|
||||
public static void setSerializer(@NotNull Function<Component, String> serializer) {
|
||||
AdventureSerializer.serializer = serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default locale used to translate {@link TranslatableComponent} if, when
|
||||
* {@link #translate(Component, Localizable)} is called with a localizable that
|
||||
* does not have a locale.
|
||||
*
|
||||
* @return the default locale
|
||||
*/
|
||||
public static @NotNull Locale getDefaultLocale() {
|
||||
return defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default locale used to translate {@link TranslatableComponent} if, when
|
||||
* {@link #translate(Component, Localizable)} is called with a localizable that
|
||||
* does not have a locale.
|
||||
*
|
||||
* @param defaultLocale the new default locale
|
||||
*/
|
||||
public static void setDefaultLocale(@NotNull Locale defaultLocale) {
|
||||
AdventureSerializer.defaultLocale = defaultLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the global translator object used by AdventureSerializer manager. This is just shorthand for
|
||||
* {@link GlobalTranslator#get()}.
|
||||
*
|
||||
* @return the global translator
|
||||
*/
|
||||
public static @NotNull GlobalTranslator getTranslator() {
|
||||
return GlobalTranslator.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a component for serialization. This runs the component through the
|
||||
* translator for the localizable's locale.
|
||||
*
|
||||
* @param component the component
|
||||
* @param localizable the localizable
|
||||
*
|
||||
* @return the prepared component
|
||||
*/
|
||||
public static @NotNull Component translate(@NotNull Component component, @NotNull Localizable localizable) {
|
||||
return GlobalTranslator.renderer().render(component, Objects.requireNonNullElse(localizable.getLocale(), AdventureSerializer.getDefaultLocale()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a component for serialization. This runs the component through the
|
||||
* translator for the locale.
|
||||
*
|
||||
* @param component the component
|
||||
* @param locale the locale
|
||||
*
|
||||
* @return the prepared component
|
||||
*/
|
||||
public static @NotNull Component translate(@NotNull Component component, @NotNull Locale locale) {
|
||||
return GlobalTranslator.renderer().render(component, locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a component into a string using {@link #getSerializer()}.
|
||||
*
|
||||
* @param component the component
|
||||
*
|
||||
* @return the serialized string
|
||||
*/
|
||||
public static @NotNull String serialize(@NotNull Component component) {
|
||||
return AdventureSerializer.serializer.apply(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares and then serializes a component.
|
||||
*
|
||||
* @param component the component
|
||||
* @param localizable the localisable
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public static String translateAndSerialize(@NotNull Component component, @NotNull Localizable localizable) {
|
||||
return AdventureSerializer.translateAndSerialize(component, Objects.requireNonNullElse(localizable.getLocale(), AdventureSerializer.getDefaultLocale()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares and then serializes a component.
|
||||
*
|
||||
* @param component the component
|
||||
* @param locale the locale
|
||||
*
|
||||
* @return the string
|
||||
*/
|
||||
public static String translateAndSerialize(@NotNull Component component, @NotNull Locale locale) {
|
||||
return AdventureSerializer.serialize(AdventureSerializer.translate(component, locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a component can be translated server-side. This is done by running the
|
||||
* component through the translator and seeing if the translated component is equal
|
||||
* to the non translated component.
|
||||
* @param component the component
|
||||
* @return {@code true} if the component can be translated server-side,
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public static boolean isTranslatable(@NotNull Component component) {
|
||||
return !component.equals(AdventureSerializer.translate(component, AdventureSerializer.getDefaultLocale()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any of a series of components are translatable server-side.
|
||||
* @param components the components
|
||||
* @return {@code true} if any of the components can be translated server-side,
|
||||
* {@code false} otherwise
|
||||
*/
|
||||
public static boolean areAnyTranslatable(@NotNull Collection<Component> components) {
|
||||
for (Component component : components) {
|
||||
if (AdventureSerializer.isTranslatable(component)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package net.minestom.server.adventure;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Represents an object that holds some amount of components.
|
||||
* @param <T> the holding class
|
||||
*/
|
||||
public interface ComponentHolder<T> {
|
||||
|
||||
/**
|
||||
* Gets the components held by this object.
|
||||
* @return the components
|
||||
*/
|
||||
@NotNull Collection<Component> components();
|
||||
|
||||
/**
|
||||
* Returns a copy of this object. For each component this object holds, the operator
|
||||
* is applied to the copy before returning.
|
||||
* @param operator the operator
|
||||
* @return the copy
|
||||
*/
|
||||
@NotNull T copyWithOperator(@NotNull UnaryOperator<Component> operator);
|
||||
|
||||
/**
|
||||
* Visits each component held by this object.
|
||||
* @param visitor the visitor
|
||||
*/
|
||||
default void visitComponents(@NotNull Consumer<Component> visitor) {
|
||||
for (Component component : this.components()) {
|
||||
visitor.accept(component);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package net.minestom.server.adventure;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Represents something which can have a locale.
|
||||
*/
|
||||
public interface Localizable {
|
||||
|
||||
/**
|
||||
* Gets a localizable that returns {@code null} for all calls to {@link #getLocale()}.
|
||||
*
|
||||
* @return the empty localizable
|
||||
*/
|
||||
static @NotNull Localizable empty() {
|
||||
return AdventureSerializer.NULL_LOCALIZABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the locale.
|
||||
*
|
||||
* @return the locale, or {@code null} if they do not have a locale set
|
||||
*/
|
||||
@Nullable Locale getLocale();
|
||||
|
||||
/**
|
||||
* Sets the locale. This can be set to {@code null} to remove a locale registration.
|
||||
*
|
||||
* @param locale the new locale
|
||||
*/
|
||||
default void setLocale(@Nullable Locale locale) {
|
||||
throw new UnsupportedOperationException("You cannot set the locale for this object!");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package net.minestom.server.adventure.audience;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A generic provider of {@link Audience}s or some subtype.
|
||||
* @param <A> the type that is provided
|
||||
*/
|
||||
public interface AudienceProvider<A> {
|
||||
|
||||
/**
|
||||
* Gets all audience members. This returns {@link #players()} combined with
|
||||
* {@link #customs()} and {@link #console()}. This can be a costly operation, so it
|
||||
* is often preferable to use {@link #server()} instead.
|
||||
* @return all audience members
|
||||
*/
|
||||
@NotNull A all();
|
||||
|
||||
/**
|
||||
* Gets all audience members that are of type {@link Player}.
|
||||
* @return all players
|
||||
*/
|
||||
@NotNull A players();
|
||||
|
||||
/**
|
||||
* Gets all audience members that are of type {@link Player} and match the predicate.
|
||||
* @param filter the predicate
|
||||
* @return all players matching the predicate
|
||||
*/
|
||||
@NotNull A players(@NotNull Predicate<Player> filter);
|
||||
|
||||
/**
|
||||
* Gets the console as an audience.
|
||||
* @return the console
|
||||
*/
|
||||
@NotNull A console();
|
||||
|
||||
/**
|
||||
* Gets the combination of {@link #players()} and {@link #console()}.
|
||||
* @return the audience of all players and the console
|
||||
*/
|
||||
@NotNull A server();
|
||||
|
||||
/**
|
||||
* Gets all custom audience members stored using the given keyed object.
|
||||
* @param keyed the keyed object
|
||||
* @return all custom audience members stored using the key of the object
|
||||
*/
|
||||
default @NotNull A custom(@NotNull Keyed keyed) {
|
||||
return this.custom(keyed.key());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all custom audience members stored using the given key.
|
||||
* @param key the key
|
||||
* @return all custom audience members stored using the key
|
||||
*/
|
||||
@NotNull A custom(@NotNull Key key);
|
||||
|
||||
/**
|
||||
* Gets all custom audience members stored using the given keyed object that match
|
||||
* the given predicate.
|
||||
* @param keyed the keyed object
|
||||
* @param filter the predicate
|
||||
* @return all custom audience members stored using the key
|
||||
*/
|
||||
default @NotNull A custom(@NotNull Keyed keyed, Predicate<Audience> filter) {
|
||||
return this.custom(keyed.key(), filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all custom audience members stored using the given key that match the
|
||||
* given predicate.
|
||||
* @param key the key
|
||||
* @param filter the predicate
|
||||
* @return all custom audience members stored using the key
|
||||
*/
|
||||
@NotNull A custom(@NotNull Key key, Predicate<Audience> filter);
|
||||
|
||||
/**
|
||||
* Gets all custom audience members.
|
||||
* @return all custom audience members
|
||||
*/
|
||||
@NotNull A customs();
|
||||
|
||||
/**
|
||||
* Gets all custom audience members matching the given predicate.
|
||||
* @param filter the predicate
|
||||
* @return all matching custom audience members
|
||||
*/
|
||||
@NotNull A customs(@NotNull Predicate<Audience> filter);
|
||||
|
||||
/**
|
||||
* Gets all audience members that match the given predicate.
|
||||
* @param filter the predicate
|
||||
* @return all matching audience members
|
||||
*/
|
||||
@NotNull A all(@NotNull Predicate<Audience> filter);
|
||||
|
||||
/**
|
||||
* Gets the audience registry used to register custom audiences.
|
||||
* @return the registry
|
||||
*/
|
||||
@NotNull AudienceRegistry registry();
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package net.minestom.server.adventure.audience;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Holder of custom audiences.
|
||||
*/
|
||||
public class AudienceRegistry {
|
||||
private final Map<Key, Collection<Audience>> registry;
|
||||
private final Function<Key, Collection<Audience>> provider;
|
||||
|
||||
/**
|
||||
* Creates a new audience registrar with a given backing map.
|
||||
* @param backingMap the backing map
|
||||
* @param backingCollection a provider for the backing collection
|
||||
*/
|
||||
public AudienceRegistry(@NotNull Map<Key, Collection<Audience>> backingMap, @NotNull Supplier<Collection<Audience>> backingCollection) {
|
||||
this.registry = backingMap;
|
||||
this.provider = key -> backingCollection.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this registry is empty.
|
||||
* @return {@code true} if it is, {@code false} otherwise
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return this.registry.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some audiences to the registry.
|
||||
* @param keyed the provider of the key
|
||||
* @param audiences the audiences
|
||||
*/
|
||||
public void register(@NotNull Keyed keyed, @NotNull Audience... audiences) {
|
||||
this.register(keyed.key(), audiences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some audiences to the registry.
|
||||
* @param keyed the provider of the key
|
||||
* @param audiences the audiences
|
||||
*/
|
||||
public void register(@NotNull Keyed keyed, @NotNull Collection<Audience> audiences) {
|
||||
this.register(keyed.key(), audiences);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some audiences to the registry.
|
||||
* @param key the key to store the audiences under
|
||||
* @param audiences the audiences
|
||||
*/
|
||||
public void register(@NotNull Key key, @NotNull Audience... audiences) {
|
||||
if (audiences == null || audiences.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.register(key, Arrays.asList(audiences));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds some audiences to the registry.
|
||||
* @param key the key to store the audiences under
|
||||
* @param audiences the audiences
|
||||
*/
|
||||
public void register(@NotNull Key key, @NotNull Collection<Audience> audiences) {
|
||||
if (!audiences.isEmpty()) {
|
||||
this.registry.computeIfAbsent(key, this.provider).addAll(audiences);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets every audience in the registry.
|
||||
* @return an iterable containing every audience member
|
||||
*/
|
||||
public @NotNull Iterable<? extends Audience> all() {
|
||||
if (this.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return this.registry.values().stream().flatMap(Collection::stream).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets every audience in the registry under a specific key.
|
||||
* @param keyed the key provider
|
||||
* @return an iterable containing the audience members
|
||||
*/
|
||||
public @NotNull Iterable<? extends Audience> of(@NotNull Keyed keyed) {
|
||||
return this.of(keyed.key());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets every audience in the registry under a specific key.
|
||||
* @param key the key
|
||||
* @return an iterable containing the audience members
|
||||
*/
|
||||
public @NotNull Iterable<? extends Audience> of(@NotNull Key key) {
|
||||
return Collections.unmodifiableCollection(this.registry.getOrDefault(key, this.provider.apply(null)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets every audience member in the registry who matches a given predicate.
|
||||
* @param filter the predicate
|
||||
* @return the matching audience members
|
||||
*/
|
||||
public @NotNull Iterable<? extends Audience> of(@NotNull Predicate<Audience> filter) {
|
||||
return this.registry.values().stream().flatMap(Collection::stream).filter(filter).collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package net.minestom.server.adventure.audience;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Utility class to access Adventure audiences.
|
||||
*/
|
||||
public class Audiences implements AudienceProvider<Audience> {
|
||||
private final IterableAudienceProvider collection;
|
||||
private final Audience players, server;
|
||||
|
||||
/**
|
||||
* Creates a new audiences instance. <b>Do not</b> instantiate this class, instead
|
||||
* you can obtain an instance using {@link #audiences()}.
|
||||
*/
|
||||
public Audiences() {
|
||||
this.collection = new IterableAudienceProvider();
|
||||
this.players = PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getOnlinePlayers());
|
||||
this.server = Audience.audience(this.players, MinecraftServer.getCommandManager().getConsoleSender());
|
||||
}
|
||||
|
||||
/**
|
||||
* Short-hand method for {@link MinecraftServer#getAudiences()}.
|
||||
* @return the audiences instance
|
||||
*/
|
||||
public static @NotNull Audiences audiences() {
|
||||
return MinecraftServer.getAudiences();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link IterableAudienceProvider} instance.
|
||||
* @return the instance
|
||||
*/
|
||||
public @NotNull IterableAudienceProvider iterable() {
|
||||
return this.collection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience all() {
|
||||
return Audience.audience(this.server, this.customs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience players() {
|
||||
return this.players;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience players(@NotNull Predicate<Player> filter) {
|
||||
return PacketGroupingAudience.of(MinecraftServer.getConnectionManager().getOnlinePlayers().stream().filter(filter).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience console() {
|
||||
return MinecraftServer.getCommandManager().getConsoleSender();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience server() {
|
||||
return this.server;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience customs() {
|
||||
return Audience.audience(this.iterable().customs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience custom(@NotNull Key key) {
|
||||
return Audience.audience(this.iterable().custom(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience custom(@NotNull Key key, Predicate<Audience> filter) {
|
||||
return Audience.audience(this.iterable().custom(key, filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience customs(@NotNull Predicate<Audience> filter) {
|
||||
return Audience.audience(this.iterable().customs(filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Audience all(@NotNull Predicate<Audience> filter) {
|
||||
return Audience.audience(this.iterable().all(filter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AudienceRegistry registry() {
|
||||
return this.iterable().registry();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package net.minestom.server.adventure.audience;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.command.ConsoleSender;
|
||||
import net.minestom.server.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* A provider of iterable audiences.
|
||||
*/
|
||||
public final class IterableAudienceProvider implements AudienceProvider<Iterable<? extends Audience>> {
|
||||
private final Collection<ConsoleSender> console = Collections.singleton(MinecraftServer.getCommandManager().getConsoleSender());
|
||||
private final AudienceRegistry registry = new AudienceRegistry(new ConcurrentHashMap<>(), CopyOnWriteArrayList::new);
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> all() {
|
||||
return Iterables.concat(this.players(), this.console(), this.customs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> players() {
|
||||
return MinecraftServer.getConnectionManager().getOnlinePlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> players(@NotNull Predicate<Player> filter) {
|
||||
return MinecraftServer.getConnectionManager().getOnlinePlayers().stream().filter(filter).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> console() {
|
||||
return this.console;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> server() {
|
||||
return Iterables.concat(this.players(), this.console());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> customs() {
|
||||
return this.registry.all();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> custom(@NotNull Key key) {
|
||||
return this.registry.of(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> custom(@NotNull Key key, Predicate<Audience> filter) {
|
||||
return StreamSupport.stream(this.registry.of(key).spliterator(), false).filter(filter).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> customs(@NotNull Predicate<Audience> filter) {
|
||||
return this.registry.of(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterable<? extends Audience> all(@NotNull Predicate<Audience> filter) {
|
||||
return StreamSupport.stream(this.all().spliterator(), false).filter(filter).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AudienceRegistry registry() {
|
||||
return this.registry;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package net.minestom.server.adventure.audience;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.audience.MessageType;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.kyori.adventure.sound.SoundStop;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
||||
import net.minestom.server.network.packet.server.play.PlayerListHeaderAndFooterPacket;
|
||||
import net.minestom.server.network.packet.server.play.TitlePacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* An audience implementation that sends grouped packets if possible.
|
||||
*/
|
||||
public interface PacketGroupingAudience extends ForwardingAudience {
|
||||
|
||||
/**
|
||||
* Creates a packet grouping audience that copies an iterable of players. The
|
||||
* underlying collection is not copied, so changes to the collection will be
|
||||
* reflected in the audience.
|
||||
* @param players the players
|
||||
* @return the audience
|
||||
*/
|
||||
static PacketGroupingAudience of(Collection<Player> players) {
|
||||
return () -> players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an iterable of the players this audience contains.
|
||||
* @return the connections
|
||||
*/
|
||||
@NotNull Collection<Player> getPlayers();
|
||||
|
||||
@Override
|
||||
default void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new ChatMessagePacket(message, ChatMessagePacket.Position.fromMessageType(type), source.uuid()));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendActionBar(@NotNull Component message) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new TitlePacket(TitlePacket.Action.SET_ACTION_BAR, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new PlayerListHeaderAndFooterPacket(header, footer));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void showTitle(@NotNull Title title) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new TitlePacket(TitlePacket.Action.SET_TITLE, title.title()));
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new TitlePacket(TitlePacket.Action.SET_SUBTITLE, title.subtitle()));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void clearTitle() {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new TitlePacket(TitlePacket.Action.HIDE));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void resetTitle() {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), new TitlePacket(TitlePacket.Action.RESET));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void showBossBar(@NotNull BossBar bar) {
|
||||
MinecraftServer.getBossBarManager().addBossBar(this.getPlayers(), bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void hideBossBar(@NotNull BossBar bar) {
|
||||
MinecraftServer.getBossBarManager().removeBossBar(this.getPlayers(), bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
default void playSound(@NotNull Sound sound, double x, double y, double z) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundPacket(sound, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
default void stopSound(@NotNull SoundStop stop) {
|
||||
PacketUtils.sendGroupedPacket(this.getPlayers(), AdventurePacketConvertor.createSoundStopPacket(stop));
|
||||
}
|
||||
|
||||
@Override
|
||||
default @NotNull Iterable<? extends Audience> audiences() {
|
||||
return this.getPlayers();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package net.minestom.server.adventure.bossbar;
|
||||
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.Viewable;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.play.BossBarPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static net.minestom.server.network.packet.server.play.BossBarPacket.Action.*;
|
||||
|
||||
/**
|
||||
* A holder of a boss bar. This class is not intended for public use, instead you should
|
||||
* use {@link BossBarManager} to manage boss bars for players.
|
||||
*/
|
||||
final class BossBarHolder implements Viewable {
|
||||
final UUID uuid;
|
||||
final BossBar bar;
|
||||
final Set<Player> players;
|
||||
boolean registered;
|
||||
|
||||
BossBarHolder(@NotNull BossBar bar) {
|
||||
this.uuid = UUID.randomUUID();
|
||||
this.bar = bar;
|
||||
this.players = new CopyOnWriteArraySet<>();
|
||||
this.registered = false;
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createRemovePacket() {
|
||||
return this.createGenericPacket(REMOVE, packet -> {});
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createAddPacket() {
|
||||
return this.createGenericPacket(ADD, packet -> {
|
||||
packet.title = bar.name();
|
||||
packet.color = bar.color();
|
||||
packet.overlay = bar.overlay();
|
||||
packet.health = bar.progress();
|
||||
packet.flags = AdventurePacketConvertor.getBossBarFlagValue(bar.flags());
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createPercentUpdate(float newPercent) {
|
||||
return this.createGenericPacket(UPDATE_HEALTH, packet -> packet.health = newPercent);
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createColorUpdate(@NotNull BossBar.Color color) {
|
||||
return this.createGenericPacket(UPDATE_STYLE, packet -> {
|
||||
packet.color = color;
|
||||
packet.overlay = bar.overlay();
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createTitleUpdate(@NotNull Component title) {
|
||||
return this.createGenericPacket(UPDATE_TITLE, packet -> packet.title = title);
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createFlagsUpdate() {
|
||||
return createFlagsUpdate(bar.flags());
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createFlagsUpdate(@NotNull Set<BossBar.Flag> newFlags) {
|
||||
return this.createGenericPacket(UPDATE_FLAGS, packet -> packet.flags = AdventurePacketConvertor.getBossBarFlagValue(newFlags));
|
||||
}
|
||||
|
||||
@NotNull BossBarPacket createOverlayUpdate(@NotNull BossBar.Overlay overlay) {
|
||||
return this.createGenericPacket(UPDATE_STYLE, packet -> {
|
||||
packet.overlay = overlay;
|
||||
packet.color = bar.color();
|
||||
});
|
||||
}
|
||||
|
||||
private @NotNull BossBarPacket createGenericPacket(@NotNull BossBarPacket.Action action, @NotNull Consumer<BossBarPacket> consumer) {
|
||||
BossBarPacket packet = new BossBarPacket();
|
||||
packet.uuid = this.uuid;
|
||||
packet.action = action;
|
||||
consumer.accept(packet);
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addViewer(@NotNull Player player) {
|
||||
return this.players.add(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeViewer(@NotNull Player player) {
|
||||
return this.players.remove(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Set<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(this.players);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package net.minestom.server.adventure.bossbar;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A listener for boss bar updates. This class is not intended for public use and it is
|
||||
* automatically added to boss bars shown to players using the methods in
|
||||
* {@link Audience}, instead you should use {@link BossBarManager} to manage boss bars
|
||||
* for players.
|
||||
*/
|
||||
class BossBarListener implements BossBar.Listener {
|
||||
private final BossBarManager manager;
|
||||
|
||||
/**
|
||||
* Creates a new boss bar listener.
|
||||
* @param manager the manager instance
|
||||
*/
|
||||
BossBarListener(BossBarManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bossBarNameChanged(@NotNull BossBar bar, @NotNull Component oldName, @NotNull Component newName) {
|
||||
this.doIfRegistered(bar, holder -> PacketUtils.sendGroupedPacket(holder.players, holder.createTitleUpdate(newName)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bossBarProgressChanged(@NotNull BossBar bar, float oldProgress, float newProgress) {
|
||||
this.doIfRegistered(bar, holder -> PacketUtils.sendGroupedPacket(holder.players, holder.createPercentUpdate(newProgress)));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bossBarColorChanged(@NotNull BossBar bar, @NotNull BossBar.Color oldColor, @NotNull BossBar.Color newColor) {
|
||||
this.doIfRegistered(bar, holder -> PacketUtils.sendGroupedPacket(holder.players, holder.createColorUpdate(newColor)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bossBarOverlayChanged(@NotNull BossBar bar, BossBar.@NotNull Overlay oldOverlay, BossBar.@NotNull Overlay newOverlay) {
|
||||
this.doIfRegistered(bar, holder -> PacketUtils.sendGroupedPacket(holder.players, holder.createOverlayUpdate(newOverlay)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bossBarFlagsChanged(@NotNull BossBar bar, @NotNull Set<BossBar.Flag> flagsAdded, @NotNull Set<BossBar.Flag> flagsRemoved) {
|
||||
this.doIfRegistered(bar, holder -> PacketUtils.sendGroupedPacket(holder.players, holder.createFlagsUpdate()));
|
||||
}
|
||||
|
||||
private void doIfRegistered(@NotNull BossBar bar, @NotNull Consumer<BossBarHolder> consumer) {
|
||||
BossBarHolder holder = this.manager.bars.get(bar);
|
||||
|
||||
if (holder != null && holder.registered) {
|
||||
consumer.accept(holder);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,181 @@
|
|||
package net.minestom.server.adventure.bossbar;
|
||||
|
||||
import com.google.common.collect.MapMaker;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.bossbar.BossBar.Color;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerDisconnectEvent;
|
||||
import net.minestom.server.network.packet.server.play.BossBarPacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
/**
|
||||
* Manages all boss bars known to this Minestom instance. Although this class can be used
|
||||
* to show boss bars to players, it is preferable to use the boss bar methods in the
|
||||
* {@link Audience} class instead.
|
||||
*
|
||||
* <p>This implementation is heavily based on
|
||||
* <a href="https://github.com/VelocityPowered/Velocity">Velocity</a>'s boss bar
|
||||
* management system.</p>
|
||||
*
|
||||
* @see Audience#showBossBar(BossBar)
|
||||
* @see Audience#hideBossBar(BossBar)
|
||||
*/
|
||||
public class BossBarManager {
|
||||
private final BossBarListener listener;
|
||||
private final Map<UUID, Set<BossBarHolder>> playerBars;
|
||||
final Map<BossBar, BossBarHolder> bars;
|
||||
|
||||
/**
|
||||
* Creates a new boss bar manager.
|
||||
*/
|
||||
public BossBarManager() {
|
||||
this.listener = new BossBarListener(this);
|
||||
this.playerBars = new ConcurrentHashMap<>();
|
||||
this.bars = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified player to the boss bar's viewers and spawns the boss bar, registering the
|
||||
* boss bar if needed.
|
||||
*
|
||||
* @param player the intended viewer
|
||||
* @param bar the boss bar to show
|
||||
*/
|
||||
public void addBossBar(@NotNull Player player, @NotNull BossBar bar) {
|
||||
BossBarHolder holder = this.getOrCreateHandler(bar);
|
||||
|
||||
if (holder.addViewer(player)) {
|
||||
player.getPlayerConnection().sendPacket(holder.createAddPacket());
|
||||
this.playerBars.computeIfAbsent(player.getUuid(), uuid -> new HashSet<>()).add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified player from the boss bar's viewers and despawns the boss bar.
|
||||
*
|
||||
* @param player the intended viewer
|
||||
* @param bar the boss bar to hide
|
||||
*/
|
||||
public void removeBossBar(@NotNull Player player, @NotNull BossBar bar) {
|
||||
BossBarHolder holder = this.getOrCreateHandler(bar);
|
||||
|
||||
if (holder.removeViewer(player)) {
|
||||
player.getPlayerConnection().sendPacket(holder.createRemovePacket());
|
||||
this.removePlayer(player, holder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified players to the boss bar's viewers and spawns the boss bar, registering the
|
||||
* boss bar if needed.
|
||||
*
|
||||
* @param players the players
|
||||
* @param bar the boss bar
|
||||
*/
|
||||
public void addBossBar(@NotNull Collection<Player> players, @NotNull BossBar bar) {
|
||||
BossBarHolder holder = this.getOrCreateHandler(bar);
|
||||
Collection<Player> addedPlayers = new ArrayList<>();
|
||||
|
||||
for (Player player : players) {
|
||||
if (holder.addViewer(player)) {
|
||||
addedPlayers.add(player);
|
||||
this.playerBars.computeIfAbsent(player.getUuid(), uuid -> new HashSet<>()).add(holder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!addedPlayers.isEmpty()) {
|
||||
PacketUtils.sendGroupedPacket(addedPlayers, holder.createAddPacket());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified players from the boss bar's viewers and despawns the boss bar.
|
||||
*
|
||||
* @param players the intended viewers
|
||||
* @param bar the boss bar to hide
|
||||
*/
|
||||
public void removeBossBar(@NotNull Collection<Player> players, @NotNull BossBar bar) {
|
||||
BossBarHolder holder = this.getOrCreateHandler(bar);
|
||||
Collection<Player> removedPlayers = new ArrayList<>();
|
||||
|
||||
for (Player player : players) {
|
||||
if (holder.removeViewer(player)) {
|
||||
removedPlayers.add(player);
|
||||
this.removePlayer(player, holder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!removedPlayers.isEmpty()) {
|
||||
PacketUtils.sendGroupedPacket(removedPlayers, holder.createRemovePacket());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completely destroys a boss bar, removing it from all players.
|
||||
*
|
||||
* @param bossBar the boss bar
|
||||
*/
|
||||
public void destroyBossBar(@NotNull BossBar bossBar) {
|
||||
BossBarHolder holder = this.bars.remove(bossBar);
|
||||
|
||||
if (holder != null) {
|
||||
PacketUtils.sendGroupedPacket(holder.players, holder.createRemovePacket());
|
||||
|
||||
for (Player player : holder.players) {
|
||||
this.removePlayer(player, holder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a player from all of their boss bars. Note that this method does not
|
||||
* send any removal packets to the player. It is meant to be used when a player is
|
||||
* disconnecting from the server.
|
||||
*
|
||||
* @param player the player
|
||||
*/
|
||||
public void removeAllBossBars(@NotNull Player player) {
|
||||
Set<BossBarHolder> holders = this.playerBars.remove(player.getUuid());
|
||||
|
||||
if (holders != null) {
|
||||
for (BossBarHolder holder : holders) {
|
||||
holder.removeViewer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or creates a handler for this bar.
|
||||
*
|
||||
* @param bar the bar
|
||||
*
|
||||
* @return the handler
|
||||
*/
|
||||
private @NotNull BossBarHolder getOrCreateHandler(@NotNull BossBar bar) {
|
||||
return this.bars.computeIfAbsent(bar, key -> {
|
||||
BossBarHolder holder = new BossBarHolder(key);
|
||||
bar.addListener(this.listener);
|
||||
return holder;
|
||||
});
|
||||
}
|
||||
|
||||
private void removePlayer(Player player, BossBarHolder holder) {
|
||||
Set<BossBarHolder> holders = this.playerBars.get(player.getUuid());
|
||||
|
||||
if (holders != null) {
|
||||
holders.remove(holder);
|
||||
|
||||
if (holders.isEmpty()) {
|
||||
this.playerBars.remove(player.getUuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,11 @@ package net.minestom.server.benchmark;
|
|||
|
||||
import it.unimi.dsi.fastutil.longs.Long2LongMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.utils.MathUtils;
|
||||
import net.minestom.server.utils.time.UpdateOption;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
@ -106,20 +109,25 @@ public final class BenchmarkManager {
|
|||
@NotNull
|
||||
public String getCpuMonitoringMessage() {
|
||||
Check.stateCondition(!enabled, "CPU monitoring is only possible when the benchmark manager is enabled.");
|
||||
StringBuilder benchmarkMessage = new StringBuilder();
|
||||
TextComponent.Builder benchmarkMessage = Component.text();
|
||||
for (Map.Entry<String, ThreadResult> resultEntry : resultMap.entrySet()) {
|
||||
final String name = resultEntry.getKey();
|
||||
final ThreadResult result = resultEntry.getValue();
|
||||
|
||||
benchmarkMessage.append(ChatColor.GRAY).append(name);
|
||||
benchmarkMessage.append(": ");
|
||||
benchmarkMessage.append(ChatColor.YELLOW.toString()).append(MathUtils.round(result.getCpuPercentage(), 2)).append("% CPU ");
|
||||
benchmarkMessage.append(ChatColor.RED.toString()).append(MathUtils.round(result.getUserPercentage(), 2)).append("% USER ");
|
||||
benchmarkMessage.append(ChatColor.PINK.toString()).append(MathUtils.round(result.getBlockedPercentage(), 2)).append("% BLOCKED ");
|
||||
benchmarkMessage.append(ChatColor.BRIGHT_GREEN.toString()).append(MathUtils.round(result.getWaitedPercentage(), 2)).append("% WAITED ");
|
||||
benchmarkMessage.append("\n");
|
||||
benchmarkMessage.append(Component.text(name, NamedTextColor.GRAY));
|
||||
benchmarkMessage.append(Component.text(": "));
|
||||
benchmarkMessage.append(Component.text(MathUtils.round(result.getCpuPercentage(), 2), NamedTextColor.YELLOW));
|
||||
benchmarkMessage.append(Component.text("% CPU "));
|
||||
benchmarkMessage.append(Component.text(MathUtils.round(result.getUserPercentage(), 2), NamedTextColor.RED));
|
||||
benchmarkMessage.append(Component.text("% USER "));
|
||||
benchmarkMessage.append(Component.text(MathUtils.round(result.getBlockedPercentage(), 2), NamedTextColor.LIGHT_PURPLE));
|
||||
benchmarkMessage.append(Component.text("% BLOCKED "));
|
||||
benchmarkMessage.append(Component.text(MathUtils.round(result.getWaitedPercentage(), 2), NamedTextColor.GREEN));
|
||||
benchmarkMessage.append(Component.text("% WAITED "));
|
||||
benchmarkMessage.append(Component.newline());
|
||||
}
|
||||
return benchmarkMessage.toString();
|
||||
|
||||
return AdventureSerializer.serialize(benchmarkMessage.build());
|
||||
}
|
||||
|
||||
private void refreshData() {
|
||||
|
|
|
@ -2,7 +2,9 @@ package net.minestom.server.bossbar;
|
|||
|
||||
/**
|
||||
* Represents the displayed color of a {@link BossBar}.
|
||||
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar}
|
||||
*/
|
||||
@Deprecated
|
||||
public enum BarColor {
|
||||
PINK,
|
||||
BLUE,
|
||||
|
@ -10,5 +12,9 @@ public enum BarColor {
|
|||
GREEN,
|
||||
YELLOW,
|
||||
PURPLE,
|
||||
WHITE
|
||||
WHITE;
|
||||
|
||||
public net.kyori.adventure.bossbar.BossBar.Color asAdventureColor() {
|
||||
return net.kyori.adventure.bossbar.BossBar.Color.valueOf(this.name());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,18 @@ package net.minestom.server.bossbar;
|
|||
|
||||
/**
|
||||
* Used to define the number of segments on a {@link BossBar}.
|
||||
*
|
||||
* @deprecated Use {@link net.kyori.adventure.bossbar.BossBar}
|
||||
*/
|
||||
@Deprecated
|
||||
public enum BarDivision {
|
||||
SOLID,
|
||||
SEGMENT_6,
|
||||
SEGMENT_10,
|
||||
SEGMENT_12,
|
||||
SEGMENT_20
|
||||
SEGMENT_20;
|
||||
|
||||
public net.kyori.adventure.bossbar.BossBar.Overlay asAdventureOverlay() {
|
||||
return net.kyori.adventure.bossbar.BossBar.Overlay.values()[this.ordinal()];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ import java.util.concurrent.CopyOnWriteArraySet;
|
|||
* and add the {@link Player} you want using {@link #addViewer(Player)} and remove them using {@link #removeViewer(Player)}.
|
||||
* <p>
|
||||
* You can retrieve all the boss bars of a {@link Player} with {@link #getBossBars(Player)}.
|
||||
*
|
||||
* @deprecated Use {@link net.kyori.adventure.audience.Audience#showBossBar(net.kyori.adventure.bossbar.BossBar)}
|
||||
*/
|
||||
@Deprecated
|
||||
public class BossBar implements Viewable {
|
||||
|
||||
private static final int MAX_BOSSBAR = 7;
|
||||
|
@ -249,10 +252,10 @@ public class BossBar implements Viewable {
|
|||
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||
bossBarPacket.uuid = uuid;
|
||||
bossBarPacket.action = BossBarPacket.Action.ADD;
|
||||
bossBarPacket.title = title;
|
||||
bossBarPacket.title = title.asComponent();
|
||||
bossBarPacket.health = progress;
|
||||
bossBarPacket.color = color;
|
||||
bossBarPacket.division = division;
|
||||
bossBarPacket.color = color.asAdventureColor();
|
||||
bossBarPacket.overlay = division.asAdventureOverlay();
|
||||
bossBarPacket.flags = flags;
|
||||
player.getPlayerConnection().sendPacket(bossBarPacket);
|
||||
}
|
||||
|
@ -275,7 +278,7 @@ public class BossBar implements Viewable {
|
|||
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||
bossBarPacket.uuid = uuid;
|
||||
bossBarPacket.action = BossBarPacket.Action.UPDATE_TITLE;
|
||||
bossBarPacket.title = title;
|
||||
bossBarPacket.title = title.asComponent();
|
||||
sendPacketToViewers(bossBarPacket);
|
||||
}
|
||||
|
||||
|
@ -291,7 +294,7 @@ public class BossBar implements Viewable {
|
|||
BossBarPacket bossBarPacket = new BossBarPacket();
|
||||
bossBarPacket.uuid = uuid;
|
||||
bossBarPacket.action = BossBarPacket.Action.UPDATE_STYLE;
|
||||
bossBarPacket.color = color;
|
||||
bossBarPacket.color = color.asAdventureColor();
|
||||
sendPacketToViewers(bossBarPacket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
/**
|
||||
* Represents a click event for a specific portion of the message.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ChatClickEvent {
|
||||
|
||||
private final String action;
|
||||
|
|
|
@ -4,6 +4,8 @@ import it.unimi.dsi.fastutil.chars.Char2ObjectMap;
|
|||
import it.unimi.dsi.fastutil.chars.Char2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -18,6 +20,7 @@ import java.util.Map;
|
|||
* <p>
|
||||
* Immutable class.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ChatColor {
|
||||
|
||||
// Special
|
||||
|
@ -272,6 +275,18 @@ public final class ChatColor {
|
|||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Adventure text color from this chat color.
|
||||
* @return the text color
|
||||
*/
|
||||
public @NotNull TextColor asTextColor() {
|
||||
return TextColor.color(red, blue, green);
|
||||
}
|
||||
|
||||
public @NotNull Color asColor() {
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
package net.minestom.server.chat;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Represents a hover event for a specific portion of the message.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ChatHoverEvent {
|
||||
|
||||
private final String action;
|
||||
|
@ -37,12 +46,12 @@ public class ChatHoverEvent {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
protected String getValue() {
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected JsonObject getValueObject() {
|
||||
public JsonObject getValueObject() {
|
||||
return valueObject;
|
||||
}
|
||||
|
||||
|
@ -80,8 +89,17 @@ public class ChatHoverEvent {
|
|||
*/
|
||||
@NotNull
|
||||
public static ChatHoverEvent showItem(@NotNull ItemStack itemStack) {
|
||||
final String json = itemStack.toNBT().toSNBT();
|
||||
return new ChatHoverEvent("show_item", json);
|
||||
HoverEvent<HoverEvent.ShowItem> event = HoverEvent.showItem(itemStack.getMaterial().key(), itemStack.getAmount());
|
||||
JsonObject obj = GsonComponentSerializer.gson().serializer().toJsonTree(Component.empty().hoverEvent(event)).getAsJsonObject();
|
||||
obj = obj.get("hoverEvent").getAsJsonObject().get("contents").getAsJsonObject();
|
||||
|
||||
if (itemStack.getItemMeta() != null) {
|
||||
NBTCompound compound = new NBTCompound();
|
||||
itemStack.getItemMeta().write(compound);
|
||||
obj.add("tag", new JsonPrimitive(compound.toSNBT()));
|
||||
}
|
||||
|
||||
return new ChatHoverEvent("show_item", obj);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,9 +110,14 @@ public class ChatHoverEvent {
|
|||
*/
|
||||
@NotNull
|
||||
public static ChatHoverEvent showEntity(@NotNull Entity entity) {
|
||||
NBTCompound compound = new NBTCompound()
|
||||
.setString("id", entity.getUuid().toString())
|
||||
.setString("type", entity.getEntityType().getNamespaceID());
|
||||
return new ChatHoverEvent("show_entity", compound.toSNBT());
|
||||
HoverEvent<HoverEvent.ShowEntity> event = HoverEvent.showEntity(entity.getEntityType().key(), entity.getUuid());
|
||||
JsonObject obj = GsonComponentSerializer.gson().serializer().toJsonTree(Component.empty().hoverEvent(event)).getAsJsonObject();
|
||||
return new ChatHoverEvent("show_entity", obj.get("hoverEvent").getAsJsonObject().get("contents").getAsJsonObject());
|
||||
}
|
||||
|
||||
public static ChatHoverEvent showEntity(UUID uuid, EntityType entityType) {
|
||||
HoverEvent<HoverEvent.ShowEntity> event = HoverEvent.showEntity(entityType.key(), uuid);
|
||||
JsonObject obj = GsonComponentSerializer.gson().serializer().toJsonTree(Component.empty().hoverEvent(event)).getAsJsonObject();
|
||||
return new ChatHoverEvent("show_entity", obj.get("hoverEvent").getAsJsonObject().get("contents").getAsJsonObject());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
/**
|
||||
* Class used to convert JSON string to proper chat message representation.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class ChatParser {
|
||||
|
||||
public static final char COLOR_CHAR = (char) 0xA7; // Represent the character '§'
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.regex.Pattern;
|
|||
* To create one, you simply call one of the static methods like {@link #of(ChatColor, String)},
|
||||
* you can then continue to append text with {@link #append(ChatColor, String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ColoredText extends JsonMessage {
|
||||
|
||||
private static final char SEPARATOR_START = '{';
|
||||
|
|
|
@ -3,6 +3,9 @@ package net.minestom.server.chat;
|
|||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.ComponentLike;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -14,7 +17,8 @@ import java.util.Objects;
|
|||
*
|
||||
* @see <a href="https://wiki.vg/Chat">Chat Format</a>
|
||||
*/
|
||||
public abstract class JsonMessage {
|
||||
@Deprecated
|
||||
public abstract class JsonMessage implements ComponentLike {
|
||||
|
||||
// true if the compiled string is up-to-date, false otherwise
|
||||
private boolean updated;
|
||||
|
@ -49,6 +53,15 @@ public abstract class JsonMessage {
|
|||
return getTextMessage(getJsonObject()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Component asComponent() {
|
||||
return GsonComponentSerializer.gson().deserializeFromTree(this.getJsonObject());
|
||||
}
|
||||
|
||||
public static @NotNull JsonMessage fromComponent(@NotNull Component component) {
|
||||
return new RawJsonMessage(GsonComponentSerializer.gson().serializer().toJsonTree(component).getAsJsonObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Json representation.
|
||||
* <p>
|
||||
|
@ -102,6 +115,7 @@ public abstract class JsonMessage {
|
|||
return message;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static class RawJsonMessage extends JsonMessage {
|
||||
|
||||
private final JsonObject jsonObject;
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
|||
* events can be assigned with {@link #setClickEvent(ChatClickEvent)} and {@link #setHoverEvent(ChatHoverEvent)}
|
||||
* and new text element can also be appended {@link #append(ColoredText)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class RichMessage extends JsonMessage {
|
||||
|
||||
private final List<RichComponent> components = new ArrayList<>();
|
||||
|
@ -159,7 +160,7 @@ public class RichMessage extends JsonMessage {
|
|||
// The value is a JsonObject
|
||||
hoverObject = new JsonObject();
|
||||
hoverObject.addProperty("action", hoverEvent.getAction());
|
||||
hoverObject.add("value", hoverEvent.getValueObject());
|
||||
hoverObject.add("contents", hoverEvent.getValueObject());
|
||||
} else {
|
||||
// The value is a raw string
|
||||
final String hoverValue = hoverEvent.getValue();
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
/**
|
||||
* Represents a translatable component which can be used in {@link ColoredText}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class TranslatableText {
|
||||
|
||||
private final String code;
|
||||
|
|
|
@ -0,0 +1,204 @@
|
|||
package net.minestom.server.color;
|
||||
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.util.RGBLike;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A general purpose class for representing colors.
|
||||
*/
|
||||
public class Color implements RGBLike {
|
||||
private static final int BIT_MASK = 0xff;
|
||||
|
||||
private int red, green, blue;
|
||||
|
||||
/**
|
||||
* Creates a color from an integer. This is done by reading each color component
|
||||
* from the lowest order 24 bits of the integer, and creating a color from those
|
||||
* components.
|
||||
*
|
||||
* @param rgb the integer
|
||||
*/
|
||||
public Color(int rgb) {
|
||||
this((rgb >> 16) & BIT_MASK, (rgb >> 8) & BIT_MASK, rgb & BIT_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a color from an RGB-like color.
|
||||
*
|
||||
* @param rgbLike the color
|
||||
*/
|
||||
public Color(RGBLike rgbLike) {
|
||||
this(rgbLike.red(), rgbLike.blue(), rgbLike.green());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a color from red, green, and blue components.
|
||||
*
|
||||
* @param red the red component
|
||||
* @param green the green component
|
||||
* @param blue the blue component
|
||||
*
|
||||
* @throws IllegalArgumentException if any component value is not between 0-255 (inclusive)
|
||||
*/
|
||||
public Color(int red, int green, int blue) {
|
||||
Validate.isTrue(red >= 0 && red <= 255, "Red is not between 0-255: ", red);
|
||||
Validate.isTrue(green >= 0 && green <= 255, "Green is not between 0-255: ", green);
|
||||
Validate.isTrue(blue >= 0 && blue <= 255, "Blue is not between 0-255: ", blue);
|
||||
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the red component.
|
||||
*
|
||||
* @return red component, between 0-255 (inclusive)
|
||||
*/
|
||||
public int getRed() {
|
||||
return this.red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
*
|
||||
* @param red the red component, from 0 to 255
|
||||
*/
|
||||
public void setRed(int red) {
|
||||
Validate.isTrue(red >= 0 && red <= 255, "Red is not between 0-255: ", red);
|
||||
this.red = red;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the green component
|
||||
*
|
||||
* @return green component, from 0 to 255
|
||||
*/
|
||||
public int getGreen() {
|
||||
return this.green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Color object with specified component
|
||||
*
|
||||
* @param green the red component, from 0 to 255
|
||||
*/
|
||||
public void setGreen(int green) {
|
||||
Validate.isTrue(green >= 0 && green <= 255, "Green is not between 0-255: ", green);
|
||||
this.green = green;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blue component
|
||||
*
|
||||
* @return blue component, from 0 to 255
|
||||
*/
|
||||
public int getBlue() {
|
||||
return this.blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the blue component of this color.
|
||||
*
|
||||
* @param blue the red component, from 0 to 255
|
||||
*/
|
||||
public void setBlue(int blue) {
|
||||
Validate.isTrue(blue >= 0 && blue <= 255, "Blue is not between 0-255: ", blue);
|
||||
this.blue = blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color as an RGB integer.
|
||||
*
|
||||
* @return An integer representation of this color, as 0xRRGGBB
|
||||
*/
|
||||
public int asRGB() {
|
||||
int rgb = red;
|
||||
rgb = (rgb << 8) + green;
|
||||
return (rgb << 8) + blue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixes this color with a series of other colors, as if they were combined in a
|
||||
* crafting table. This function works out the average of each RGB component and then
|
||||
* multiplies the components by a scale factor that is calculated from the average
|
||||
* of all maximum values divided by the maximum of each average value. This is how
|
||||
* Minecraft mixes colors.
|
||||
*
|
||||
* @param colors the colors
|
||||
*/
|
||||
public void mixWith(@NotNull RGBLike... colors) {
|
||||
Validate.noNullElements(colors, "Colors cannot be null");
|
||||
|
||||
// store the current highest component
|
||||
int max = Math.max(Math.max(this.red, this.green), this.blue);
|
||||
|
||||
// now combine all of the color components, adding to the max
|
||||
for (RGBLike color : colors) {
|
||||
this.red += color.red();
|
||||
this.green += color.green();
|
||||
this.blue += color.blue();
|
||||
max += Math.max(Math.max(color.red(), color.green()), color.blue());
|
||||
}
|
||||
|
||||
// work out the averages
|
||||
float count = colors.length + 1;
|
||||
float averageRed = this.red / count;
|
||||
float averageGreen = this.green / count;
|
||||
float averageBlue = this.blue / count;
|
||||
float averageMax = max / count;
|
||||
|
||||
// work out the scale factor
|
||||
float maximumOfAverages = Math.max(Math.max(averageRed, averageGreen), averageBlue);
|
||||
float gainFactor = averageMax / maximumOfAverages;
|
||||
|
||||
// round and multiply
|
||||
this.red = Math.round(averageRed * gainFactor);
|
||||
this.blue = Math.round(averageBlue * gainFactor);
|
||||
this.green = Math.round(averageGreen * gainFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ChatColor representation of this color.
|
||||
*
|
||||
* @return the chat color
|
||||
* @deprecated ChatColor is deprecated and should not be used
|
||||
*/
|
||||
@Deprecated
|
||||
public ChatColor asLegacyChatColor() {
|
||||
return ChatColor.fromRGB((byte) red, (byte) blue, (byte) green);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Color color = (Color) o;
|
||||
return red == color.red && green == color.green && blue == color.blue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(red, green, blue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int red() {
|
||||
return this.red;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int green() {
|
||||
return this.green;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int blue() {
|
||||
return this.blue;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package net.minestom.server.color;
|
||||
|
||||
import net.kyori.adventure.util.RGBLike;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Color values for dyes, wool and cloth items.
|
||||
*/
|
||||
public enum DyeColor implements RGBLike {
|
||||
WHITE(new Color(0xF9FFFE), new Color(0xF0F0F0)),
|
||||
ORANGE(new Color(0xF9801D), new Color(0xEB8844)),
|
||||
MAGENTA(new Color(0xC74EBD), new Color(0xC354CD)),
|
||||
LIGHT_BLUE(new Color(0x3AB3DA), new Color(0x6689D3)),
|
||||
YELLOW(new Color(0xFED83D), new Color(0xDECF2A)),
|
||||
LIME(new Color(0x80C71F), new Color(0x41CD34)),
|
||||
PINK(new Color(0xF38BAA), new Color(0xD88198)),
|
||||
GRAY(new Color(0x474F52), new Color(0x434343)),
|
||||
LIGHT_GRAY(new Color(0x9D9D97), new Color(0xABABAB)),
|
||||
CYAN(new Color(0x169C9C), new Color(0x287697)),
|
||||
PURPLE(new Color(0x8932B8), new Color(0x7B2FBE)),
|
||||
BLUE(new Color(0x3C44AA), new Color(0x253192)),
|
||||
BROWN(new Color(0x835432), new Color(0x51301A)),
|
||||
GREEN(new Color(0x5E7C16), new Color(0x3B511A)),
|
||||
RED(new Color(0xB02E26), new Color(0xB3312C)),
|
||||
BLACK(new Color(0x1D1D21), new Color(0x1E1B1B));
|
||||
|
||||
private final Color color;
|
||||
private final Color firework;
|
||||
|
||||
DyeColor(Color color, Color firework) {
|
||||
this.color = color;
|
||||
this.firework = firework;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color that this dye represents.
|
||||
*
|
||||
* @return The {@link Color} that this dye represents
|
||||
*/
|
||||
@NotNull
|
||||
public Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the firework color that this dye represents.
|
||||
*
|
||||
* @return The {@link Color} that this dye represents
|
||||
*/
|
||||
@NotNull
|
||||
public Color getFireworkColor() {
|
||||
return this.firework;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int red() {
|
||||
return this.color.red();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int green() {
|
||||
return this.color.green();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int blue() {
|
||||
return this.color.blue();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.command;
|
||||
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.permission.PermissionHandler;
|
||||
|
@ -10,20 +12,26 @@ import org.jetbrains.annotations.NotNull;
|
|||
* <p>
|
||||
* Main implementations are {@link Player} and {@link ConsoleSender}.
|
||||
*/
|
||||
public interface CommandSender extends PermissionHandler {
|
||||
public interface CommandSender extends PermissionHandler, Audience {
|
||||
|
||||
/**
|
||||
* Sends a raw string message.
|
||||
*
|
||||
* @param message the message to send
|
||||
*
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
*/
|
||||
void sendMessage(@NotNull String message);
|
||||
@Deprecated
|
||||
default void sendMessage(@NotNull String message) { this.sendMessage(Component.text(message)); }
|
||||
|
||||
/**
|
||||
* Sends multiple raw string messages.
|
||||
*
|
||||
* @param messages the messages to send
|
||||
*
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
default void sendMessage(@NotNull String[] messages) {
|
||||
for (String message : messages) {
|
||||
sendMessage(message);
|
||||
|
@ -35,13 +43,12 @@ public interface CommandSender extends PermissionHandler {
|
|||
* If this is not a {@link Player}, only the content of the message will be sent as a string.
|
||||
*
|
||||
* @param text The {@link JsonMessage} to send.
|
||||
*
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
* */
|
||||
@Deprecated
|
||||
default void sendMessage(@NotNull JsonMessage text) {
|
||||
if (this instanceof Player) {
|
||||
this.sendMessage(text);
|
||||
} else {
|
||||
sendMessage(text.getRawMessage());
|
||||
}
|
||||
this.sendMessage(text.asComponent());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package net.minestom.server.command;
|
||||
|
||||
import net.kyori.adventure.audience.MessageType;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainComponentSerializer;
|
||||
import net.minestom.server.permission.Permission;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -18,8 +22,9 @@ public class ConsoleSender implements CommandSender {
|
|||
private final Set<Permission> permissions = new CopyOnWriteArraySet<>();
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull String message) {
|
||||
LOGGER.info(message);
|
||||
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||
// we don't use the serializer here as we just need the plain text of the message
|
||||
LOGGER.info(PlainComponentSerializer.plain().serialize(message));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.minestom.server.command;
|
||||
|
||||
import net.minestom.server.command.builder.CommandContext;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.minestom.server.command.builder.Arguments;
|
||||
import net.minestom.server.permission.Permission;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -11,18 +13,14 @@ import java.util.Set;
|
|||
/**
|
||||
* Sender used in {@link CommandManager#executeServerCommand(String)}.
|
||||
* <p>
|
||||
* Be aware that {@link #sendMessage(String)} is empty on purpose because the purpose
|
||||
* of this sender is to process the data of {@link CommandContext#getReturnData()}.
|
||||
* Although this class implemented {@link CommandSender} and thus {@link Audience}, no
|
||||
* data can be sent to this sender because it's purpose is to process the data of
|
||||
* {@link CommandContext#getReturnData()}.
|
||||
*/
|
||||
public class ServerSender implements CommandSender {
|
||||
|
||||
private final Set<Permission> permissions = Collections.unmodifiableSet(new HashSet<>());
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull String message) {
|
||||
// Empty on purpose
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Permission> getAllPermissions() {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
|
@ -8,11 +10,12 @@ import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Represents an argument which will give you a {@link ChatColor}.
|
||||
* Represents an argument which will give you a {@link Style} containing the colour or no
|
||||
* colour if the argument was {@code reset}.
|
||||
* <p>
|
||||
* Example: red, white, reset
|
||||
*/
|
||||
public class ArgumentColor extends Argument<ChatColor> {
|
||||
public class ArgumentColor extends Argument<Style> {
|
||||
|
||||
public static final int UNDEFINED_COLOR = -2;
|
||||
|
||||
|
@ -22,12 +25,21 @@ public class ArgumentColor extends Argument<ChatColor> {
|
|||
|
||||
@NotNull
|
||||
@Override
|
||||
public ChatColor parse(@NotNull String input) throws ArgumentSyntaxException {
|
||||
final ChatColor color = ChatColor.fromName(input);
|
||||
if (color == ChatColor.NO_COLOR)
|
||||
throw new ArgumentSyntaxException("Undefined color", input, UNDEFINED_COLOR);
|
||||
public Style parse(@NotNull String input) throws ArgumentSyntaxException {
|
||||
String uppercaseInput = input.toUpperCase();
|
||||
|
||||
return color;
|
||||
// check for colour
|
||||
NamedTextColor color = NamedTextColor.NAMES.value(uppercaseInput);
|
||||
if (color != null) {
|
||||
return Style.style(color);
|
||||
}
|
||||
|
||||
// check for reset
|
||||
if (uppercaseInput.equals("RESET")) {
|
||||
return Style.empty();
|
||||
}
|
||||
|
||||
throw new ArgumentSyntaxException("Undefined color", input, UNDEFINED_COLOR);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
package net.minestom.server.command.builder.arguments.minecraft;
|
||||
|
||||
import com.google.gson.JsonParseException;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.command.builder.NodeMaker;
|
||||
import net.minestom.server.command.builder.arguments.Argument;
|
||||
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
|
||||
import net.minestom.server.network.packet.server.play.DeclareCommandsPacket;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ArgumentComponent extends Argument<JsonMessage> {
|
||||
public class ArgumentComponent extends Argument<Component> {
|
||||
|
||||
public static final int INVALID_JSON_ERROR = 1;
|
||||
|
||||
|
@ -18,9 +19,9 @@ public class ArgumentComponent extends Argument<JsonMessage> {
|
|||
|
||||
@NotNull
|
||||
@Override
|
||||
public JsonMessage parse(@NotNull String input) throws ArgumentSyntaxException {
|
||||
public Component parse(@NotNull String input) throws ArgumentSyntaxException {
|
||||
try {
|
||||
return new JsonMessage.RawJsonMessage(input);
|
||||
return GsonComponentSerializer.gson().deserialize(input);
|
||||
} catch (JsonParseException e) {
|
||||
throw new ArgumentSyntaxException("Invalid JSON", input, INVALID_JSON_ERROR);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.command.builder.suggestion;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
@ -7,15 +8,25 @@ import org.jetbrains.annotations.Nullable;
|
|||
public class SuggestionEntry {
|
||||
|
||||
private final String entry;
|
||||
private final JsonMessage tooltip;
|
||||
private final Component tooltip;
|
||||
|
||||
/**
|
||||
* @deprecated Use {{@link #SuggestionEntry(String, JsonMessage)}}
|
||||
*/
|
||||
@Deprecated
|
||||
public SuggestionEntry(@NotNull String entry, @Nullable JsonMessage tooltip) {
|
||||
this.entry = entry;
|
||||
this.tooltip = tooltip;
|
||||
this.tooltip = tooltip.asComponent();
|
||||
}
|
||||
|
||||
public SuggestionEntry(@NotNull String entry, @Nullable Component tooltip) {
|
||||
this.entry = entry;
|
||||
this.tooltip = tooltip.asComponent();
|
||||
}
|
||||
|
||||
public SuggestionEntry(@NotNull String entry) {
|
||||
this(entry, null);
|
||||
this.entry = entry;
|
||||
this.tooltip = null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
@ -24,7 +35,16 @@ public class SuggestionEntry {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public JsonMessage getTooltip() {
|
||||
public Component getTooltip() {
|
||||
return tooltip;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getTooltip()}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public JsonMessage getTooltipJson() {
|
||||
return JsonMessage.fromComponent(tooltip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
|
||||
import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.Viewable;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
|
@ -46,13 +50,14 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Could be a player, a monster, or an object.
|
||||
* <p>
|
||||
* To create your own entity you probably want to extends {@link LivingEntity} or {@link EntityCreature} instead.
|
||||
*/
|
||||
public class Entity implements Viewable, EventHandler, DataContainer, PermissionHandler {
|
||||
public class Entity implements Viewable, EventHandler, DataContainer, PermissionHandler, HoverEventSource<ShowEntity> {
|
||||
|
||||
private static final Map<Integer, Entity> entityById = new ConcurrentHashMap<>();
|
||||
private static final Map<UUID, Entity> entityByUuid = new ConcurrentHashMap<>();
|
||||
|
@ -1189,13 +1194,25 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission
|
|||
this.entityMeta.setPose(pose);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity custom name.
|
||||
*
|
||||
* @return the custom name of the entity, null if there is not
|
||||
* @deprecated Use {@link #getCustomName()}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public JsonMessage getCustomNameJson() {
|
||||
return this.entityMeta.getCustomNameJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity custom name.
|
||||
*
|
||||
* @return the custom name of the entity, null if there is not
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage getCustomName() {
|
||||
public Component getCustomName() {
|
||||
return this.entityMeta.getCustomName();
|
||||
}
|
||||
|
||||
|
@ -1203,11 +1220,22 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission
|
|||
* Changes the entity custom name.
|
||||
*
|
||||
* @param customName the custom name of the entity, null to remove it
|
||||
* @deprecated Use {@link #setCustomName(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setCustomName(@Nullable JsonMessage customName) {
|
||||
this.entityMeta.setCustomName(customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the entity custom name.
|
||||
*
|
||||
* @param customName the custom name of the entity, null to remove it
|
||||
*/
|
||||
public void setCustomName(@Nullable Component customName) {
|
||||
this.entityMeta.setCustomName(customName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the custom name visible metadata field.
|
||||
*
|
||||
|
@ -1504,6 +1532,11 @@ public class Entity implements Viewable, EventHandler, DataContainer, Permission
|
|||
this.customSynchronizationCooldown = cooldown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HoverEvent<ShowEntity> asHoverEvent(@NotNull UnaryOperator<ShowEntity> op) {
|
||||
return HoverEvent.showEntity(ShowEntity.of(this.entityType, this.uuid));
|
||||
}
|
||||
|
||||
private UpdateOption getSynchronizationCooldown() {
|
||||
if (this.customSynchronizationCooldown != null) {
|
||||
return this.customSynchronizationCooldown;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import net.kyori.adventure.sound.Sound.Source;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.AttributeInstance;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
|
@ -19,8 +20,7 @@ import net.minestom.server.network.ConnectionState;
|
|||
import net.minestom.server.network.packet.server.play.*;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.utils.BlockPosition;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.Vector;
|
||||
|
@ -386,14 +386,14 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
|||
setHealth(getHealth() - remainingDamage);
|
||||
|
||||
// play damage sound
|
||||
final Sound sound = type.getSound(this);
|
||||
final SoundEvent sound = type.getSound(this);
|
||||
if (sound != null) {
|
||||
SoundCategory soundCategory;
|
||||
Source soundCategory;
|
||||
if (this instanceof Player) {
|
||||
soundCategory = SoundCategory.PLAYERS;
|
||||
soundCategory = Source.PLAYER;
|
||||
} else {
|
||||
// TODO: separate living entity categories
|
||||
soundCategory = SoundCategory.HOSTILE;
|
||||
soundCategory = Source.HOSTILE;
|
||||
}
|
||||
|
||||
SoundEffectPacket damageSoundPacket =
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.play.EntityMetaDataPacket;
|
||||
|
@ -36,10 +38,12 @@ public class Metadata {
|
|||
return new Value<>(TYPE_STRING, value, writer -> writer.writeSizedString(value));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Value<JsonMessage> Chat(@NotNull JsonMessage value) {
|
||||
return new Value<>(TYPE_CHAT, value, writer -> writer.writeSizedString(value.toString()));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Value<JsonMessage> OptChat(@Nullable JsonMessage value) {
|
||||
return new Value<>(TYPE_OPTCHAT, value, writer -> {
|
||||
final boolean present = value != null;
|
||||
|
@ -50,6 +54,20 @@ public class Metadata {
|
|||
});
|
||||
}
|
||||
|
||||
public static Value<Component> Chat(@NotNull Component value) {
|
||||
return new Value<>(TYPE_CHAT, value, writer -> writer.writeSizedString(AdventureSerializer.serialize(value)));
|
||||
}
|
||||
|
||||
public static Value<Component> OptChat(@Nullable Component value) {
|
||||
return new Value<>(TYPE_OPTCHAT, value, writer -> {
|
||||
final boolean present = value != null;
|
||||
writer.writeBoolean(present);
|
||||
if (present) {
|
||||
writer.writeSizedString(AdventureSerializer.serialize(value));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static Value<ItemStack> Slot(@NotNull ItemStack value) {
|
||||
return new Value<>(TYPE_SLOT, value, writer -> writer.writeItemStack(value));
|
||||
}
|
||||
|
|
|
@ -1,14 +1,26 @@
|
|||
package net.minestom.server.entity;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import net.kyori.adventure.audience.MessageType;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.identity.Identified;
|
||||
import net.kyori.adventure.identity.Identity;
|
||||
import net.kyori.adventure.inventory.Book;
|
||||
import net.kyori.adventure.sound.SoundStop;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent.ShowEntity;
|
||||
import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.advancements.AdvancementTab;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.adventure.Localizable;
|
||||
import net.minestom.server.adventure.audience.Audiences;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.bossbar.BossBar;
|
||||
import net.minestom.server.chat.ChatParser;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.chat.RichMessage;
|
||||
import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.command.CommandSender;
|
||||
|
@ -45,7 +57,7 @@ import net.minestom.server.recipe.RecipeManager;
|
|||
import net.minestom.server.resourcepack.ResourcePack;
|
||||
import net.minestom.server.scoreboard.BelowNameTag;
|
||||
import net.minestom.server.scoreboard.Team;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.stat.PlayerStatistic;
|
||||
import net.minestom.server.utils.*;
|
||||
|
@ -67,6 +79,7 @@ import java.util.*;
|
|||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Those are the major actors of the server,
|
||||
|
@ -74,7 +87,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
* <p>
|
||||
* You can easily create your own implementation of this and use it with {@link ConnectionManager#setPlayerProvider(PlayerProvider)}.
|
||||
*/
|
||||
public class Player extends LivingEntity implements CommandSender {
|
||||
public class Player extends LivingEntity implements CommandSender, Localizable, HoverEventSource<ShowEntity>, Identified {
|
||||
|
||||
private long lastKeepAlive;
|
||||
private boolean answerKeepAlive;
|
||||
|
@ -85,7 +98,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
protected final Set<Entity> viewableEntities = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private int latency;
|
||||
private JsonMessage displayName;
|
||||
private Component displayName;
|
||||
private PlayerSkin skin;
|
||||
|
||||
private DimensionType dimensionType;
|
||||
|
@ -163,6 +176,9 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
// Tick related
|
||||
private final PlayerTickEvent playerTickEvent = new PlayerTickEvent(this);
|
||||
|
||||
// Adventure
|
||||
private Identity identity;
|
||||
|
||||
public Player(@NotNull UUID uuid, @NotNull String username, @NotNull PlayerConnection playerConnection) {
|
||||
super(EntityType.PLAYER, uuid);
|
||||
this.username = username;
|
||||
|
@ -187,6 +203,8 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
|
||||
// FakePlayer init its connection there
|
||||
playerConnectionInit();
|
||||
|
||||
this.identity = Identity.identity(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -464,15 +482,15 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
public void kill() {
|
||||
if (!isDead()) {
|
||||
|
||||
JsonMessage deathText;
|
||||
JsonMessage chatMessage;
|
||||
Component deathText;
|
||||
Component chatMessage;
|
||||
|
||||
// get death screen text to the killed player
|
||||
{
|
||||
if (lastDamageSource != null) {
|
||||
deathText = lastDamageSource.buildDeathScreenText(this);
|
||||
} else { // may happen if killed by the server without applying damage
|
||||
deathText = ColoredText.of("Killed by poor programming.");
|
||||
deathText = Component.text("Killed by poor programming.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -481,7 +499,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
if (lastDamageSource != null) {
|
||||
chatMessage = lastDamageSource.buildDeathMessage(this);
|
||||
} else { // may happen if killed by the server without applying damage
|
||||
chatMessage = ColoredText.of(getUsername() + " was killed by poor programming.");
|
||||
chatMessage = Component.text(getUsername() + " was killed by poor programming.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -500,7 +518,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
|
||||
// #buildDeathMessage can return null, check here
|
||||
if (chatMessage != null) {
|
||||
MinecraftServer.getConnectionManager().broadcastMessage(chatMessage);
|
||||
Audiences.audiences().players().sendMessage(chatMessage);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -552,14 +570,16 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
|
||||
// Boss bars cache
|
||||
{
|
||||
Set<BossBar> bossBars = BossBar.getBossBars(this);
|
||||
Set<net.minestom.server.bossbar.BossBar> bossBars = net.minestom.server.bossbar.BossBar.getBossBars(this);
|
||||
if (bossBars != null) {
|
||||
for (BossBar bossBar : bossBars) {
|
||||
for (net.minestom.server.bossbar.BossBar bossBar : bossBars) {
|
||||
bossBar.removeViewer(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MinecraftServer.getBossBarManager().removeAllBossBars(this);
|
||||
|
||||
// Advancement tabs cache
|
||||
{
|
||||
Set<AdvancementTab> advancementTabs = AdvancementTab.getTabs(this);
|
||||
|
@ -755,27 +775,15 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
sendPluginMessage(channel, bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull String message) {
|
||||
sendMessage(ColoredText.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to the player.
|
||||
*
|
||||
* @param message the message to send,
|
||||
* you can use {@link ColoredText} and/or {@link RichMessage} to create it easily
|
||||
*/
|
||||
public void sendMessage(@NotNull JsonMessage message) {
|
||||
sendJsonMessage(message.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a legacy message with the specified color char.
|
||||
*
|
||||
* @param text the text with the legacy color formatting
|
||||
* @param colorChar the color character
|
||||
*
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendLegacyMessage(@NotNull String text, char colorChar) {
|
||||
ColoredText coloredText = ColoredText.ofLegacy(text, colorChar);
|
||||
sendJsonMessage(coloredText.toString());
|
||||
|
@ -785,15 +793,26 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* Sends a legacy message with the default color char {@link ChatParser#COLOR_CHAR}.
|
||||
*
|
||||
* @param text the text with the legacy color formatting
|
||||
*
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendLegacyMessage(@NotNull String text) {
|
||||
ColoredText coloredText = ColoredText.ofLegacy(text, ChatParser.COLOR_CHAR);
|
||||
sendJsonMessage(coloredText.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #sendMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendJsonMessage(@NotNull String json) {
|
||||
ChatMessagePacket chatMessagePacket =
|
||||
new ChatMessagePacket(json, ChatMessagePacket.Position.CHAT);
|
||||
this.sendMessage(json);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(@NotNull Identity source, @NotNull Component message, @NotNull MessageType type) {
|
||||
ChatMessagePacket chatMessagePacket = new ChatMessagePacket(message, ChatMessagePacket.Position.fromMessageType(type), source.uuid());
|
||||
playerConnection.sendPacket(chatMessagePacket);
|
||||
}
|
||||
|
||||
|
@ -809,7 +828,7 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
}
|
||||
|
||||
/**
|
||||
* Plays a sound from the {@link Sound} enum.
|
||||
* Plays a sound from the {@link SoundEvent} enum.
|
||||
*
|
||||
* @param sound the sound to play
|
||||
* @param soundCategory the sound category
|
||||
|
@ -818,12 +837,13 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param z the effect Z
|
||||
* @param volume the volume of the sound (1 is 100%)
|
||||
* @param pitch the pitch of the sound, between 0.5 and 2.0
|
||||
* @deprecated Use {@link #playSound(net.kyori.adventure.sound.Sound, double, double, double)}
|
||||
*/
|
||||
public void playSound(@NotNull Sound sound, @NotNull SoundCategory soundCategory,
|
||||
int x, int y, int z, float volume, float pitch) {
|
||||
@Deprecated
|
||||
public void playSound(@NotNull SoundEvent sound, @NotNull SoundCategory soundCategory, int x, int y, int z, float volume, float pitch) {
|
||||
SoundEffectPacket soundEffectPacket = new SoundEffectPacket();
|
||||
soundEffectPacket.soundId = sound.getId();
|
||||
soundEffectPacket.soundCategory = soundCategory;
|
||||
soundEffectPacket.soundSource = soundCategory.asSource();
|
||||
soundEffectPacket.x = x;
|
||||
soundEffectPacket.y = y;
|
||||
soundEffectPacket.z = z;
|
||||
|
@ -833,12 +853,13 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
}
|
||||
|
||||
/**
|
||||
* Plays a sound from the {@link Sound} enum.
|
||||
* Plays a sound from the {@link SoundEvent} enum.
|
||||
*
|
||||
* @see #playSound(Sound, SoundCategory, int, int, int, float, float)
|
||||
* @see #playSound(SoundEvent, SoundCategory, int, int, int, float, float)
|
||||
* @deprecated Use {@link #playSound(net.kyori.adventure.sound.Sound, double, double, double)}
|
||||
*/
|
||||
public void playSound(@NotNull Sound sound, @NotNull SoundCategory soundCategory,
|
||||
BlockPosition position, float volume, float pitch) {
|
||||
@Deprecated
|
||||
public void playSound(@NotNull SoundEvent sound, @NotNull SoundCategory soundCategory, BlockPosition position, float volume, float pitch) {
|
||||
playSound(sound, soundCategory, position.getX(), position.getY(), position.getZ(), volume, pitch);
|
||||
}
|
||||
|
||||
|
@ -852,12 +873,13 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param z the effect Z
|
||||
* @param volume the volume of the sound (1 is 100%)
|
||||
* @param pitch the pitch of the sound, between 0.5 and 2.0
|
||||
* @deprecated Use {@link #playSound(net.kyori.adventure.sound.Sound, double, double, double)}
|
||||
*/
|
||||
public void playSound(@NotNull String identifier, @NotNull SoundCategory soundCategory,
|
||||
int x, int y, int z, float volume, float pitch) {
|
||||
@Deprecated
|
||||
public void playSound(@NotNull String identifier, @NotNull SoundCategory soundCategory, int x, int y, int z, float volume, float pitch) {
|
||||
NamedSoundEffectPacket namedSoundEffectPacket = new NamedSoundEffectPacket();
|
||||
namedSoundEffectPacket.soundName = identifier;
|
||||
namedSoundEffectPacket.soundCategory = soundCategory;
|
||||
namedSoundEffectPacket.soundSource = soundCategory.asSource();
|
||||
namedSoundEffectPacket.x = x;
|
||||
namedSoundEffectPacket.y = y;
|
||||
namedSoundEffectPacket.z = z;
|
||||
|
@ -870,7 +892,9 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* Plays a sound from an identifier (represents a custom sound in a resource pack).
|
||||
*
|
||||
* @see #playSound(String, SoundCategory, int, int, int, float, float)
|
||||
* @deprecated Use {@link #playSound(net.kyori.adventure.sound.Sound, double, double, double)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void playSound(@NotNull String identifier, @NotNull SoundCategory soundCategory, BlockPosition position, float volume, float pitch) {
|
||||
playSound(identifier, soundCategory, position.getX(), position.getY(), position.getZ(), volume, pitch);
|
||||
}
|
||||
|
@ -882,17 +906,34 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param soundCategory the sound category
|
||||
* @param volume the volume of the sound (1 is 100%)
|
||||
* @param pitch the pitch of the sound, between 0.5 and 2.0
|
||||
* @deprecated Use {@link #playSound(net.kyori.adventure.sound.Sound)}
|
||||
*/
|
||||
public void playSound(@NotNull Sound sound, @NotNull SoundCategory soundCategory, float volume, float pitch) {
|
||||
@Deprecated
|
||||
public void playSound(@NotNull SoundEvent sound, @NotNull SoundCategory soundCategory, float volume, float pitch) {
|
||||
EntitySoundEffectPacket entitySoundEffectPacket = new EntitySoundEffectPacket();
|
||||
entitySoundEffectPacket.entityId = getEntityId();
|
||||
entitySoundEffectPacket.soundId = sound.getId();
|
||||
entitySoundEffectPacket.soundCategory = soundCategory;
|
||||
entitySoundEffectPacket.soundSource = soundCategory.asSource();
|
||||
entitySoundEffectPacket.volume = volume;
|
||||
entitySoundEffectPacket.pitch = pitch;
|
||||
playerConnection.sendPacket(entitySoundEffectPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(net.kyori.adventure.sound.@NotNull Sound sound) {
|
||||
this.playSound(sound, this.position.getX(), this.position.getY(), this.position.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(net.kyori.adventure.sound.@NotNull Sound sound, double x, double y, double z) {
|
||||
playerConnection.sendPacket(AdventurePacketConvertor.createSoundPacket(sound, x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(@NotNull SoundStop stop) {
|
||||
playerConnection.sendPacket(AdventurePacketConvertor.createSoundStopPacket(stop));
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a given effect at the given position for this player.
|
||||
*
|
||||
|
@ -914,7 +955,9 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
|
||||
/**
|
||||
* Sends a {@link StopSoundPacket} packet.
|
||||
* @deprecated Use {@link #stopSound(SoundStop)} with {@link SoundStop#all()}
|
||||
*/
|
||||
@Deprecated
|
||||
public void stopSound() {
|
||||
StopSoundPacket stopSoundPacket = new StopSoundPacket();
|
||||
stopSoundPacket.flags = 0x00;
|
||||
|
@ -926,13 +969,19 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
*
|
||||
* @param header the header text, null to set empty
|
||||
* @param footer the footer text, null to set empty
|
||||
*
|
||||
* @deprecated Use {@link #sendPlayerListHeaderAndFooter(Component, Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendHeaderFooter(@Nullable JsonMessage header, @Nullable JsonMessage footer) {
|
||||
PlayerListHeaderAndFooterPacket playerListHeaderAndFooterPacket = new PlayerListHeaderAndFooterPacket();
|
||||
playerListHeaderAndFooterPacket.header = header;
|
||||
playerListHeaderAndFooterPacket.footer = footer;
|
||||
this.sendPlayerListHeaderAndFooter(header == null ? Component.empty() : header.asComponent(),
|
||||
footer == null ? Component.empty() : footer.asComponent());
|
||||
}
|
||||
|
||||
playerConnection.sendPacket(playerListHeaderAndFooterPacket);
|
||||
@Override
|
||||
public void sendPlayerListHeaderAndFooter(@NotNull Component header, @NotNull Component footer) {
|
||||
PlayerListHeaderAndFooterPacket packet = new PlayerListHeaderAndFooterPacket(header, footer);
|
||||
playerConnection.sendPacket(packet);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -941,25 +990,12 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param text the text of the title
|
||||
* @param action the action of the title (where to show it)
|
||||
* @see #sendTitleTime(int, int, int) to specify the display time
|
||||
*
|
||||
* @deprecated Use {@link #showTitle(Title)} and {@link #sendActionBar(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
private void sendTitle(@NotNull JsonMessage text, @NotNull TitlePacket.Action action) {
|
||||
TitlePacket titlePacket = new TitlePacket();
|
||||
titlePacket.action = action;
|
||||
|
||||
switch (action) {
|
||||
case SET_TITLE:
|
||||
titlePacket.titleText = text;
|
||||
break;
|
||||
case SET_SUBTITLE:
|
||||
titlePacket.subtitleText = text;
|
||||
break;
|
||||
case SET_ACTION_BAR:
|
||||
titlePacket.actionBarText = text;
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException("Invalid TitlePacket.Action type!");
|
||||
}
|
||||
|
||||
TitlePacket titlePacket = new TitlePacket(action, text.asComponent());
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
|
@ -969,10 +1005,12 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param title the title message
|
||||
* @param subtitle the subtitle message
|
||||
* @see #sendTitleTime(int, int, int) to specify the display time
|
||||
*
|
||||
* @deprecated Use {@link #showTitle(Title)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendTitleSubtitleMessage(@NotNull JsonMessage title, @NotNull JsonMessage subtitle) {
|
||||
sendTitle(title, TitlePacket.Action.SET_TITLE);
|
||||
sendTitle(subtitle, TitlePacket.Action.SET_SUBTITLE);
|
||||
this.showTitle(Title.title(title.asComponent(), subtitle.asComponent()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -980,9 +1018,12 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
*
|
||||
* @param title the title message
|
||||
* @see #sendTitleTime(int, int, int) to specify the display time
|
||||
*
|
||||
* @deprecated Use {@link #showTitle(Title)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendTitleMessage(@NotNull JsonMessage title) {
|
||||
sendTitle(title, TitlePacket.Action.SET_TITLE);
|
||||
this.showTitle(Title.title(title.asComponent(), Component.empty()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -990,9 +1031,12 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
*
|
||||
* @param subtitle the subtitle message
|
||||
* @see #sendTitleTime(int, int, int) to specify the display time
|
||||
*
|
||||
* @deprecated Use {@link #showTitle(Title)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendSubtitleMessage(@NotNull JsonMessage subtitle) {
|
||||
sendTitle(subtitle, TitlePacket.Action.SET_SUBTITLE);
|
||||
this.showTitle(Title.title(Component.empty(), subtitle.asComponent()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1000,9 +1044,27 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
*
|
||||
* @param actionBar the action bar message
|
||||
* @see #sendTitleTime(int, int, int) to specify the display time
|
||||
*
|
||||
* @deprecated Use {@link #sendActionBar(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendActionBarMessage(@NotNull JsonMessage actionBar) {
|
||||
sendTitle(actionBar, TitlePacket.Action.SET_ACTION_BAR);
|
||||
this.sendActionBar(actionBar.asComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showTitle(@NotNull Title title) {
|
||||
Collection<TitlePacket> packet = TitlePacket.of(Title.title(title.title(), title.subtitle(), title.times()));
|
||||
|
||||
for (TitlePacket titlePacket : packet) {
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(@NotNull Component message) {
|
||||
TitlePacket titlePacket = new TitlePacket(TitlePacket.Action.SET_ACTION_BAR, message);
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1011,39 +1073,56 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* @param fadeIn ticks to spend fading in
|
||||
* @param stay ticks to keep the title displayed
|
||||
* @param fadeOut ticks to spend out, not when to start fading out
|
||||
*
|
||||
* @deprecated Use {@link #showTitle(Title)}. Note that this will overwrite the
|
||||
* existing title. This is expected behavior and will be the case in 1.17.
|
||||
*/
|
||||
@Deprecated
|
||||
public void sendTitleTime(int fadeIn, int stay, int fadeOut) {
|
||||
TitlePacket titlePacket = new TitlePacket();
|
||||
titlePacket.action = TitlePacket.Action.SET_TIMES_AND_DISPLAY;
|
||||
titlePacket.fadeIn = fadeIn;
|
||||
titlePacket.stay = stay;
|
||||
titlePacket.fadeOut = fadeOut;
|
||||
TitlePacket titlePacket = new TitlePacket(fadeIn, stay, fadeOut);
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides the previous title.
|
||||
* @deprecated Use {@link #clearTitle()}
|
||||
*/
|
||||
@Deprecated
|
||||
public void hideTitle() {
|
||||
TitlePacket titlePacket = new TitlePacket();
|
||||
titlePacket.action = TitlePacket.Action.HIDE;
|
||||
TitlePacket titlePacket = new TitlePacket(TitlePacket.Action.HIDE);
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the previous title.
|
||||
*/
|
||||
@Override
|
||||
public void resetTitle() {
|
||||
TitlePacket titlePacket = new TitlePacket();
|
||||
titlePacket.action = TitlePacket.Action.RESET;
|
||||
TitlePacket titlePacket = new TitlePacket(TitlePacket.Action.RESET);
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearTitle() {
|
||||
TitlePacket titlePacket = new TitlePacket(TitlePacket.Action.HIDE);
|
||||
playerConnection.sendPacket(titlePacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showBossBar(@NotNull BossBar bar) {
|
||||
MinecraftServer.getBossBarManager().addBossBar(this, bar);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideBossBar(@NotNull BossBar bar) {
|
||||
MinecraftServer.getBossBarManager().removeBossBar(this, bar);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a book ui for the player with the given book metadata.
|
||||
*
|
||||
* @param bookMeta The metadata of the book to open
|
||||
*
|
||||
* @deprecated Use {@link #openBook(Book)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void openBook(@NotNull WrittenBookMeta bookMeta) {
|
||||
// Set book in offhand
|
||||
final ItemStack writtenBook = new ItemStack(Material.WRITTEN_BOOK, (byte) 1);
|
||||
|
@ -1063,6 +1142,32 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
this.inventory.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openBook(@NotNull Book book) {
|
||||
// make the book
|
||||
ItemStack writtenBook = new ItemStack(Material.WRITTEN_BOOK, (byte) 1);
|
||||
writtenBook.setItemMeta(WrittenBookMeta.fromAdventure(book, this));
|
||||
|
||||
// Set book in offhand
|
||||
SetSlotPacket setBookPacket = new SetSlotPacket();
|
||||
setBookPacket.windowId = 0;
|
||||
setBookPacket.slot = 45;
|
||||
setBookPacket.itemStack = writtenBook;
|
||||
playerConnection.sendPacket(setBookPacket);
|
||||
|
||||
// Open the book
|
||||
OpenBookPacket openBookPacket = new OpenBookPacket();
|
||||
openBookPacket.hand = Hand.OFF;
|
||||
playerConnection.sendPacket(openBookPacket);
|
||||
|
||||
// Restore the item in offhand
|
||||
SetSlotPacket restoreItemPacket = new SetSlotPacket();
|
||||
restoreItemPacket.windowId = 0;
|
||||
restoreItemPacket.slot = 45;
|
||||
restoreItemPacket.itemStack = getItemInOffHand();
|
||||
playerConnection.sendPacket(restoreItemPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isImmune(@NotNull DamageType type) {
|
||||
if (!getGameMode().canTakeDamage()) {
|
||||
|
@ -1165,9 +1270,21 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* Gets the player display name in the tab-list.
|
||||
*
|
||||
* @return the player display name, null means that {@link #getUsername()} is displayed
|
||||
* @deprecated Use {@link #getDisplayName()}
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage getDisplayName() {
|
||||
@Deprecated
|
||||
public JsonMessage getDisplayNameJson() {
|
||||
return JsonMessage.fromComponent(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player display name in the tab-list.
|
||||
*
|
||||
* @return the player display name, null means that {@link #getUsername()} is displayed
|
||||
*/
|
||||
@Nullable
|
||||
public Component getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
|
@ -1177,8 +1294,21 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* Sets to null to show the player username.
|
||||
*
|
||||
* @param displayName the display name, null to display the username
|
||||
* @deprecated Use {@link #setDisplayName(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDisplayName(@Nullable JsonMessage displayName) {
|
||||
this.setDisplayName(displayName == null ? null : displayName.asComponent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the player display name in the tab-list.
|
||||
* <p>
|
||||
* Sets to null to show the player username.
|
||||
*
|
||||
* @param displayName the display name, null to display the username
|
||||
*/
|
||||
public void setDisplayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName;
|
||||
|
||||
PlayerInfoPacket infoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME);
|
||||
|
@ -1730,16 +1860,40 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
* Kicks the player with a reason.
|
||||
*
|
||||
* @param text the kick reason
|
||||
*
|
||||
* @deprecated Use {@link #kick(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void kick(@NotNull JsonMessage text) {
|
||||
this.kick(text.asComponent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the player with a reason.
|
||||
*
|
||||
* @param message the kick reason
|
||||
*
|
||||
* @deprecated Use {@link #kick(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void kick(@NotNull String message) {
|
||||
this.kick(Component.text(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the player with a reason.
|
||||
*
|
||||
* @param component the reason
|
||||
*/
|
||||
public void kick(@NotNull Component component) {
|
||||
final ConnectionState connectionState = playerConnection.getConnectionState();
|
||||
|
||||
// Packet type depends on the current player connection state
|
||||
final ServerPacket disconnectPacket;
|
||||
if (connectionState == ConnectionState.LOGIN) {
|
||||
disconnectPacket = new LoginDisconnectPacket(text);
|
||||
disconnectPacket = new LoginDisconnectPacket(component);
|
||||
} else {
|
||||
disconnectPacket = new DisconnectPacket(text);
|
||||
disconnectPacket = new DisconnectPacket(component);
|
||||
}
|
||||
|
||||
if (playerConnection instanceof NettyPlayerConnection) {
|
||||
|
@ -1751,15 +1905,6 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the player with a reason.
|
||||
*
|
||||
* @param message the kick reason
|
||||
*/
|
||||
public void kick(@NotNull String message) {
|
||||
kick(ColoredText.of(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the current held slot for the player.
|
||||
*
|
||||
|
@ -2362,6 +2507,11 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
return lastKeepAlive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HoverEvent<ShowEntity> asHoverEvent(@NotNull UnaryOperator<ShowEntity> op) {
|
||||
return HoverEvent.showEntity(ShowEntity.of(EntityType.PLAYER, this.uuid, this.displayName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packet to add the player from the tab-list.
|
||||
*
|
||||
|
@ -2501,6 +2651,34 @@ public class Player extends LivingEntity implements CommandSender {
|
|||
inventory.setBoots(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return settings.locale == null ? null : Locale.forLanguageTag(settings.locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's locale. This will only set the locale of the player as it
|
||||
* is stored in the server. This will also be reset if the settings are refreshed.
|
||||
*
|
||||
* @param locale the new locale
|
||||
*/
|
||||
@Override
|
||||
public void setLocale(@Nullable Locale locale) {
|
||||
settings.locale = locale == null ? null : locale.toLanguageTag();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Identity identity() {
|
||||
return this.identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUuid(@NotNull UUID uuid) {
|
||||
super.setUuid(uuid);
|
||||
// update identity
|
||||
this.identity = Identity.identity(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the main or off hand of the player.
|
||||
*/
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package net.minestom.server.entity.damage;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.chat.RichMessage;
|
||||
|
@ -8,7 +11,7 @@ import net.minestom.server.data.DataContainer;
|
|||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
@ -26,8 +29,8 @@ public class DamageType implements DataContainer {
|
|||
public static final DamageType GRAVITY = new DamageType("attack.fall");
|
||||
public static final DamageType ON_FIRE = new DamageType("attack.onFire") {
|
||||
@Override
|
||||
protected Sound getPlayerSound(@NotNull Player player) {
|
||||
return Sound.ENTITY_PLAYER_HURT_ON_FIRE;
|
||||
protected SoundEvent getPlayerSound(@NotNull Player player) {
|
||||
return SoundEvent.ENTITY_PLAYER_HURT_ON_FIRE;
|
||||
}
|
||||
};
|
||||
private final String identifier;
|
||||
|
@ -55,18 +58,25 @@ public class DamageType implements DataContainer {
|
|||
return identifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #buildDeathMessage(Player)}
|
||||
*/
|
||||
@Deprecated
|
||||
public JsonMessage buildDeathMessageJson(@NotNull Player killed) {
|
||||
return JsonMessage.fromComponent(this.buildDeathMessage(killed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the death message linked to this damage type.
|
||||
* <p>
|
||||
* Used in {@link Player#kill()} to broadcast the proper message.
|
||||
*
|
||||
* @param killed the player who has been killed
|
||||
* @return the death message, null to do not send anything.
|
||||
* Can be for instance, of type {@link ColoredText} or {@link RichMessage}.
|
||||
* @return the death message, null to do not send anything
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage buildDeathMessage(@NotNull Player killed) {
|
||||
return ColoredText.of("{@death." + identifier + "," + killed.getUsername() + "}");
|
||||
public Component buildDeathMessage(@NotNull Player killed) {
|
||||
return Component.translatable("death." + identifier, Component.text(killed.getUsername()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,15 +113,23 @@ public class DamageType implements DataContainer {
|
|||
return new EntityDamage(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #buildDeathScreenText(Player)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public JsonMessage buildDeathScreenTextJson(@NotNull Player killed) {
|
||||
return JsonMessage.fromComponent(this.buildDeathScreenText(killed));
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the text sent to a player in his death screen.
|
||||
*
|
||||
* @param killed the player who has been killed
|
||||
* @return the death screen text, null to do not send anything
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage buildDeathScreenText(@NotNull Player killed) {
|
||||
return ColoredText.of("{@death." + identifier + "}");
|
||||
public Component buildDeathScreenText(@NotNull Player killed) {
|
||||
return Component.translatable("death." + identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,19 +139,19 @@ public class DamageType implements DataContainer {
|
|||
* @return the sound to play when the given entity is hurt by this damage type. Can be null if no sound should play
|
||||
*/
|
||||
@Nullable
|
||||
public Sound getSound(@NotNull LivingEntity entity) {
|
||||
public SoundEvent getSound(@NotNull LivingEntity entity) {
|
||||
if (entity instanceof Player) {
|
||||
return getPlayerSound((Player) entity);
|
||||
}
|
||||
return getGenericSound(entity);
|
||||
}
|
||||
|
||||
protected Sound getGenericSound(@NotNull LivingEntity entity) {
|
||||
return Sound.ENTITY_GENERIC_HURT;
|
||||
protected SoundEvent getGenericSound(@NotNull LivingEntity entity) {
|
||||
return SoundEvent.ENTITY_GENERIC_HURT;
|
||||
}
|
||||
|
||||
protected Sound getPlayerSound(@NotNull Player player) {
|
||||
return Sound.ENTITY_PLAYER_HURT;
|
||||
protected SoundEvent getPlayerSound(@NotNull Player player) {
|
||||
return SoundEvent.ENTITY_PLAYER_HURT;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.entity.hologram;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.Viewable;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
|
@ -13,7 +14,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents an invisible armor stand showing a {@link JsonMessage}.
|
||||
* Represents an invisible armor stand showing a {@link Component}.
|
||||
*/
|
||||
public class Hologram implements Viewable {
|
||||
|
||||
|
@ -22,7 +23,7 @@ public class Hologram implements Viewable {
|
|||
private final HologramEntity entity;
|
||||
|
||||
private Position position;
|
||||
private JsonMessage text;
|
||||
private Component text;
|
||||
|
||||
private boolean removed;
|
||||
|
||||
|
@ -33,14 +34,24 @@ public class Hologram implements Viewable {
|
|||
* @param spawnPosition The spawn position of this hologram.
|
||||
* @param text The text of this hologram.
|
||||
* @param autoViewable {@code true}if the hologram should be visible automatically, otherwise {@code false}.
|
||||
* @deprecated Use {@link #Hologram(Instance, Position, Component, boolean)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Hologram(Instance instance, Position spawnPosition, JsonMessage text, boolean autoViewable) {
|
||||
this.entity = new HologramEntity(spawnPosition.clone().add(0, OFFSET_Y, 0));
|
||||
this.entity.setInstance(instance);
|
||||
this.entity.setAutoViewable(autoViewable);
|
||||
this(instance, spawnPosition, text.asComponent(), autoViewable);
|
||||
}
|
||||
|
||||
this.position = spawnPosition;
|
||||
setText(text);
|
||||
/**
|
||||
* Constructs a new {@link Hologram} with the given parameters.
|
||||
*
|
||||
* @param instance The instance where the hologram should be spawned.
|
||||
* @param spawnPosition The spawn position of this hologram.
|
||||
* @param text The text of this hologram.
|
||||
* @deprecated Use {@link #Hologram(Instance, Position, Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Hologram(Instance instance, Position spawnPosition, JsonMessage text) {
|
||||
this(instance, spawnPosition, text, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,10 +61,27 @@ public class Hologram implements Viewable {
|
|||
* @param spawnPosition The spawn position of this hologram.
|
||||
* @param text The text of this hologram.
|
||||
*/
|
||||
public Hologram(Instance instance, Position spawnPosition, JsonMessage text) {
|
||||
public Hologram(Instance instance, Position spawnPosition, Component text) {
|
||||
this(instance, spawnPosition, text, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@link Hologram} with the given parameters.
|
||||
*
|
||||
* @param instance The instance where the hologram should be spawned.
|
||||
* @param spawnPosition The spawn position of this hologram.
|
||||
* @param text The text of this hologram.
|
||||
* @param autoViewable {@code true}if the hologram should be visible automatically, otherwise {@code false}.
|
||||
*/
|
||||
public Hologram(Instance instance, Position spawnPosition, Component text, boolean autoViewable) {
|
||||
this.entity = new HologramEntity(spawnPosition.clone().add(0, OFFSET_Y, 0));
|
||||
this.entity.setInstance(instance);
|
||||
this.entity.setAutoViewable(autoViewable);
|
||||
|
||||
this.position = spawnPosition;
|
||||
setText(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the position of the hologram.
|
||||
*
|
||||
|
@ -79,8 +107,19 @@ public class Hologram implements Viewable {
|
|||
* Gets the hologram text.
|
||||
*
|
||||
* @return the hologram text
|
||||
* @deprecated Use {@link #getText()}
|
||||
*/
|
||||
public JsonMessage getText() {
|
||||
@Deprecated
|
||||
public JsonMessage getTextJson() {
|
||||
return JsonMessage.fromComponent(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the hologram text.
|
||||
*
|
||||
* @return the hologram text
|
||||
*/
|
||||
public Component getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
|
@ -88,8 +127,19 @@ public class Hologram implements Viewable {
|
|||
* Changes the hologram text.
|
||||
*
|
||||
* @param text the new hologram text
|
||||
* @deprecated Use {@link #setText(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setText(JsonMessage text) {
|
||||
this.setText(text.asComponent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the hologram text.
|
||||
*
|
||||
* @param text the new hologram text
|
||||
*/
|
||||
public void setText(Component text) {
|
||||
checkRemoved();
|
||||
this.text = text;
|
||||
this.entity.setCustomName(text);
|
||||
|
@ -166,7 +216,7 @@ public class Hologram implements Viewable {
|
|||
setSmall(true);
|
||||
|
||||
setNoGravity(true);
|
||||
setCustomName(ColoredText.of(""));
|
||||
setCustomName(Component.empty());
|
||||
setCustomNameVisible(true);
|
||||
setInvisible(true);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.entity.metadata;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Metadata;
|
||||
|
@ -106,11 +107,29 @@ public class EntityMeta {
|
|||
this.metadata.setIndex((byte) 1, Metadata.VarInt(value));
|
||||
}
|
||||
|
||||
public JsonMessage getCustomName() {
|
||||
/**
|
||||
* @deprecated Use {@link #getCustomName()}
|
||||
*/
|
||||
@Deprecated
|
||||
public JsonMessage getCustomNameJson() {
|
||||
return JsonMessage.fromComponent(this.getCustomName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setCustomName(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setCustomName(JsonMessage value) {
|
||||
if (value != null) {
|
||||
this.setCustomName(value.asComponent());
|
||||
}
|
||||
}
|
||||
|
||||
public Component getCustomName() {
|
||||
return this.metadata.getIndex((byte) 2, null);
|
||||
}
|
||||
|
||||
public void setCustomName(JsonMessage value) {
|
||||
public void setCustomName(Component value) {
|
||||
this.metadata.setIndex((byte) 2, Metadata.OptChat(value));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.entity.metadata.minecart;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Entity;
|
||||
|
@ -21,12 +22,29 @@ public class CommandBlockMinecartMeta extends AbstractMinecartMeta {
|
|||
super.metadata.setIndex((byte) 13, Metadata.String(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getLastOutput()}
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
public JsonMessage getLastOutput() {
|
||||
return super.metadata.getIndex((byte) 14, ColoredText.of(""));
|
||||
public JsonMessage getLastOutputJson() {
|
||||
return JsonMessage.fromComponent(getLastOutput());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Component getLastOutput() {
|
||||
return super.metadata.getIndex((byte) 14, Component.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #setLastOutput(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setLastOutput(@NotNull JsonMessage value) {
|
||||
this.setLastOutput(value.asComponent());
|
||||
}
|
||||
|
||||
public void setLastOutput(@NotNull Component value) {
|
||||
super.metadata.setIndex((byte) 14, Metadata.Chat(value));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.minestom.server.event.player;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.CancellableEvent;
|
||||
|
@ -19,7 +20,7 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent {
|
|||
|
||||
private final Collection<Player> recipients;
|
||||
private String message;
|
||||
private Function<PlayerChatEvent, JsonMessage> chatFormat;
|
||||
private Function<PlayerChatEvent, Component> chatFormat;
|
||||
|
||||
private boolean cancelled;
|
||||
|
||||
|
@ -33,8 +34,19 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent {
|
|||
* Changes the chat format.
|
||||
*
|
||||
* @param chatFormat the custom chat format, null to use the default one
|
||||
* @deprecated Use {@link #setChatFormat(Function)}
|
||||
*/
|
||||
public void setChatFormat(@Nullable Function<PlayerChatEvent, JsonMessage> chatFormat) {
|
||||
@Deprecated
|
||||
public void setChatFormatJson(@Nullable Function<PlayerChatEvent, JsonMessage> chatFormat) {
|
||||
this.chatFormat = chatFormat == null ? null : chatFormat.andThen(JsonMessage::asComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the chat format.
|
||||
*
|
||||
* @param chatFormat the custom chat format, null to use the default one
|
||||
*/
|
||||
public void setChatFormat(@Nullable Function<PlayerChatEvent, Component> chatFormat) {
|
||||
this.chatFormat = chatFormat;
|
||||
}
|
||||
|
||||
|
@ -77,7 +89,7 @@ public class PlayerChatEvent extends PlayerEvent implements CancellableEvent {
|
|||
* @return the chat format which will be used, null if this is the default one
|
||||
*/
|
||||
@Nullable
|
||||
public Function<PlayerChatEvent, JsonMessage> getChatFormatFunction() {
|
||||
public Function<PlayerChatEvent, Component> getChatFormatFunction() {
|
||||
return chatFormat;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.server.event.player;
|
||||
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.PlayerEvent;
|
||||
|
@ -12,10 +13,18 @@ import org.jetbrains.annotations.Nullable;
|
|||
*/
|
||||
public class PlayerDeathEvent extends PlayerEvent {
|
||||
|
||||
private JsonMessage deathText;
|
||||
private JsonMessage chatMessage;
|
||||
private Component deathText;
|
||||
private Component chatMessage;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #PlayerDeathEvent(Player, Component, Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public PlayerDeathEvent(@NotNull Player player, JsonMessage deathText, JsonMessage chatMessage) {
|
||||
this(player, deathText.asComponent(), chatMessage.asComponent());
|
||||
}
|
||||
|
||||
public PlayerDeathEvent(@NotNull Player player, Component deathText, Component chatMessage) {
|
||||
super(player);
|
||||
this.deathText = deathText;
|
||||
this.chatMessage = chatMessage;
|
||||
|
@ -25,9 +34,21 @@ public class PlayerDeathEvent extends PlayerEvent {
|
|||
* Gets the text displayed in the death screen.
|
||||
*
|
||||
* @return the death text, can be null
|
||||
* @deprecated Use {@link #getDeathText()}
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage getDeathText() {
|
||||
@Deprecated
|
||||
public JsonMessage getDeathTextJson() {
|
||||
return JsonMessage.fromComponent(deathText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the text displayed in the death screen.
|
||||
*
|
||||
* @return the death text, can be null
|
||||
*/
|
||||
@Nullable
|
||||
public Component getDeathText() {
|
||||
return deathText;
|
||||
}
|
||||
|
||||
|
@ -35,18 +56,41 @@ public class PlayerDeathEvent extends PlayerEvent {
|
|||
* Changes the text displayed in the death screen.
|
||||
*
|
||||
* @param deathText the death text to display, null to remove
|
||||
* @deprecated Use {@link #setDeathText(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDeathText(@Nullable JsonMessage deathText) {
|
||||
this.deathText = deathText == null ? null : deathText.asComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the text displayed in the death screen.
|
||||
*
|
||||
* @param deathText the death text to display, null to remove
|
||||
*/
|
||||
public void setDeathText(@Nullable Component deathText) {
|
||||
this.deathText = deathText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message sent to chat.
|
||||
*
|
||||
* @return the death chat message
|
||||
* @deprecated Use {@link #getChatMessage()}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public JsonMessage getChatMessageJson() {
|
||||
return JsonMessage.fromComponent(chatMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message sent to chat.
|
||||
*
|
||||
* @return the death chat message
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage getChatMessage() {
|
||||
public Component getChatMessage() {
|
||||
return chatMessage;
|
||||
}
|
||||
|
||||
|
@ -54,8 +98,19 @@ public class PlayerDeathEvent extends PlayerEvent {
|
|||
* Changes the text sent in chat
|
||||
*
|
||||
* @param chatMessage the death message to send, null to remove
|
||||
* @deprecated Use {@link #setChatMessage(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setChatMessage(@Nullable JsonMessage chatMessage) {
|
||||
this.chatMessage = chatMessage == null ? null : chatMessage.asComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the text sent in chat
|
||||
*
|
||||
* @param chatMessage the death message to send, null to remove
|
||||
*/
|
||||
public void setChatMessage(@Nullable Component chatMessage) {
|
||||
this.chatMessage = chatMessage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package net.minestom.server.instance;
|
||||
|
||||
import com.google.common.collect.Queues;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.UpdateManager;
|
||||
import net.minestom.server.adventure.audience.PacketGroupingAudience;
|
||||
import net.minestom.server.data.Data;
|
||||
import net.minestom.server.data.DataContainer;
|
||||
import net.minestom.server.entity.Entity;
|
||||
|
@ -53,7 +59,7 @@ import java.util.function.Consumer;
|
|||
* you need to be sure to signal the {@link UpdateManager} of the changes using
|
||||
* {@link UpdateManager#signalChunkLoad(Instance, int, int)} and {@link UpdateManager#signalChunkUnload(Instance, int, int)}.
|
||||
*/
|
||||
public abstract class Instance implements BlockModifier, EventHandler, DataContainer {
|
||||
public abstract class Instance implements BlockModifier, EventHandler, DataContainer, PacketGroupingAudience {
|
||||
|
||||
protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager();
|
||||
protected static final UpdateManager UPDATE_MANAGER = MinecraftServer.getUpdateManager();
|
||||
|
@ -450,6 +456,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta
|
|||
*
|
||||
* @return an unmodifiable {@link Set} containing all the players in the instance
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
public Set<Player> getPlayers() {
|
||||
return Collections.unmodifiableSet(players);
|
||||
|
|
|
@ -1,13 +1,31 @@
|
|||
package net.minestom.server.item;
|
||||
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ItemDisplay {
|
||||
|
||||
private JsonMessage displayName;
|
||||
private JsonMessage[] lore;
|
||||
private Component displayName;
|
||||
private Component[] lore;
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #ItemDisplay(Component, Component[])}
|
||||
*/
|
||||
@Deprecated
|
||||
public ItemDisplay(JsonMessage displayName, JsonMessage[] lore) {
|
||||
this.displayName = displayName.asComponent();
|
||||
this.lore = new Component[lore.length];
|
||||
|
||||
for (int i = 0; i < lore.length; i++) {
|
||||
this.lore[i] = lore[i].asComponent();
|
||||
}
|
||||
}
|
||||
|
||||
public ItemDisplay(Component displayName, Component[] lore) {
|
||||
this.displayName = displayName;
|
||||
this.lore = lore;
|
||||
}
|
||||
|
@ -16,8 +34,34 @@ public class ItemDisplay {
|
|||
* Gets the item display name.
|
||||
*
|
||||
* @return the item display name
|
||||
* @deprecated Use {@link #getDisplayName()}
|
||||
*/
|
||||
public JsonMessage getDisplayName() {
|
||||
@Deprecated
|
||||
public JsonMessage getDisplayNameJson() {
|
||||
return JsonMessage.fromComponent(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item lore.
|
||||
*
|
||||
* @return the item lore
|
||||
* @deprecated Use {@link #getLore()}
|
||||
*/
|
||||
@Deprecated
|
||||
public JsonMessage[] getLoreJson() {
|
||||
JsonMessage[] loreOld = new JsonMessage[lore.length];
|
||||
for (int i = 0; i < lore.length; i++) {
|
||||
loreOld[i] = JsonMessage.fromComponent(lore[i]);
|
||||
}
|
||||
return loreOld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item display name.
|
||||
*
|
||||
* @return the item display name
|
||||
*/
|
||||
public Component getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
|
@ -26,7 +70,7 @@ public class ItemDisplay {
|
|||
*
|
||||
* @return the item lore
|
||||
*/
|
||||
public JsonMessage[] getLore() {
|
||||
public Component[] getLore() {
|
||||
return lore;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@ package net.minestom.server.item;
|
|||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ShortMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ShortOpenHashMap;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent.ShowItem;
|
||||
import net.kyori.adventure.text.event.HoverEventSource;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.data.Data;
|
||||
|
@ -26,6 +30,8 @@ import org.jetbrains.annotations.Nullable;
|
|||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
// TODO should we cache a ByteBuf of this item for faster packet write
|
||||
|
||||
|
@ -38,7 +44,7 @@ import java.util.*;
|
|||
* Here a non-exhaustive list of what you can do to update the item:
|
||||
* {@link PlayerInventory#refreshSlot(short)}, {@link Inventory#refreshSlot(short)} or a raw {@link SetSlotPacket}.
|
||||
*/
|
||||
public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
||||
public class ItemStack implements DataContainer, PublicCloneable<ItemStack>, HoverEventSource<ShowItem> {
|
||||
|
||||
public static final OwnershipHandler<Data> DATA_OWNERSHIP = new OwnershipHandler<>();
|
||||
public static final String OWNERSHIP_DATA_KEY = "ownership_identifier";
|
||||
|
@ -54,9 +60,9 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
private byte amount;
|
||||
private int damage;
|
||||
|
||||
private JsonMessage displayName;
|
||||
private Component displayName;
|
||||
private boolean unbreakable;
|
||||
private List<JsonMessage> lore;
|
||||
private List<Component> lore;
|
||||
|
||||
private Object2ShortMap<Enchantment> enchantmentMap;
|
||||
private List<ItemAttribute> attributes;
|
||||
|
@ -176,7 +182,7 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
return true;
|
||||
}
|
||||
|
||||
final JsonMessage itemDisplayName = itemStack.getDisplayName();
|
||||
final Component itemDisplayName = itemStack.getDisplayName();
|
||||
final boolean displayNameCheck = (displayName == null && itemDisplayName == null) ||
|
||||
(displayName != null && displayName.equals(itemDisplayName));
|
||||
|
||||
|
@ -309,13 +315,25 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
this.itemMeta = itemMeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item display name.
|
||||
*
|
||||
* @return the item display name, can be null if not present
|
||||
* @deprecated Use {@link #getDisplayName()}
|
||||
*/
|
||||
@Deprecated
|
||||
@Nullable
|
||||
public JsonMessage getDisplayNameJson() {
|
||||
return JsonMessage.fromComponent(displayName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item display name.
|
||||
*
|
||||
* @return the item display name, can be null if not present
|
||||
*/
|
||||
@Nullable
|
||||
public JsonMessage getDisplayName() {
|
||||
public Component getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
|
@ -323,8 +341,19 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
* Sets the item display name.
|
||||
*
|
||||
* @param displayName the item display name
|
||||
* @deprecated Use {@link #setDisplayName(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDisplayName(@Nullable JsonMessage displayName) {
|
||||
this.setDisplayName(displayName == null ? null : displayName.asComponent());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item display name.
|
||||
*
|
||||
* @param displayName the item display name
|
||||
*/
|
||||
public void setDisplayName(@Nullable Component displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
|
@ -337,13 +366,25 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
return displayName != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item lore.
|
||||
*
|
||||
* @return a modifiable list containing the item lore, can be empty if not present
|
||||
* @deprecated Use {@link #getLore()}
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
public List<JsonMessage> getLoreJson() {
|
||||
return lore.stream().map(JsonMessage::fromComponent).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item lore.
|
||||
*
|
||||
* @return a modifiable list containing the item lore, can be empty if not present
|
||||
*/
|
||||
@NotNull
|
||||
public List<JsonMessage> getLore() {
|
||||
public List<Component> getLore() {
|
||||
return lore;
|
||||
}
|
||||
|
||||
|
@ -351,8 +392,20 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
* Sets the item lore.
|
||||
*
|
||||
* @param lore the item lore, can be empty to remove
|
||||
* @deprecated Use {@link #setLore}
|
||||
*/
|
||||
public void setLore(@NotNull List<JsonMessage> lore) {
|
||||
@Deprecated
|
||||
public void setLoreJson(@NotNull List<JsonMessage> lore) {
|
||||
this.lore = lore.stream().map(JsonMessage::asComponent).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the item lore.
|
||||
*
|
||||
* @param lore the item lore, can be empty to remove
|
||||
*/
|
||||
@NotNull
|
||||
public void setLore(List<Component> lore) {
|
||||
this.lore = lore;
|
||||
}
|
||||
|
||||
|
@ -801,6 +854,11 @@ public class ItemStack implements DataContainer, PublicCloneable<ItemStack> {
|
|||
throw new UnsupportedOperationException("Not implemented yet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HoverEvent<ShowItem> asHoverEvent(@NotNull UnaryOperator<ShowItem> op) {
|
||||
return HoverEvent.showItem(op.apply(ShowItem.of(this.material, this.amount, NBTUtils.asBinaryTagHolder(this.toNBT().getCompound("tag")))));
|
||||
}
|
||||
|
||||
// Callback events
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.minestom.server.item.firework;
|
||||
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
|
@ -11,8 +13,23 @@ public class FireworkEffect {
|
|||
private final boolean flicker;
|
||||
private final boolean trail;
|
||||
private final FireworkEffectType type;
|
||||
private final ChatColor color;
|
||||
private final ChatColor fadeColor;
|
||||
private final Color color;
|
||||
private final Color fadeColor;
|
||||
|
||||
/**
|
||||
* Initializes a new firework effect.
|
||||
*
|
||||
* @param flicker {@code true} if this explosion has the Twinkle effect (glowstone dust), otherwise {@code false}.
|
||||
* @param trail {@code true} if this explosion hsa the Trail effect (diamond), otherwise {@code false}.
|
||||
* @param type The shape of this firework's explosion.
|
||||
* @param color The primary color of this firework effect.
|
||||
* @param fadeColor The secondary color of this firework effect.
|
||||
* @deprecated Use {@link #FireworkEffect(boolean, boolean, FireworkEffectType, Color, Color)}
|
||||
*/
|
||||
@Deprecated
|
||||
public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, ChatColor color, ChatColor fadeColor) {
|
||||
this(flicker, trail, type, color.asColor(), fadeColor.asColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a new firework effect.
|
||||
|
@ -23,7 +40,7 @@ public class FireworkEffect {
|
|||
* @param color The primary color of this firework effect.
|
||||
* @param fadeColor The secondary color of this firework effect.
|
||||
*/
|
||||
public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, ChatColor color, ChatColor fadeColor) {
|
||||
public FireworkEffect(boolean flicker, boolean trail, FireworkEffectType type, Color color, Color fadeColor) {
|
||||
this.flicker = flicker;
|
||||
this.trail = trail;
|
||||
this.type = type;
|
||||
|
@ -39,17 +56,17 @@ public class FireworkEffect {
|
|||
*/
|
||||
public static FireworkEffect fromCompound(@NotNull NBTCompound compound) {
|
||||
|
||||
ChatColor primaryColor = null;
|
||||
ChatColor secondaryColor = null;
|
||||
Color primaryColor = null;
|
||||
Color secondaryColor = null;
|
||||
|
||||
if (compound.containsKey("Colors")) {
|
||||
int[] color = compound.getIntArray("Colors");
|
||||
primaryColor = ChatColor.fromRGB((byte) color[0], (byte) color[1], (byte) color[2]);
|
||||
primaryColor = new Color(color[0], color[1], color[2]);
|
||||
}
|
||||
|
||||
if (compound.containsKey("FadeColors")) {
|
||||
int[] fadeColor = compound.getIntArray("FadeColors");
|
||||
secondaryColor = ChatColor.fromRGB((byte) fadeColor[0], (byte) fadeColor[1], (byte) fadeColor[2]);
|
||||
secondaryColor = new Color(fadeColor[0], fadeColor[1], fadeColor[2]);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
||||
|
@ -8,25 +9,18 @@ import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
|||
* Represents the item meta for leather armor parts.
|
||||
*/
|
||||
public class LeatherArmorMeta extends ItemMeta {
|
||||
|
||||
private static final int BIT_MASK = 0xFF;
|
||||
|
||||
private boolean modified;
|
||||
private byte red;
|
||||
private byte green;
|
||||
private byte blue;
|
||||
private Color color;
|
||||
|
||||
/**
|
||||
* Sets the color of the leather armor piece.
|
||||
*
|
||||
* @param color the color of the leather armor
|
||||
* @deprecated Use {@link #setColor(Color)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setColor(ChatColor color) {
|
||||
// TODO using "CHAT color" is pretty weird, maybe that the class should be renamed to "Color"
|
||||
this.red = color.getRed();
|
||||
this.green = color.getGreen();
|
||||
this.blue = color.getBlue();
|
||||
this.modified = true;
|
||||
this.setColor(color.asColor());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -35,21 +29,37 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
* @param red The red color of the leather armor piece.
|
||||
* @param green The green color of the leather armor piece.
|
||||
* @param blue The blue color of the leather armor piece.
|
||||
* @deprecated Use {@link #setColor(Color)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setColor(byte red, byte green, byte blue) {
|
||||
this.red = red;
|
||||
this.green = green;
|
||||
this.blue = blue;
|
||||
this.modified = true;
|
||||
this.setColor(new Color(red, green, blue));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this leather armor piece.
|
||||
*
|
||||
* @param color the new color
|
||||
*/
|
||||
public void setColor(@NotNull Color color) {
|
||||
this.modified = !color.equals(this.color);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the color of this leather armor piece.
|
||||
*
|
||||
* @return the color
|
||||
*/
|
||||
public @NotNull Color getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the color to the default leather one.
|
||||
*/
|
||||
public void reset() {
|
||||
this.red = 0;
|
||||
this.green = 0;
|
||||
this.blue = 0;
|
||||
this.color = new Color(0, 0, 0);
|
||||
this.modified = false;
|
||||
}
|
||||
|
||||
|
@ -57,27 +67,33 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
* Gets the red component.
|
||||
*
|
||||
* @return the red component
|
||||
* @deprecated Use {@link #getColor}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getRed() {
|
||||
return BIT_MASK & red;
|
||||
return this.color.getRed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the green component.
|
||||
*
|
||||
* @return the green component
|
||||
* @deprecated Use {@link #getColor}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getGreen() {
|
||||
return BIT_MASK & green;
|
||||
return this.color.getGreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blue component.
|
||||
*
|
||||
* @return the blue component
|
||||
* @deprecated Use {@link #getColor}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getBlue() {
|
||||
return BIT_MASK & blue;
|
||||
return this.color.getBlue();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -105,9 +121,7 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
if (!(itemMeta instanceof LeatherArmorMeta)) return false;
|
||||
final LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) itemMeta;
|
||||
return leatherArmorMeta.isModified() == isModified()
|
||||
&& leatherArmorMeta.getRed() == getRed()
|
||||
&& leatherArmorMeta.getGreen() == getGreen()
|
||||
&& leatherArmorMeta.getBlue() == getBlue();
|
||||
&& leatherArmorMeta.getColor().equals(getColor());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,10 +137,7 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
// Sets the color of the leather armor piece
|
||||
// This also fixes that the armor pieces do not decolorize again when you are in creative
|
||||
// mode.
|
||||
this.setColor(
|
||||
(byte) ((color >> 16) & BIT_MASK),
|
||||
(byte) ((color >> 8) & BIT_MASK),
|
||||
(byte) ((color) & BIT_MASK));
|
||||
this.setColor(new Color(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,9 +154,7 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
} else {
|
||||
displayCompound = compound.getCompound("display");
|
||||
}
|
||||
final int color = this.getRed() << 16 | this.getGreen() << 8 | this.getBlue();
|
||||
|
||||
displayCompound.setInt("color", color);
|
||||
displayCompound.setInt("color", color.asRGB());
|
||||
// Adds the color compound to the display compound
|
||||
compound.set("display", displayCompound);
|
||||
}
|
||||
|
@ -159,9 +168,7 @@ public class LeatherArmorMeta extends ItemMeta {
|
|||
public ItemMeta clone() {
|
||||
LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) super.clone();
|
||||
leatherArmorMeta.modified = this.isModified();
|
||||
leatherArmorMeta.red = (byte) this.getRed();
|
||||
leatherArmorMeta.green = (byte) this.getGreen();
|
||||
leatherArmorMeta.blue = (byte) this.getBlue();
|
||||
leatherArmorMeta.color = color;
|
||||
|
||||
return leatherArmorMeta;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.color.DyeColor;
|
||||
import net.minestom.server.utils.clone.CloneUtils;
|
||||
import net.minestom.server.utils.clone.PublicCloneable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -17,7 +20,7 @@ public class MapMeta extends ItemMeta {
|
|||
private int mapId;
|
||||
private int mapScaleDirection = 1;
|
||||
private List<MapDecoration> decorations = new CopyOnWriteArrayList<>();
|
||||
private ChatColor mapColor = ChatColor.NO_COLOR;
|
||||
private Color mapColor = new Color(0, 0, 0);
|
||||
|
||||
public MapMeta() {
|
||||
}
|
||||
|
@ -84,21 +87,40 @@ public class MapMeta extends ItemMeta {
|
|||
* Gets the map color.
|
||||
*
|
||||
* @return the map color
|
||||
* @deprecated Use {@link #getMapColor()}
|
||||
*/
|
||||
public ChatColor getMapColor() {
|
||||
return mapColor;
|
||||
@Deprecated
|
||||
public ChatColor getLegacyMapColor() {
|
||||
return this.mapColor.asLegacyChatColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map color.
|
||||
*
|
||||
* @return the map color
|
||||
*/
|
||||
public @NotNull Color getMapColor() {
|
||||
return this.mapColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the map color.
|
||||
* <p>
|
||||
* WARNING: RGB colors are not supported.
|
||||
*
|
||||
* @param mapColor the new map color
|
||||
* @deprecated Use {@link #setMapColor(Color)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setMapColor(ChatColor mapColor) {
|
||||
mapColor.getId(); // used to throw an error if rgb color is used
|
||||
this.mapColor = mapColor;
|
||||
this.setMapColor(mapColor.asColor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the map color.
|
||||
*
|
||||
* @param color the new map color
|
||||
*/
|
||||
public void setMapColor(@NotNull Color color) {
|
||||
this.mapColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -156,8 +178,7 @@ public class MapMeta extends ItemMeta {
|
|||
if (compound.containsKey("display")) {
|
||||
final NBTCompound displayCompound = compound.getCompound("display");
|
||||
if (displayCompound.containsKey("MapColor")) {
|
||||
final int color = displayCompound.getAsInt("MapColor");
|
||||
this.mapColor = ChatColor.fromId(color);
|
||||
this.mapColor = new Color(displayCompound.getAsInt("MapColor"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +212,7 @@ public class MapMeta extends ItemMeta {
|
|||
} else {
|
||||
displayCompound = new NBTCompound();
|
||||
}
|
||||
displayCompound.setInt("MapColor", mapColor.getId());
|
||||
displayCompound.setInt("MapColor", mapColor.asRGB());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.potion.CustomPotionEffect;
|
||||
import net.minestom.server.potion.PotionType;
|
||||
import net.minestom.server.registry.Registries;
|
||||
|
@ -29,8 +31,7 @@ public class PotionMeta extends ItemMeta {
|
|||
// Not final because of #clone()
|
||||
private List<CustomPotionEffect> customPotionEffects = new CopyOnWriteArrayList<>();
|
||||
|
||||
private boolean hasColor;
|
||||
private byte red, green, blue;
|
||||
private Color color;
|
||||
|
||||
/**
|
||||
* Gets the potion type.
|
||||
|
@ -65,19 +66,20 @@ public class PotionMeta extends ItemMeta {
|
|||
* Changes the color of the potion.
|
||||
*
|
||||
* @param color the new color of the potion
|
||||
* @deprecated Use {@link #setColor(Color)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setColor(ChatColor color) {
|
||||
// FIXME: weird usage of ChatColor, should maybe rename
|
||||
this.setColor(color.asColor());
|
||||
}
|
||||
|
||||
if (color == null) {
|
||||
this.hasColor = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.red = color.getRed();
|
||||
this.green = color.getGreen();
|
||||
this.blue = color.getBlue();
|
||||
this.hasColor = true;
|
||||
/**
|
||||
* Changes the color of the potion.
|
||||
*
|
||||
* @param color the new color of the potion
|
||||
*/
|
||||
public void setColor(@Nullable Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -93,10 +95,7 @@ public class PotionMeta extends ItemMeta {
|
|||
PotionMeta potionMeta = (PotionMeta) itemMeta;
|
||||
return potionMeta.potionType == potionType &&
|
||||
potionMeta.customPotionEffects.equals(customPotionEffects) &&
|
||||
potionMeta.hasColor == hasColor &&
|
||||
potionMeta.red == red &&
|
||||
potionMeta.green == green &&
|
||||
potionMeta.blue == blue;
|
||||
potionMeta.color.equals(color);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,10 +120,7 @@ public class PotionMeta extends ItemMeta {
|
|||
}
|
||||
|
||||
if (compound.containsKey("CustomPotionColor")) {
|
||||
final int color = compound.getInt("CustomPotionColor");
|
||||
this.red = (byte) ((color >> 16) & 0x000000FF);
|
||||
this.green = (byte) ((color >> 8) & 0x000000FF);
|
||||
this.blue = (byte) ((color) & 0x000000FF);
|
||||
this.color = new Color(compound.getInt("CustomPotionColor"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,9 +147,8 @@ public class PotionMeta extends ItemMeta {
|
|||
compound.set("CustomPotionEffects", potionList);
|
||||
}
|
||||
|
||||
if (hasColor) {
|
||||
final int color = red << 16 + green << 8 + blue;
|
||||
compound.setInt("CustomPotionColor", color);
|
||||
if (color != null) {
|
||||
compound.setInt("CustomPotionColor", color.asRGB());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -165,10 +160,7 @@ public class PotionMeta extends ItemMeta {
|
|||
potionMeta.potionType = potionType;
|
||||
potionMeta.customPotionEffects = CloneUtils.cloneCopyOnWriteArrayList(customPotionEffects);
|
||||
|
||||
potionMeta.hasColor = hasColor;
|
||||
potionMeta.red = red;
|
||||
potionMeta.green = green;
|
||||
potionMeta.blue = blue;
|
||||
potionMeta.color = color;
|
||||
|
||||
return potionMeta;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
@ -14,7 +17,7 @@ public class WritableBookMeta extends ItemMeta {
|
|||
|
||||
private String title;
|
||||
private String author;
|
||||
private List<String> pages = new ArrayList<>();
|
||||
private List<Component> pages = new ArrayList<>();
|
||||
|
||||
@Nullable
|
||||
public String getTitle() {
|
||||
|
@ -42,7 +45,7 @@ public class WritableBookMeta extends ItemMeta {
|
|||
* @return a modifiable {@link ArrayList} containing the book pages
|
||||
*/
|
||||
@NotNull
|
||||
public List<String> getPages() {
|
||||
public List<Component> getPages() {
|
||||
return pages;
|
||||
}
|
||||
|
||||
|
@ -51,7 +54,7 @@ public class WritableBookMeta extends ItemMeta {
|
|||
*
|
||||
* @param pages the pages list
|
||||
*/
|
||||
public void setPages(@NotNull List<String> pages) {
|
||||
public void setPages(@NotNull List<Component> pages) {
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
|
@ -82,7 +85,7 @@ public class WritableBookMeta extends ItemMeta {
|
|||
if (compound.containsKey("pages")) {
|
||||
final NBTList<NBTString> list = compound.getList("pages");
|
||||
for (NBTString page : list) {
|
||||
this.pages.add(page.getValue());
|
||||
this.pages.add(GsonComponentSerializer.gson().deserialize(page.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -100,8 +103,8 @@ public class WritableBookMeta extends ItemMeta {
|
|||
|
||||
if (!pages.isEmpty()) {
|
||||
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
|
||||
for (String page : pages) {
|
||||
list.add(new NBTString(page));
|
||||
for (Component page : pages) {
|
||||
list.add(new NBTString(AdventureSerializer.serialize(page)));
|
||||
}
|
||||
compound.set("pages", list);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.minestom.server.chat.ChatParser;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.inventory.Book;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minestom.server.adventure.AdventureSerializer;
|
||||
import net.minestom.server.adventure.Localizable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
||||
|
@ -18,7 +20,7 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
private WrittenBookGeneration generation;
|
||||
private String author;
|
||||
private String title;
|
||||
private List<JsonMessage> pages = new ArrayList<>();
|
||||
private List<Component> pages = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Gets if the book is resolved.
|
||||
|
@ -96,11 +98,12 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
/**
|
||||
* Gets an {@link ArrayList} containing all the pages.
|
||||
* <p>
|
||||
* The list is modifiable.
|
||||
* The list is not modifiable as it is .
|
||||
*
|
||||
* @return a modifiable {@link ArrayList} with the pages of the book
|
||||
*/
|
||||
public List<JsonMessage> getPages() {
|
||||
@Deprecated
|
||||
public List<Component> getPagesJson() {
|
||||
return pages;
|
||||
}
|
||||
|
||||
|
@ -109,7 +112,7 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
*
|
||||
* @param pages the array list containing the book pages
|
||||
*/
|
||||
public void setPages(List<JsonMessage> pages) {
|
||||
public void setPages(List<Component> pages) {
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
|
@ -149,9 +152,7 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
if (compound.containsKey("pages")) {
|
||||
final NBTList<NBTString> list = compound.getList("pages");
|
||||
for (NBTString page : list) {
|
||||
final String jsonPage = page.getValue();
|
||||
final ColoredText coloredText = ChatParser.toColoredText(jsonPage);
|
||||
this.pages.add(coloredText);
|
||||
this.pages.add(GsonComponentSerializer.gson().deserialize(page.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -172,8 +173,8 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
}
|
||||
if (!pages.isEmpty()) {
|
||||
NBTList<NBTString> list = new NBTList<>(NBTTypes.TAG_String);
|
||||
for (JsonMessage page : pages) {
|
||||
list.add(new NBTString(page.toString()));
|
||||
for (Component page : pages) {
|
||||
list.add(new NBTString(AdventureSerializer.serialize(page)));
|
||||
}
|
||||
compound.set("pages", list);
|
||||
}
|
||||
|
@ -196,4 +197,25 @@ public class WrittenBookMeta extends ItemMeta {
|
|||
ORIGINAL, COPY_OF_ORIGINAL, COPY_OF_COPY, TATTERED
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a written book meta from an Adventure book. This meta will not be
|
||||
* resolved and the generation will default to {@link WrittenBookGeneration#ORIGINAL}.
|
||||
*
|
||||
* @param book the book
|
||||
* @param localizable who the book is for
|
||||
*
|
||||
* @return the meta
|
||||
*/
|
||||
public static @NotNull WrittenBookMeta fromAdventure(@NotNull Book book, @NotNull Localizable localizable) {
|
||||
// make the book
|
||||
WrittenBookMeta meta = new WrittenBookMeta();
|
||||
meta.resolved = false;
|
||||
meta.generation = WrittenBookGeneration.ORIGINAL;
|
||||
meta.author = AdventureSerializer.translateAndSerialize(book.author(), localizable);
|
||||
meta.title = AdventureSerializer.translateAndSerialize(book.title(), localizable);
|
||||
meta.pages = new ArrayList<>();
|
||||
meta.pages.addAll(book.pages());
|
||||
|
||||
return meta;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package net.minestom.server.listener;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.*;
|
||||
import net.minestom.server.command.CommandManager;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.player.PlayerChatEvent;
|
||||
|
@ -9,7 +10,6 @@ import net.minestom.server.network.ConnectionManager;
|
|||
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
|
||||
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Function;
|
||||
|
@ -39,9 +39,9 @@ public class ChatMessageListener {
|
|||
// Call the event
|
||||
player.callCancellableEvent(PlayerChatEvent.class, playerChatEvent, () -> {
|
||||
|
||||
final Function<PlayerChatEvent, JsonMessage> formatFunction = playerChatEvent.getChatFormatFunction();
|
||||
final Function<PlayerChatEvent, Component> formatFunction = playerChatEvent.getChatFormatFunction();
|
||||
|
||||
JsonMessage textObject;
|
||||
Component textObject;
|
||||
|
||||
if (formatFunction != null) {
|
||||
// Custom format
|
||||
|
@ -53,11 +53,9 @@ public class ChatMessageListener {
|
|||
|
||||
final Collection<Player> recipients = playerChatEvent.getRecipients();
|
||||
if (!recipients.isEmpty()) {
|
||||
final String jsonMessage = textObject.toString();
|
||||
|
||||
// Send the message with the correct player UUID
|
||||
ChatMessagePacket chatMessagePacket =
|
||||
new ChatMessagePacket(jsonMessage, ChatMessagePacket.Position.CHAT, player.getUuid());
|
||||
new ChatMessagePacket(textObject, ChatMessagePacket.Position.CHAT, player.getUuid());
|
||||
|
||||
PacketUtils.sendGroupedPacket(recipients, chatMessagePacket);
|
||||
}
|
||||
|
@ -66,15 +64,13 @@ public class ChatMessageListener {
|
|||
|
||||
}
|
||||
|
||||
private static RichMessage buildDefaultChatMessage(PlayerChatEvent chatEvent) {
|
||||
private static Component buildDefaultChatMessage(PlayerChatEvent chatEvent) {
|
||||
final String username = chatEvent.getPlayer().getUsername();
|
||||
|
||||
final ColoredText usernameText = ColoredText.of(String.format("<%s>", username));
|
||||
|
||||
return RichMessage.of(usernameText)
|
||||
.setHoverEvent(ChatHoverEvent.showText("Click to send a message to " + username))
|
||||
.setClickEvent(ChatClickEvent.suggestCommand("/msg " + username + StringUtils.SPACE))
|
||||
.append(ColoredText.of(StringUtils.SPACE + chatEvent.getMessage()));
|
||||
return Component.text("<" + username + ">")
|
||||
.hoverEvent(Component.text("Click to send a message to " + username))
|
||||
.clickEvent(ClickEvent.suggestCommand("/msg " + username + " "))
|
||||
.append(Component.text(" " + chatEvent.getMessage()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package net.minestom.server.listener;
|
||||
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
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.client.play.ClientKeepAlivePacket;
|
||||
|
||||
|
@ -12,7 +12,7 @@ public class KeepAliveListener {
|
|||
final long playerId = player.getLastKeepAlive();
|
||||
final boolean equals = packetId == playerId;
|
||||
if (!equals) {
|
||||
player.kick(ColoredText.of(ChatColor.RED + "Bad Keep Alive packet"));
|
||||
player.kick(Component.text("Bad Keep Alive packet", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package net.minestom.server.network;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import net.kyori.adventure.audience.ForwardingAudience;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.adventure.audience.Audiences;
|
||||
import net.minestom.server.adventure.audience.PacketGroupingAudience;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.fakeplayer.FakePlayer;
|
||||
|
@ -14,12 +18,10 @@ import net.minestom.server.listener.manager.ClientPacketConsumer;
|
|||
import net.minestom.server.listener.manager.ServerPacketConsumer;
|
||||
import net.minestom.server.network.packet.client.login.LoginStartPacket;
|
||||
import net.minestom.server.network.packet.server.login.LoginSuccessPacket;
|
||||
import net.minestom.server.network.packet.server.play.ChatMessagePacket;
|
||||
import net.minestom.server.network.packet.server.play.DisconnectPacket;
|
||||
import net.minestom.server.network.packet.server.play.KeepAlivePacket;
|
||||
import net.minestom.server.network.player.NettyPlayerConnection;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.utils.PacketUtils;
|
||||
import net.minestom.server.utils.async.AsyncUtils;
|
||||
import net.minestom.server.utils.callback.validator.PlayerValidator;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
|
@ -33,6 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Manages the connected clients.
|
||||
|
@ -41,7 +44,7 @@ public final class ConnectionManager {
|
|||
|
||||
private static final long KEEP_ALIVE_DELAY = 10_000;
|
||||
private static final long KEEP_ALIVE_KICK = 30_000;
|
||||
private static final ColoredText TIMEOUT_TEXT = ColoredText.of(ChatColor.RED + "Timeout");
|
||||
private static final Component TIMEOUT_TEXT = Component.text("Timeout", NamedTextColor.RED);
|
||||
|
||||
private final Queue<Player> waitingPlayers = new ConcurrentLinkedQueue<>();
|
||||
private final Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
|
@ -58,7 +61,7 @@ public final class ConnectionManager {
|
|||
// The consumers to call once a player connect, mostly used to init events
|
||||
private final List<Consumer<Player>> playerInitializations = new CopyOnWriteArrayList<>();
|
||||
|
||||
private JsonMessage shutdownText = ColoredText.of(ChatColor.RED, "The server is shutting down.");
|
||||
private Component shutdownText = Component.text("The server is shutting down.", NamedTextColor.RED);
|
||||
|
||||
/**
|
||||
* Gets the {@link Player} linked to a {@link PlayerConnection}.
|
||||
|
@ -144,13 +147,15 @@ public final class ConnectionManager {
|
|||
*
|
||||
* @param jsonMessage the message to send, probably a {@link net.minestom.server.chat.ColoredText} or {@link net.minestom.server.chat.RichMessage}
|
||||
* @param condition the condition to receive the message
|
||||
*
|
||||
* @deprecated Use {@link Audiences#players(Predicate)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void broadcastMessage(@NotNull JsonMessage jsonMessage, @Nullable PlayerValidator condition) {
|
||||
final Collection<Player> recipients = getRecipients(condition);
|
||||
|
||||
if (!recipients.isEmpty()) {
|
||||
final String jsonText = jsonMessage.toString();
|
||||
broadcastJson(jsonText, recipients);
|
||||
if (condition == null) {
|
||||
Audiences.audiences().players().sendMessage(jsonMessage);
|
||||
} else {
|
||||
Audiences.audiences().players(condition).sendMessage(jsonMessage);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,16 +163,11 @@ public final class ConnectionManager {
|
|||
* Sends a {@link JsonMessage} to all online players.
|
||||
*
|
||||
* @param jsonMessage the message to send, probably a {@link net.minestom.server.chat.ColoredText} or {@link net.minestom.server.chat.RichMessage}
|
||||
* @deprecated Use {@link Audience#sendMessage(Component)} on {@link Audiences#players()}
|
||||
*/
|
||||
@Deprecated
|
||||
public void broadcastMessage(@NotNull JsonMessage jsonMessage) {
|
||||
broadcastMessage(jsonMessage, null);
|
||||
}
|
||||
|
||||
private void broadcastJson(@NotNull String json, @NotNull Collection<Player> recipients) {
|
||||
ChatMessagePacket chatMessagePacket =
|
||||
new ChatMessagePacket(json, ChatMessagePacket.Position.SYSTEM_MESSAGE);
|
||||
|
||||
PacketUtils.sendGroupedPacket(recipients, chatMessagePacket);
|
||||
this.broadcastMessage(jsonMessage, null);
|
||||
}
|
||||
|
||||
private Collection<Player> getRecipients(@Nullable PlayerValidator condition) {
|
||||
|
@ -313,23 +313,48 @@ public final class ConnectionManager {
|
|||
this.playerInitializations.remove(playerInitialization);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kick reason when the server is shutdown using {@link MinecraftServer#stopCleanly()}.
|
||||
*
|
||||
* @return the kick reason in case on a shutdown
|
||||
*
|
||||
* @deprecated Use {@link #getShutdownText()}
|
||||
*/
|
||||
@Deprecated
|
||||
@NotNull
|
||||
public JsonMessage getShutdownTextJson() {
|
||||
return JsonMessage.fromComponent(shutdownText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kick reason when the server is shutdown using {@link MinecraftServer#stopCleanly()}.
|
||||
*
|
||||
* @return the kick reason in case on a shutdown
|
||||
*/
|
||||
@NotNull
|
||||
public JsonMessage getShutdownText() {
|
||||
public Component getShutdownText() {
|
||||
return shutdownText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the kick reason in case of a shutdown.
|
||||
*
|
||||
* @param shutdownText the new shutdown kick reason
|
||||
* @see #getShutdownTextJson()
|
||||
* @deprecated Use {@link #setShutdownText(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setShutdownText(@NotNull JsonMessage shutdownText) {
|
||||
this.shutdownText = shutdownText.asComponent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the kick reason in case of a shutdown.
|
||||
*
|
||||
* @param shutdownText the new shutdown kick reason
|
||||
* @see #getShutdownText()
|
||||
*/
|
||||
public void setShutdownText(@NotNull JsonMessage shutdownText) {
|
||||
public void setShutdownText(@NotNull Component shutdownText) {
|
||||
this.shutdownText = shutdownText;
|
||||
}
|
||||
|
||||
|
@ -459,7 +484,7 @@ public final class ConnectionManager {
|
|||
* Shutdowns the connection manager by kicking all the currently connected players.
|
||||
*/
|
||||
public void shutdown() {
|
||||
DisconnectPacket disconnectPacket = new DisconnectPacket(getShutdownText());
|
||||
DisconnectPacket disconnectPacket = new DisconnectPacket(shutdownText);
|
||||
for (Player player : getOnlinePlayers()) {
|
||||
final PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
if (playerConnection instanceof NettyPlayerConnection) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.minestom.server.network.packet.client.handshake;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.PlayerSkin;
|
||||
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
||||
import net.minestom.server.network.ConnectionState;
|
||||
|
@ -21,9 +21,8 @@ public class HandshakePacket implements ClientPreplayPacket {
|
|||
/**
|
||||
* Text sent if a player tries to connect with an invalid version of the client
|
||||
*/
|
||||
private static final ColoredText INVALID_VERSION_TEXT = ColoredText.of(ChatColor.RED, "Invalid Version, please use " + MinecraftServer.VERSION_NAME);
|
||||
|
||||
private static final ColoredText INVALID_BUNGEE_FORWARDING = ColoredText.of(ChatColor.RED, "If you wish to use IP forwarding, please enable it in your BungeeCord config as well!");
|
||||
private static final Component INVALID_VERSION_TEXT = Component.text("Invalid Version, please use " + MinecraftServer.VERSION_NAME, NamedTextColor.RED);
|
||||
private static final Component INVALID_BUNGEE_FORWARDING = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.RED);
|
||||
|
||||
private int protocolVersion;
|
||||
private String serverAddress;
|
||||
|
@ -95,7 +94,7 @@ public class HandshakePacket implements ClientPreplayPacket {
|
|||
}
|
||||
} else {
|
||||
// Incorrect client version
|
||||
connection.sendPacket(new LoginDisconnectPacket(INVALID_VERSION_TEXT.toString()));
|
||||
connection.sendPacket(new LoginDisconnectPacket(INVALID_VERSION_TEXT));
|
||||
connection.disconnect();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.minestom.server.network.packet.client.login;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.entity.PlayerSkin;
|
||||
import net.minestom.server.extras.velocity.VelocityProxy;
|
||||
|
@ -23,7 +23,7 @@ public class LoginPluginResponsePacket implements ClientPreplayPacket {
|
|||
|
||||
private final static ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
|
||||
|
||||
public static final ColoredText INVALID_PROXY_RESPONSE = ColoredText.of(ChatColor.RED, "Invalid proxy response!");
|
||||
public static final Component INVALID_PROXY_RESPONSE = Component.text("Invalid proxy response!", NamedTextColor.RED);
|
||||
|
||||
public int messageId;
|
||||
public boolean successful;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package net.minestom.server.network.packet.client.login;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.extras.MojangAuth;
|
||||
import net.minestom.server.extras.bungee.BungeeCordProxy;
|
||||
|
@ -22,7 +22,7 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
|
||||
public class LoginStartPacket implements ClientPreplayPacket {
|
||||
|
||||
private static final ColoredText ALREADY_CONNECTED_JSON = ColoredText.of(ChatColor.RED, "You are already on this server");
|
||||
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
|
||||
|
||||
public String username;
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||
if (MojangAuth.isEnabled() && isNettyClient) {
|
||||
// Mojang auth
|
||||
if (CONNECTION_MANAGER.getPlayer(username) != null) {
|
||||
connection.sendPacket(new LoginDisconnectPacket(ALREADY_CONNECTED_JSON));
|
||||
connection.sendPacket(new LoginDisconnectPacket(ALREADY_CONNECTED));
|
||||
connection.disconnect();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package net.minestom.server.network.packet.server;
|
||||
|
||||
import net.minestom.server.adventure.ComponentHolder;
|
||||
|
||||
/**
|
||||
* A server packet that can hold components.
|
||||
*/
|
||||
public interface ComponentHoldingServerPacket extends ServerPacket, ComponentHolder<ServerPacket> { }
|
|
@ -1,26 +1,34 @@
|
|||
package net.minestom.server.network.packet.server.login;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class LoginDisconnectPacket implements ServerPacket {
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
private final String kickMessage; // JSON text
|
||||
public class LoginDisconnectPacket implements ComponentHoldingServerPacket {
|
||||
public Component kickMessage;
|
||||
|
||||
public LoginDisconnectPacket(@NotNull String kickMessage) {
|
||||
public LoginDisconnectPacket(@NotNull Component kickMessage) {
|
||||
this.kickMessage = kickMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #LoginDisconnectPacket(Component)}
|
||||
*/
|
||||
@Deprecated
|
||||
public LoginDisconnectPacket(@NotNull JsonMessage jsonKickMessage) {
|
||||
this(jsonKickMessage.toString());
|
||||
this(jsonKickMessage.asComponent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeSizedString(kickMessage);
|
||||
writer.writeComponent(kickMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -28,4 +36,13 @@ public class LoginDisconnectPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.LOGIN_DISCONNECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
return List.of(this.kickMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull LoginDisconnectPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
return new LoginDisconnectPacket(operator.apply(this.kickMessage));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.advancements.FrameType;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import net.minestom.server.utils.binary.Writeable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AdvancementsPacket implements ServerPacket {
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class AdvancementsPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public boolean resetAdvancements;
|
||||
public AdvancementMapping[] advancementMappings;
|
||||
|
@ -37,6 +44,32 @@ public class AdvancementsPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.ADVANCEMENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
List<Component> components = new ArrayList<>();
|
||||
for (AdvancementMapping advancementMapping : advancementMappings) {
|
||||
components.add(advancementMapping.value.displayData.title);
|
||||
components.add(advancementMapping.value.displayData.description);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
AdvancementsPacket packet = new AdvancementsPacket();
|
||||
packet.resetAdvancements = this.resetAdvancements;
|
||||
packet.advancementMappings = Arrays.copyOf(this.advancementMappings, this.advancementMappings.length);
|
||||
packet.identifiersToRemove = Arrays.copyOf(this.identifiersToRemove, this.identifiersToRemove.length);
|
||||
packet.progressMappings = Arrays.copyOf(this.progressMappings, this.progressMappings.length);
|
||||
|
||||
for (AdvancementMapping advancementMapping : packet.advancementMappings) {
|
||||
advancementMapping.value.displayData.title = operator.apply(advancementMapping.value.displayData.title);
|
||||
advancementMapping.value.displayData.description = operator.apply(advancementMapping.value.displayData.title);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
/**
|
||||
* AdvancementMapping maps the namespaced ID to the Advancement.
|
||||
*/
|
||||
|
@ -84,8 +117,8 @@ public class AdvancementsPacket implements ServerPacket {
|
|||
}
|
||||
|
||||
public static class DisplayData implements Writeable {
|
||||
public JsonMessage title; // Only text
|
||||
public JsonMessage description; // Only text
|
||||
public Component title; // Only text
|
||||
public Component description; // Only text
|
||||
public ItemStack icon;
|
||||
public FrameType frameType;
|
||||
public int flags;
|
||||
|
@ -95,8 +128,8 @@ public class AdvancementsPacket implements ServerPacket {
|
|||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeSizedString(title.toString());
|
||||
writer.writeSizedString(description.toString());
|
||||
writer.writeComponent(title);
|
||||
writer.writeComponent(description);
|
||||
writer.writeItemStack(icon);
|
||||
writer.writeVarInt(frameType.ordinal());
|
||||
writer.writeInt(flags);
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.bossbar.BarColor;
|
||||
import net.minestom.server.bossbar.BarDivision;
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.bossbar.BossBar;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class BossBarPacket implements ServerPacket {
|
||||
public class BossBarPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public UUID uuid;
|
||||
public Action action;
|
||||
|
||||
public JsonMessage title; // Only text
|
||||
public Component title; // Only text
|
||||
public float health;
|
||||
public BarColor color;
|
||||
public BarDivision division;
|
||||
public BossBar.Color color;
|
||||
public BossBar.Overlay overlay;
|
||||
public byte flags;
|
||||
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeUuid(uuid);
|
||||
|
@ -29,10 +32,10 @@ public class BossBarPacket implements ServerPacket {
|
|||
|
||||
switch (action) {
|
||||
case ADD:
|
||||
writer.writeSizedString(title.toString());
|
||||
writer.writeComponent(title);
|
||||
writer.writeFloat(health);
|
||||
writer.writeVarInt(color.ordinal());
|
||||
writer.writeVarInt(division.ordinal());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getBossBarColorValue(color));
|
||||
writer.writeVarInt(AdventurePacketConvertor.getBossBarOverlayValue(overlay));
|
||||
writer.writeByte(flags);
|
||||
break;
|
||||
case REMOVE:
|
||||
|
@ -42,11 +45,11 @@ public class BossBarPacket implements ServerPacket {
|
|||
writer.writeFloat(health);
|
||||
break;
|
||||
case UPDATE_TITLE:
|
||||
writer.writeSizedString(title.toString());
|
||||
writer.writeComponent(title);
|
||||
break;
|
||||
case UPDATE_STYLE:
|
||||
writer.writeVarInt(color.ordinal());
|
||||
writer.writeVarInt(division.ordinal());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getBossBarColorValue(color));
|
||||
writer.writeVarInt(AdventurePacketConvertor.getBossBarOverlayValue(overlay));
|
||||
break;
|
||||
case UPDATE_FLAGS:
|
||||
writer.writeByte(flags);
|
||||
|
@ -59,6 +62,40 @@ public class BossBarPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.BOSS_BAR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (title != null) {
|
||||
return Collections.singleton(title);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
switch (action) {
|
||||
case UPDATE_TITLE: {
|
||||
BossBarPacket packet = new BossBarPacket();
|
||||
packet.action = action;
|
||||
packet.uuid = uuid;
|
||||
packet.title = operator.apply(title);
|
||||
return packet;
|
||||
}
|
||||
case ADD: {
|
||||
BossBarPacket packet = new BossBarPacket();
|
||||
packet.action = action;
|
||||
packet.uuid = uuid;
|
||||
packet.title = operator.apply(title);
|
||||
packet.health = health;
|
||||
packet.overlay = overlay;
|
||||
packet.color = color;
|
||||
packet.flags = flags;
|
||||
return packet;
|
||||
}
|
||||
default: return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
ADD,
|
||||
REMOVE,
|
||||
|
|
|
@ -1,31 +1,42 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.kyori.adventure.audience.MessageType;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.UUID;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ChatMessagePacket implements ServerPacket {
|
||||
/**
|
||||
* Represents an outgoing chat message packet.
|
||||
*/
|
||||
public class ChatMessagePacket implements ComponentHoldingServerPacket {
|
||||
private static final UUID NULL_UUID = new UUID(0, 0);
|
||||
|
||||
public String jsonMessage;
|
||||
public Component message;
|
||||
public Position position;
|
||||
public UUID uuid;
|
||||
|
||||
public ChatMessagePacket(String jsonMessage, Position position, UUID uuid) {
|
||||
this.jsonMessage = jsonMessage;
|
||||
public ChatMessagePacket(Component message, Position position, UUID uuid) {
|
||||
this.message = message;
|
||||
this.position = position;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
public ChatMessagePacket(String jsonMessage, Position position) {
|
||||
this(jsonMessage, position, new UUID(0, 0));
|
||||
public ChatMessagePacket(Component message, Position position) {
|
||||
this(message, position, NULL_UUID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeSizedString(jsonMessage);
|
||||
writer.writeComponent(message);
|
||||
writer.writeByte((byte) position.ordinal());
|
||||
writer.writeUuid(uuid);
|
||||
}
|
||||
|
@ -35,9 +46,50 @@ public class ChatMessagePacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.CHAT_MESSAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
return Collections.singleton(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
return new ChatMessagePacket(operator.apply(message), position, uuid);
|
||||
}
|
||||
|
||||
public enum Position {
|
||||
CHAT,
|
||||
SYSTEM_MESSAGE,
|
||||
GAME_INFO
|
||||
CHAT(MessageType.CHAT),
|
||||
SYSTEM_MESSAGE(MessageType.SYSTEM),
|
||||
GAME_INFO(null);
|
||||
|
||||
private final MessageType messageType;
|
||||
|
||||
Position(MessageType messageType) {
|
||||
this.messageType = messageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Adventure message type from this position. Note that there is no
|
||||
* message type for {@link #GAME_INFO}, as Adventure uses the title methods for this.
|
||||
*
|
||||
* @return the message type, if any
|
||||
*/
|
||||
public @Nullable MessageType getMessageType() {
|
||||
return this.messageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a position from an Adventure message type.
|
||||
*
|
||||
* @param messageType the message type
|
||||
*
|
||||
* @return the position
|
||||
*/
|
||||
public static @NotNull Position fromMessageType(@NotNull MessageType messageType) {
|
||||
switch (messageType) {
|
||||
case CHAT: return CHAT;
|
||||
case SYSTEM: return SYSTEM_MESSAGE;
|
||||
}
|
||||
throw new IllegalArgumentException("Cannot get position from message type!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Packet sent during combat to a {@link Player}.
|
||||
* Only death is supported for the moment (other events are ignored anyway as of 1.15.2)
|
||||
*/
|
||||
public class CombatEventPacket implements ServerPacket {
|
||||
public class CombatEventPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
private EventType type;
|
||||
private int duration;
|
||||
private int opponent;
|
||||
private int playerID;
|
||||
private JsonMessage deathMessage; // Only text
|
||||
private Component deathMessage;
|
||||
|
||||
private CombatEventPacket() {
|
||||
}
|
||||
|
@ -39,7 +42,7 @@ public class CombatEventPacket implements ServerPacket {
|
|||
return packet;
|
||||
}
|
||||
|
||||
public static CombatEventPacket death(Player player, Entity killer, JsonMessage message) {
|
||||
public static CombatEventPacket death(Player player, Entity killer, Component message) {
|
||||
CombatEventPacket packet = new CombatEventPacket();
|
||||
packet.type = EventType.DEATH;
|
||||
packet.playerID = player.getEntityId();
|
||||
|
@ -64,7 +67,7 @@ public class CombatEventPacket implements ServerPacket {
|
|||
case DEATH:
|
||||
writer.writeVarInt(playerID);
|
||||
writer.writeInt(opponent);
|
||||
writer.writeSizedString(deathMessage.toString());
|
||||
writer.writeComponent(deathMessage);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +77,29 @@ public class CombatEventPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.COMBAT_EVENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (this.type == EventType.DEATH) {
|
||||
return Collections.singleton(deathMessage);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (this.type == EventType.DEATH) {
|
||||
CombatEventPacket packet = new CombatEventPacket();
|
||||
packet.type = type;
|
||||
packet.playerID = playerID;
|
||||
packet.opponent = opponent;
|
||||
packet.deathMessage = deathMessage;
|
||||
return packet;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
ENTER_COMBAT, END_COMBAT, // both ignored by Notchian client
|
||||
DEATH,
|
||||
|
|
|
@ -1,26 +1,44 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DisconnectPacket implements ServerPacket {
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public JsonMessage message; // Only text
|
||||
public class DisconnectPacket implements ComponentHoldingServerPacket {
|
||||
public Component message;
|
||||
|
||||
public DisconnectPacket(@NotNull JsonMessage message){
|
||||
/**
|
||||
* Creates a new disconnect packet with a given message.
|
||||
* @param message the message
|
||||
*/
|
||||
public DisconnectPacket(@NotNull Component message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeSizedString(message.toString());
|
||||
writer.writeComponent(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ServerPacketIdentifier.DISCONNECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
return Collections.singleton(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
return new DisconnectPacket(operator.apply(message));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class EntitySoundEffectPacket implements ServerPacket {
|
||||
|
||||
public int soundId;
|
||||
public SoundCategory soundCategory;
|
||||
public Sound.Source soundSource;
|
||||
public int entityId;
|
||||
public float volume;
|
||||
public float pitch;
|
||||
|
@ -17,7 +18,7 @@ public class EntitySoundEffectPacket implements ServerPacket {
|
|||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeVarInt(soundId);
|
||||
writer.writeVarInt(soundCategory.ordinal());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getSoundSourceValue(soundSource));
|
||||
writer.writeVarInt(entityId);
|
||||
writer.writeFloat(volume);
|
||||
writer.writeFloat(pitch);
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class MapDataPacket implements ServerPacket {
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class MapDataPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public int mapId;
|
||||
public byte scale;
|
||||
|
@ -59,11 +63,49 @@ public class MapDataPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.MAP_DATA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (icons == null || icons.length == 0) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<Component> components = new ArrayList<>();
|
||||
for (Icon icon : icons) {
|
||||
components.add(icon.displayName);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (this.icons == null || this.icons.length == 0) {
|
||||
return this;
|
||||
} else {
|
||||
MapDataPacket packet = new MapDataPacket();
|
||||
packet.mapId = this.mapId;
|
||||
packet.scale = this.scale;
|
||||
packet.trackingPosition = this.trackingPosition;
|
||||
packet.locked = this.locked;
|
||||
packet.columns = this.columns;
|
||||
packet.rows = this.rows;
|
||||
packet.x = this.x;
|
||||
packet.z = this.z;
|
||||
packet.data = this.data;
|
||||
|
||||
packet.icons = Arrays.copyOf(this.icons, this.icons.length);
|
||||
for (Icon icon : packet.icons) {
|
||||
icon.displayName = operator.apply(icon.displayName);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Icon {
|
||||
public int type;
|
||||
public byte x, z;
|
||||
public byte direction;
|
||||
public JsonMessage displayName; // Only text
|
||||
public Component displayName;
|
||||
|
||||
private void write(BinaryWriter writer) {
|
||||
writer.writeVarInt(type);
|
||||
|
@ -74,7 +116,7 @@ public class MapDataPacket implements ServerPacket {
|
|||
final boolean hasDisplayName = displayName != null;
|
||||
writer.writeBoolean(hasDisplayName);
|
||||
if (hasDisplayName) {
|
||||
writer.writeSizedString(displayName.toString());
|
||||
writer.writeComponent(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.kyori.adventure.sound.Sound.Source;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class NamedSoundEffectPacket implements ServerPacket {
|
||||
|
||||
public String soundName;
|
||||
public SoundCategory soundCategory;
|
||||
public Source soundSource;
|
||||
public int x, y, z;
|
||||
public float volume;
|
||||
public float pitch;
|
||||
|
@ -17,7 +18,7 @@ public class NamedSoundEffectPacket implements ServerPacket {
|
|||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeSizedString(soundName);
|
||||
writer.writeVarInt(soundCategory.ordinal());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getSoundSourceValue(soundSource));
|
||||
writer.writeInt(x * 8);
|
||||
writer.writeInt(y * 8);
|
||||
writer.writeInt(z * 8);
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.adventure.ComponentHolder;
|
||||
import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class PlayerInfoPacket implements ServerPacket {
|
||||
public class PlayerInfoPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public Action action;
|
||||
public List<PlayerInfo> playerInfos;
|
||||
|
@ -38,6 +39,40 @@ public class PlayerInfoPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.PLAYER_INFO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
switch (this.action) {
|
||||
case ADD_PLAYER:
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
List<Component> components = new ArrayList<>();
|
||||
for (PlayerInfo playerInfo : playerInfos) {
|
||||
if (playerInfo instanceof ComponentHolder) {
|
||||
components.addAll(((ComponentHolder<? extends PlayerInfo>) playerInfo).components());
|
||||
}
|
||||
}
|
||||
return components;
|
||||
default: return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
switch (this.action) {
|
||||
case ADD_PLAYER:
|
||||
case UPDATE_DISPLAY_NAME:
|
||||
PlayerInfoPacket packet = new PlayerInfoPacket(action);
|
||||
packet.playerInfos = new ArrayList<>(playerInfos.size());
|
||||
for (PlayerInfo playerInfo : playerInfos) {
|
||||
if (playerInfo instanceof ComponentHolder) {
|
||||
playerInfos.add(((ComponentHolder<? extends PlayerInfo>) playerInfo).copyWithOperator(operator));
|
||||
} else {
|
||||
playerInfos.add(playerInfo);
|
||||
}
|
||||
}
|
||||
default: return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
|
||||
ADD_PLAYER(AddPlayer.class),
|
||||
|
@ -69,13 +104,13 @@ public class PlayerInfoPacket implements ServerPacket {
|
|||
public abstract void write(BinaryWriter writer);
|
||||
}
|
||||
|
||||
public static class AddPlayer extends PlayerInfo {
|
||||
public static class AddPlayer extends PlayerInfo implements ComponentHolder<AddPlayer> {
|
||||
|
||||
public String name;
|
||||
public List<Property> properties;
|
||||
public GameMode gameMode;
|
||||
public int ping;
|
||||
public JsonMessage displayName; // Only text
|
||||
public Component displayName;
|
||||
|
||||
public AddPlayer(UUID uuid, String name, GameMode gameMode, int ping) {
|
||||
super(uuid);
|
||||
|
@ -98,7 +133,27 @@ public class PlayerInfoPacket implements ServerPacket {
|
|||
final boolean hasDisplayName = displayName != null;
|
||||
writer.writeBoolean(hasDisplayName);
|
||||
if (hasDisplayName)
|
||||
writer.writeSizedString(displayName.toString());
|
||||
writer.writeComponent(displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (displayName == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.singleton(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull AddPlayer copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (displayName == null) {
|
||||
return this;
|
||||
} else {
|
||||
AddPlayer addPlayer = new AddPlayer(uuid, name, gameMode, ping);
|
||||
addPlayer.displayName = operator.apply(displayName);
|
||||
return addPlayer;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Property {
|
||||
|
@ -159,11 +214,11 @@ public class PlayerInfoPacket implements ServerPacket {
|
|||
}
|
||||
}
|
||||
|
||||
public static class UpdateDisplayName extends PlayerInfo {
|
||||
public static class UpdateDisplayName extends PlayerInfo implements ComponentHolder<UpdateDisplayName> {
|
||||
|
||||
public JsonMessage displayName; // Only text
|
||||
public Component displayName;
|
||||
|
||||
public UpdateDisplayName(UUID uuid, JsonMessage displayName) {
|
||||
public UpdateDisplayName(UUID uuid, Component displayName) {
|
||||
super(uuid);
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
@ -173,7 +228,25 @@ public class PlayerInfoPacket implements ServerPacket {
|
|||
final boolean hasDisplayName = displayName != null;
|
||||
writer.writeBoolean(hasDisplayName);
|
||||
if (hasDisplayName)
|
||||
writer.writeSizedString(displayName.toString());
|
||||
writer.writeComponent(displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (displayName == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
return Collections.singleton(displayName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull UpdateDisplayName copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (displayName == null) {
|
||||
return this;
|
||||
} else {
|
||||
return new UpdateDisplayName(uuid, operator.apply(displayName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,35 +1,53 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PlayerListHeaderAndFooterPacket implements ServerPacket {
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
private static final String EMPTY_COMPONENT = "{\"translate\":\"\"}";
|
||||
public class PlayerListHeaderAndFooterPacket implements ComponentHoldingServerPacket {
|
||||
public Component header;
|
||||
public Component footer;
|
||||
|
||||
public JsonMessage header; // Only text
|
||||
public JsonMessage footer; // Only text
|
||||
public PlayerListHeaderAndFooterPacket(@Nullable Component header, @Nullable Component footer) {
|
||||
this.header = header;
|
||||
this.footer = footer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
if (header == null) {
|
||||
writer.writeSizedString(EMPTY_COMPONENT);
|
||||
} else {
|
||||
writer.writeSizedString(header.toString());
|
||||
}
|
||||
|
||||
if (footer == null) {
|
||||
writer.writeSizedString(EMPTY_COMPONENT);
|
||||
} else {
|
||||
writer.writeSizedString(footer.toString());
|
||||
}
|
||||
writer.writeComponent(Objects.requireNonNullElse(header, Component.empty()));
|
||||
writer.writeComponent(Objects.requireNonNullElse(footer, Component.empty()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ServerPacketIdentifier.PLAYER_LIST_HEADER_AND_FOOTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
List<Component> components = new ArrayList<>();
|
||||
if (header != null) {
|
||||
components.add(header);
|
||||
}
|
||||
if (footer != null) {
|
||||
components.add(footer);
|
||||
}
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
return new PlayerListHeaderAndFooterPacket(header == null ? null : operator.apply(header), footer == null ? null : operator.apply(footer));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ScoreboardObjectivePacket implements ServerPacket {
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ScoreboardObjectivePacket implements ComponentHoldingServerPacket {
|
||||
|
||||
/**
|
||||
* An unique name for the objective
|
||||
|
@ -21,7 +26,7 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
|||
/**
|
||||
* The text to be displayed for the score
|
||||
*/
|
||||
public JsonMessage objectiveValue; // Only text
|
||||
public Component objectiveValue; // Only text
|
||||
/**
|
||||
* The type how the score is displayed
|
||||
*/
|
||||
|
@ -33,7 +38,7 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
|||
writer.writeByte(mode);
|
||||
|
||||
if (mode == 0 || mode == 2) {
|
||||
writer.writeSizedString(objectiveValue.toString());
|
||||
writer.writeComponent(objectiveValue);
|
||||
writer.writeVarInt(type.ordinal());
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +48,29 @@ public class ScoreboardObjectivePacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.SCOREBOARD_OBJECTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (mode == 0 || mode == 2) {
|
||||
return Collections.singleton(objectiveValue);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (mode == 0 || mode == 2) {
|
||||
ScoreboardObjectivePacket packet = new ScoreboardObjectivePacket();
|
||||
packet.objectiveName = objectiveName;
|
||||
packet.mode = mode;
|
||||
packet.objectiveValue = operator.apply(objectiveValue);
|
||||
packet.type = type;
|
||||
return packet;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This enumeration represents all available types for the scoreboard objective
|
||||
*/
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.kyori.adventure.sound.Sound.Source;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.sound.Sound;
|
||||
import net.minestom.server.sound.SoundCategory;
|
||||
import net.minestom.server.sound.SoundEvent;
|
||||
import net.minestom.server.utils.Position;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -11,15 +12,16 @@ import org.jetbrains.annotations.NotNull;
|
|||
public class SoundEffectPacket implements ServerPacket {
|
||||
|
||||
public int soundId;
|
||||
public SoundCategory soundCategory;
|
||||
public Source soundSource;
|
||||
public int x, y, z;
|
||||
public float volume;
|
||||
public float pitch;
|
||||
|
||||
public static SoundEffectPacket create(SoundCategory category, Sound sound, Position position, float volume, float pitch) {
|
||||
@NotNull
|
||||
public static SoundEffectPacket create(Source category, SoundEvent sound, Position position, float volume, float pitch) {
|
||||
SoundEffectPacket packet = new SoundEffectPacket();
|
||||
packet.soundId = sound.getId();
|
||||
packet.soundCategory = category;
|
||||
packet.soundSource = category;
|
||||
// *8 converts to fixed-point representation with 3 bits for fractional part
|
||||
packet.x = (int) position.getX();
|
||||
packet.y = (int) position.getY();
|
||||
|
@ -28,11 +30,10 @@ public class SoundEffectPacket implements ServerPacket {
|
|||
packet.pitch = pitch;
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeVarInt(soundId);
|
||||
writer.writeVarInt(soundCategory.ordinal());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getSoundSourceValue(soundSource));
|
||||
writer.writeInt(x * 8);
|
||||
writer.writeInt(y * 8);
|
||||
writer.writeInt(z * 8);
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.minestom.server.adventure.ComponentHolder;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TabCompletePacket implements ServerPacket {
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class TabCompletePacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public int transactionId;
|
||||
public int start;
|
||||
|
@ -24,7 +32,7 @@ public class TabCompletePacket implements ServerPacket {
|
|||
writer.writeSizedString(match.match);
|
||||
writer.writeBoolean(match.hasTooltip);
|
||||
if (match.hasTooltip)
|
||||
writer.writeSizedString(match.tooltip.toString());
|
||||
writer.writeComponent(match.tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,10 +41,66 @@ public class TabCompletePacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.TAB_COMPLETE;
|
||||
}
|
||||
|
||||
public static class Match {
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (matches == null || matches.length == 0) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<Component> components = new ArrayList<>(matches.length);
|
||||
for (Match match : matches) {
|
||||
if (match.hasTooltip) {
|
||||
components.add(match.tooltip);
|
||||
}
|
||||
}
|
||||
return components;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (matches == null || matches.length == 0) {
|
||||
return this;
|
||||
} else {
|
||||
TabCompletePacket packet = new TabCompletePacket();
|
||||
packet.transactionId = transactionId;
|
||||
packet.start = start;
|
||||
packet.length = length;
|
||||
packet.matches = new Match[matches.length];
|
||||
|
||||
for (int i = 0; i < matches.length; i++) {
|
||||
packet.matches[i] = matches[i].copyWithOperator(operator);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Match implements ComponentHolder<Match> {
|
||||
public String match;
|
||||
public boolean hasTooltip;
|
||||
public JsonMessage tooltip; // Only text
|
||||
public Component tooltip;
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (hasTooltip) {
|
||||
return Collections.singleton(tooltip);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Match copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (hasTooltip) {
|
||||
Match newMatch = new Match();
|
||||
newMatch.match = match;
|
||||
newMatch.hasTooltip = hasTooltip;
|
||||
newMatch.tooltip = tooltip;
|
||||
return newMatch;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.adventure.AdventurePacketConvertor;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* The packet creates or updates teams
|
||||
*/
|
||||
public class TeamsPacket implements ServerPacket {
|
||||
public class TeamsPacket implements ComponentHoldingServerPacket {
|
||||
|
||||
/**
|
||||
* The registry name of the team
|
||||
|
@ -23,7 +31,7 @@ public class TeamsPacket implements ServerPacket {
|
|||
/**
|
||||
* The display name for the team
|
||||
*/
|
||||
public JsonMessage teamDisplayName;
|
||||
public Component teamDisplayName;
|
||||
/**
|
||||
* The friendly flags to
|
||||
*/
|
||||
|
@ -39,15 +47,15 @@ public class TeamsPacket implements ServerPacket {
|
|||
/**
|
||||
* The color of the team
|
||||
*/
|
||||
public int teamColor;
|
||||
public NamedTextColor teamColor;
|
||||
/**
|
||||
* The prefix of the team
|
||||
*/
|
||||
public JsonMessage teamPrefix;
|
||||
public Component teamPrefix;
|
||||
/**
|
||||
* The suffix of the team
|
||||
*/
|
||||
public JsonMessage teamSuffix;
|
||||
public Component teamSuffix;
|
||||
/**
|
||||
* An array with all entities in the team
|
||||
*/
|
||||
|
@ -66,13 +74,13 @@ public class TeamsPacket implements ServerPacket {
|
|||
switch (action) {
|
||||
case CREATE_TEAM:
|
||||
case UPDATE_TEAM_INFO:
|
||||
writer.writeSizedString(this.teamDisplayName.toString());
|
||||
writer.writeComponent(this.teamDisplayName);
|
||||
writer.writeByte(this.friendlyFlags);
|
||||
writer.writeSizedString(this.nameTagVisibility.getIdentifier());
|
||||
writer.writeSizedString(this.collisionRule.getIdentifier());
|
||||
writer.writeVarInt(this.teamColor);
|
||||
writer.writeSizedString(this.teamPrefix.toString());
|
||||
writer.writeSizedString(this.teamSuffix.toString());
|
||||
writer.writeVarInt(AdventurePacketConvertor.getNamedTextColorValue(this.teamColor));
|
||||
writer.writeComponent(this.teamPrefix);
|
||||
writer.writeComponent(this.teamSuffix);
|
||||
break;
|
||||
case REMOVE_TEAM:
|
||||
|
||||
|
@ -99,6 +107,35 @@ public class TeamsPacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.TEAMS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (this.action == Action.UPDATE_TEAM_INFO || this.action == Action.CREATE_TEAM) {
|
||||
return List.of(teamDisplayName, teamPrefix, teamSuffix);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (this.action == Action.UPDATE_TEAM_INFO || this.action == Action.CREATE_TEAM) {
|
||||
TeamsPacket packet = new TeamsPacket();
|
||||
packet.teamName = teamName;
|
||||
packet.action = action;
|
||||
packet.teamDisplayName = teamDisplayName == null ? null : operator.apply(teamDisplayName);
|
||||
packet.friendlyFlags = friendlyFlags;
|
||||
packet.nameTagVisibility = nameTagVisibility;
|
||||
packet.collisionRule = collisionRule;
|
||||
packet.teamColor = teamColor;
|
||||
packet.teamPrefix = teamPrefix == null ? null : operator.apply(teamPrefix);
|
||||
packet.teamSuffix = teamSuffix == null ? null : operator.apply(teamSuffix);
|
||||
packet.entities = entities;
|
||||
return packet;
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An enumeration which representing all actions for the packet
|
||||
*/
|
||||
|
|
|
@ -1,38 +1,81 @@
|
|||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import net.minestom.server.chat.JsonMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.TickUtils;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TitlePacket implements ServerPacket {
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
import static net.minestom.server.network.packet.server.play.TitlePacket.Action.*;
|
||||
|
||||
public class TitlePacket implements ComponentHoldingServerPacket {
|
||||
|
||||
public Action action;
|
||||
|
||||
public JsonMessage titleText; // Only text
|
||||
|
||||
public JsonMessage subtitleText; // Only text
|
||||
|
||||
public JsonMessage actionBarText; // Only text
|
||||
public Component payload;
|
||||
|
||||
public int fadeIn;
|
||||
public int stay;
|
||||
public int fadeOut;
|
||||
|
||||
/**
|
||||
* Constructs a new title packet from an action that can take a component argument.
|
||||
*
|
||||
* @param action the action
|
||||
* @param payload the payload
|
||||
* @throws IllegalArgumentException if the action is not {@link Action#SET_TITLE},
|
||||
* {@link Action#SET_SUBTITLE} or {@link Action#SET_ACTION_BAR}
|
||||
*/
|
||||
public TitlePacket(@NotNull Action action, @NotNull Component payload) {
|
||||
Validate.isTrue(action == SET_TITLE || action == SET_SUBTITLE || action == SET_ACTION_BAR, "Invalid action type");
|
||||
this.action = action;
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new title packet from a clear or reset action.
|
||||
*
|
||||
* @param action the action
|
||||
* @throws IllegalArgumentException if the action is not {@link Action#RESET},
|
||||
* or {@link Action#HIDE}
|
||||
*/
|
||||
public TitlePacket(@NotNull Action action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new title packet for {@link Action#SET_TIMES_AND_DISPLAY}.
|
||||
*
|
||||
* @param fadeIn the fade in time
|
||||
* @param stay the stay time
|
||||
* @param fadeOut the fade out time
|
||||
*/
|
||||
public TitlePacket(int fadeIn, int stay, int fadeOut) {
|
||||
this.action = SET_TIMES_AND_DISPLAY;
|
||||
this.fadeIn = fadeIn;
|
||||
this.stay = stay;
|
||||
this.fadeOut = fadeOut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull BinaryWriter writer) {
|
||||
writer.writeVarInt(action.ordinal());
|
||||
|
||||
switch (action) {
|
||||
case SET_TITLE:
|
||||
writer.writeSizedString(titleText.toString());
|
||||
break;
|
||||
case SET_SUBTITLE:
|
||||
writer.writeSizedString(subtitleText.toString());
|
||||
break;
|
||||
case SET_ACTION_BAR:
|
||||
writer.writeSizedString(actionBarText.toString());
|
||||
writer.writeComponent(payload);
|
||||
break;
|
||||
case SET_TIMES_AND_DISPLAY:
|
||||
writer.writeInt(fadeIn);
|
||||
|
@ -50,6 +93,24 @@ public class TitlePacket implements ServerPacket {
|
|||
return ServerPacketIdentifier.TITLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Collection<Component> components() {
|
||||
if (action == SET_TITLE || action == SET_SUBTITLE || action == SET_ACTION_BAR) {
|
||||
return Collections.singleton(payload);
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
|
||||
if (action == SET_TITLE || action == SET_SUBTITLE || action == SET_ACTION_BAR) {
|
||||
return new TitlePacket(action, operator.apply(payload));
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
SET_TITLE,
|
||||
SET_SUBTITLE,
|
||||
|
@ -59,4 +120,27 @@ public class TitlePacket implements ServerPacket {
|
|||
RESET
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a collection of title packets from an Adventure title.
|
||||
*
|
||||
* @param title the title
|
||||
* @return the packets
|
||||
*/
|
||||
public static Collection<TitlePacket> of(Title title) {
|
||||
List<TitlePacket> packets = new ArrayList<>(4);
|
||||
|
||||
// base packets
|
||||
packets.add(new TitlePacket(SET_TITLE, title.title()));
|
||||
packets.add(new TitlePacket(SET_SUBTITLE, title.subtitle()));
|
||||
|
||||
// times packet
|
||||
Title.Times times = title.times();
|
||||
if (times != null) {
|
||||
packets.add(new TitlePacket(TickUtils.fromDuration(times.fadeIn(), TickUtils.CLIENT_TICK_MS),
|
||||
TickUtils.fromDuration(times.stay(), TickUtils.CLIENT_TICK_MS),
|
||||
TickUtils.fromDuration(times.fadeOut(), TickUtils.CLIENT_TICK_MS)));
|
||||
}
|
||||
|
||||
return packets;
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue