Merge remote-tracking branch 'upstream/master'
# Conflicts: # .github/workflows/dev-build-release.yml # api/build.gradle.kts # platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java
This commit is contained in:
commit
b2d6cd6d93
30 changed files with 960 additions and 186 deletions
47
.github/workflows/dev-build-release.yml
vendored
Normal file
47
.github/workflows/dev-build-release.yml
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
name: Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: ['*']
|
||||||
|
pull_request:
|
||||||
|
branches: ['*']
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
TYCOONS_REPO_USER: ${{ secrets.EVOKE_REPO_USERNAME }}
|
||||||
|
TYCOONS_REPO_PASS: ${{ secrets.EVOKE_REPO_PASSWORD }}
|
||||||
|
steps:
|
||||||
|
- name: Clone project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install JDK 8
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
java-version: '8'
|
||||||
|
distribution: 'temurin'
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
|
- name: Setup gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Run build & publish with Gradle Wrapper
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
|
run: chmod +x ./gradlew && ./gradlew publishAllPublicationsToMavenRepository
|
||||||
|
|
||||||
|
- name: Run build with Gradle Wrapper
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
|
run: chmod +x ./gradlew && ./gradlew build
|
||||||
|
|
||||||
|
- name: Create Release
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
name: '${{ github.ref_name }}: ${{ github.event.head_commit.message }} (${{ github.sha }})'
|
||||||
|
prerelease: ${{ github.ref != 'refs/heads/master' }}
|
||||||
|
tag_name: ${{ github.ref_name }}-${{ github.sha }}
|
|
@ -1,6 +1,7 @@
|
||||||
plugins {
|
plugins {
|
||||||
entitylib.`shadow-conventions`
|
entitylib.`shadow-conventions`
|
||||||
entitylib.`library-conventions`
|
entitylib.`library-conventions`
|
||||||
|
`el-version`
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
@ -8,4 +9,23 @@ dependencies {
|
||||||
|
|
||||||
compileOnly(libs.bundles.adventure)
|
compileOnly(libs.bundles.adventure)
|
||||||
compileOnly(libs.packetevents.api)
|
compileOnly(libs.packetevents.api)
|
||||||
|
testCompileOnly(libs.packetevents.api)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
javadoc {
|
||||||
|
mustRunAfter(generateVersionsFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcesJar {
|
||||||
|
mustRunAfter(generateVersionsFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<JavaCompile> {
|
||||||
|
dependsOn(generateVersionsFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
generateVersionsFile {
|
||||||
|
packageName = "me.tofaa.entitylib.utils"
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,9 @@
|
||||||
package me.tofaa.entitylib;
|
package me.tofaa.entitylib;
|
||||||
|
|
||||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
|
||||||
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
|
||||||
import com.github.retrooper.packetevents.protocol.world.Location;
|
|
||||||
import me.tofaa.entitylib.container.EntityContainer;
|
import me.tofaa.entitylib.container.EntityContainer;
|
||||||
import me.tofaa.entitylib.tick.TickContainer;
|
import me.tofaa.entitylib.tick.TickContainer;
|
||||||
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
||||||
import me.tofaa.entitylib.wrapper.WrapperPlayer;
|
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
@ -58,4 +53,6 @@ public interface EntityLibAPI<T> {
|
||||||
@NotNull
|
@NotNull
|
||||||
EntityContainer getDefaultContainer();
|
EntityContainer getDefaultContainer();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
UserLocaleProvider getUserLocaleProvider();
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,13 @@ public interface Platform<P> {
|
||||||
*/
|
*/
|
||||||
@NotNull EntityUuidProvider getEntityUuidProvider();
|
@NotNull EntityUuidProvider getEntityUuidProvider();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the provider responsible for retrieving the locale of a user.
|
||||||
|
*
|
||||||
|
* @return a non-null {@link UserLocaleProvider} instance.
|
||||||
|
*/
|
||||||
|
@NotNull UserLocaleProvider getUserLocaleProvider();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the entityId integer provider. This can be provided by a platform if needed.
|
* Sets the entityId integer provider. This can be provided by a platform if needed.
|
||||||
* @param provider the entityId integer provider.
|
* @param provider the entityId integer provider.
|
||||||
|
@ -38,6 +45,12 @@ public interface Platform<P> {
|
||||||
*/
|
*/
|
||||||
void setEntityUuidProvider(@NotNull EntityUuidProvider provider);
|
void setEntityUuidProvider(@NotNull EntityUuidProvider provider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the provider responsible for retrieving the locale of a user.
|
||||||
|
*
|
||||||
|
* @param provider the {@link UserLocaleProvider} instance to be set. Must not be null.
|
||||||
|
*/
|
||||||
|
void setUserLocaleProvider(@NotNull UserLocaleProvider provider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the logger EntityLib uses internally.
|
* @return the logger EntityLib uses internally.
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package me.tofaa.entitylib;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface UserLocaleProvider {
|
||||||
|
Locale locale(UUID user);
|
||||||
|
}
|
|
@ -228,6 +228,7 @@ public class EntityMeta implements EntityMetadataProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annoying java 8 not letting me do OFFSET + amount in the method call so this is a workaround
|
* Annoying java 8 not letting me do OFFSET + amount in the method call so this is a workaround
|
||||||
|
*
|
||||||
* @param value the value to offset
|
* @param value the value to offset
|
||||||
* @param amount the amount to offset by
|
* @param amount the amount to offset by
|
||||||
* @return the offset value
|
* @return the offset value
|
||||||
|
@ -271,12 +272,12 @@ public class EntityMeta implements EntityMetadataProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EntityData> entityData(ClientVersion clientVersion) {
|
public @NotNull List<EntityData<?>> entityData(@NotNull ClientVersion clientVersion) {
|
||||||
return metadata.getEntries(); // TODO: Atm this is useless cause of the way the api works. Might change in the future
|
return metadata.getEntries(); // TODO: Atm this is useless cause of the way the api works. Might change in the future
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<EntityData> entityData() {
|
public @NotNull List<EntityData<?>> entityData() {
|
||||||
return metadata.getEntries();
|
return metadata.getEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package me.tofaa.entitylib.meta;
|
package me.tofaa.entitylib.meta;
|
||||||
|
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
|
||||||
import me.tofaa.entitylib.meta.display.BlockDisplayMeta;
|
import me.tofaa.entitylib.meta.display.BlockDisplayMeta;
|
||||||
import me.tofaa.entitylib.meta.display.ItemDisplayMeta;
|
import me.tofaa.entitylib.meta.display.ItemDisplayMeta;
|
||||||
import me.tofaa.entitylib.meta.display.TextDisplayMeta;
|
import me.tofaa.entitylib.meta.display.TextDisplayMeta;
|
||||||
|
@ -50,9 +49,9 @@ final class MetaConverterRegistry {
|
||||||
MetaConverterRegistry() {
|
MetaConverterRegistry() {
|
||||||
put(ABSTRACT_WIND_CHARGE, SmallFireballMeta.class, SmallFireballMeta::new); // TODO: Verify correctness
|
put(ABSTRACT_WIND_CHARGE, SmallFireballMeta.class, SmallFireballMeta::new); // TODO: Verify correctness
|
||||||
put(AREA_EFFECT_CLOUD, AreaEffectCloudMeta.class, AreaEffectCloudMeta::new);
|
put(AREA_EFFECT_CLOUD, AreaEffectCloudMeta.class, AreaEffectCloudMeta::new);
|
||||||
|
put(ALLAY, LivingEntityMeta.class, LivingEntityMeta::new); // TODO: Implement
|
||||||
put(ARMADILLO, ArmadilloMeta.class, ArmadilloMeta::new); // TODO: Verify correctness
|
put(ARMADILLO, ArmadilloMeta.class, ArmadilloMeta::new); // TODO: Verify correctness
|
||||||
put(ARMOR_STAND, ArmorStandMeta.class, ArmorStandMeta::new);
|
put(ARMOR_STAND, ArmorStandMeta.class, ArmorStandMeta::new);
|
||||||
put(ALLAY, LivingEntityMeta.class, LivingEntityMeta::new); // TODO: Implement
|
|
||||||
put(ARROW, ArrowMeta.class, ArrowMeta::new);
|
put(ARROW, ArrowMeta.class, ArrowMeta::new);
|
||||||
put(AXOLOTL, AxolotlMeta.class, AxolotlMeta::new);
|
put(AXOLOTL, AxolotlMeta.class, AxolotlMeta::new);
|
||||||
put(BAT, BatMeta.class, BatMeta::new);
|
put(BAT, BatMeta.class, BatMeta::new);
|
||||||
|
@ -69,8 +68,9 @@ final class MetaConverterRegistry {
|
||||||
put(CHEST_MINECART, ChestMinecartMeta.class, ChestMinecartMeta::new);
|
put(CHEST_MINECART, ChestMinecartMeta.class, ChestMinecartMeta::new);
|
||||||
put(CHICKEN, ChickenMeta.class, ChickenMeta::new);
|
put(CHICKEN, ChickenMeta.class, ChickenMeta::new);
|
||||||
put(COD, CodMeta.class, CodMeta::new);
|
put(COD, CodMeta.class, CodMeta::new);
|
||||||
put(COW, CowMeta.class, CowMeta::new);
|
|
||||||
put(COMMAND_BLOCK_MINECART, CommandBlockMinecartMeta.class, CommandBlockMinecartMeta::new);
|
put(COMMAND_BLOCK_MINECART, CommandBlockMinecartMeta.class, CommandBlockMinecartMeta::new);
|
||||||
|
put(COW, CowMeta.class, CowMeta::new);
|
||||||
|
put(CREAKING, LivingEntityMeta.class, LivingEntityMeta::new); // TODO: Implement
|
||||||
put(CREEPER, CreeperMeta.class, CreeperMeta::new);
|
put(CREEPER, CreeperMeta.class, CreeperMeta::new);
|
||||||
put(DOLPHIN, DolphinMeta.class, DolphinMeta::new);
|
put(DOLPHIN, DolphinMeta.class, DolphinMeta::new);
|
||||||
put(DONKEY, DonkeyMeta.class, DonkeyMeta::new);
|
put(DONKEY, DonkeyMeta.class, DonkeyMeta::new);
|
||||||
|
@ -80,11 +80,12 @@ final class MetaConverterRegistry {
|
||||||
put(ELDER_GUARDIAN, ElderGuardianMeta.class, ElderGuardianMeta::new);
|
put(ELDER_GUARDIAN, ElderGuardianMeta.class, ElderGuardianMeta::new);
|
||||||
put(END_CRYSTAL, EndCrystalMeta.class, EndCrystalMeta::new);
|
put(END_CRYSTAL, EndCrystalMeta.class, EndCrystalMeta::new);
|
||||||
put(ENDER_DRAGON, EnderDragonMeta.class, EnderDragonMeta::new);
|
put(ENDER_DRAGON, EnderDragonMeta.class, EnderDragonMeta::new);
|
||||||
|
put(ENDER_PEARL, ThrownEnderPearlMeta.class, ThrownEnderPearlMeta::new);
|
||||||
put(ENDERMAN, EndermanMeta.class, EndermanMeta::new);
|
put(ENDERMAN, EndermanMeta.class, EndermanMeta::new);
|
||||||
put(ENDERMITE, EndermiteMeta.class, EndermiteMeta::new);
|
put(ENDERMITE, EndermiteMeta.class, EndermiteMeta::new);
|
||||||
put(EVOKER, EvokerMeta.class, EvokerMeta::new);
|
put(EVOKER, EvokerMeta.class, EvokerMeta::new);
|
||||||
put(EYE_OF_ENDER, EyeOfEnderMeta.class, EyeOfEnderMeta::new);
|
|
||||||
put(EVOKER_FANGS, EvokerFangsMeta.class, EvokerFangsMeta::new);
|
put(EVOKER_FANGS, EvokerFangsMeta.class, EvokerFangsMeta::new);
|
||||||
|
put(EYE_OF_ENDER, EyeOfEnderMeta.class, EyeOfEnderMeta::new);
|
||||||
put(FALLING_BLOCK, FallingBlockMeta.class, FallingBlockMeta::new);
|
put(FALLING_BLOCK, FallingBlockMeta.class, FallingBlockMeta::new);
|
||||||
put(FIREBALL, LargeFireballMeta.class, LargeFireballMeta::new); // TODO: Verify correctness
|
put(FIREBALL, LargeFireballMeta.class, LargeFireballMeta::new); // TODO: Verify correctness
|
||||||
put(FIREWORK_ROCKET, FireworkRocketMeta.class, FireworkRocketMeta::new);
|
put(FIREWORK_ROCKET, FireworkRocketMeta.class, FireworkRocketMeta::new);
|
||||||
|
@ -92,11 +93,13 @@ final class MetaConverterRegistry {
|
||||||
put(FOX, FoxMeta.class, FoxMeta::new);
|
put(FOX, FoxMeta.class, FoxMeta::new);
|
||||||
put(FROG, FrogMeta.class, FrogMeta::new);
|
put(FROG, FrogMeta.class, FrogMeta::new);
|
||||||
put(FURNACE_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
|
put(FURNACE_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
|
||||||
|
put(GHAST, GhastMeta.class, GhastMeta::new);
|
||||||
put(GIANT, GiantMeta.class, GiantMeta::new);
|
put(GIANT, GiantMeta.class, GiantMeta::new);
|
||||||
put(GLOW_ITEM_FRAME, GlowItemFrameMeta.class, GlowItemFrameMeta::new);
|
put(GLOW_ITEM_FRAME, GlowItemFrameMeta.class, GlowItemFrameMeta::new);
|
||||||
put(GLOW_SQUID, GlowSquidMeta.class, GlowSquidMeta::new);
|
put(GLOW_SQUID, GlowSquidMeta.class, GlowSquidMeta::new);
|
||||||
put(GOAT, GoatMeta.class, GoatMeta::new);
|
put(GOAT, GoatMeta.class, GoatMeta::new);
|
||||||
put(GUARDIAN, GuardianMeta.class, GuardianMeta::new);
|
put(GUARDIAN, GuardianMeta.class, GuardianMeta::new);
|
||||||
|
put(HAPPY_GHAST, GhastMeta.class, GhastMeta::new); // TODO: Implement
|
||||||
put(HOGLIN, HoglinMeta.class, HoglinMeta::new);
|
put(HOGLIN, HoglinMeta.class, HoglinMeta::new);
|
||||||
put(HOPPER_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
|
put(HOPPER_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
|
||||||
put(HORSE, HorseMeta.class, HorseMeta::new);
|
put(HORSE, HorseMeta.class, HorseMeta::new);
|
||||||
|
@ -104,35 +107,35 @@ final class MetaConverterRegistry {
|
||||||
put(ILLUSIONER, IllusionerMeta.class, IllusionerMeta::new);
|
put(ILLUSIONER, IllusionerMeta.class, IllusionerMeta::new);
|
||||||
put(INTERACTION, InteractionMeta.class, InteractionMeta::new);
|
put(INTERACTION, InteractionMeta.class, InteractionMeta::new);
|
||||||
put(IRON_GOLEM, IronGolemMeta.class, IronGolemMeta::new);
|
put(IRON_GOLEM, IronGolemMeta.class, IronGolemMeta::new);
|
||||||
|
put(ITEM, ItemEntityMeta.class, ItemEntityMeta::new);
|
||||||
put(ITEM_DISPLAY, ItemDisplayMeta.class, ItemDisplayMeta::new);
|
put(ITEM_DISPLAY, ItemDisplayMeta.class, ItemDisplayMeta::new);
|
||||||
put(ITEM_FRAME, ItemFrameMeta.class, ItemFrameMeta::new);
|
put(ITEM_FRAME, ItemFrameMeta.class, ItemFrameMeta::new);
|
||||||
put(ITEM, ItemEntityMeta.class, ItemEntityMeta::new);
|
|
||||||
put(LEASH_KNOT, LeashKnotMeta.class, LeashKnotMeta::new);
|
put(LEASH_KNOT, LeashKnotMeta.class, LeashKnotMeta::new);
|
||||||
put(LIGHTNING_BOLT, LightningBoltMeta.class, LightningBoltMeta::new);
|
put(LIGHTNING_BOLT, LightningBoltMeta.class, LightningBoltMeta::new);
|
||||||
put(LLAMA, LlamaMeta.class, LlamaMeta::new);
|
put(LLAMA, LlamaMeta.class, LlamaMeta::new);
|
||||||
put(LLAMA_SPIT, LlamaSpitMeta.class, LlamaSpitMeta::new);
|
put(LLAMA_SPIT, LlamaSpitMeta.class, LlamaSpitMeta::new);
|
||||||
put(MAGMA_CUBE, MagmaCubeMeta.class, MagmaCubeMeta::new);
|
put(MAGMA_CUBE, MagmaCubeMeta.class, MagmaCubeMeta::new);
|
||||||
put(MARKER, MarkerMeta.class, MarkerMeta::new);
|
put(MARKER, MarkerMeta.class, MarkerMeta::new);
|
||||||
|
put(MOOSHROOM, MooshroomMeta.class, MooshroomMeta::new);
|
||||||
put(MULE, MuleMeta.class, MuleMeta::new);
|
put(MULE, MuleMeta.class, MuleMeta::new);
|
||||||
put(OCELOT, OcelotMeta.class, OcelotMeta::new);
|
put(OCELOT, OcelotMeta.class, OcelotMeta::new);
|
||||||
put(PAINTING, PaintingMeta.class, PaintingMeta::new);
|
put(PAINTING, PaintingMeta.class, PaintingMeta::new);
|
||||||
put(PANDA, PandaMeta.class, PandaMeta::new);
|
put(PANDA, PandaMeta.class, PandaMeta::new);
|
||||||
put(POTION, ThrownPotionMeta.class, ThrownPotionMeta::new);
|
|
||||||
put(PARROT, ParrotMeta.class, ParrotMeta::new);
|
put(PARROT, ParrotMeta.class, ParrotMeta::new);
|
||||||
|
put(PHANTOM, PhantomMeta.class, PhantomMeta::new);
|
||||||
put(PIG, PigMeta.class, PigMeta::new);
|
put(PIG, PigMeta.class, PigMeta::new);
|
||||||
put(PIGLIN, PiglinMeta.class, PiglinMeta::new);
|
put(PIGLIN, PiglinMeta.class, PiglinMeta::new);
|
||||||
put(PIGLIN_BRUTE, PiglinBruteMeta.class, PiglinBruteMeta::new);
|
put(PIGLIN_BRUTE, PiglinBruteMeta.class, PiglinBruteMeta::new);
|
||||||
put(PILLAGER, PillagerMeta.class, PillagerMeta::new);
|
put(PILLAGER, PillagerMeta.class, PillagerMeta::new);
|
||||||
put(PLAYER, PlayerMeta.class, PlayerMeta::new);
|
put(PLAYER, PlayerMeta.class, PlayerMeta::new);
|
||||||
put(POLAR_BEAR, PolarBearMeta.class, PolarBearMeta::new);
|
put(POLAR_BEAR, PolarBearMeta.class, PolarBearMeta::new);
|
||||||
put(POTION, ThrownTridentMeta.class, ThrownTridentMeta::new);
|
put(POTION, ThrownPotionMeta.class, ThrownPotionMeta::new);
|
||||||
put(PRIMED_TNT, PrimedTntMeta.class, PrimedTntMeta::new);
|
put(PRIMED_TNT, PrimedTntMeta.class, PrimedTntMeta::new);
|
||||||
put(PUFFERFISH, PufferFishMeta.class, PufferFishMeta::new);
|
put(PUFFERFISH, PufferFishMeta.class, PufferFishMeta::new);
|
||||||
put(RABBIT, RabbitMeta.class, RabbitMeta::new);
|
put(RABBIT, RabbitMeta.class, RabbitMeta::new);
|
||||||
put(RAVAGER, RavagerMeta.class, RavagerMeta::new);
|
put(RAVAGER, RavagerMeta.class, RavagerMeta::new);
|
||||||
put(SALMON, SalmonMeta.class, SalmonMeta::new);
|
put(SALMON, SalmonMeta.class, SalmonMeta::new);
|
||||||
put(SHEEP, SheepMeta.class, SheepMeta::new);
|
put(SHEEP, SheepMeta.class, SheepMeta::new);
|
||||||
put(SNOWBALL, SnowballMeta.class, SnowballMeta::new);
|
|
||||||
put(SHULKER, ShulkerMeta.class, ShulkerMeta::new);
|
put(SHULKER, ShulkerMeta.class, ShulkerMeta::new);
|
||||||
put(SHULKER_BULLET, ShulkerBulletMeta.class, ShulkerBulletMeta::new);
|
put(SHULKER_BULLET, ShulkerBulletMeta.class, ShulkerBulletMeta::new);
|
||||||
put(SILVERFISH, SilverfishMeta.class, SilverfishMeta::new);
|
put(SILVERFISH, SilverfishMeta.class, SilverfishMeta::new);
|
||||||
|
@ -142,14 +145,16 @@ final class MetaConverterRegistry {
|
||||||
put(SMALL_FIREBALL, SmallFireballMeta.class, SmallFireballMeta::new);
|
put(SMALL_FIREBALL, SmallFireballMeta.class, SmallFireballMeta::new);
|
||||||
put(SNIFFER, SnifferMeta.class, SnifferMeta::new);
|
put(SNIFFER, SnifferMeta.class, SnifferMeta::new);
|
||||||
put(SNOW_GOLEM, SnowGolemMeta.class, SnowGolemMeta::new);
|
put(SNOW_GOLEM, SnowGolemMeta.class, SnowGolemMeta::new);
|
||||||
|
put(SNOWBALL, SnowballMeta.class, SnowballMeta::new);
|
||||||
put(SPAWNER_MINECART, SpawnerMinecartMeta.class, SpawnerMinecartMeta::new);
|
put(SPAWNER_MINECART, SpawnerMinecartMeta.class, SpawnerMinecartMeta::new);
|
||||||
put(SPIDER, SpiderMeta.class, SpiderMeta::new);
|
put(SPIDER, SpiderMeta.class, SpiderMeta::new);
|
||||||
|
put(SQUID, SquidMeta.class, SquidMeta::new);
|
||||||
put(STRAY, StrayMeta.class, StrayMeta::new);
|
put(STRAY, StrayMeta.class, StrayMeta::new);
|
||||||
put(STRIDER, StriderMeta.class, StriderMeta::new);
|
put(STRIDER, StriderMeta.class, StriderMeta::new);
|
||||||
put(TADPOLE, LivingEntityMeta.class, LivingEntityMeta::new); // TODO: Implement
|
put(TADPOLE, LivingEntityMeta.class, LivingEntityMeta::new); // TODO: Implement
|
||||||
put(TEXT_DISPLAY, TextDisplayMeta.class, TextDisplayMeta::new);
|
put(TEXT_DISPLAY, TextDisplayMeta.class, TextDisplayMeta::new);
|
||||||
put(THROWN_EXP_BOTTLE, ThrownExpBottleMeta.class, ThrownExpBottleMeta::new);
|
put(THROWN_EXP_BOTTLE, ThrownExpBottleMeta.class, ThrownExpBottleMeta::new);
|
||||||
put(ENDER_PEARL, ThrownEnderPearlMeta.class, ThrownEnderPearlMeta::new);
|
put(TNT, TntMeta.class, TntMeta::new);
|
||||||
put(TNT_MINECART, TntMinecartMeta.class, TntMinecartMeta::new);
|
put(TNT_MINECART, TntMinecartMeta.class, TntMinecartMeta::new);
|
||||||
put(TRADER_LLAMA, TraderLlamaMeta.class, TraderLlamaMeta::new);
|
put(TRADER_LLAMA, TraderLlamaMeta.class, TraderLlamaMeta::new);
|
||||||
put(TRIDENT, ThrownTridentMeta.class, ThrownTridentMeta::new);
|
put(TRIDENT, ThrownTridentMeta.class, ThrownTridentMeta::new);
|
||||||
|
|
|
@ -19,8 +19,8 @@ public class Metadata {
|
||||||
|
|
||||||
private final int entityId;
|
private final int entityId;
|
||||||
private volatile boolean notifyAboutChanges = true;
|
private volatile boolean notifyAboutChanges = true;
|
||||||
private final HashMap<Byte, EntityData> notNotifiedChanges = new HashMap<>();
|
private final HashMap<Byte, EntityData<?>> notNotifiedChanges = new HashMap<>();
|
||||||
private final ConcurrentHashMap<Byte, EntityData> metadataMap = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<Byte, EntityData<?>> metadataMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
public Metadata(int entityId) {
|
public Metadata(int entityId) {
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
|
@ -47,13 +47,13 @@ public class Metadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T getIndex(byte index, @Nullable T defaultValue) {
|
public <T> T getIndex(byte index, @Nullable T defaultValue) {
|
||||||
EntityData value = this.metadataMap.get(index);
|
EntityData<?> value = this.metadataMap.get(index);
|
||||||
return value != null ? (T) value.getValue() : defaultValue;
|
return value != null ? (T) value.getValue() : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> void setIndex(byte index, @NotNull EntityDataType<T> dataType, T value) {
|
public <T> void setIndex(byte index, @NotNull EntityDataType<T> dataType, T value) {
|
||||||
|
|
||||||
final EntityData entry = new EntityData(index, dataType, value);
|
final EntityData<?> entry = new EntityData<>(index, dataType, value);
|
||||||
this.metadataMap.put(index, entry);
|
this.metadataMap.put(index, entry);
|
||||||
|
|
||||||
final Optional<EntityLibAPI<?>> optionalApi = EntityLib.getOptionalApi();
|
final Optional<EntityLibAPI<?>> optionalApi = EntityLib.getOptionalApi();
|
||||||
|
@ -75,7 +75,7 @@ public class Metadata {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<EntityData> entries = null;
|
List<EntityData<?>> entries = null;
|
||||||
synchronized (this.notNotifiedChanges) {
|
synchronized (this.notNotifiedChanges) {
|
||||||
this.notifyAboutChanges = notifyAboutChanges;
|
this.notifyAboutChanges = notifyAboutChanges;
|
||||||
if (notifyAboutChanges) {
|
if (notifyAboutChanges) {
|
||||||
|
@ -96,7 +96,7 @@ public class Metadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMetaFromPacket(WrapperPlayServerEntityMetadata wrapper) {
|
public void setMetaFromPacket(WrapperPlayServerEntityMetadata wrapper) {
|
||||||
for (EntityData data : wrapper.getEntityMetadata()) {
|
for (EntityData<?> data : wrapper.getEntityMetadata()) {
|
||||||
metadataMap.put((byte) data.getIndex(), data);
|
metadataMap.put((byte) data.getIndex(), data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ public class Metadata {
|
||||||
return notifyAboutChanges;
|
return notifyAboutChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull List<EntityData> getEntries() {
|
@NotNull List<EntityData<?>> getEntries() {
|
||||||
return Collections.unmodifiableList(new ArrayList<>(metadataMap.values()));
|
return Collections.unmodifiableList(new ArrayList<>(metadataMap.values()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package me.tofaa.entitylib.meta.display;
|
package me.tofaa.entitylib.meta.display;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
|
|
||||||
public class BlockDisplayMeta extends AbstractDisplayMeta {
|
public class BlockDisplayMeta extends AbstractDisplayMeta {
|
||||||
|
@ -20,4 +22,11 @@ public class BlockDisplayMeta extends AbstractDisplayMeta {
|
||||||
super.metadata.setIndex(OFFSET, EntityDataTypes.BLOCK_STATE, blockId);
|
super.metadata.setIndex(OFFSET, EntityDataTypes.BLOCK_STATE, blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WrappedBlockState getBlockState() {
|
||||||
|
return WrappedBlockState.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), getBlockId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockState(WrappedBlockState blockState) {
|
||||||
|
setBlockId(blockState.getGlobalId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package me.tofaa.entitylib.meta.mobs.golem;
|
package me.tofaa.entitylib.meta.mobs.golem;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.color.DyeColor;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
import com.github.retrooper.packetevents.protocol.world.Direction;
|
import com.github.retrooper.packetevents.protocol.world.Direction;
|
||||||
import com.github.retrooper.packetevents.util.Vector3i;
|
import com.github.retrooper.packetevents.util.Vector3i;
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
import me.tofaa.entitylib.meta.types.MobMeta;
|
import me.tofaa.entitylib.meta.types.MobMeta;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ -13,42 +15,43 @@ public class ShulkerMeta extends MobMeta {
|
||||||
public static final byte OFFSET = MobMeta.MAX_OFFSET;
|
public static final byte OFFSET = MobMeta.MAX_OFFSET;
|
||||||
public static final byte MAX_OFFSET = OFFSET + 1;
|
public static final byte MAX_OFFSET = OFFSET + 1;
|
||||||
|
|
||||||
|
private static final DyeColor[] DYE_COLORS = DyeColor.values();
|
||||||
|
|
||||||
|
|
||||||
public ShulkerMeta(int entityId, Metadata metadata) {
|
public ShulkerMeta(int entityId, Metadata metadata) {
|
||||||
super(entityId, metadata);
|
super(entityId, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction getAttachFace() {
|
public Direction getAttachFace() {
|
||||||
return super.metadata.getIndex(OFFSET, Direction.DOWN);
|
return super.metadata.getIndex((byte)16, Direction.DOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAttachFace(Direction value) {
|
public void setAttachFace(Direction value) {
|
||||||
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value.ordinal());
|
super.metadata.setIndex((byte)16, EntityDataTypes.INT, value.ordinal());
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<Vector3i> getAttachmentPosition() {
|
|
||||||
return super.metadata.getIndex(offset(OFFSET, 1), Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAttachmentPosition(Vector3i value) {
|
|
||||||
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.OPTIONAL_BLOCK_POSITION, Optional.of(value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getShieldHeight() {
|
public byte getShieldHeight() {
|
||||||
return super.metadata.getIndex(offset(OFFSET, 2), (byte) 0);
|
return super.metadata.getIndex(offset(OFFSET, 1), (byte) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShieldHeight(byte value) {
|
public void setShieldHeight(byte value) {
|
||||||
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BYTE, value);
|
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BYTE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getColor() {
|
public byte getColor() {
|
||||||
return super.metadata.getIndex(offset(OFFSET, 3), (byte) 10);
|
return super.metadata.getIndex(offset(OFFSET, 2), (byte) 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DyeColor getColorEnum() {
|
||||||
|
return DYE_COLORS[getColor()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setColor(byte value) {
|
public void setColor(byte value) {
|
||||||
super.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BYTE, value);
|
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BYTE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setColor(DyeColor color) {
|
||||||
|
setColor((byte)color.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
package me.tofaa.entitylib.meta.mobs.horse;
|
package me.tofaa.entitylib.meta.mobs.horse;
|
||||||
|
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
import me.tofaa.entitylib.meta.types.MobMeta;
|
import me.tofaa.entitylib.meta.types.AgeableMeta;
|
||||||
|
|
||||||
import java.util.Optional;
|
public abstract class BaseHorseMeta extends AgeableMeta {
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
public abstract class BaseHorseMeta extends MobMeta {
|
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
|
||||||
|
public static final byte MAX_OFFSET = OFFSET + 1;
|
||||||
public static final byte OFFSET = MobMeta.MAX_OFFSET;
|
|
||||||
public static final byte MAX_OFFSET = OFFSET + 2;
|
|
||||||
|
|
||||||
private final static byte TAMED_BIT = 0x02;
|
private final static byte TAMED_BIT = 0x02;
|
||||||
private final static byte SADDLED_BIT = 0x04;
|
private final static byte SADDLED_BIT = 0x04;
|
||||||
|
@ -70,13 +66,4 @@ public abstract class BaseHorseMeta extends MobMeta {
|
||||||
public void setMouthOpen(boolean value) {
|
public void setMouthOpen(boolean value) {
|
||||||
setMaskBit(OFFSET, MOUTH_OPEN_BIT, value);
|
setMaskBit(OFFSET, MOUTH_OPEN_BIT, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<UUID> getOwner() {
|
|
||||||
return super.metadata.getIndex(offset(OFFSET, 1), Optional.empty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOwner(UUID value) {
|
|
||||||
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.OPTIONAL_UUID, Optional.of(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package me.tofaa.entitylib.meta.mobs.monster;
|
package me.tofaa.entitylib.meta.mobs.monster;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
import me.tofaa.entitylib.meta.types.MobMeta;
|
import me.tofaa.entitylib.meta.types.MobMeta;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class EndermanMeta extends MobMeta {
|
public class EndermanMeta extends MobMeta {
|
||||||
|
|
||||||
|
@ -24,6 +25,20 @@ public class EndermanMeta extends MobMeta {
|
||||||
super.metadata.setIndex(OFFSET, EntityDataTypes.OPTIONAL_INT, Optional.ofNullable(value));
|
super.metadata.setIndex(OFFSET, EntityDataTypes.OPTIONAL_INT, Optional.ofNullable(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WrappedBlockState getCarriedBlockState() {
|
||||||
|
Integer carriedBlockID = getCarriedBlockID();
|
||||||
|
if (carriedBlockID == null) return null;
|
||||||
|
return WrappedBlockState.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), carriedBlockID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCarriedBlockState(WrappedBlockState blockState) {
|
||||||
|
if (blockState == null) {
|
||||||
|
setCarriedBlockID(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCarriedBlockID(blockState.getGlobalId());
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isScreaming() {
|
public boolean isScreaming() {
|
||||||
return super.metadata.getIndex(offset(OFFSET, 1), false);
|
return super.metadata.getIndex(offset(OFFSET, 1), false);
|
||||||
}
|
}
|
||||||
|
@ -33,7 +48,7 @@ public class EndermanMeta extends MobMeta {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStaring() {
|
public boolean isStaring() {
|
||||||
return super.metadata.getIndex(offset(OFFSET, 2), false);
|
return super.metadata.getIndex(offset(OFFSET, 2), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStaring(boolean value) {
|
public void setStaring(boolean value) {
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package me.tofaa.entitylib.meta.other;
|
package me.tofaa.entitylib.meta.other;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||||
import com.github.retrooper.packetevents.util.Vector3i;
|
import com.github.retrooper.packetevents.util.Vector3i;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
|
@ -34,6 +36,14 @@ public class FallingBlockMeta extends EntityMeta implements ObjectData {
|
||||||
this.blockStateId = blockStateId;
|
this.blockStateId = blockStateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WrappedBlockState getBlockState() {
|
||||||
|
return WrappedBlockState.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), getBlockStateId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockState(WrappedBlockState blockState) {
|
||||||
|
setBlockStateId(blockState.getGlobalId());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getObjectData() {
|
public int getObjectData() {
|
||||||
return blockStateId;
|
return blockStateId;
|
||||||
|
|
42
api/src/main/java/me/tofaa/entitylib/meta/other/TntMeta.java
Normal file
42
api/src/main/java/me/tofaa/entitylib/meta/other/TntMeta.java
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package me.tofaa.entitylib.meta.other;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.states.type.StateTypes;
|
||||||
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
|
|
||||||
|
public class TntMeta extends EntityMeta {
|
||||||
|
public static final byte OFFSET = EntityMeta.MAX_OFFSET;
|
||||||
|
public static final byte MAX_OFFSET = OFFSET + 2;
|
||||||
|
|
||||||
|
public TntMeta(int entityId, Metadata metadata) {
|
||||||
|
super(entityId, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFuseTime() {
|
||||||
|
return super.metadata.getIndex(OFFSET, 80);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFuseTime(int value) {
|
||||||
|
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlockData() {
|
||||||
|
return super.metadata.getIndex(offset(OFFSET, 1), StateTypes.TNT.createBlockState().getGlobalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockData(int blockData) {
|
||||||
|
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BLOCK_STATE, blockData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrappedBlockState getBlockState() {
|
||||||
|
return WrappedBlockState.getByGlobalId(PacketEvents.getAPI().getServerManager().getVersion().toClientVersion(), getBlockData());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBlockState(WrappedBlockState blockState) {
|
||||||
|
setBlockData(blockState.getGlobalId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java
Normal file
34
api/src/main/java/me/tofaa/entitylib/utils/PacketUtil.java
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
package me.tofaa.entitylib.utils;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||||
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.translation.GlobalTranslator;
|
||||||
|
|
||||||
|
public class PacketUtil {
|
||||||
|
private PacketUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void renderPacket(UUID user, WrapperPlayServerEntityMetadata metadata) {
|
||||||
|
Locale locale = EntityLib.getApi().getUserLocaleProvider().locale(user);
|
||||||
|
for (final EntityData<?> entityData : metadata.getEntityMetadata()) {
|
||||||
|
if (entityData.getType() == EntityDataTypes.ADV_COMPONENT) {
|
||||||
|
Component component = (Component) entityData.getValue();
|
||||||
|
final Component rendered = GlobalTranslator.render(component, locale);
|
||||||
|
((EntityData<Component>) entityData).setValue(rendered);
|
||||||
|
} else if (entityData.getType() == EntityDataTypes.OPTIONAL_ADV_COMPONENT) {
|
||||||
|
final Optional<Component> optional = (Optional<Component>) entityData.getValue();
|
||||||
|
if (optional.isPresent()) {
|
||||||
|
final Component component = optional.get();
|
||||||
|
final Component rendered = GlobalTranslator.render(component, locale);
|
||||||
|
((EntityData<Optional<Component>>) entityData).setValue(Optional.of(rendered));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,21 +25,57 @@ public class ViewerEngine {
|
||||||
private final Set<WrapperEntity> tracked;
|
private final Set<WrapperEntity> tracked;
|
||||||
private final ViewerEngineListener listener;
|
private final ViewerEngineListener listener;
|
||||||
private Executor executor;
|
private Executor executor;
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of ViewerEngine
|
||||||
|
* It is recommended to specify explicitly the Executor that should be used.
|
||||||
|
*/
|
||||||
public ViewerEngine() {
|
public ViewerEngine() {
|
||||||
|
this(Executors.newSingleThreadExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of ViewerEngine with a specific executor. Depending on your rules one thread might not be enough
|
||||||
|
* @param executor The executor that is used to process entity tracking.
|
||||||
|
*/
|
||||||
|
public ViewerEngine(Executor executor) {
|
||||||
this.globalRules = new CopyOnWriteArrayList<>();
|
this.globalRules = new CopyOnWriteArrayList<>();
|
||||||
this.tracked = Collections.newSetFromMap(new WeakHashMap<>());
|
this.tracked = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
this.executor = Executors.newSingleThreadExecutor();
|
this.executor = executor;
|
||||||
this.listener = new ViewerEngineListener(this);
|
this.listener = new ViewerEngineListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables this viewer engine.
|
||||||
|
* Registers a viewer engine listener to handle tracking
|
||||||
|
*/
|
||||||
public void enable() {
|
public void enable() {
|
||||||
|
if (enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
enabled = true;
|
||||||
EntityLib.getApi().getPacketEvents().getEventManager().registerListener(listener);
|
EntityLib.getApi().getPacketEvents().getEventManager().registerListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables this viewer engine.
|
||||||
|
* Unregisters the viewer engine listener that handles tracking.
|
||||||
|
*/
|
||||||
public void disable() {
|
public void disable() {
|
||||||
|
if (!enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
enabled = false;
|
||||||
EntityLib.getApi().getPacketEvents().getEventManager().unregisterListener(listener);
|
EntityLib.getApi().getPacketEvents().getEventManager().unregisterListener(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes and updates every tracked by this viewer engine entities viewers to see if they follow the spawning rules.
|
||||||
|
* If they do not they will no longer see the entity;
|
||||||
|
*/
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
getTracked0().forEach(entity -> {
|
getTracked0().forEach(entity -> {
|
||||||
for (UUID viewer : entity.getViewers()) {
|
for (UUID viewer : entity.getViewers()) {
|
||||||
|
@ -58,19 +94,40 @@ public class ViewerEngine {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells this ViewerEngine to begin tracking a specific {@link WrapperEntity}
|
||||||
|
* @param entity the entity to begin tracking.
|
||||||
|
*/
|
||||||
public void track(@NotNull WrapperEntity entity) {
|
public void track(@NotNull WrapperEntity entity) {
|
||||||
tracked.add(entity);
|
tracked.add(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells this ViewerEngine to stop tracking a specific {@link WrapperEntity}
|
||||||
|
* @param entity the entity to stop tracking.
|
||||||
|
*/
|
||||||
|
public void untrack(@NotNull WrapperEntity entity) {
|
||||||
|
tracked.remove(entity);
|
||||||
|
}
|
||||||
|
|
||||||
public void clearTracked() {
|
public void clearTracked() {
|
||||||
tracked.clear();
|
tracked.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a viewer/user validates every viewer rule handled by this viewer engine or not.
|
||||||
|
* @param user The user to check
|
||||||
|
* @param entity The entity that is getting its own viewer rules checked as well as the global defined one with {@link ViewerEngine#addViewerRule(ViewerRule)}
|
||||||
|
* @return true if the user passed and did not fail any rules, false otherwise
|
||||||
|
*/
|
||||||
public boolean canSpawnFor(User user, WrapperEntity entity) {
|
public boolean canSpawnFor(User user, WrapperEntity entity) {
|
||||||
if (entity.getViewerRules().stream().anyMatch(rule -> rule.shouldSee(user))) return true;
|
if (entity.getViewerRules().stream().anyMatch(rule -> rule.shouldSee(user))) return true;
|
||||||
return globalRules.stream().anyMatch(rule -> rule.shouldSee(user));
|
return globalRules.stream().anyMatch(rule -> rule.shouldSee(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Same as {@link ViewerEngine#canSpawnFor(User, WrapperEntity)} but with UUID instead of User
|
||||||
|
*/
|
||||||
public boolean canSpawnFor(UUID userId, WrapperEntity entity) {
|
public boolean canSpawnFor(UUID userId, WrapperEntity entity) {
|
||||||
User user = EntityLib.getApi().getPacketEvents().getProtocolManager().getUser(
|
User user = EntityLib.getApi().getPacketEvents().getProtocolManager().getUser(
|
||||||
EntityLib.getApi().getPacketEvents().getProtocolManager().getChannel(userId)
|
EntityLib.getApi().getPacketEvents().getProtocolManager().getChannel(userId)
|
||||||
|
@ -79,6 +136,9 @@ public class ViewerEngine {
|
||||||
return canSpawnFor(user, entity);
|
return canSpawnFor(user, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return An unmodifiable view of the entities that are being tracked.
|
||||||
|
*/
|
||||||
public @UnmodifiableView Collection<WrapperEntity> getTracked() {
|
public @UnmodifiableView Collection<WrapperEntity> getTracked() {
|
||||||
return Collections.unmodifiableCollection(tracked);
|
return Collections.unmodifiableCollection(tracked);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,31 +5,44 @@ import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
import com.github.retrooper.packetevents.protocol.world.Location;
|
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||||
import com.github.retrooper.packetevents.util.Vector3d;
|
import com.github.retrooper.packetevents.util.Vector3d;
|
||||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerBundle;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRotation;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityTeleport;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityVelocity;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSetPassengers;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSystemChatMessage;
|
||||||
import me.tofaa.entitylib.EntityLib;
|
import me.tofaa.entitylib.EntityLib;
|
||||||
import me.tofaa.entitylib.container.EntityContainer;
|
import me.tofaa.entitylib.container.EntityContainer;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
import me.tofaa.entitylib.meta.types.ObjectData;
|
import me.tofaa.entitylib.meta.types.ObjectData;
|
||||||
import me.tofaa.entitylib.tick.Tickable;
|
import me.tofaa.entitylib.tick.Tickable;
|
||||||
|
import me.tofaa.entitylib.utils.PacketUtil;
|
||||||
import me.tofaa.entitylib.ve.ViewerRule;
|
import me.tofaa.entitylib.ve.ViewerRule;
|
||||||
import me.tofaa.entitylib.wrapper.spawning.SpawnPacketProvider;
|
import me.tofaa.entitylib.wrapper.spawning.SpawnPacketProvider;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.UnmodifiableView;
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public class WrapperEntity implements Tickable {
|
public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
private final UUID uuid;
|
private final UUID uuid;
|
||||||
private final int entityId;
|
private final int entityId;
|
||||||
private EntityType entityType;
|
private final EntityType entityType;
|
||||||
private EntityMeta entityMeta;
|
private final EntityMeta entityMeta;
|
||||||
private boolean ticking;
|
private boolean ticking;
|
||||||
protected Location location;
|
protected Location location;
|
||||||
private Location preRidingLocation;
|
private Location preRidingLocation;
|
||||||
|
@ -62,6 +75,7 @@ public class WrapperEntity implements Tickable {
|
||||||
public WrapperEntity(UUID uuid, EntityType entityType) {
|
public WrapperEntity(UUID uuid, EntityType entityType) {
|
||||||
this(EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType), uuid, entityType);
|
this(EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType), uuid, entityType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperEntity(EntityType entityType) {
|
public WrapperEntity(EntityType entityType) {
|
||||||
this(EntityLib.getPlatform().getEntityUuidProvider().provide(entityType), entityType);
|
this(EntityLib.getPlatform().getEntityUuidProvider().provide(entityType), entityType);
|
||||||
}
|
}
|
||||||
|
@ -72,25 +86,20 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
public boolean spawn(Location location, EntityContainer parent) {
|
public boolean spawn(Location location, EntityContainer parent) {
|
||||||
if (spawned) return false;
|
if (spawned) return false;
|
||||||
|
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.spawned = true;
|
this.spawned = true;
|
||||||
|
|
||||||
sendPacketsToViewers(
|
sendPacketsToViewers(
|
||||||
new WrapperPlayServerSpawnEntity(
|
createSpawnPacket(),
|
||||||
entityId,
|
|
||||||
Optional.of(this.uuid),
|
|
||||||
entityType,
|
|
||||||
location.getPosition(),
|
|
||||||
location.getPitch(),
|
|
||||||
location.getYaw(),
|
|
||||||
location.getYaw(),
|
|
||||||
getObjectData(),
|
|
||||||
createVeloPacket()
|
|
||||||
),
|
|
||||||
entityMeta.createPacket()
|
entityMeta.createPacket()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this instanceof WrapperLivingEntity) {
|
if (this instanceof WrapperLivingEntity) {
|
||||||
sendPacketsToViewers(((WrapperLivingEntity)this).getAttributes().createPacket());
|
WrapperLivingEntity wrapperLivingEntity = (WrapperLivingEntity) this;
|
||||||
|
wrapperLivingEntity.createSpawnPackets().forEach(this::sendPacketsToViewers);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
parent.addEntity(this);
|
parent.addEntity(this);
|
||||||
return true;
|
return true;
|
||||||
|
@ -101,7 +110,7 @@ public class WrapperEntity implements Tickable {
|
||||||
return SpawnPacketProvider.GENERAL.provide(this);
|
return SpawnPacketProvider.GENERAL.provide(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean spawn(Location location) {
|
public boolean spawn(@NotNull Location location) {
|
||||||
return spawn(location, EntityLib.getApi().getDefaultContainer());
|
return spawn(location, EntityLib.getApi().getDefaultContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,6 +119,7 @@ public class WrapperEntity implements Tickable {
|
||||||
if (entityMeta instanceof ObjectData) {
|
if (entityMeta instanceof ObjectData) {
|
||||||
return ((ObjectData) entityMeta).getObjectData();
|
return ((ObjectData) entityMeta).getObjectData();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +127,7 @@ public class WrapperEntity implements Tickable {
|
||||||
public Optional<Vector3d> createVeloPacket() {
|
public Optional<Vector3d> createVeloPacket() {
|
||||||
Optional<Vector3d> velocity;
|
Optional<Vector3d> velocity;
|
||||||
double veloX = 0, veloY = 0, veloZ = 0;
|
double veloX = 0, veloY = 0, veloZ = 0;
|
||||||
|
|
||||||
if (entityMeta instanceof ObjectData) {
|
if (entityMeta instanceof ObjectData) {
|
||||||
ObjectData od = (ObjectData) entityMeta;
|
ObjectData od = (ObjectData) entityMeta;
|
||||||
if (od.requiresVelocityPacketAtSpawn()) {
|
if (od.requiresVelocityPacketAtSpawn()) {
|
||||||
|
@ -126,11 +137,13 @@ public class WrapperEntity implements Tickable {
|
||||||
veloZ = veloPacket.getVelocity().getZ();
|
veloZ = veloPacket.getVelocity().getZ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (veloX == 0 && veloY == 0 && veloZ == 0) {
|
if (veloX == 0 && veloY == 0 && veloZ == 0) {
|
||||||
velocity = Optional.of(Vector3d.zero());
|
velocity = Optional.of(Vector3d.zero());
|
||||||
} else {
|
} else {
|
||||||
velocity = Optional.of(new Vector3d(veloX, veloY, veloZ));
|
velocity = Optional.of(new Vector3d(veloX, veloY, veloZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,37 +154,37 @@ public class WrapperEntity implements Tickable {
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
parent.removeEntity(this, true);
|
parent.removeEntity(this, true);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
despawn();
|
despawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void despawn() {
|
public void despawn() {
|
||||||
if (!spawned) return;
|
if (!spawned) return;
|
||||||
|
|
||||||
spawned = false;
|
spawned = false;
|
||||||
|
|
||||||
if (this instanceof WrapperPlayer) {
|
if (this instanceof WrapperPlayer) {
|
||||||
WrapperPlayer p = (WrapperPlayer) this;
|
WrapperPlayer p = (WrapperPlayer) this;
|
||||||
sendPacketsToViewers(p.tabListRemovePacket());
|
sendPacketsToViewers(p.tabListRemovePacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPacketToViewers(new WrapperPlayServerDestroyEntities(entityId));
|
sendPacketToViewers(new WrapperPlayServerDestroyEntities(entityId));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void teleport(@NotNull Location location, boolean onGround) {
|
public void teleport(@NotNull Location location, boolean onGround) {
|
||||||
if (!spawned) {
|
if (!spawned) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.onGround = onGround;
|
this.onGround = onGround;
|
||||||
sendPacketToViewers(
|
|
||||||
new WrapperPlayServerEntityTeleport(
|
sendPacketToViewers(new WrapperPlayServerEntityTeleport(
|
||||||
entityId,
|
entityId,
|
||||||
location.getPosition(),
|
location.getPosition(),
|
||||||
location.getYaw(),
|
location.getYaw(),
|
||||||
location.getPitch(),
|
location.getPitch(),
|
||||||
onGround
|
onGround
|
||||||
)
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void teleport(@NotNull Location location) {
|
public void teleport(@NotNull Location location) {
|
||||||
|
@ -180,30 +193,38 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a viewer to the viewers set. The viewer will receive all packets and be informed of this addition
|
* Adds a viewer to the viewers set. The viewer will receive all packets and be informed of this addition
|
||||||
|
*
|
||||||
* @param uuid the uuid of the user to add
|
* @param uuid the uuid of the user to add
|
||||||
*/
|
*/
|
||||||
public void addViewer(UUID uuid) {
|
public void addViewer(@NotNull UUID uuid) {
|
||||||
if (!viewers.add(uuid)) {
|
if (!viewers.add(uuid)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location == null) {
|
if (location == null) {
|
||||||
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
||||||
EntityLib.getPlatform().getLogger().warning("Location is null for entity " + entityId + ". Cannot spawn.");
|
EntityLib.getPlatform().getLogger().warning("Location is null for entity " + entityId + ". Cannot spawn.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (spawned) {
|
if (spawned) {
|
||||||
if (this instanceof WrapperPlayer) {
|
if (this instanceof WrapperPlayer) {
|
||||||
WrapperPlayer p = (WrapperPlayer) this;
|
WrapperPlayer p = (WrapperPlayer) this;
|
||||||
sendPacket(uuid, p.tabListPacket());
|
sendPacket(uuid, p.tabListPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPacket(uuid, createSpawnPacket());
|
sendPacket(uuid, createSpawnPacket());
|
||||||
sendPacket(uuid, entityMeta.createPacket());
|
sendPacket(uuid, entityMeta.createPacket());
|
||||||
sendPacket(uuid, createPassengerPacket());
|
sendPacket(uuid, createPassengerPacket());
|
||||||
|
|
||||||
if (this instanceof WrapperLivingEntity) {
|
if (this instanceof WrapperLivingEntity) {
|
||||||
sendPacket(uuid, ((WrapperLivingEntity)this).getAttributes().createPacket());
|
WrapperLivingEntity wrapperLivingEntity = (WrapperLivingEntity) this;
|
||||||
|
wrapperLivingEntity.createSpawnPackets().forEach(packetWrapper -> sendPacket(uuid, packetWrapper));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
||||||
EntityLib.getPlatform().getLogger().info("Added viewer " + uuid + " to entity " + entityId);
|
EntityLib.getPlatform().getLogger().info("Added viewer " + uuid + " to entity " + entityId);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +242,7 @@ public class WrapperEntity implements Tickable {
|
||||||
sendPacketToViewers(new WrapperPlayServerSystemChatMessage(true, message));
|
sendPacketToViewers(new WrapperPlayServerSystemChatMessage(true, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected WrapperPlayServerSpawnEntity createSpawnPacket() {
|
protected PacketWrapper<?> createSpawnPacket() {
|
||||||
return new WrapperPlayServerSpawnEntity(
|
return new WrapperPlayServerSpawnEntity(
|
||||||
entityId,
|
entityId,
|
||||||
Optional.of(this.uuid),
|
Optional.of(this.uuid),
|
||||||
|
@ -235,62 +256,70 @@ public class WrapperEntity implements Tickable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addViewer(User user) {
|
public void addViewer(@NotNull User user) {
|
||||||
addViewer(user.getUUID());
|
addViewer(user.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this addition
|
* Adds a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this addition
|
||||||
|
*
|
||||||
* @param uuid the uuid of the user to add
|
* @param uuid the uuid of the user to add
|
||||||
*/
|
*/
|
||||||
public void addViewerSilently(UUID uuid) {
|
public void addViewerSilently(@NotNull UUID uuid) {
|
||||||
viewers.add(uuid);
|
viewers.add(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this addition
|
* Adds a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this addition
|
||||||
|
*
|
||||||
* @param user the user to add
|
* @param user the user to add
|
||||||
*/
|
*/
|
||||||
public void addViewerSilently(User user) {
|
public void addViewerSilently(@NotNull User user) {
|
||||||
addViewerSilently(user.getUUID());
|
addViewerSilently(user.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a viewer from the viewers set of this entity. The viewer will be informed of this removal and will no longer receive any packets
|
* Removes a viewer from the viewers set of this entity. The viewer will be informed of this removal and will no longer receive any packets
|
||||||
|
*
|
||||||
* @param uuid the uuid of the user to remove
|
* @param uuid the uuid of the user to remove
|
||||||
*/
|
*/
|
||||||
public void removeViewer(UUID uuid) {
|
public void removeViewer(@NotNull UUID uuid) {
|
||||||
if (!viewers.remove(uuid)) {
|
if (!viewers.remove(uuid)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this instanceof WrapperPlayer) {
|
if (this instanceof WrapperPlayer) {
|
||||||
WrapperPlayer p = (WrapperPlayer) this;
|
WrapperPlayer p = (WrapperPlayer) this;
|
||||||
sendPacket(uuid, p.tabListRemovePacket());
|
sendPacket(uuid, p.tabListRemovePacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
sendPacket(uuid, new WrapperPlayServerDestroyEntities(entityId));
|
sendPacket(uuid, new WrapperPlayServerDestroyEntities(entityId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a viewer from the viewers set of this entity. The viewer will be informed of this removal and will no longer receive any packets
|
* Removes a viewer from the viewers set of this entity. The viewer will be informed of this removal and will no longer receive any packets
|
||||||
|
*
|
||||||
* @param user the user to remove
|
* @param user the user to remove
|
||||||
*/
|
*/
|
||||||
public void removeViewer(User user) {
|
public void removeViewer(@NotNull User user) {
|
||||||
removeViewer(user.getUUID());
|
removeViewer(user.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this removal
|
* removes a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this removal
|
||||||
|
*
|
||||||
* @param uuid of the user to remove
|
* @param uuid of the user to remove
|
||||||
*/
|
*/
|
||||||
public void removeViewerSilently(UUID uuid) {
|
public void removeViewerSilently(@NotNull UUID uuid) {
|
||||||
viewers.remove(uuid);
|
viewers.remove(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* removes a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this removal
|
* removes a viewer silently into the viewers set. The viewer will not receive any packets or be informed of this removal
|
||||||
|
*
|
||||||
* @param user the user to remove
|
* @param user the user to remove
|
||||||
*/
|
*/
|
||||||
public void removeViewerSilently(User user) {
|
public void removeViewerSilently(@NotNull User user) {
|
||||||
removeViewerSilently(user.getUUID());
|
removeViewerSilently(user.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,11 +327,11 @@ public class WrapperEntity implements Tickable {
|
||||||
return onGround;
|
return onGround;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Vector3d getVelocity() {
|
public @NotNull Vector3d getVelocity() {
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVelocity(Vector3d velocity) {
|
public void setVelocity(@NotNull Vector3d velocity) {
|
||||||
this.velocity = velocity;
|
this.velocity = velocity;
|
||||||
sendPacketToViewers(getVelocityPacket());
|
sendPacketToViewers(getVelocityPacket());
|
||||||
}
|
}
|
||||||
|
@ -331,7 +360,7 @@ public class WrapperEntity implements Tickable {
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EntityMeta getEntityMeta() {
|
public @NotNull EntityMeta getEntityMeta() {
|
||||||
return entityMeta;
|
return entityMeta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,12 +368,12 @@ public class WrapperEntity implements Tickable {
|
||||||
return metaClass.cast(entityMeta);
|
return metaClass.cast(entityMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends EntityMeta> void consumeEntityMeta(@NotNull Class<T> metaClass, Consumer<T> consumer) {
|
public <T extends EntityMeta> void consumeEntityMeta(@NotNull Class<T> metaClass, @NotNull Consumer<T> consumer) {
|
||||||
T meta = getEntityMeta(metaClass);
|
T meta = getEntityMeta(metaClass);
|
||||||
consumer.accept(meta);
|
consumer.accept(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void consumeMeta(Consumer<EntityMeta> consumer) {
|
public void consumeMeta(@NotNull Consumer<EntityMeta> consumer) {
|
||||||
consumer.accept(entityMeta);
|
consumer.accept(entityMeta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,13 +387,14 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an unmodifiable set of the passengers of the entity.
|
* Returns an unmodifiable set of the passengers of the entity.
|
||||||
|
*
|
||||||
* @return the passengers of the entity
|
* @return the passengers of the entity
|
||||||
*/
|
*/
|
||||||
public Set<Integer> getPassengers() {
|
public @NotNull Set<Integer> getPassengers() {
|
||||||
return Collections.unmodifiableSet(passengers);
|
return Collections.unmodifiableSet(passengers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperEntity getRiding() {
|
public @Nullable WrapperEntity getRiding() {
|
||||||
return EntityLib.getApi().getEntity(riding);
|
return EntityLib.getApi().getEntity(riding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,20 +463,22 @@ public class WrapperEntity implements Tickable {
|
||||||
new WrapperPlayServerEntityRotation(entityId, yaw, pitch, onGround),
|
new WrapperPlayServerEntityRotation(entityId, yaw, pitch, onGround),
|
||||||
new WrapperPlayServerEntityHeadLook(entityId, yaw)
|
new WrapperPlayServerEntityHeadLook(entityId, yaw)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.location.setYaw(yaw);
|
this.location.setYaw(yaw);
|
||||||
this.location.setPitch(pitch);
|
this.location.setPitch(pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rotateHead(Location location) {
|
public void rotateHead(@NotNull Location location) {
|
||||||
rotateHead(location.getYaw(), location.getPitch());
|
rotateHead(location.getYaw(), location.getPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rotateHead(WrapperEntity entity) {
|
public void rotateHead(@NotNull WrapperEntity entity) {
|
||||||
rotateHead(entity.getLocation());
|
rotateHead(entity.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
if (!spawned) return;
|
if (!spawned) return;
|
||||||
|
|
||||||
sendPacketsToViewers(entityMeta.createPacket(), createPassengerPacket());
|
sendPacketsToViewers(entityMeta.createPacket(), createPassengerPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -457,13 +489,12 @@ public class WrapperEntity implements Tickable {
|
||||||
sendPacket(uuid, packet);
|
sendPacket(uuid, packet);
|
||||||
sendPacket(uuid, new WrapperPlayServerBundle());
|
sendPacket(uuid, new WrapperPlayServerBundle());
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
viewers.forEach(uuid -> sendPacket(uuid, packet));
|
viewers.forEach(uuid -> sendPacket(uuid, packet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendPacketsToViewers(PacketWrapper<?>... wrappers) {
|
public void sendPacketsToViewers(PacketWrapper<?> @NotNull ... wrappers) {
|
||||||
for (PacketWrapper<?> wrapper : wrappers) {
|
for (PacketWrapper<?> wrapper : wrappers) {
|
||||||
sendPacketToViewers(wrapper);
|
sendPacketToViewers(wrapper);
|
||||||
}
|
}
|
||||||
|
@ -483,13 +514,21 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
private static void sendPacket(UUID user, PacketWrapper<?> wrapper) {
|
private static void sendPacket(UUID user, PacketWrapper<?> wrapper) {
|
||||||
if (wrapper == null) return;
|
if (wrapper == null) return;
|
||||||
|
|
||||||
Object channel = EntityLib.getApi().getPacketEvents().getProtocolManager().getChannel(user);
|
Object channel = EntityLib.getApi().getPacketEvents().getProtocolManager().getChannel(user);
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
if (EntityLib.getApi().getSettings().isDebugMode()) {
|
||||||
EntityLib.getPlatform().getLogger().warning("Failed to send packet to " + user + " because the channel was null. They may be disconnected/not online.");
|
EntityLib.getPlatform().getLogger().warning("Failed to send packet to " + user + " because the channel was null. They may be disconnected/not online.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special handling for entity metadata packets to support `GlobalTranslator` functionality and component rendering
|
||||||
|
if (wrapper instanceof WrapperPlayServerEntityMetadata) {
|
||||||
|
PacketUtil.renderPacket(user, (WrapperPlayServerEntityMetadata) wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
EntityLib.getApi().getPacketEvents().getProtocolManager().sendPacket(channel, wrapper);
|
EntityLib.getApi().getPacketEvents().getProtocolManager().sendPacket(channel, wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -504,12 +543,14 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
|
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passenger the entity id of the passenger
|
* @param passenger the entity id of the passenger
|
||||||
*/
|
*/
|
||||||
public void addPassenger(int passenger) {
|
public void addPassenger(int passenger) {
|
||||||
if (passengers.contains(passenger)) {
|
if (passengers.contains(passenger)) {
|
||||||
throw new IllegalArgumentException("Passenger already exists");
|
throw new IllegalArgumentException("Passenger already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
passengers.add(passenger);
|
passengers.add(passenger);
|
||||||
sendPacketToViewers(createPassengerPacket());
|
sendPacketToViewers(createPassengerPacket());
|
||||||
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
|
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
|
||||||
|
@ -533,9 +574,10 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
|
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passengers the entity ids of the passengers
|
* @param passengers the entity ids of the passengers
|
||||||
*/
|
*/
|
||||||
public void addPassengers(int... passengers) {
|
public void addPassengers(int @NotNull ... passengers) {
|
||||||
for (int passenger : passengers) {
|
for (int passenger : passengers) {
|
||||||
addPassenger(passenger);
|
addPassenger(passenger);
|
||||||
}
|
}
|
||||||
|
@ -543,17 +585,19 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
|
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passenger the wrapper entity passenger
|
* @param passenger the wrapper entity passenger
|
||||||
*/
|
*/
|
||||||
public void addPassenger(WrapperEntity passenger) {
|
public void addPassenger(@NotNull WrapperEntity passenger) {
|
||||||
addPassenger(passenger.getEntityId());
|
addPassenger(passenger.getEntityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
|
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passengers the wrapper entity passengers
|
* @param passengers the wrapper entity passengers
|
||||||
*/
|
*/
|
||||||
public void addPassengers(WrapperEntity... passengers) {
|
public void addPassengers(WrapperEntity @NotNull ... passengers) {
|
||||||
for (WrapperEntity passenger : passengers) {
|
for (WrapperEntity passenger : passengers) {
|
||||||
addPassenger(passenger);
|
addPassenger(passenger);
|
||||||
}
|
}
|
||||||
|
@ -561,12 +605,14 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
|
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passenger the entity id of the passenger
|
* @param passenger the entity id of the passenger
|
||||||
*/
|
*/
|
||||||
public void removePassenger(int passenger) {
|
public void removePassenger(int passenger) {
|
||||||
if (!passengers.contains(passenger)) {
|
if (!passengers.contains(passenger)) {
|
||||||
throw new IllegalArgumentException("Passenger does not exist");
|
throw new IllegalArgumentException("Passenger does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
passengers.remove(passenger);
|
passengers.remove(passenger);
|
||||||
sendPacketToViewers(createPassengerPacket());
|
sendPacketToViewers(createPassengerPacket());
|
||||||
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
|
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
|
||||||
|
@ -588,15 +634,16 @@ public class WrapperEntity implements Tickable {
|
||||||
* @param passenger the passenger wrapper entity
|
* @param passenger the passenger wrapper entity
|
||||||
* @return true if the entity has the passenger, false otherwise
|
* @return true if the entity has the passenger, false otherwise
|
||||||
*/
|
*/
|
||||||
public boolean hasPassenger(WrapperEntity passenger) {
|
public boolean hasPassenger(@NotNull WrapperEntity passenger) {
|
||||||
return hasPassenger(passenger.getEntityId());
|
return hasPassenger(passenger.getEntityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
|
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passengers the entity ids of the passengers
|
* @param passengers the entity ids of the passengers
|
||||||
*/
|
*/
|
||||||
public void removePassengers(int... passengers) {
|
public void removePassengers(int @NotNull ... passengers) {
|
||||||
for (int passenger : passengers) {
|
for (int passenger : passengers) {
|
||||||
removePassenger(passenger);
|
removePassenger(passenger);
|
||||||
}
|
}
|
||||||
|
@ -604,17 +651,19 @@ public class WrapperEntity implements Tickable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
|
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passenger the wrapper entity passenger
|
* @param passenger the wrapper entity passenger
|
||||||
*/
|
*/
|
||||||
public void removePassenger(WrapperEntity passenger) {
|
public void removePassenger(@NotNull WrapperEntity passenger) {
|
||||||
removePassenger(passenger.getEntityId());
|
removePassenger(passenger.getEntityId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
|
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
|
||||||
|
*
|
||||||
* @param passengers the wrapper entity passengers
|
* @param passengers the wrapper entity passengers
|
||||||
*/
|
*/
|
||||||
public void removePassengers(WrapperEntity... passengers) {
|
public void removePassengers(WrapperEntity @NotNull ... passengers) {
|
||||||
for (WrapperEntity passenger : passengers) {
|
for (WrapperEntity passenger : passengers) {
|
||||||
removePassenger(passenger);
|
removePassenger(passenger);
|
||||||
}
|
}
|
||||||
|
@ -631,11 +680,11 @@ public class WrapperEntity implements Tickable {
|
||||||
return Collections.unmodifiableSet(viewers);
|
return Collections.unmodifiableSet(viewers);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasViewer(UUID uuid) {
|
public boolean hasViewer(@NotNull UUID uuid) {
|
||||||
return viewers.contains(uuid);
|
return viewers.contains(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasViewer(User user) {
|
public boolean hasViewer(@NotNull User user) {
|
||||||
return hasViewer(user.getUUID());
|
return hasViewer(user.getUUID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,229 @@
|
||||||
|
package me.tofaa.entitylib.wrapper;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerRemoveEntityEffect;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class WrapperEntityPotionEffect {
|
||||||
|
private final WrapperLivingEntity entity;
|
||||||
|
private final Map<PotionType, WrapperPotionEffect> effects = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
private boolean notifyChanges = true;
|
||||||
|
|
||||||
|
public WrapperEntityPotionEffect(WrapperLivingEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
|
* @param ambient A
|
||||||
|
* @param visible A
|
||||||
|
* @param showIcons A
|
||||||
|
* @param factorData The factor data of the potion effect, if hasFactorData is false this will be ignored
|
||||||
|
*/
|
||||||
|
public void addPotionEffect(
|
||||||
|
PotionType type,
|
||||||
|
int amplifier,
|
||||||
|
int duration,
|
||||||
|
boolean ambient,
|
||||||
|
boolean visible,
|
||||||
|
boolean showIcons,
|
||||||
|
@Nullable NBTCompound factorData
|
||||||
|
) {
|
||||||
|
WrapperPotionEffect effect = new WrapperPotionEffect(type, amplifier, duration, ambient, visible, showIcons, factorData);
|
||||||
|
|
||||||
|
this.effects.put(type, effect);
|
||||||
|
|
||||||
|
this.entity.sendPacketToViewers(createEffectPacket(effect));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
|
* @param flags The bit flags of the potion effect see: <a href="https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect">https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect</a>
|
||||||
|
* @param factorData The factor data of the potion effect, if hasFactorData is false this will be ignored
|
||||||
|
*/
|
||||||
|
public void addPotionEffect(
|
||||||
|
PotionType type,
|
||||||
|
int amplifier,
|
||||||
|
int duration,
|
||||||
|
byte flags,
|
||||||
|
@Nullable NBTCompound factorData
|
||||||
|
) {
|
||||||
|
BitSet flagsBitSet = BitSet.valueOf(new byte[]{flags});
|
||||||
|
|
||||||
|
boolean ambient = flagsBitSet.get(0);
|
||||||
|
boolean visible = flagsBitSet.get(1);
|
||||||
|
boolean icons = flagsBitSet.get(2);
|
||||||
|
|
||||||
|
addPotionEffect(type, amplifier, duration, ambient, visible, icons, factorData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
|
* @param flags The bit flags of the potion effect see: <a href="https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect">https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect</a>
|
||||||
|
* @param hasFactorData Whether the potion effect has factor data
|
||||||
|
* @param factorData The factor data of the potion effect, if hasFactorData is false this will be ignored
|
||||||
|
*/
|
||||||
|
public void addPotionEffect(
|
||||||
|
PotionType type,
|
||||||
|
int amplifier,
|
||||||
|
int duration,
|
||||||
|
byte flags,
|
||||||
|
boolean hasFactorData,
|
||||||
|
@Nullable NBTCompound factorData
|
||||||
|
) {
|
||||||
|
addPotionEffect(type, amplifier, duration, flags, hasFactorData ? factorData : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a potion effect to the entity.
|
||||||
|
* EntityLib will not keep track of the potions you give or what you do with them,
|
||||||
|
* this simply sends the packet to the viewers of the entity.
|
||||||
|
*
|
||||||
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
|
* @param flags The bit flags of the potion effect see: <a href="https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect">https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect</a>
|
||||||
|
*/
|
||||||
|
public void addPotionEffect(
|
||||||
|
PotionType type,
|
||||||
|
int amplifier,
|
||||||
|
int duration,
|
||||||
|
byte flags
|
||||||
|
) {
|
||||||
|
addPotionEffect(type, amplifier, duration, flags, false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePotionEffect(@NotNull PotionType potionType) {
|
||||||
|
if (this.effects.remove(potionType) != null) {
|
||||||
|
this.entity.sendPacketsToViewers(createRemoveEffectPacket(potionType));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearPotionEffects() {
|
||||||
|
new ArrayList<>(this.effects.keySet()).forEach(this::removePotionEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull List<WrapperPlayServerEntityEffect> createEffectPackets() {
|
||||||
|
List<WrapperPlayServerEntityEffect> packets = new ArrayList<>();
|
||||||
|
|
||||||
|
this.effects.forEach((potionType, effect) -> packets.add(createEffectPacket(effect)));
|
||||||
|
|
||||||
|
return packets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull WrapperPlayServerEntityEffect createEffectPacket(@NotNull WrapperPotionEffect effect) {
|
||||||
|
PotionType potionType = effect.getPotionType();
|
||||||
|
int amplifier = effect.getAmplifier();
|
||||||
|
int duration = effect.getDuration();
|
||||||
|
boolean ambient = effect.isAmbient();
|
||||||
|
boolean visible = effect.isVisible();
|
||||||
|
boolean icons = effect.hasIcons();
|
||||||
|
NBTCompound factorData = effect.getFactorData();
|
||||||
|
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
|
flags |= ambient ? 1 : 0; // Bit 0 para ambient
|
||||||
|
flags |= visible ? (1 << 1) : 0; // Bit 1 para visible
|
||||||
|
flags |= icons ? (1 << 2) : 0; // Bit 2 para icons
|
||||||
|
|
||||||
|
WrapperPlayServerEntityEffect wrapperPlayServerEntityEffect = new WrapperPlayServerEntityEffect(
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
(byte) flags
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapperPlayServerEntityEffect.setEntityId(this.entity.getEntityId());
|
||||||
|
wrapperPlayServerEntityEffect.setPotionType(potionType);
|
||||||
|
wrapperPlayServerEntityEffect.setEffectAmplifier(amplifier);
|
||||||
|
wrapperPlayServerEntityEffect.setEffectDurationTicks(duration);
|
||||||
|
wrapperPlayServerEntityEffect.setFactorData(factorData);
|
||||||
|
|
||||||
|
return wrapperPlayServerEntityEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull WrapperPlayServerRemoveEntityEffect createRemoveEffectPacket(@NotNull PotionType potionType) {
|
||||||
|
return new WrapperPlayServerRemoveEntityEffect(this.entity.getEntityId(), potionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refresh() {
|
||||||
|
if (notifyChanges) {
|
||||||
|
new ArrayList<>(this.effects.values()).forEach(effect -> {
|
||||||
|
WrapperPlayServerEntityEffect wrapperPlayServerEntityEffect = createEffectPacket(effect);
|
||||||
|
|
||||||
|
this.entity.sendPacketToViewers(wrapperPlayServerEntityEffect);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNotifyingChanges() {
|
||||||
|
return notifyChanges;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotifyChanges(boolean notifyChanges) {
|
||||||
|
this.notifyChanges = notifyChanges;
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WrapperPotionEffect {
|
||||||
|
private final PotionType potionType;
|
||||||
|
private final int amplifier;
|
||||||
|
private final int duration;
|
||||||
|
private final boolean ambient;
|
||||||
|
private final boolean visible;
|
||||||
|
private final boolean icons;
|
||||||
|
private final @Nullable NBTCompound factorData;
|
||||||
|
|
||||||
|
private WrapperPotionEffect(PotionType potionType, int amplifier, int duration, boolean ambient, boolean visible, boolean icons, @Nullable NBTCompound factorData) {
|
||||||
|
this.potionType = potionType;
|
||||||
|
this.amplifier = amplifier;
|
||||||
|
this.duration = duration;
|
||||||
|
this.ambient = ambient;
|
||||||
|
this.visible = visible;
|
||||||
|
this.icons = icons;
|
||||||
|
this.factorData = factorData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PotionType getPotionType() {
|
||||||
|
return potionType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmplifier() {
|
||||||
|
return amplifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getDuration() {
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAmbient() {
|
||||||
|
return ambient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasIcons() {
|
||||||
|
return icons;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable NBTCompound getFactorData() {
|
||||||
|
return factorData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,37 @@
|
||||||
package me.tofaa.entitylib.wrapper;
|
package me.tofaa.entitylib.wrapper;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
import com.github.retrooper.packetevents.protocol.potion.PotionType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityAnimation;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEffect;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerHurtAnimation;
|
||||||
import me.tofaa.entitylib.EntityLib;
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import me.tofaa.entitylib.container.EntityContainer;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
|
import me.tofaa.entitylib.utils.VersionUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class WrapperLivingEntity extends WrapperEntity{
|
public class WrapperLivingEntity extends WrapperEntity {
|
||||||
|
|
||||||
private final WrapperEntityEquipment equipment;
|
private final WrapperEntityEquipment equipment;
|
||||||
private final WrapperEntityAttributes attributes;
|
private final WrapperEntityAttributes attributes;
|
||||||
|
private final WrapperEntityPotionEffect potionEffect;
|
||||||
|
|
||||||
public WrapperLivingEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
|
public WrapperLivingEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
|
||||||
super(entityId, uuid, entityType, entityMeta);
|
super(entityId, uuid, entityType, entityMeta);
|
||||||
|
|
||||||
this.equipment = new WrapperEntityEquipment(this);
|
this.equipment = new WrapperEntityEquipment(this);
|
||||||
this.attributes = new WrapperEntityAttributes(this);
|
this.attributes = new WrapperEntityAttributes(this);
|
||||||
|
this.potionEffect = new WrapperEntityPotionEffect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperLivingEntity(int entityId, UUID uuid, EntityType entityType) {
|
public WrapperLivingEntity(int entityId, UUID uuid, EntityType entityType) {
|
||||||
|
@ -33,6 +45,7 @@ public class WrapperLivingEntity extends WrapperEntity{
|
||||||
public WrapperLivingEntity(UUID uuid, EntityType entityType) {
|
public WrapperLivingEntity(UUID uuid, EntityType entityType) {
|
||||||
this(EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType), uuid, entityType);
|
this(EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType), uuid, entityType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperLivingEntity(EntityType entityType) {
|
public WrapperLivingEntity(EntityType entityType) {
|
||||||
this(EntityLib.getPlatform().getEntityUuidProvider().provide(entityType), entityType);
|
this(EntityLib.getPlatform().getEntityUuidProvider().provide(entityType), entityType);
|
||||||
}
|
}
|
||||||
|
@ -40,60 +53,74 @@ public class WrapperLivingEntity extends WrapperEntity{
|
||||||
@Override
|
@Override
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
super.refresh();
|
super.refresh();
|
||||||
equipment.refresh();
|
|
||||||
attributes.refresh();
|
this.equipment.refresh();
|
||||||
|
this.potionEffect.refresh();
|
||||||
|
this.attributes.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperEntityAttributes getAttributes() {
|
public WrapperEntityAttributes getAttributes() {
|
||||||
return attributes;
|
return this.attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WrapperEntityEquipment getEquipment() {
|
||||||
|
return this.equipment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WrapperEntityPotionEffect getPotionEffect() {
|
||||||
|
return this.potionEffect;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull List<PacketWrapper<?>> createSpawnPackets() {
|
||||||
|
List<PacketWrapper<?>> packets = new ArrayList<>();
|
||||||
|
|
||||||
|
packets.add(getAttributes().createPacket());
|
||||||
|
packets.add(getEquipment().createPacket());
|
||||||
|
packets.addAll(getPotionEffect().createEffectPackets());
|
||||||
|
|
||||||
|
return packets;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a potion effect to the entity.
|
* Adds a potion effect to the entity.
|
||||||
* EntityLib will not keep track of the potions you give or what you do with them,
|
* EntityLib will not keep track of the potions you give or what you do with them,
|
||||||
* this simply sends the packet to the viewers of the entity.
|
* this simply sends the packet to the viewers of the entity.
|
||||||
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
*
|
||||||
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
* @param flags The bit flags of the potion effect see: https://wiki.vg/Protocol#Entity_Effect
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
|
* @param flags The bit flags of the potion effect see:
|
||||||
|
* <a href="https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect">https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect</a>
|
||||||
* @param hasFactorData Whether the potion effect has factor data
|
* @param hasFactorData Whether the potion effect has factor data
|
||||||
* @param factorData The factor data of the potion effect, if hasFactorData is false this will be ignored
|
* @param factorData The factor data of the potion effect, if hasFactorData is false this will be ignored
|
||||||
*/
|
*/
|
||||||
public void addPotionEffect(
|
public void addPotionEffect(
|
||||||
PotionType type,
|
PotionType type,
|
||||||
int amplifier,
|
int amplifier,
|
||||||
int duration,
|
int duration,
|
||||||
byte flags,
|
byte flags,
|
||||||
boolean hasFactorData,
|
boolean hasFactorData,
|
||||||
@Nullable NBTCompound factorData
|
@Nullable NBTCompound factorData
|
||||||
) {
|
) {
|
||||||
sendPacketToViewers(
|
this.potionEffect.addPotionEffect(type, amplifier, duration, flags, hasFactorData, factorData);
|
||||||
new WrapperPlayServerEntityEffect(
|
|
||||||
getEntityId(),
|
|
||||||
type,
|
|
||||||
amplifier,
|
|
||||||
duration,
|
|
||||||
flags
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a potion effect to the entity.
|
* Adds a potion effect to the entity.
|
||||||
* EntityLib will not keep track of the potions you give or what you do with them,
|
* EntityLib will not keep track of the potions you give or what you do with them,
|
||||||
* this simply sends the packet to the viewers of the entity.
|
* this simply sends the packet to the viewers of the entity.
|
||||||
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
*
|
||||||
|
* @param type The type of the potion effect {@link com.github.retrooper.packetevents.protocol.potion.PotionTypes}
|
||||||
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
* @param amplifier The amplifier of the potion effect. The notchian client displays the number as (amplifier + 1)
|
||||||
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
* @param duration The duration of the potion effect in ticks, if set to -1 the client will display the effect as infinite
|
||||||
* @param flags The bit flags of the potion effect see: https://wiki.vg/Protocol#Entity_Effect
|
* @param flags The bit flags of the potion effect see:
|
||||||
|
* <a href="https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect">https://minecraft.wiki/w/Java_Edition_protocol#Entity_Effect</a>
|
||||||
*/
|
*/
|
||||||
public void addPotionEffect(
|
public void addPotionEffect(
|
||||||
PotionType type,
|
PotionType type,
|
||||||
int amplifier,
|
int amplifier,
|
||||||
int duration,
|
int duration,
|
||||||
byte flags
|
byte flags
|
||||||
) {
|
) {
|
||||||
addPotionEffect(type, amplifier, duration, flags, false, null);
|
addPotionEffect(type, amplifier, duration, flags, false, null);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +137,30 @@ public class WrapperLivingEntity extends WrapperEntity{
|
||||||
sendAnimation(WrapperPlayServerEntityAnimation.EntityAnimationType.WAKE_UP);
|
sendAnimation(WrapperPlayServerEntityAnimation.EntityAnimationType.WAKE_UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays the hurt animation of the entity.
|
||||||
|
* This method is deprecated and should use {@link #playHurtAnimation(int)} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public void playHurtAnimation() {
|
public void playHurtAnimation() {
|
||||||
|
playHurtAnimation(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays the hurt animation of the entity.
|
||||||
|
*
|
||||||
|
* @param yaw The yaw of the entity when the hurt animation is played.
|
||||||
|
* For any entity other than a player it's safe to simply put 0, as it's not used.
|
||||||
|
* The yaw is only used on 1.19.4+.
|
||||||
|
*/
|
||||||
|
public void playHurtAnimation(int yaw) {
|
||||||
|
// 1.19.4+ uses a different packet for hurt animation than previous versions
|
||||||
|
if (VersionUtil.isNewerThan(ServerVersion.V_1_19_4)) {
|
||||||
|
sendPacketToViewers(
|
||||||
|
new WrapperPlayServerHurtAnimation(getEntityId(), yaw)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendAnimation(WrapperPlayServerEntityAnimation.EntityAnimationType.HURT);
|
sendAnimation(WrapperPlayServerEntityAnimation.EntityAnimationType.HURT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,8 +177,4 @@ public class WrapperLivingEntity extends WrapperEntity{
|
||||||
new WrapperPlayServerEntityAnimation(getEntityId(), type)
|
new WrapperPlayServerEntityAnimation(getEntityId(), type)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperEntityEquipment getEquipment() {
|
|
||||||
return equipment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
package me.tofaa.entitylib.wrapper;
|
package me.tofaa.entitylib.wrapper;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||||
import com.github.retrooper.packetevents.protocol.player.*;
|
import com.github.retrooper.packetevents.protocol.player.GameMode;
|
||||||
import com.github.retrooper.packetevents.protocol.world.Location;
|
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||||
import com.github.retrooper.packetevents.util.Vector3d;
|
import com.github.retrooper.packetevents.protocol.player.UserProfile;
|
||||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityHeadLook;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityRotation;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoRemove;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerPlayerInfoUpdate;
|
||||||
|
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnPlayer;
|
||||||
import me.tofaa.entitylib.EntityLib;
|
import me.tofaa.entitylib.EntityLib;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class WrapperPlayer extends WrapperLivingEntity {
|
public class WrapperPlayer extends WrapperLivingEntity {
|
||||||
|
|
||||||
|
@ -25,6 +33,27 @@ public class WrapperPlayer extends WrapperLivingEntity {
|
||||||
this.profile = profile;
|
this.profile = profile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PacketWrapper<?> createSpawnPacket() {
|
||||||
|
if (EntityLib.getApi().getPacketEvents().getServerManager().getVersion().isOlderThanOrEquals(ServerVersion.V_1_20_1)) {
|
||||||
|
return new WrapperPlayServerSpawnPlayer(
|
||||||
|
getEntityId(),
|
||||||
|
profile.getUUID(),
|
||||||
|
getLocation(),
|
||||||
|
getEntityMeta().entityData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return super.createSpawnPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull List<PacketWrapper<?>> createSpawnPackets() {
|
||||||
|
final List<PacketWrapper<?>> packets = super.createSpawnPackets();
|
||||||
|
packets.add(new WrapperPlayServerEntityRotation(getEntityId(), getYaw(), getPitch(), isOnGround()));
|
||||||
|
packets.add(new WrapperPlayServerEntityHeadLook(getEntityId(), getYaw()));
|
||||||
|
return packets;
|
||||||
|
}
|
||||||
|
|
||||||
public WrapperPlayServerPlayerInfoUpdate tabListPacket() {
|
public WrapperPlayServerPlayerInfoUpdate tabListPacket() {
|
||||||
EnumSet<WrapperPlayServerPlayerInfoUpdate.Action> actions = EnumSet.of(
|
EnumSet<WrapperPlayServerPlayerInfoUpdate.Action> actions = EnumSet.of(
|
||||||
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
|
WrapperPlayServerPlayerInfoUpdate.Action.ADD_PLAYER,
|
||||||
|
|
|
@ -41,6 +41,7 @@ abstract class ELVersionTask : DefaultTask() {
|
||||||
*/
|
*/
|
||||||
package $packageName;
|
package $packageName;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
import com.github.retrooper.packetevents.util.PEVersion;
|
import com.github.retrooper.packetevents.util.PEVersion;
|
||||||
|
|
||||||
public final class ELVersions {
|
public final class ELVersions {
|
||||||
|
@ -52,6 +53,29 @@ abstract class ELVersionTask : DefaultTask() {
|
||||||
private ELVersions() {
|
private ELVersions() {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Version {
|
||||||
|
|
||||||
|
private final long timestamp;
|
||||||
|
|
||||||
|
public Version(long timestamp) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTimestampFormatted() {
|
||||||
|
return DateFormat.getDateTimeInstance().format(new java.util.Date(timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOlderThan(Version version) {
|
||||||
|
return this.timestamp < version.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,17 +4,19 @@ import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||||
import me.tofaa.entitylib.APIConfig;
|
import me.tofaa.entitylib.APIConfig;
|
||||||
import me.tofaa.entitylib.EntityLibAPI;
|
import me.tofaa.entitylib.EntityLibAPI;
|
||||||
import me.tofaa.entitylib.Platform;
|
import me.tofaa.entitylib.Platform;
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
import me.tofaa.entitylib.container.EntityContainer;
|
import me.tofaa.entitylib.container.EntityContainer;
|
||||||
import me.tofaa.entitylib.tick.TickContainer;
|
import me.tofaa.entitylib.tick.TickContainer;
|
||||||
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
|
public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
|
||||||
|
|
||||||
protected final Platform<P> platform;
|
protected final Platform<P> platform;
|
||||||
protected final PacketEventsAPI<?> packetEvents;
|
protected final PacketEventsAPI<?> packetEvents;
|
||||||
protected final APIConfig settings;
|
protected final APIConfig settings;
|
||||||
|
@ -36,7 +38,6 @@ public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
|
||||||
@Override
|
@Override
|
||||||
public @Nullable WrapperEntity getEntity(@NotNull UUID uuid) {
|
public @Nullable WrapperEntity getEntity(@NotNull UUID uuid) {
|
||||||
return defaultEntityContainer.getEntity(uuid);
|
return defaultEntityContainer.getEntity(uuid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -49,9 +50,8 @@ public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
|
||||||
return defaultEntityContainer;
|
return defaultEntityContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public APIConfig getSettings() {
|
public @NotNull APIConfig getSettings() {
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,13 @@ public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
|
||||||
return packetEvents;
|
return packetEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<TickContainer<?, T>> getTickContainers() {
|
public @NotNull Collection<TickContainer<?, T>> getTickContainers() {
|
||||||
return tickContainers;
|
return tickContainers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull UserLocaleProvider getUserLocaleProvider() {
|
||||||
|
return platform.getUserLocaleProvider();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
[versions]
|
[versions]
|
||||||
adventure = "4.16.0"
|
adventure = "4.22.0"
|
||||||
jetbrains-annotations = "24.0.0"
|
jetbrains-annotations = "26.0.2"
|
||||||
gson = "2.11.0"
|
gson = "2.13.1"
|
||||||
packetevents = "2.7.0"
|
packetevents = "2.9.1"
|
||||||
paper = "1.21-R0.1-SNAPSHOT"
|
paper = "1.21-R0.1-SNAPSHOT"
|
||||||
velocity = "3.3.0-SNAPSHOT"
|
velocity = "3.3.0-SNAPSHOT"
|
||||||
run-paper = "2.3.0"
|
run-paper = "2.3.0"
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
package me.tofaa.entitylib.spigot;
|
package me.tofaa.entitylib.spigot;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||||
|
import io.github.retrooper.packetevents.bstats.bukkit.Metrics;
|
||||||
|
import io.github.retrooper.packetevents.bstats.charts.SimplePie;
|
||||||
import me.tofaa.entitylib.APIConfig;
|
import me.tofaa.entitylib.APIConfig;
|
||||||
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
import me.tofaa.entitylib.common.AbstractPlatform;
|
import me.tofaa.entitylib.common.AbstractPlatform;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
|
public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
|
||||||
|
|
||||||
private SpigotEntityLibAPI api;
|
private SpigotEntityLibAPI api;
|
||||||
|
private UserLocaleProvider userLocaleProvider = new SpigotPlayerLocaleProvider();
|
||||||
|
|
||||||
public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) {
|
public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) {
|
||||||
super(plugin);
|
super(plugin);
|
||||||
|
@ -23,6 +29,12 @@ public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
|
||||||
this.setEntityIdProvider(new SpigotEntityIdProvider(this));
|
this.setEntityIdProvider(new SpigotEntityIdProvider(this));
|
||||||
this.api.onLoad();
|
this.api.onLoad();
|
||||||
this.api.onEnable();
|
this.api.onEnable();
|
||||||
|
if (settings.shouldUseBstats()) {
|
||||||
|
PacketEventsAPI<Plugin> pe = (PacketEventsAPI<Plugin>) api.getPacketEvents();
|
||||||
|
Metrics metrics = new Metrics(pe.getPlugin(), 21916);
|
||||||
|
metrics.addCustomChart(new SimplePie("entitylib-version", () -> EntityLib.getVersion().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -34,4 +46,14 @@ public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Spigot";
|
return "Spigot";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull UserLocaleProvider getUserLocaleProvider() {
|
||||||
|
return userLocaleProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUserLocaleProvider(@NotNull final UserLocaleProvider provider) {
|
||||||
|
this.userLocaleProvider = provider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package me.tofaa.entitylib.spigot;
|
||||||
|
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import net.kyori.adventure.translation.Translator;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implementation is based on code from the scoreboard-library project:
|
||||||
|
* <a href="https://github.com/MegavexNetwork/scoreboard-library/blob/bc8e3c2d2ecf9973ec0d6bb8ae4af94ed008b360/commons/src/main/java/net/megavex/scoreboardlibrary/implementation/commons/LocaleProvider.java">LocaleProvider</a>
|
||||||
|
* Modified and adapted for use in EntityLib.
|
||||||
|
*/
|
||||||
|
public class SpigotPlayerLocaleProvider implements UserLocaleProvider {
|
||||||
|
private static final Locale DEFAULT_LOCALE = Locale.US;
|
||||||
|
private static final Function<Player, Locale> provider = get();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Locale locale(final UUID user) {
|
||||||
|
final Player player = Bukkit.getPlayer(user);
|
||||||
|
return player == null ? DEFAULT_LOCALE : provider.apply(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static @NotNull Function<Player, Locale> get() {
|
||||||
|
MethodHandles.Lookup lookup = MethodHandles.publicLookup();
|
||||||
|
try {
|
||||||
|
MethodHandle adventureMethod = lookup.findVirtual(Player.class, "locale", MethodType.methodType(Locale.class));
|
||||||
|
return player -> {
|
||||||
|
try {
|
||||||
|
return (Locale) adventureMethod.invokeExact(player);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (IllegalAccessException | NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodType methodType = MethodType.methodType(String.class);
|
||||||
|
try {
|
||||||
|
MethodHandle legacySpigotMethod = lookup.findVirtual(Player.Spigot.class, "getLocale", methodType);
|
||||||
|
return player -> {
|
||||||
|
try {
|
||||||
|
Locale locale = Translator.parseLocale((String) legacySpigotMethod.invokeExact(player.spigot()));
|
||||||
|
return locale == null ? DEFAULT_LOCALE : locale;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (IllegalAccessException | NoSuchMethodException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
MethodHandle legacyMethod = lookup.findVirtual(Player.class, "getLocale", methodType);
|
||||||
|
return player -> {
|
||||||
|
try {
|
||||||
|
Locale locale = Translator.parseLocale((String) legacyMethod.invokeExact(player));
|
||||||
|
return locale == null ? DEFAULT_LOCALE : locale;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} catch (IllegalAccessException | NoSuchMethodException ignored) {
|
||||||
|
throw new RuntimeException("No way to get players locale found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,15 +2,18 @@ package me.tofaa.entitylib.standalone;
|
||||||
|
|
||||||
import me.tofaa.entitylib.APIConfig;
|
import me.tofaa.entitylib.APIConfig;
|
||||||
import me.tofaa.entitylib.EntityLibAPI;
|
import me.tofaa.entitylib.EntityLibAPI;
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
import me.tofaa.entitylib.common.AbstractPlatform;
|
import me.tofaa.entitylib.common.AbstractPlatform;
|
||||||
|
import java.util.Locale;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class StandaloneEntityLibPlatform extends AbstractPlatform<Object> {
|
public class StandaloneEntityLibPlatform extends AbstractPlatform<Object> {
|
||||||
|
|
||||||
|
|
||||||
private StandaloneEntityLibApi api;
|
private StandaloneEntityLibApi api;
|
||||||
|
private UserLocaleProvider userLocaleProvider = (user) -> Locale.US;
|
||||||
|
|
||||||
private StandaloneEntityLibPlatform() {
|
public StandaloneEntityLibPlatform() {
|
||||||
super(null);
|
super(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,4 +37,14 @@ public class StandaloneEntityLibPlatform extends AbstractPlatform<Object> {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Standalone";
|
return "Standalone";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull UserLocaleProvider getUserLocaleProvider() {
|
||||||
|
return userLocaleProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUserLocaleProvider(@NotNull final UserLocaleProvider provider) {
|
||||||
|
this.userLocaleProvider = provider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import io.github.retrooper.packetevents.velocity.factory.VelocityPacketEventsBuilder;
|
import io.github.retrooper.packetevents.velocity.factory.VelocityPacketEventsBuilder;
|
||||||
import me.tofaa.entitylib.APIConfig;
|
import me.tofaa.entitylib.APIConfig;
|
||||||
import me.tofaa.entitylib.EntityLibAPI;
|
import me.tofaa.entitylib.EntityLibAPI;
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
import me.tofaa.entitylib.common.AbstractPlatform;
|
import me.tofaa.entitylib.common.AbstractPlatform;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
@ -16,6 +17,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
public class VelocityEntityLibPlatform extends AbstractPlatform<ProxyServer> {
|
public class VelocityEntityLibPlatform extends AbstractPlatform<ProxyServer> {
|
||||||
private VelocityEntityLibAPI api;
|
private VelocityEntityLibAPI api;
|
||||||
|
private UserLocaleProvider userLocaleProvider;
|
||||||
private Object plugin;
|
private Object plugin;
|
||||||
|
|
||||||
public VelocityEntityLibPlatform(Object plugin, ProxyServer handle) {
|
public VelocityEntityLibPlatform(Object plugin, ProxyServer handle) {
|
||||||
|
@ -54,4 +56,14 @@ public class VelocityEntityLibPlatform extends AbstractPlatform<ProxyServer> {
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Velocity";
|
return "Velocity";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @NotNull UserLocaleProvider getUserLocaleProvider() {
|
||||||
|
return userLocaleProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUserLocaleProvider(final UserLocaleProvider userLocaleProvider) {
|
||||||
|
this.userLocaleProvider = userLocaleProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
package me.tofaa.entitylib.velocity;
|
||||||
|
|
||||||
|
import com.velocitypowered.api.proxy.Player;
|
||||||
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
|
import me.tofaa.entitylib.UserLocaleProvider;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class VelocityPlayerLocaleProvider implements UserLocaleProvider {
|
||||||
|
private final ProxyServer proxyServer;
|
||||||
|
|
||||||
|
public VelocityPlayerLocaleProvider(final ProxyServer proxyServer) {
|
||||||
|
this.proxyServer = proxyServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Locale locale(final UUID user) {
|
||||||
|
return proxyServer.getPlayer(user).map(Player::getEffectiveLocale).orElse(Locale.US);
|
||||||
|
}
|
||||||
|
}
|
|
@ -34,7 +34,7 @@ include(":platforms:spigot")
|
||||||
include(":platforms:velocity")
|
include(":platforms:velocity")
|
||||||
include(":platforms:standalone")
|
include(":platforms:standalone")
|
||||||
|
|
||||||
if (!System.getenv("JITPACK").toBoolean()) {
|
if (System.getenv("PRIVATE").toBoolean()) {
|
||||||
include("discord-bot")
|
include("discord-bot")
|
||||||
include(":code-gen")
|
include(":code-gen")
|
||||||
include(":test-plugin")
|
include(":test-plugin")
|
||||||
|
|
|
@ -9,11 +9,13 @@ import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
|
||||||
public class TestEntityLibPlugin extends JavaPlugin {
|
public class TestEntityLibPlugin extends JavaPlugin {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
DateFormat.getDateTimeInstance().format(new java.util.Date(timestamp));
|
||||||
|
|
||||||
SpigotEntityLibPlatform platform = new SpigotEntityLibPlatform(this);
|
SpigotEntityLibPlatform platform = new SpigotEntityLibPlatform(this);
|
||||||
APIConfig settings = new APIConfig(PacketEvents.getAPI())
|
APIConfig settings = new APIConfig(PacketEvents.getAPI())
|
||||||
|
|
Loading…
Reference in a new issue