fancyholograms v3: Remove implementation modules for 1.194 - 1.20.4

This commit is contained in:
Oliver
2025-07-25 19:01:58 +02:00
parent b797da3b7f
commit 9d6305607d
15 changed files with 4 additions and 1250 deletions

View File

@@ -53,11 +53,6 @@ dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT") compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api")) implementation(project(":plugins:fancyholograms:fh-api"))
implementation(project(":plugins:fancyholograms:implementation_1_20_4", configuration = "reobf"))
implementation(project(":plugins:fancyholograms:implementation_1_20_2", configuration = "reobf"))
implementation(project(":plugins:fancyholograms:implementation_1_20_1", configuration = "reobf"))
implementation(project(":plugins:fancyholograms:implementation_1_19_4", configuration = "reobf"))
rootProject.subprojects rootProject.subprojects
.filter { it.path.startsWith(":libraries:packets:implementations") } .filter { it.path.startsWith(":libraries:packets:implementations") }

View File

@@ -1,33 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.19.4"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api"))
implementation(project(":libraries:common"))
compileOnly("com.viaversion:viaversion-api:5.2.1")
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
}

View File

@@ -1,253 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
import com.mojang.math.Transformation;
import de.oliver.fancyholograms.api.data.*;
import de.oliver.fancyholograms.api.events.HologramDespawnEvent;
import de.oliver.fancyholograms.api.events.HologramSpawnEvent;
import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancylib.ReflectionUtils;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData.DataItem;
import net.minecraft.network.syncher.SynchedEntityData.DataValue;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Brightness;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Display.TextDisplay;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import java.util.ArrayList;
import static de.oliver.fancylib.ReflectionUtils.getValue;
public final class Hologram1_19_4 extends Hologram {
@Nullable
private Display display;
public Hologram1_19_4(@NotNull final HologramData data) {
super(data);
create();
}
public void create() {
final var location = data.getLocation();
if (location.getWorld() == null) {
return; // no location data, cannot be created
}
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
switch (data.getType()) {
case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world);
case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world);
case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world);
}
}
public void syncWithData() {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to update
}
// location data
final var location = data.getLocation();
if (!location.isWorldLoaded()) {
return;
} else {
display.setPosRaw(location.x(), location.y(), location.z());
display.setYRot(location.getYaw());
display.setXRot(location.getPitch());
}
if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) {
// line width
final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_LINE_WIDTH_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH);
// background
final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_19_4.DATA_BACKGROUND_COLOR_ID.getMapping());
final var background = textData.getBackground();
if (background == null) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND);
} else if (background == Hologram.TRANSPARENT) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, 0);
} else {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, background.asARGB());
}
// text shadow
if (textData.hasTextShadow()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SHADOW));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SHADOW));
}
// text alignment
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.LEFT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_LEFT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_LEFT));
}
// see through
if (textData.isSeeThrough()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SEE_THROUGH));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SEE_THROUGH));
}
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.RIGHT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_RIGHT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT));
}
} else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) {
// item
itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack()));
} else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':'));
blockDisplay.setBlockState(block.defaultBlockState());
}
if (data instanceof DisplayHologramData displayData) {
// interpolation
final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_DURATION_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_DURATION_ID, displayData.getInterpolationDuration());
final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_19_4.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0);
// billboard data
display.setBillboardConstraints(switch (displayData.getBillboard()) {
case FIXED -> Display.BillboardConstraints.FIXED;
case VERTICAL -> Display.BillboardConstraints.VERTICAL;
case HORIZONTAL -> Display.BillboardConstraints.HORIZONTAL;
case CENTER -> Display.BillboardConstraints.CENTER;
});
// brightness
if (displayData.getBrightness() != null) {
display.setBrightnessOverride(new Brightness(displayData.getBrightness().getBlockLight(), displayData.getBrightness().getSkyLight()));
}
// entity scale AND MORE!
display.setTransformation(new Transformation(
displayData.getTranslation(),
new Quaternionf(),
displayData.getScale(),
new Quaternionf())
);
// entity shadow
display.setShadowRadius(displayData.getShadowRadius());
display.setShadowStrength(displayData.getShadowStrength());
// view range
display.setViewRange(displayData.getVisibilityDistance());
}
}
@Override
public void spawnTo(@NotNull final Player player) {
if (!new HologramSpawnEvent(this, player).callEvent()) {
return;
}
if (this.display == null) {
create(); // try to create it if it doesn't exist every time
}
final var display = this.display;
if (display == null) {
return; // could not be created, nothing to show
}
if (!data.getWorldName().equals(player.getLocation().getWorld().getName())) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
// TODO: cache player protocol version
// TODO: fix this
// final var protocolVersion = FancyHologramsPlugin.get().isUsingViaVersion() ? Via.getAPI().getPlayerVersion(player) : MINIMUM_PROTOCOL_VERSION;
// if (protocolVersion < MINIMUM_PROTOCOL_VERSION) {
// return false;
// }
serverPlayer.connection.send(new ClientboundAddEntityPacket(display));
this.viewers.add(player.getUniqueId());
updateFor(player);
}
@Override
public void despawnFrom(@NotNull final Player player) {
if (!new HologramDespawnEvent(this, player).callEvent()) {
return;
}
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to hide
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId()));
this.viewers.remove(player.getUniqueId());
}
@Override
public void updateFor(@NotNull final Player player) {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to refresh
}
if (!isViewer(player)) {
return;
}
syncWithData();
((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display));
if (display instanceof TextDisplay textDisplay) {
textDisplay.setText(PaperAdventure.asVanilla(getShownText(player)));
}
final var values = new ArrayList<DataValue<?>>();
//noinspection unchecked
for (final var item : ((Int2ObjectMap<DataItem<?>>) getValue(display.getEntityData(), "e")).values()) {
values.add(item.value());
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values));
}
}

View File

@@ -1,20 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
public enum MappingKeys1_19_4 {
DATA_INTERPOLATION_DURATION_ID("r"),
DATA_INTERPOLATION_START_DELTA_TICKS_ID("q"),
DATA_LINE_WIDTH_ID("aL"),
DATA_BACKGROUND_COLOR_ID("aM"),
;
private final String mapping;
MappingKeys1_19_4(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -1,33 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.20.1"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api"))
implementation(project(":libraries:common"))
compileOnly("com.viaversion:viaversion-api:5.2.1")
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
}

View File

@@ -1,253 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
import com.mojang.math.Transformation;
import de.oliver.fancyholograms.api.data.*;
import de.oliver.fancyholograms.api.events.HologramDespawnEvent;
import de.oliver.fancyholograms.api.events.HologramSpawnEvent;
import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancylib.ReflectionUtils;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData.DataItem;
import net.minecraft.network.syncher.SynchedEntityData.DataValue;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Brightness;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Display.TextDisplay;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import java.util.ArrayList;
import static de.oliver.fancylib.ReflectionUtils.getValue;
public final class Hologram1_20_1 extends Hologram {
@Nullable
private Display display;
public Hologram1_20_1(@NotNull final HologramData data) {
super(data);
create();
}
public void create() {
final var location = data.getLocation();
if (location.getWorld() == null) {
return; // no location data, cannot be created
}
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
switch (data.getType()) {
case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world);
case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world);
case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world);
}
}
public void syncWithData() {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to update
}
// location data
final var location = data.getLocation();
if (!location.isWorldLoaded()) {
return;
} else {
display.setPosRaw(location.x(), location.y(), location.z());
display.setYRot(location.getYaw());
display.setXRot(location.getPitch());
}
if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) {
// line width
final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_1.DATA_LINE_WIDTH_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH);
// background
final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_1.DATA_BACKGROUND_COLOR_ID.getMapping()); //DATA_BACKGROUND_COLOR_ID
final var background = textData.getBackground();
if (background == null) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND);
} else if (background == Hologram.TRANSPARENT) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, 0);
} else {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, background.asARGB());
}
// text shadow
if (textData.hasTextShadow()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SHADOW));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SHADOW));
}
// text alignment
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.LEFT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_LEFT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_LEFT));
}
// see through
if (textData.isSeeThrough()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SEE_THROUGH));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SEE_THROUGH));
}
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.RIGHT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_RIGHT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT));
}
} else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) {
// item
itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack()));
} else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':'));
blockDisplay.setBlockState(block.defaultBlockState());
}
if (data instanceof DisplayHologramData displayData) {
// interpolation
final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_1.DATA_INTERPOLATION_DURATION_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_DURATION_ID, displayData.getInterpolationDuration());
final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_1.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0);
// billboard data
display.setBillboardConstraints(switch (displayData.getBillboard()) {
case FIXED -> Display.BillboardConstraints.FIXED;
case VERTICAL -> Display.BillboardConstraints.VERTICAL;
case HORIZONTAL -> Display.BillboardConstraints.HORIZONTAL;
case CENTER -> Display.BillboardConstraints.CENTER;
});
// brightness
if (displayData.getBrightness() != null) {
display.setBrightnessOverride(new Brightness(displayData.getBrightness().getBlockLight(), displayData.getBrightness().getSkyLight()));
}
// entity scale AND MORE!
display.setTransformation(new Transformation(
displayData.getTranslation(),
new Quaternionf(),
displayData.getScale(),
new Quaternionf())
);
// entity shadow
display.setShadowRadius(displayData.getShadowRadius());
display.setShadowStrength(displayData.getShadowStrength());
// view range
display.setViewRange(displayData.getVisibilityDistance());
}
}
@Override
public void spawnTo(@NotNull final Player player) {
if (!new HologramSpawnEvent(this, player).callEvent()) {
return;
}
if (this.display == null) {
create(); // try to create it if it doesn't exist every time
}
final var display = this.display;
if (display == null) {
return; // could not be created, nothing to show
}
if (!data.getWorldName().equals(player.getLocation().getWorld().getName())) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
// TODO: cache player protocol version
// TODO: fix this
// final var protocolVersion = FancyHologramsPlugin.get().isUsingViaVersion() ? Via.getAPI().getPlayerVersion(player) : MINIMUM_PROTOCOL_VERSION;
// if (protocolVersion < MINIMUM_PROTOCOL_VERSION) {
// return false;
// }
serverPlayer.connection.send(new ClientboundAddEntityPacket(display));
this.viewers.add(player.getUniqueId());
updateFor(player);
}
@Override
public void despawnFrom(@NotNull final Player player) {
if (!new HologramDespawnEvent(this, player).callEvent()) {
return;
}
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to hide
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId()));
this.viewers.remove(player.getUniqueId());
}
@Override
public void updateFor(@NotNull final Player player) {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to refresh
}
if (!isViewer(player)) {
return;
}
syncWithData();
((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display));
if (display instanceof TextDisplay textDisplay) {
textDisplay.setText(PaperAdventure.asVanilla(getShownText(player)));
}
final var values = new ArrayList<DataValue<?>>();
//noinspection unchecked
for (final var item : ((Int2ObjectMap<DataItem<?>>) getValue(display.getEntityData(), "e")).values()) {
values.add(item.value());
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values));
}
}

View File

@@ -1,20 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
public enum MappingKeys1_20_1 {
DATA_INTERPOLATION_DURATION_ID("q"),
DATA_INTERPOLATION_START_DELTA_TICKS_ID("p"),
DATA_LINE_WIDTH_ID("aM"),
DATA_BACKGROUND_COLOR_ID("aN"),
;
private final String mapping;
MappingKeys1_20_1(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -1,33 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.20.2"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api"))
implementation(project(":libraries:common"))
compileOnly("com.viaversion:viaversion-api:5.2.1")
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
}

View File

@@ -1,253 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
import com.mojang.math.Transformation;
import de.oliver.fancyholograms.api.data.*;
import de.oliver.fancyholograms.api.events.HologramDespawnEvent;
import de.oliver.fancyholograms.api.events.HologramSpawnEvent;
import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancylib.ReflectionUtils;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData.DataItem;
import net.minecraft.network.syncher.SynchedEntityData.DataValue;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Brightness;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Display.TextDisplay;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import java.util.ArrayList;
import static de.oliver.fancylib.ReflectionUtils.getValue;
public final class Hologram1_20_2 extends Hologram {
@Nullable
private Display display;
public Hologram1_20_2(@NotNull final HologramData data) {
super(data);
create();
}
public void create() {
final var location = data.getLocation();
if (location.getWorld() == null) {
return; // no location data, cannot be created
}
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
switch (data.getType()) {
case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world);
case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world);
case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world);
}
}
public void syncWithData() {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to update
}
// location data
final var location = data.getLocation();
if (!location.isWorldLoaded()) {
return;
} else {
display.setPosRaw(location.x(), location.y(), location.z());
display.setYRot(location.getYaw());
display.setXRot(location.getPitch());
}
if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) {
// line width
final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_2.DATA_LINE_WIDTH_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH);
// background
final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_2.DATA_BACKGROUND_COLOR_ID.getMapping()); //DATA_BACKGROUND_COLOR_ID
final var background = textData.getBackground();
if (background == null) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND);
} else if (background == Hologram.TRANSPARENT) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, 0);
} else {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, background.asARGB());
}
// text shadow
if (textData.hasTextShadow()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SHADOW));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SHADOW));
}
// text alignment
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.LEFT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_LEFT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_LEFT));
}
// see through
if (textData.isSeeThrough()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SEE_THROUGH));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SEE_THROUGH));
}
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.RIGHT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_RIGHT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT));
}
} else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) {
// item
itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack()));
} else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':'));
blockDisplay.setBlockState(block.defaultBlockState());
}
if (data instanceof DisplayHologramData displayData) {
// interpolation
final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_2.DATA_INTERPOLATION_DURATION_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_DURATION_ID, displayData.getInterpolationDuration());
final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_2.DATA_INTERPOLATION_START_DELTA_TICKS_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0);
// billboard data
display.setBillboardConstraints(switch (displayData.getBillboard()) {
case FIXED -> Display.BillboardConstraints.FIXED;
case VERTICAL -> Display.BillboardConstraints.VERTICAL;
case HORIZONTAL -> Display.BillboardConstraints.HORIZONTAL;
case CENTER -> Display.BillboardConstraints.CENTER;
});
// brightness
if (displayData.getBrightness() != null) {
display.setBrightnessOverride(new Brightness(displayData.getBrightness().getBlockLight(), displayData.getBrightness().getSkyLight()));
}
// entity scale AND MORE!
display.setTransformation(new Transformation(
displayData.getTranslation(),
new Quaternionf(),
displayData.getScale(),
new Quaternionf())
);
// entity shadow
display.setShadowRadius(displayData.getShadowRadius());
display.setShadowStrength(displayData.getShadowStrength());
// view range
display.setViewRange(displayData.getVisibilityDistance());
}
}
@Override
public void spawnTo(@NotNull final Player player) {
if (!new HologramSpawnEvent(this, player).callEvent()) {
return;
}
if (this.display == null) {
create(); // try to create it if it doesn't exist every time
}
final var display = this.display;
if (display == null) {
return; // could not be created, nothing to show
}
if (!data.getWorldName().equals(player.getLocation().getWorld().getName())) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
// TODO: cache player protocol version
// TODO: fix this
// final var protocolVersion = FancyHologramsPlugin.get().isUsingViaVersion() ? Via.getAPI().getPlayerVersion(player) : MINIMUM_PROTOCOL_VERSION;
// if (protocolVersion < MINIMUM_PROTOCOL_VERSION) {
// return false;
// }
serverPlayer.connection.send(new ClientboundAddEntityPacket(display));
this.viewers.add(player.getUniqueId());
updateFor(player);
}
@Override
public void despawnFrom(@NotNull final Player player) {
if (!new HologramDespawnEvent(this, player).callEvent()) {
return;
}
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to hide
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId()));
this.viewers.remove(player.getUniqueId());
}
@Override
public void updateFor(@NotNull final Player player) {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to refresh
}
if (!isViewer(player)) {
return;
}
syncWithData();
((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display));
if (display instanceof TextDisplay textDisplay) {
textDisplay.setText(PaperAdventure.asVanilla(getShownText(player)));
}
final var values = new ArrayList<DataValue<?>>();
//noinspection unchecked
for (final var item : ((Int2ObjectMap<DataItem<?>>) getValue(display.getEntityData(), "e")).values()) {
values.add(item.value());
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values));
}
}

View File

@@ -1,20 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
public enum MappingKeys1_20_2 {
DATA_INTERPOLATION_DURATION_ID("r"),
DATA_INTERPOLATION_START_DELTA_TICKS_ID("q"),
DATA_LINE_WIDTH_ID("aN"),
DATA_BACKGROUND_COLOR_ID("aO"),
;
private final String mapping;
MappingKeys1_20_2(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -1,33 +0,0 @@
plugins {
id("java-library")
id("io.papermc.paperweight.userdev")
}
val minecraftVersion = "1.20.4"
dependencies {
paperweight.paperDevBundle("$minecraftVersion-R0.1-SNAPSHOT")
implementation(project(":plugins:fancyholograms:fh-api"))
implementation(project(":libraries:common"))
compileOnly("com.viaversion:viaversion-api:5.2.1")
}
tasks {
named("assemble") {
dependsOn(named("reobfJar"))
}
javadoc {
options.encoding = Charsets.UTF_8.name()
}
compileJava {
options.encoding = Charsets.UTF_8.name()
options.release.set(17)
}
}

View File

@@ -1,253 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
import com.mojang.math.Transformation;
import de.oliver.fancyholograms.api.data.*;
import de.oliver.fancyholograms.api.events.HologramDespawnEvent;
import de.oliver.fancyholograms.api.events.HologramSpawnEvent;
import de.oliver.fancyholograms.api.hologram.Hologram;
import de.oliver.fancylib.ReflectionUtils;
import io.papermc.paper.adventure.PaperAdventure;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket;
import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData.DataItem;
import net.minecraft.network.syncher.SynchedEntityData.DataValue;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Brightness;
import net.minecraft.world.entity.Display;
import net.minecraft.world.entity.Display.TextDisplay;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joml.Quaternionf;
import java.util.ArrayList;
import static de.oliver.fancylib.ReflectionUtils.getValue;
public final class Hologram1_20_4 extends Hologram {
@Nullable
private Display display;
public Hologram1_20_4(@NotNull final HologramData data) {
super(data);
create();
}
public void create() {
final var location = data.getLocation();
if (location.getWorld() == null) {
return; // no location data, cannot be created
}
ServerLevel world = ((CraftWorld) location.getWorld()).getHandle();
switch (data.getType()) {
case TEXT -> this.display = new Display.TextDisplay(EntityType.TEXT_DISPLAY, world);
case BLOCK -> this.display = new Display.BlockDisplay(EntityType.BLOCK_DISPLAY, world);
case ITEM -> this.display = new Display.ItemDisplay(EntityType.ITEM_DISPLAY, world);
}
}
public void syncWithData() {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to update
}
// location data
final var location = data.getLocation();
if (!location.isWorldLoaded()) {
return;
} else {
display.setPosRaw(location.x(), location.y(), location.z());
display.setYRot(location.getYaw());
display.setXRot(location.getPitch());
}
if (display instanceof TextDisplay textDisplay && data instanceof TextHologramData textData) {
// line width
final var DATA_LINE_WIDTH_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_4.TEXT_DISPLAY__DATA_LINE_WIDTH_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_LINE_WIDTH_ID, Hologram.LINE_WIDTH);
// background
final var DATA_BACKGROUND_COLOR_ID = ReflectionUtils.getStaticValue(TextDisplay.class, MappingKeys1_20_4.TEXT_DISPLAY__DATA_BACKGROUND_COLOR_ID.getMapping()); //DATA_BACKGROUND_COLOR_ID
final var background = textData.getBackground();
if (background == null) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, TextDisplay.INITIAL_BACKGROUND);
} else if (background == Hologram.TRANSPARENT) {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, 0);
} else {
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_BACKGROUND_COLOR_ID, background.asARGB());
}
// text shadow
if (textData.hasTextShadow()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SHADOW));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SHADOW));
}
// text alignment
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.LEFT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_LEFT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_LEFT));
}
// see through
if (textData.isSeeThrough()) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_SEE_THROUGH));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_SEE_THROUGH));
}
if (textData.getTextAlignment() == org.bukkit.entity.TextDisplay.TextAlignment.RIGHT) {
textDisplay.setFlags((byte) (textDisplay.getFlags() | TextDisplay.FLAG_ALIGN_RIGHT));
} else {
textDisplay.setFlags((byte) (textDisplay.getFlags() & ~TextDisplay.FLAG_ALIGN_RIGHT));
}
} else if (display instanceof Display.ItemDisplay itemDisplay && data instanceof ItemHologramData itemData) {
// item
itemDisplay.setItemStack(ItemStack.fromBukkitCopy(itemData.getItemStack()));
} else if (display instanceof Display.BlockDisplay blockDisplay && data instanceof BlockHologramData blockData) {
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.of("minecraft:" + blockData.getBlock().name().toLowerCase(), ':'));
blockDisplay.setBlockState(block.defaultBlockState());
}
if (data instanceof DisplayHologramData displayData) {
// interpolation
final var DATA_INTERPOLATION_DURATION_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_4.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_DURATION_ID, displayData.getInterpolationDuration());
final var DATA_INTERPOLATION_START_DELTA_TICKS_ID = ReflectionUtils.getStaticValue(Display.class, MappingKeys1_20_4.DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID.getMapping());
display.getEntityData().set((EntityDataAccessor<Integer>) DATA_INTERPOLATION_START_DELTA_TICKS_ID, 0);
// billboard data
display.setBillboardConstraints(switch (displayData.getBillboard()) {
case FIXED -> Display.BillboardConstraints.FIXED;
case VERTICAL -> Display.BillboardConstraints.VERTICAL;
case HORIZONTAL -> Display.BillboardConstraints.HORIZONTAL;
case CENTER -> Display.BillboardConstraints.CENTER;
});
// brightness
if (displayData.getBrightness() != null) {
display.setBrightnessOverride(new Brightness(displayData.getBrightness().getBlockLight(), displayData.getBrightness().getSkyLight()));
}
// entity scale AND MORE!
display.setTransformation(new Transformation(
displayData.getTranslation(),
new Quaternionf(),
displayData.getScale(),
new Quaternionf())
);
// entity shadow
display.setShadowRadius(displayData.getShadowRadius());
display.setShadowStrength(displayData.getShadowStrength());
// view range
display.setViewRange(displayData.getVisibilityDistance());
}
}
@Override
public void spawnTo(@NotNull final Player player) {
if (!new HologramSpawnEvent(this, player).callEvent()) {
return;
}
if (this.display == null) {
create(); // try to create it if it doesn't exist every time
}
final var display = this.display;
if (display == null) {
return; // could not be created, nothing to show
}
if (!data.getWorldName().equals(player.getLocation().getWorld().getName())) {
return;
}
ServerPlayer serverPlayer = ((CraftPlayer) player).getHandle();
// TODO: cache player protocol version
// TODO: fix this
// final var protocolVersion = FancyHologramsPlugin.get().isUsingViaVersion() ? Via.getAPI().getPlayerVersion(player) : MINIMUM_PROTOCOL_VERSION;
// if (protocolVersion < MINIMUM_PROTOCOL_VERSION) {
// return false;
// }
serverPlayer.connection.send(new ClientboundAddEntityPacket(display));
this.viewers.add(player.getUniqueId());
updateFor(player);
}
@Override
public void despawnFrom(@NotNull final Player player) {
if (!new HologramDespawnEvent(this, player).callEvent()) {
return;
}
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to hide
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(display.getId()));
this.viewers.remove(player.getUniqueId());
}
@Override
public void updateFor(@NotNull final Player player) {
final var display = this.display;
if (display == null) {
return; // doesn't exist, nothing to refresh
}
if (!isViewer(player)) {
return;
}
syncWithData();
((CraftPlayer) player).getHandle().connection.send(new ClientboundTeleportEntityPacket(display));
if (display instanceof TextDisplay textDisplay) {
textDisplay.setText(PaperAdventure.asVanilla(getShownText(player)));
}
final var values = new ArrayList<DataValue<?>>();
//noinspection unchecked
for (final var item : ((Int2ObjectMap<DataItem<?>>) getValue(display.getEntityData(), "e")).values()) {
values.add(item.value());
}
((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(display.getId(), values));
}
}

View File

@@ -1,20 +0,0 @@
package de.oliver.fancyholograms.hologram.version;
public enum MappingKeys1_20_4 {
DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_DURATION_ID("r"),
DISPLAY__DATA_TRANSFORMATION_INTERPOLATION_START_DELTA_TICKS_ID("q"),
TEXT_DISPLAY__DATA_LINE_WIDTH_ID("aN"),
TEXT_DISPLAY__DATA_BACKGROUND_COLOR_ID("aO"),
;
private final String mapping;
MappingKeys1_20_4(String mapping) {
this.mapping = mapping;
}
public String getMapping() {
return mapping;
}
}

View File

@@ -163,18 +163,16 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
"""); """);
} }
hologramFactory = resolveHologramFactory(); if (ServerVersion.isVersionSupported(Bukkit.getMinecraftVersion())) {
if (hologramFactory == null) { hologramFactory = HologramImpl::new;
List<String> supportedVersions = new ArrayList<>(List.of("1.19.4", "1.20", "1.20.1", "1.20.2", "1.20.3", "1.20.4")); } else {
supportedVersions.addAll(ServerVersion.getSupportedVersions());
fancyLogger.warn(""" fancyLogger.warn("""
-------------------------------------------------- --------------------------------------------------
Unsupported minecraft server version. Unsupported minecraft server version.
Please update the server to one of (%s). Please update the server to one of (%s).
Disabling the FancyHolograms plugin. Disabling the FancyHolograms plugin.
-------------------------------------------------- --------------------------------------------------
""".formatted(String.join(" / ", supportedVersions))); """.formatted(String.join(" / ", ServerVersion.getSupportedVersions())));
Bukkit.getPluginManager().disablePlugin(this); Bukkit.getPluginManager().disablePlugin(this);
return; return;
} }
@@ -248,17 +246,6 @@ public final class FancyHologramsPlugin extends JavaPlugin implements FancyHolog
INSTANCE = null; INSTANCE = null;
} }
private @Nullable Function<HologramData, Hologram> resolveHologramFactory() {
final var version = Bukkit.getMinecraftVersion();
// check if the server version is supported by FancySitula
if (ServerVersion.isVersionSupported(version)) {
return HologramImpl::new;
}
return null;
}
private void registerCommands() { private void registerCommands() {
Collection<Command> commands = Arrays.asList(new HologramCMD(this), new FancyHologramsCMD(this)); Collection<Command> commands = Arrays.asList(new HologramCMD(this), new FancyHologramsCMD(this));

View File

@@ -23,10 +23,6 @@ include(":plugins:fancyholograms-v2:implementation_1_19_4")
include(":plugins:fancyholograms") include(":plugins:fancyholograms")
include(":plugins:fancyholograms:fh-api") include(":plugins:fancyholograms:fh-api")
include(":plugins:fancyholograms:implementation_1_20_4")
include(":plugins:fancyholograms:implementation_1_20_2")
include(":plugins:fancyholograms:implementation_1_20_1")
include(":plugins:fancyholograms:implementation_1_19_4")
include(":plugins:fancyvisuals") include(":plugins:fancyvisuals")