mirror of
https://github.com/GeyserExtensionists/GeyserUtils.git
synced 2025-12-19 14:59:18 +00:00
fix
This commit is contained in:
@@ -79,13 +79,13 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc.geyser</groupId>
|
||||||
<artifactId>api</artifactId>
|
<artifactId>api</artifactId>
|
||||||
<version>2.2.2-SNAPSHOT</version>
|
<version>2.2.3-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.geysermc.geyser</groupId>
|
<groupId>org.geysermc.geyser</groupId>
|
||||||
<artifactId>core</artifactId>
|
<artifactId>core</artifactId>
|
||||||
<version>2.2.2-SNAPSHOT</version>
|
<version>2.2.3-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.github.steveice10.packetlib.event.session.SessionAdapter;
|
|||||||
import com.github.steveice10.packetlib.packet.Packet;
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import it.unimi.dsi.fastutil.bytes.ByteArrays;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import me.zimzaza4.geyserutils.common.camera.data.CameraPreset;
|
import me.zimzaza4.geyserutils.common.camera.data.CameraPreset;
|
||||||
import me.zimzaza4.geyserutils.common.camera.instruction.ClearInstruction;
|
import me.zimzaza4.geyserutils.common.camera.instruction.ClearInstruction;
|
||||||
@@ -49,6 +48,8 @@ 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.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class GeyserUtils implements Extension {
|
public class GeyserUtils implements Extension {
|
||||||
@@ -61,15 +62,21 @@ public class GeyserUtils implements Extension {
|
|||||||
@Getter
|
@Getter
|
||||||
public static Map<String, SkinProvider.SkinData> LOADED_SKIN_DATA = new HashMap<>();
|
public static Map<String, SkinProvider.SkinData> LOADED_SKIN_DATA = new HashMap<>();
|
||||||
|
|
||||||
static final SkinProvider.Cape EMPTY_CAPE = new SkinProvider.Cape("", "no-cape", ByteArrays.EMPTY_ARRAY, -1, true);
|
static SkinProvider.Cape EMPTY_CAPE = new SkinProvider.Cape("", "no-cape", new byte[0], -1, true);
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onLoad(GeyserPostInitializeEvent event) {
|
public void onLoad(GeyserPostInitializeEvent event) {
|
||||||
|
|
||||||
packetManager = new PacketManager();
|
packetManager = new PacketManager();
|
||||||
CameraPreset.load();
|
|
||||||
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
|
Registries.BEDROCK_PACKET_TRANSLATORS.register(NpcRequestPacket.class, new NPCFormResponseTranslator());
|
||||||
|
logger().info("Loading Skins:");
|
||||||
loadSkins();
|
loadSkins();
|
||||||
|
|
||||||
|
CameraPreset.load();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +113,7 @@ public class GeyserUtils implements Extension {
|
|||||||
}
|
}
|
||||||
String geoName = "{\"geometry\" :{\"default\" :\"" + geoId + "\"}}";
|
String geoName = "{\"geometry\" :{\"default\" :\"" + geoId + "\"}}";
|
||||||
SkinProvider.SkinGeometry geometry = new SkinProvider.SkinGeometry(geoName, Files.readString(geometryFile.toPath()), false);
|
SkinProvider.SkinGeometry geometry = new SkinProvider.SkinGeometry(geoName, Files.readString(geometryFile.toPath()), false);
|
||||||
LOADED_SKIN_DATA.put(file.getName(), new SkinProvider.SkinData(skin, EMPTY_CAPE, geometry));
|
LOADED_SKIN_DATA.put(file.getName(), new SkinProvider.SkinData(skin, getEmptyCapeData(), geometry));
|
||||||
this.logger().info("Loaded skin: " + file.getName() + "| geo:" + geoName);
|
this.logger().info("Loaded skin: " + file.getName() + "| geo:" + geoName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -118,136 +125,153 @@ public class GeyserUtils implements Extension {
|
|||||||
@Subscribe
|
@Subscribe
|
||||||
public void onSessionJoin(SessionLoginEvent event) {
|
public void onSessionJoin(SessionLoginEvent event) {
|
||||||
if (event.connection() instanceof GeyserSession session) {
|
if (event.connection() instanceof GeyserSession session) {
|
||||||
GeyserImpl.getInstance().getScheduledThread()
|
registerPacketListener(session);
|
||||||
.schedule(() -> session.getDownstream().getSession().addListener(new SessionAdapter() {
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void packetSending(PacketSendingEvent event) {
|
|
||||||
Packet packet = event.getPacket();
|
|
||||||
if (packet instanceof ServerboundCustomPayloadPacket payloadPacket) {
|
|
||||||
if (payloadPacket.getChannel().equals("minecraft:register")) {
|
|
||||||
String channels = new String(payloadPacket.getData(), StandardCharsets.UTF_8);
|
|
||||||
channels = channels + "\0" + GeyserUtilsChannels.MAIN;
|
|
||||||
event.setPacket(new ServerboundCustomPayloadPacket("minecraft:register", channels.getBytes(StandardCharsets.UTF_8)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void packetReceived(Session tcpSession, Packet packet) {
|
|
||||||
|
|
||||||
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
|
|
||||||
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {
|
|
||||||
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
|
|
||||||
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
|
|
||||||
event.connection().camera().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
|
|
||||||
} else if (customPacket instanceof NpcDialogueFormDataCustomPayloadPacket formData) {
|
|
||||||
|
|
||||||
if (formData.action().equals("CLOSE")) {
|
|
||||||
NpcDialogueForm openForm = NpcDialogueForms.getOpenNpcDialogueForms(session);
|
|
||||||
if (openForm != null) {
|
|
||||||
openForm.close(session);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NpcDialogueForm form = new NpcDialogueForm();
|
|
||||||
form.title(formData.title())
|
|
||||||
.dialogue(formData.dialogue())
|
|
||||||
.bindEntity(session.getEntityCache().getEntityByJavaId(formData.bindEntity()))
|
|
||||||
.hasNextForm(formData.hasNextForm());
|
|
||||||
|
|
||||||
if (formData.skinData() != null) {
|
|
||||||
form.skinData(formData.skinData());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
List<Button> buttons = new ArrayList<>();
|
|
||||||
|
|
||||||
if (formData.buttons() != null) {
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for (NpcDialogueButton button : formData.buttons()) {
|
|
||||||
|
|
||||||
|
|
||||||
int finalI = i;
|
|
||||||
buttons.add(new Button(button.text(), button.commands(),
|
|
||||||
button.mode(), () -> {
|
|
||||||
if (button.mode() == NpcDialogueButton.ButtonMode.BUTTON_MODE) {
|
|
||||||
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), finalI))));
|
|
||||||
}
|
|
||||||
}, button.hasNextForm()));
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
form.closeHandler(() -> session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), -1)))));
|
|
||||||
form.buttons(buttons);
|
|
||||||
|
|
||||||
form.createAndSend(session);
|
|
||||||
|
|
||||||
} else if (customPacket instanceof AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
|
|
||||||
AnimateEntityPacket animateEntityPacket = getAnimateEntityPacket(animateEntityCustomPayloadPacket);
|
|
||||||
for (int id : animateEntityCustomPayloadPacket.getEntityJavaIds()) {
|
|
||||||
Entity entity = session.getEntityCache().getEntityByJavaId(id);
|
|
||||||
if (entity != null) {
|
|
||||||
animateEntityPacket.getRuntimeEntityIds().add(entity.getGeyserId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
session.sendUpstreamPacket(animateEntityPacket);
|
|
||||||
} else if (customPacket instanceof CameraInstructionCustomPayloadPacket cameraInstructionPacket) {
|
|
||||||
if (cameraInstructionPacket.getInstruction() instanceof SetInstruction instruction) {
|
|
||||||
session.camera().sendCameraPosition(Converter.serializeSetInstruction(instruction));
|
|
||||||
session.getCameraData().forceCameraPerspective(Converter.serializeCameraPerspective(instruction.getPreset()));
|
|
||||||
|
|
||||||
} else if (cameraInstructionPacket.getInstruction() instanceof FadeInstruction instruction) {
|
|
||||||
session.camera().sendCameraFade(Converter.serializeFadeInstruction(instruction));
|
|
||||||
} else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction) {
|
|
||||||
session.camera().clearCameraInstructions();
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (customPacket instanceof CustomParticleEffectPayloadPacket customParticleEffectPacket) {
|
|
||||||
SpawnParticleEffectPacket spawnParticleEffectPacket = new SpawnParticleEffectPacket();
|
|
||||||
spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
|
||||||
spawnParticleEffectPacket.setPosition(Converter.serializePos(customParticleEffectPacket.getPos()));
|
|
||||||
spawnParticleEffectPacket.setIdentifier(customParticleEffectPacket.getParticle().identifier());
|
|
||||||
spawnParticleEffectPacket.setMolangVariablesJson(Optional.ofNullable(customParticleEffectPacket.getParticle().molangVariablesJson()));
|
|
||||||
session.sendUpstreamPacket(spawnParticleEffectPacket);
|
|
||||||
} else if (customPacket instanceof CustomSkinPayloadPacket customSkinPayloadPacket) {
|
|
||||||
if (session.getEntityCache().getEntityByJavaId(customSkinPayloadPacket.getEntityId()) instanceof PlayerEntity player) {
|
|
||||||
SkinProvider.SkinData data = LOADED_SKIN_DATA.get(customSkinPayloadPacket.getSkinId());
|
|
||||||
if (data != null) {
|
|
||||||
sendSkinPacket(session, player, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (customPacket instanceof CustomHitBoxPacket customHitBoxPacket) {
|
|
||||||
Entity entity = (session.getEntityCache().getEntityByJavaId(customHitBoxPacket.getEntityId()));
|
|
||||||
if (entity != null) {
|
|
||||||
entity.setBoundingBoxHeight(customHitBoxPacket.getHeight());
|
|
||||||
entity.setBoundingBoxWidth(customHitBoxPacket.getWidth());
|
|
||||||
entity.updateBedrockMetadata();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static AnimateEntityPacket getAnimateEntityPacket(AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
|
|
||||||
AnimateEntityPacket animateEntityPacket = new AnimateEntityPacket();
|
|
||||||
animateEntityPacket.setAnimation(animateEntityCustomPayloadPacket.getAnimation());
|
|
||||||
animateEntityPacket.setController(animateEntityCustomPayloadPacket.getController());
|
|
||||||
animateEntityPacket.setBlendOutTime(animateEntityCustomPayloadPacket.getBlendOutTime());
|
|
||||||
animateEntityPacket.setNextState(animateEntityCustomPayloadPacket.getNextState());
|
|
||||||
animateEntityPacket.setStopExpressionVersion(animateEntityCustomPayloadPacket.getStopExpressionVersion());
|
|
||||||
animateEntityPacket.setStopExpression(animateEntityCustomPayloadPacket.getStopExpression());
|
|
||||||
return animateEntityPacket;
|
|
||||||
}
|
|
||||||
}), 100, TimeUnit.MILLISECONDS);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerPacketListener(GeyserSession session) {
|
||||||
|
|
||||||
|
scheduler.schedule(() -> {
|
||||||
|
if (session.getDownstream() == null) {
|
||||||
|
registerPacketListener(session);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.getDownstream().getSession().addListener(new SessionAdapter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packetSending(PacketSendingEvent event) {
|
||||||
|
Packet packet = event.getPacket();
|
||||||
|
if (packet instanceof ServerboundCustomPayloadPacket payloadPacket) {
|
||||||
|
if (payloadPacket.getChannel().equals("minecraft:register")) {
|
||||||
|
String channels = new String(payloadPacket.getData(), StandardCharsets.UTF_8);
|
||||||
|
channels = channels + "\0" + GeyserUtilsChannels.MAIN;
|
||||||
|
event.setPacket(new ServerboundCustomPayloadPacket("minecraft:register", channels.getBytes(StandardCharsets.UTF_8)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void packetReceived(Session tcpSession, Packet packet) {
|
||||||
|
|
||||||
|
if (packet instanceof ClientboundCustomPayloadPacket payloadPacket) {
|
||||||
|
if (payloadPacket.getChannel().equals(GeyserUtilsChannels.MAIN)) {
|
||||||
|
CustomPayloadPacket customPacket = packetManager.decodePacket(payloadPacket.getData());
|
||||||
|
if (customPacket instanceof CameraShakeCustomPayloadPacket cameraShakePacket) {
|
||||||
|
session.camera().shakeCamera(cameraShakePacket.getIntensity(), cameraShakePacket.getDuration(), CameraShake.values()[cameraShakePacket.getType()]);
|
||||||
|
} else if (customPacket instanceof NpcDialogueFormDataCustomPayloadPacket formData) {
|
||||||
|
|
||||||
|
if (formData.action().equals("CLOSE")) {
|
||||||
|
NpcDialogueForm openForm = NpcDialogueForms.getOpenNpcDialogueForms(session);
|
||||||
|
if (openForm != null) {
|
||||||
|
openForm.close(session);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NpcDialogueForm form = new NpcDialogueForm();
|
||||||
|
form.title(formData.title())
|
||||||
|
.dialogue(formData.dialogue())
|
||||||
|
.bindEntity(session.getEntityCache().getEntityByJavaId(formData.bindEntity()))
|
||||||
|
.hasNextForm(formData.hasNextForm());
|
||||||
|
|
||||||
|
if (formData.skinData() != null) {
|
||||||
|
form.skinData(formData.skinData());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<Button> buttons = new ArrayList<>();
|
||||||
|
|
||||||
|
if (formData.buttons() != null) {
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (NpcDialogueButton button : formData.buttons()) {
|
||||||
|
|
||||||
|
|
||||||
|
int finalI = i;
|
||||||
|
buttons.add(new Button(button.text(), button.commands(),
|
||||||
|
button.mode(), () -> {
|
||||||
|
if (button.mode() == NpcDialogueButton.ButtonMode.BUTTON_MODE) {
|
||||||
|
session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), finalI))));
|
||||||
|
}
|
||||||
|
}, button.hasNextForm()));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
form.closeHandler(() -> session.sendDownstreamPacket(new ServerboundCustomPayloadPacket(GeyserUtilsChannels.MAIN, packetManager.encodePacket(new NpcFormResponseCustomPayloadPacket(formData.formId(), -1)))));
|
||||||
|
form.buttons(buttons);
|
||||||
|
|
||||||
|
form.createAndSend(session);
|
||||||
|
|
||||||
|
} else if (customPacket instanceof AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
|
||||||
|
AnimateEntityPacket animateEntityPacket = getAnimateEntityPacket(animateEntityCustomPayloadPacket);
|
||||||
|
for (int id : animateEntityCustomPayloadPacket.getEntityJavaIds()) {
|
||||||
|
Entity entity = session.getEntityCache().getEntityByJavaId(id);
|
||||||
|
if (entity != null) {
|
||||||
|
try {
|
||||||
|
// because of shaded jar
|
||||||
|
Object object = AnimateEntityPacket.class.getMethod("getRuntimeEntityIds").invoke(animateEntityPacket);
|
||||||
|
object.getClass().getMethod("add", Long.class).invoke(object, entity.getGeyserId());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
session.sendUpstreamPacket(animateEntityPacket);
|
||||||
|
} else if (customPacket instanceof CameraInstructionCustomPayloadPacket cameraInstructionPacket) {
|
||||||
|
if (cameraInstructionPacket.getInstruction() instanceof SetInstruction instruction) {
|
||||||
|
session.camera().sendCameraPosition(Converter.serializeSetInstruction(instruction));
|
||||||
|
session.getCameraData().forceCameraPerspective(Converter.serializeCameraPerspective(instruction.getPreset()));
|
||||||
|
|
||||||
|
} else if (cameraInstructionPacket.getInstruction() instanceof FadeInstruction instruction) {
|
||||||
|
session.camera().sendCameraFade(Converter.serializeFadeInstruction(instruction));
|
||||||
|
} else if (cameraInstructionPacket.getInstruction() instanceof ClearInstruction) {
|
||||||
|
session.camera().clearCameraInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (customPacket instanceof CustomParticleEffectPayloadPacket customParticleEffectPacket) {
|
||||||
|
SpawnParticleEffectPacket spawnParticleEffectPacket = new SpawnParticleEffectPacket();
|
||||||
|
spawnParticleEffectPacket.setDimensionId(DimensionUtils.javaToBedrock(session.getDimension()));
|
||||||
|
spawnParticleEffectPacket.setPosition(Converter.serializePos(customParticleEffectPacket.getPos()));
|
||||||
|
spawnParticleEffectPacket.setIdentifier(customParticleEffectPacket.getParticle().identifier());
|
||||||
|
spawnParticleEffectPacket.setMolangVariablesJson(Optional.ofNullable(customParticleEffectPacket.getParticle().molangVariablesJson()));
|
||||||
|
session.sendUpstreamPacket(spawnParticleEffectPacket);
|
||||||
|
} else if (customPacket instanceof CustomSkinPayloadPacket customSkinPayloadPacket) {
|
||||||
|
if (session.getEntityCache().getEntityByJavaId(customSkinPayloadPacket.getEntityId()) instanceof PlayerEntity player) {
|
||||||
|
SkinProvider.SkinData data = LOADED_SKIN_DATA.get(customSkinPayloadPacket.getSkinId());
|
||||||
|
if (data != null) {
|
||||||
|
sendSkinPacket(session, player, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (customPacket instanceof CustomHitBoxPacket customHitBoxPacket) {
|
||||||
|
Entity entity = (session.getEntityCache().getEntityByJavaId(customHitBoxPacket.getEntityId()));
|
||||||
|
if (entity != null) {
|
||||||
|
entity.setBoundingBoxHeight(customHitBoxPacket.getHeight());
|
||||||
|
entity.setBoundingBoxWidth(customHitBoxPacket.getWidth());
|
||||||
|
entity.updateBedrockMetadata();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
}, 80, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static AnimateEntityPacket getAnimateEntityPacket(AnimateEntityCustomPayloadPacket animateEntityCustomPayloadPacket) {
|
||||||
|
AnimateEntityPacket animateEntityPacket = new AnimateEntityPacket();
|
||||||
|
animateEntityPacket.setAnimation(animateEntityCustomPayloadPacket.getAnimation());
|
||||||
|
animateEntityPacket.setController(animateEntityCustomPayloadPacket.getController());
|
||||||
|
animateEntityPacket.setBlendOutTime(animateEntityCustomPayloadPacket.getBlendOutTime());
|
||||||
|
animateEntityPacket.setNextState(animateEntityCustomPayloadPacket.getNextState());
|
||||||
|
animateEntityPacket.setStopExpressionVersion(animateEntityCustomPayloadPacket.getStopExpressionVersion());
|
||||||
|
animateEntityPacket.setStopExpression(animateEntityCustomPayloadPacket.getStopExpression());
|
||||||
|
return animateEntityPacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) {
|
public static void sendSkinPacket(GeyserSession session, PlayerEntity entity, SkinProvider.SkinData skinData) {
|
||||||
@@ -308,5 +332,9 @@ public class GeyserUtils implements Extension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static SkinProvider.Cape getEmptyCapeData() {
|
||||||
|
return EMPTY_CAPE;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user