9
0
mirror of https://github.com/GeyserExtensionists/GeyserUtils.git synced 2025-12-19 15:09:24 +00:00

Merge pull request #6 from OmeWillem/custom-entity

Willem's update
This commit is contained in:
Willem
2024-07-06 23:33:04 +02:00
committed by GitHub
12 changed files with 517 additions and 126 deletions

View File

@@ -0,0 +1,20 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.*;
import java.util.ArrayList;
import java.util.List;
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class BundlePacket extends CustomPayloadPacket {
private List<CustomPayloadPacket> packets = new ArrayList<>();
public void addPacket(CustomPayloadPacket packet) {
this.packets.add(packet);
}
}

View File

@@ -5,6 +5,8 @@ import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import java.awt.*;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
@Getter @Getter
@@ -17,4 +19,6 @@ public class CustomEntityDataPacket extends CustomPayloadPacket {
private Float scale; private Float scale;
private Integer color;
} }

View File

@@ -0,0 +1,18 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class EntityPropertyPacket<T> extends CustomPayloadPacket {
private int entityId;
private String identifier;
private T value;
}

View File

@@ -0,0 +1,18 @@
package me.zimzaza4.geyserutils.common.packet;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class EntityPropertyRegisterPacket extends CustomPayloadPacket {
private int entityId;
private String identifier;
private Class<?> type;
}

View File

@@ -21,7 +21,9 @@ import me.zimzaza4.geyserutils.geyser.replace.JavaAddEntityTranslatorReplace;
import me.zimzaza4.geyserutils.geyser.scoreboard.EntityScoreboard; import me.zimzaza4.geyserutils.geyser.scoreboard.EntityScoreboard;
import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator; import me.zimzaza4.geyserutils.geyser.translator.NPCFormResponseTranslator;
import me.zimzaza4.geyserutils.geyser.util.Converter; import me.zimzaza4.geyserutils.geyser.util.Converter;
import me.zimzaza4.geyserutils.geyser.util.DeltaUtils;
import me.zimzaza4.geyserutils.geyser.util.ReflectionUtils; import me.zimzaza4.geyserutils.geyser.util.ReflectionUtils;
import net.kyori.adventure.text.format.TextColor;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
@@ -44,6 +46,7 @@ import org.geysermc.geyser.api.skin.Skin;
import org.geysermc.geyser.api.skin.SkinData; import org.geysermc.geyser.api.skin.SkinData;
import org.geysermc.geyser.api.skin.SkinGeometry; import org.geysermc.geyser.api.skin.SkinGeometry;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
@@ -63,6 +66,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level.Clien
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.*;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
@@ -70,6 +74,7 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.concurrent.*; import java.util.concurrent.*;
public class GeyserUtils implements Extension { public class GeyserUtils implements Extension {
@@ -93,13 +98,19 @@ public class GeyserUtils implements Extension {
public static ItemParticlesMappings particlesMappings = new ItemParticlesMappings(); public static ItemParticlesMappings particlesMappings = new ItemParticlesMappings();
static Cape EMPTY_CAPE = new Cape("", "no-cape", new byte[0], true); static Cape EMPTY_CAPE = new Cape("", "no-cape", new byte[0], true);
public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2); public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
private static final Map<String, List<Map.Entry<String, Class<?>>>> properties = new HashMap<>();
@Getter
private static GeyserUtils instance;
public GeyserUtils() {
instance = this;
}
@Subscribe @Subscribe
public void onEnable(GeyserPostInitializeEvent event) { public void onEnable(GeyserPostInitializeEvent event) {
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator()); Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
loadSkins(); loadSkins();
ReflectionUtils.init(); ReflectionUtils.init();
@@ -114,6 +125,60 @@ public class GeyserUtils implements Extension {
particlesMappings.read(dataFolder().resolve("item_particles_mappings.json")); particlesMappings.read(dataFolder().resolve("item_particles_mappings.json"));
} }
// the static here is crazy ;(
private static GeyserEntityProperties getProperties(String id) {
if (!properties.containsKey(id)) return null;
GeyserEntityProperties.Builder builder = new GeyserEntityProperties.Builder();
List<Map.Entry<String, Class<?>>> pairs = properties.get(id);
pairs.forEach(p -> {
// only bool, float and int support for now
if (p.getValue() == Boolean.class) builder.addBoolean(p.getKey());
else if (p.getValue() == Float.class) builder.addBoolean(p.getKey());
else if (p.getValue() == Integer.class) builder.addBoolean(p.getKey());
else instance.logger().info("Found unknown property: " + p.getKey());
});
return builder.build();
}
private static boolean containsProperty(String entityId, String identifier) {
if (!properties.containsKey(entityId)) return false;
return properties.get(entityId).stream().anyMatch(p -> p.getKey().equalsIgnoreCase(identifier));
}
public static void addProperty(String entityId, String identifier, Class<?> type) {
if (containsProperty(entityId, identifier)) return;
List<Map.Entry<String, Class<?>>> pairs = properties.getOrDefault(entityId, new ArrayList<>());
pairs.add(new AbstractMap.SimpleEntry<>(identifier, type));
if (properties.containsKey(entityId)) properties.replace(entityId, pairs);
else properties.put(entityId, pairs);
}
public static void registerProperties(String entityId) {
GeyserEntityProperties entityProperties = getProperties(entityId);
if (entityProperties == null) return;
properties.values().stream()
.flatMap(List::stream)
.map(Map.Entry::getKey)
.forEach(id -> {
Registries.BEDROCK_ENTITY_PROPERTIES.get().removeIf(i -> i.containsKey(id));
});
Registries.BEDROCK_ENTITY_PROPERTIES.get().add(entityProperties.toNbtMap(entityId));
EntityDefinition old = LOADED_ENTITY_DEFINITIONS.get(entityId);
LOADED_ENTITY_DEFINITIONS.replace(entityId, new EntityDefinition(old.factory(), old.entityType(), old.identifier(),
old.width(), old.height(), old.offset(), entityProperties, old.translators()));
instance.logger().info("Defined property: " + entityId + " in registry.");
}
public static void addCustomEntity(String id) { public static void addCustomEntity(String id) {
/* /*
LOADED_ENTITY_DEFINITIONS.put(id, LOADED_ENTITY_DEFINITIONS.put(id,
@@ -139,7 +204,9 @@ public class GeyserUtils implements Extension {
Registries.BEDROCK_ENTITY_IDENTIFIERS.set(NbtMap.builder() Registries.BEDROCK_ENTITY_IDENTIFIERS.set(NbtMap.builder()
.putList("idlist", NbtType.COMPOUND, idList).build() .putList("idlist", NbtType.COMPOUND, idList).build()
); );
EntityDefinition<Entity> def = EntityDefinition.builder(null).height(0.1f).width(0.1f).identifier(id).build();
EntityDefinition<Entity> def = EntityDefinition.builder(null)
.height(0.1f).width(0.1f).identifier(id).registeredProperties(getProperties(id)).build();
LOADED_ENTITY_DEFINITIONS.put(id, def); LOADED_ENTITY_DEFINITIONS.put(id, def);
} }
@@ -258,7 +325,57 @@ public class GeyserUtils implements Extension {
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) { if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
if (ReflectionUtils.getChannel(payloadPacket).toString().equals(GeyserUtilsChannels.MAIN)) { if (ReflectionUtils.getChannel(payloadPacket).toString().equals(GeyserUtilsChannels.MAIN)) {
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData()); CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) { handleCustomPacket(session, customPacket);
}
} else if (packet instanceof ClientboundLevelParticlesPacket particlesPacket) {
if (particlesPacket.getParticle().getData() instanceof ItemParticleData data) {
GeyserItemStack itemStack = GeyserItemStack.from(data.getItemStack());
Map<Integer, String> map = particlesMappings.getMappings().get(itemStack.asItem().javaIdentifier());
if (map != null) {
int id = itemStack.getOrCreateComponents().getOrDefault(DataComponentType.CUSTOM_MODEL_DATA, -1);
String particle = map.get(id);
if (particle != null) {
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
stringPacket.setIdentifier(particle);
stringPacket.setDimensionId(dimensionId);
stringPacket.setMolangVariablesJson(Optional.empty());
session.sendUpstreamPacket(stringPacket);
if (particlesPacket.getAmount() == 0) {
// 0 means don't apply the offset
Vector3f position = Vector3f.from(particlesPacket.getX(), particlesPacket.getY(), particlesPacket.getZ());
stringPacket.setPosition(position);
} else {
Random random = ThreadLocalRandom.current();
for (int i = 0; i < particlesPacket.getAmount(); i++) {
double offsetX = random.nextGaussian() * (double) particlesPacket.getOffsetX();
double offsetY = random.nextGaussian() * (double) particlesPacket.getOffsetY();
double offsetZ = random.nextGaussian() * (double) particlesPacket.getOffsetZ();
Vector3f position = Vector3f.from(particlesPacket.getX() + offsetX, particlesPacket.getY() + offsetY, particlesPacket.getZ() + offsetZ);
stringPacket.setPosition(position);
}
}
session.sendUpstreamPacket(stringPacket);
}
}
}
}
}
});
}, 80, TimeUnit.MILLISECONDS);
}
private void handleCustomPacket(GeyserSession session, CustomPayloadPacket customPacket) {
if (customPacket instanceof BundlePacket bundlePacket) {
bundlePacket.getPackets().forEach(p -> handleCustomPacket(session, p));
}
else if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
session.camera().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]); session.camera().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
} else if (customPacket instanceof NpcDialogueFormDataCustomPayloadPacket formData) { } else if (customPacket instanceof NpcDialogueFormDataCustomPayloadPacket formData) {
@@ -348,13 +465,45 @@ public class GeyserUtils implements Extension {
} }
} else if (customPacket instanceof CustomEntityDataPacket customEntityDataPacket) { } else if (customPacket instanceof CustomEntityDataPacket customEntityDataPacket) {
Entity entity = (session.getEntityCache().getEntityByJavaId(customEntityDataPacket.getEntityId())); Entity entity = session.getEntityCache().getEntityByJavaId(customEntityDataPacket.getEntityId());
if (entity != null) { if (entity != null) {
if (customEntityDataPacket.getHeight() != null) entity.setBoundingBoxHeight(customEntityDataPacket.getHeight()); if (customEntityDataPacket.getHeight() != null) entity.setBoundingBoxHeight(customEntityDataPacket.getHeight());
if (customEntityDataPacket.getWidth() != null) entity.setBoundingBoxWidth(customEntityDataPacket.getWidth()); if (customEntityDataPacket.getWidth() != null) entity.setBoundingBoxWidth(customEntityDataPacket.getWidth());
if (customEntityDataPacket.getScale() != null) entity.getDirtyMetadata().put(EntityDataTypes.SCALE, customEntityDataPacket.getScale()); if (customEntityDataPacket.getScale() != null) entity.getDirtyMetadata().put(EntityDataTypes.SCALE, customEntityDataPacket.getScale());
if (customEntityDataPacket.getColor() != null)
entity.getDirtyMetadata().put(EntityDataTypes.COLOR, Byte.parseByte(String.valueOf(getColor(customEntityDataPacket.getColor()))));
entity.updateBedrockMetadata(); entity.updateBedrockMetadata();
} }
} else if (customPacket instanceof EntityPropertyPacket entityPropertyPacket) {
Entity entity = session.getEntityCache().getEntityByJavaId(entityPropertyPacket.getEntityId());
if (entity != null) {
if (entityPropertyPacket.getIdentifier() == null
|| entityPropertyPacket.getValue() == null) return;
if (entity.getPropertyManager() == null) return;
entity.getPropertyManager().add(entityPropertyPacket.getIdentifier(),
(Boolean) entityPropertyPacket.getValue());
entity.updateBedrockEntityProperties();
}
} else if (customPacket instanceof EntityPropertyRegisterPacket entityPropertyRegisterPacket) {
if (entityPropertyRegisterPacket.getIdentifier() == null
|| entityPropertyRegisterPacket.getType() == null) return;
Entity entity = (session.getEntityCache().getEntityByJavaId(entityPropertyRegisterPacket.getEntityId()));
if (entity != null) {
String def = CUSTOM_ENTITIES.get(session).getIfPresent(entity.getEntityId());
if (def == null) return;
if (!containsProperty(def, entityPropertyRegisterPacket.getIdentifier())) {
addProperty(def, entityPropertyRegisterPacket.getIdentifier(), entityPropertyRegisterPacket.getType());
registerProperties(def);
logger().info("DEF PROPERTIES: " + entityPropertyRegisterPacket.getIdentifier());
}
}
} else if (customPacket instanceof CustomEntityPacket customEntityPacket) { } else if (customPacket instanceof CustomEntityPacket customEntityPacket) {
if (!LOADED_ENTITY_DEFINITIONS.containsKey(customEntityPacket.getIdentifier())) { if (!LOADED_ENTITY_DEFINITIONS.containsKey(customEntityPacket.getIdentifier())) {
return; return;
@@ -370,52 +519,6 @@ public class GeyserUtils implements Extension {
} }
} }
} }
} else if (packet instanceof ClientboundLevelParticlesPacket particlesPacket) {
if (particlesPacket.getParticle().getData() instanceof ItemParticleData data) {
GeyserItemStack itemStack = GeyserItemStack.from(data.getItemStack());
Map<Integer, String> map = particlesMappings.getMappings().get(itemStack.asItem().javaIdentifier());
if (map != null) {
int id = itemStack.getOrCreateComponents().getOrDefault(DataComponentType.CUSTOM_MODEL_DATA, -1);
String particle = map.get(id);
if (particle != null) {
int dimensionId = DimensionUtils.javaToBedrock(session.getDimension());
SpawnParticleEffectPacket stringPacket = new SpawnParticleEffectPacket();
stringPacket.setIdentifier(particle);
stringPacket.setDimensionId(dimensionId);
stringPacket.setMolangVariablesJson(Optional.empty());
session.sendUpstreamPacket(stringPacket);
if (particlesPacket.getAmount() == 0) {
// 0 means don't apply the offset
Vector3f position = Vector3f.from(particlesPacket.getX(), particlesPacket.getY(), particlesPacket.getZ());
stringPacket.setPosition(position);
} else {
Random random = ThreadLocalRandom.current();
for (int i = 0; i < particlesPacket.getAmount(); i++) {
double offsetX = random.nextGaussian() * (double) particlesPacket.getOffsetX();
double offsetY = random.nextGaussian() * (double) particlesPacket.getOffsetY();
double offsetZ = random.nextGaussian() * (double) particlesPacket.getOffsetZ();
Vector3f position = Vector3f.from(particlesPacket.getX() + offsetX, particlesPacket.getY() + offsetY, particlesPacket.getZ() + offsetZ);
stringPacket.setPosition(position);
}
}
session.sendUpstreamPacket(stringPacket);
}
}
}
}
}
});
}, 80, TimeUnit.MILLISECONDS);
}
@NotNull @NotNull
private static AnimateEntityPacket getAnimateEntityPacket(AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) { private static AnimateEntityPacket getAnimateEntityPacket(AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
@@ -505,5 +608,47 @@ public class GeyserUtils implements Extension {
return EMPTY_CAPE; return EMPTY_CAPE;
} }
private static int getColor(int argb) {
int r = (argb >> 16) & 0xFF;
int g = (argb >> 8) & 0xFF;
int b = argb & 0xFF;
double[] colorLab = DeltaUtils.rgbToLab(r, g, b);
List<int[]> colors = Arrays.asList(
new int[]{249, 255, 254}, // 0: White
new int[]{249, 128, 29}, // 1: Orange
new int[]{199, 78, 189}, // 2: Magenta
new int[]{58, 179, 218}, // 3: Light Blue
new int[]{254, 216, 61}, // 4: Yellow
new int[]{128, 199, 31}, // 5: Lime
new int[]{243, 139, 170}, // 6: Pink
new int[]{71, 79, 82}, // 7: Gray
new int[]{159, 157, 151}, // 8: Light Gray
new int[]{22, 156, 156}, // 9: Cyan
new int[]{137, 50, 184}, // 10: Purple
new int[]{60, 68, 170}, // 11: Blue
new int[]{131, 84, 50}, // 12: Brown
new int[]{94, 124, 22}, // 13: Green
new int[]{176, 46, 38}, // 14: Red
new int[]{29, 29, 33} // 15: Black
);
int closestColorIndex = -1;
double minDeltaE = Double.MAX_VALUE;
for (int i = 0; i < colors.size(); i++) {
int[] rgb = colors.get(i);
double[] lab = DeltaUtils.rgbToLab(rgb[0], rgb[1], rgb[2]);
double deltaE = DeltaUtils.calculateDeltaE(colorLab, lab);
if (deltaE < minDeltaE) {
minDeltaE = deltaE;
closestColorIndex = i;
}
}
return closestColorIndex;
}
} }

View File

@@ -25,6 +25,8 @@
package me.zimzaza4.geyserutils.geyser.replace; package me.zimzaza4.geyserutils.geyser.replace;
import me.zimzaza4.geyserutils.geyser.GeyserUtils;
import org.geysermc.geyser.entity.properties.GeyserEntityPropertyManager;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData;
@@ -44,6 +46,8 @@ import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import java.lang.reflect.Field;
import static me.zimzaza4.geyserutils.geyser.GeyserUtils.CUSTOM_ENTITIES; import static me.zimzaza4.geyserutils.geyser.GeyserUtils.CUSTOM_ENTITIES;
import static me.zimzaza4.geyserutils.geyser.GeyserUtils.LOADED_ENTITY_DEFINITIONS; import static me.zimzaza4.geyserutils.geyser.GeyserUtils.LOADED_ENTITY_DEFINITIONS;
@@ -127,8 +131,12 @@ public class JavaAddEntityTranslatorReplace extends PacketTranslator<Clientbound
String def = CUSTOM_ENTITIES.get(session).getIfPresent(entity.getEntityId()); String def = CUSTOM_ENTITIES.get(session).getIfPresent(entity.getEntityId());
if (def != null) { if (def != null) {
// System.out.println("CUSTOM ENTITY :" + event.entityId() + " | " + def); EntityDefinition newDef = LOADED_ENTITY_DEFINITIONS.getOrDefault(def, entity.getDefinition());
entity.setDefinition(LOADED_ENTITY_DEFINITIONS.getOrDefault(def, entity.getDefinition())); entity.setDefinition(newDef);
// reinstantiate the entity object to create the propertymanager.
entity = new Entity(entity.getSession(), entity.getEntityId(), entity.getGeyserId(), entity.getUuid(),
entity.getDefinition(), entity.getPosition(), entity.getMotion(), yaw, pitch, headYaw);
} }
session.getEntityCache().spawnEntity(entity); session.getEntityCache().spawnEntity(entity);

View File

@@ -0,0 +1,91 @@
package me.zimzaza4.geyserutils.geyser.util;
public class DeltaUtils {
public static double calculateDeltaE(double[] lab1, double[] lab2) {
// CIEDE2000 algorithm implementation
double deltaL = lab2[0] - lab1[0];
double lBar = (lab1[0] + lab2[0]) / 2.0;
double c1 = Math.sqrt(lab1[1] * lab1[1] + lab1[2] * lab1[2]);
double c2 = Math.sqrt(lab2[1] * lab2[1] + lab2[2] * lab2[2]);
double cBar = (c1 + c2) / 2.0;
double a1Prime = lab1[1] + lab1[1] / 2.0 * (1 - Math.sqrt(Math.pow(cBar, 7) / (Math.pow(cBar, 7) + Math.pow(25, 7))));
double a2Prime = lab2[1] + lab2[1] / 2.0 * (1 - Math.sqrt(Math.pow(cBar, 7) / (Math.pow(cBar, 7) + Math.pow(25, 7))));
double c1Prime = Math.sqrt(a1Prime * a1Prime + lab1[2] * lab1[2]);
double c2Prime = Math.sqrt(a2Prime * a2Prime + lab2[2] * lab2[2]);
double cBarPrime = (c1Prime + c2Prime) / 2.0;
double deltaCPrime = c2Prime - c1Prime;
double h1Prime = Math.atan2(lab1[2], a1Prime);
if (h1Prime < 0) h1Prime += 2 * Math.PI;
double h2Prime = Math.atan2(lab2[2], a2Prime);
if (h2Prime < 0) h2Prime += 2 * Math.PI;
double deltahPrime = h2Prime - h1Prime;
if (Math.abs(deltahPrime) > Math.PI) deltahPrime -= 2 * Math.PI * Math.signum(deltahPrime);
double deltaHPrime = 2 * Math.sqrt(c1Prime * c2Prime) * Math.sin(deltahPrime / 2.0);
double lBarPrime = (lab1[0] + lab2[0]) / 2.0;
double cBarPrimeDelta = (c1Prime + c2Prime) / 2.0;
double hBarPrime = (h1Prime + h2Prime) / 2.0;
if (Math.abs(h1Prime - h2Prime) > Math.PI) hBarPrime -= Math.PI;
double t = 1 - 0.17 * Math.cos(hBarPrime - Math.PI / 6) + 0.24 * Math.cos(2 * hBarPrime) + 0.32 * Math.cos(3 * hBarPrime + Math.PI / 30) - 0.20 * Math.cos(4 * hBarPrime - 63 * Math.PI / 180);
double deltaTheta = 30 * Math.exp(-((hBarPrime - 275 * Math.PI / 180) / 25 * Math.PI / 180) * ((hBarPrime - 275 * Math.PI / 180) / 25 * Math.PI / 180));
double rC = 2 * Math.sqrt(Math.pow(cBarPrimeDelta, 7) / (Math.pow(cBarPrimeDelta, 7) + Math.pow(25, 7)));
double sL = 1 + (0.015 * (lBarPrime - 50) * (lBarPrime - 50)) / Math.sqrt(20 + (lBarPrime - 50) * (lBarPrime - 50));
double sC = 1 + 0.045 * cBarPrimeDelta;
double sH = 1 + 0.015 * cBarPrimeDelta * t;
double rT = -Math.sin(2 * deltaTheta) * rC;
return Math.sqrt((deltaL / sL) * (deltaL / sL) + (deltaCPrime / sC) * (deltaCPrime / sC) + (deltaHPrime / sH) * (deltaHPrime / sH) + rT * (deltaCPrime / sC) * (deltaHPrime / sH));
}
public static double[] rgbToLab(int r, int g, int b) {
// Convert RGB to XYZ
double[] xyz = rgbToXyz(r, g, b);
// Convert XYZ to Lab
return xyzToLab(xyz[0], xyz[1], xyz[2]);
}
private static double[] rgbToXyz(int r, int g, int b) {
double var_R = (r / 255.0);
double var_G = (g / 255.0);
double var_B = (b / 255.0);
if (var_R > 0.04045) var_R = Math.pow((var_R + 0.055) / 1.055, 2.4);
else var_R = var_R / 12.92;
if (var_G > 0.04045) var_G = Math.pow((var_G + 0.055) / 1.055, 2.4);
else var_G = var_G / 12.92;
if (var_B > 0.04045) var_B = Math.pow((var_B + 0.055) / 1.055, 2.4);
else var_B = var_B / 12.92;
var_R = var_R * 100.0;
var_G = var_G * 100.0;
var_B = var_B * 100.0;
// Observer. = 2°, Illuminant = D65
double x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
double y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
double z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
return new double[]{x, y, z};
}
private static double[] xyzToLab(double x, double y, double z) {
double ref_X = 95.047;
double ref_Y = 100.000;
double ref_Z = 108.883;
double var_X = x / ref_X;
double var_Y = y / ref_Y;
double var_Z = z / ref_Z;
if (var_X > 0.008856) var_X = Math.pow(var_X, 1.0/3.0);
else var_X = (7.787 * var_X) + (16.0 / 116.0);
if (var_Y > 0.008856) var_Y = Math.pow(var_Y, 1.0/3.0);
else var_Y = (7.787 * var_Y) + (16.0 / 116.0);
if (var_Z > 0.008856) var_Z = Math.pow(var_Z, 1.0/3.0);
else var_Z = (7.787 * var_Z) + (16.0 / 116.0);
double l = (116.0 * var_Y) - 16.0;
double a = 500.0 * (var_X - var_Y);
double b = 200.0 * (var_Y - var_Z);
return new double[]{l, a, b};
}
}

View File

@@ -30,11 +30,7 @@ public class ReflectionUtils {
@SneakyThrows @SneakyThrows
public static void init() { public static void init() {
PlatformType type = GeyserImpl.getInstance().platformType(); PlatformType type = GeyserImpl.getInstance().platformType();
if (type == PlatformType.STANDALONE || type == PlatformType.VELOCITY) { prefix = type == PlatformType.STANDALONE || type == PlatformType.VELOCITY ? "" : "org.geysermc.geyser.platform." + type.platformName().toLowerCase() + ".shaded.";
prefix = "";
} else {
prefix = "org.geysermc.geyser.platform." + type.platformName().toLowerCase() + ".shaded.";
}
CLIENTBOUND_PAYLOAD_PACKET_CLASS = ClientboundCustomPayloadPacket.class; CLIENTBOUND_PAYLOAD_PACKET_CLASS = ClientboundCustomPayloadPacket.class;
SERVERBOUND_PAYLOAD_PACKET_CLASS = ServerboundCustomPayloadPacket.class; SERVERBOUND_PAYLOAD_PACKET_CLASS = ServerboundCustomPayloadPacket.class;
KEY_CLASS = Class.forName(prefix + "net.kyori.adventure.key.Key"); KEY_CLASS = Class.forName(prefix + "net.kyori.adventure.key.Key");

View File

@@ -3,4 +3,4 @@ id: geyserutils
main: me.zimzaza4.geyserutils.geyser.GeyserUtils main: me.zimzaza4.geyserutils.geyser.GeyserUtils
api: 1.0.0 api: 1.0.0
version: 1.0.0 version: 1.0.0
authors: [zimzaza4] authors: [zimzaza4, willem.dev]

View File

@@ -61,6 +61,10 @@
<id>sonatype</id> <id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url> <url>https://oss.sonatype.org/content/groups/public/</url>
</repository> </repository>
<repository>
<id>opencollab-snapshot</id>
<url>https://repo.opencollab.dev/main/</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>

View File

@@ -7,12 +7,15 @@ import me.zimzaza4.geyserutils.common.packet.*;
import me.zimzaza4.geyserutils.common.particle.CustomParticle; import me.zimzaza4.geyserutils.common.particle.CustomParticle;
import me.zimzaza4.geyserutils.common.util.Pos; import me.zimzaza4.geyserutils.common.util.Pos;
import me.zimzaza4.geyserutils.spigot.GeyserUtils; import me.zimzaza4.geyserutils.spigot.GeyserUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
public class PlayerUtils { public class PlayerUtils {
@@ -77,6 +80,14 @@ public class PlayerUtils {
} }
public static void sendCustomColor(Player player, Entity entity, Color color) {
CustomEntityDataPacket packet = new CustomEntityDataPacket();
packet.setEntityId(entity.getEntityId());
packet.setColor(color.getRGB());
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void setCustomEntity(Player player, int entityId, String def) { public static void setCustomEntity(Player player, int entityId, String def) {
CustomEntityPacket packet = new CustomEntityPacket(entityId, def); CustomEntityPacket packet = new CustomEntityPacket(entityId, def);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet)); player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
@@ -88,4 +99,77 @@ public class PlayerUtils {
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet)); player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
} }
// (yes I'm aware it's "horrible" code), also this aint player packets at all lmao
public static void registerProperty(Player player, Entity entity, String identifier, Class<?> type) {
EntityPropertyRegisterPacket packet = new EntityPropertyRegisterPacket();
packet.setEntityId(entity.getEntityId());
packet.setIdentifier(identifier);
packet.setType(type);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendBoolProperty(Player player, Entity entity, String identifier, Boolean value) {
EntityPropertyPacket<Boolean> packet = new EntityPropertyPacket<>();
packet.setEntityId(entity.getEntityId());
packet.setIdentifier(identifier);
packet.setValue(value);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendBoolProperties(Player player, Entity entity, Map<String, Boolean> bundle) {
BundlePacket packet = new BundlePacket();
bundle.forEach((identifier, value) -> {
EntityPropertyPacket<Boolean> propertyPacket = new EntityPropertyPacket<>();
propertyPacket.setEntityId(entity.getEntityId());
propertyPacket.setIdentifier(identifier);
propertyPacket.setValue(value);
packet.addPacket(propertyPacket);
});
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendFloatProperty(Player player, Entity entity, String identifier, Float value) {
EntityPropertyPacket<Float> packet = new EntityPropertyPacket<>();
packet.setEntityId(entity.getEntityId());
packet.setIdentifier(identifier);
packet.setValue(value);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendFloatProperties(Player player, Entity entity, Map<String, Float> bundle) {
BundlePacket packet = new BundlePacket();
bundle.forEach((identifier, value) -> {
EntityPropertyPacket<Float> propertyPacket = new EntityPropertyPacket<>();
propertyPacket.setEntityId(entity.getEntityId());
propertyPacket.setIdentifier(identifier);
propertyPacket.setValue(value);
packet.addPacket(propertyPacket);
});
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendIntProperty(Player player, Entity entity, String identifier, Integer value) {
EntityPropertyPacket<Integer> packet = new EntityPropertyPacket<>();
packet.setEntityId(entity.getEntityId());
packet.setIdentifier(identifier);
packet.setValue(value);
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
public static void sendIntProperties(Player player, Entity entity, Map<String, Integer> bundle) {
BundlePacket packet = new BundlePacket();
bundle.forEach((identifier, value) -> {
EntityPropertyPacket<Integer> propertyPacket = new EntityPropertyPacket<>();
propertyPacket.setEntityId(entity.getEntityId());
propertyPacket.setIdentifier(identifier);
propertyPacket.setValue(value);
packet.addPacket(propertyPacket);
});
player.sendPluginMessage(GeyserUtils.getInstance(), GeyserUtilsChannels.MAIN, GeyserUtils.getPacketManager().encodePacket(packet));
}
} }

View File

@@ -1,3 +1,6 @@
name: GeyserUtils name: GeyserUtils
version: '${project.version}' version: '${project.version}'
main: me.zimzaza4.geyserutils.spigot.GeyserUtils main: me.zimzaza4.geyserutils.spigot.GeyserUtils
authors:
- zimzaza4
- willem.dev