Skip to content

Commit

Permalink
Add 1.21.4 support
Browse files Browse the repository at this point in the history
  • Loading branch information
Flowsqy committed Dec 3, 2024
1 parent 8da0491 commit 5c074ff
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 1 deletion.
5 changes: 4 additions & 1 deletion nms/all/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
<properties>
<builtFilePath>target/${project.build.finalName}-${nms-classifier}.jar</builtFilePath>
</properties>

<!-- Ensure build order for assembly -->
<dependencies>
<dependency>
Expand Down Expand Up @@ -80,6 +79,10 @@
<groupId>de.epiceric</groupId>
<artifactId>shopchest-nms-v1_21_R2</artifactId>
</dependency>
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-nms-v1_21_R3</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
7 changes: 7 additions & 0 deletions nms/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<module>v1_20_R4</module>
<module>v1_21_R1</module>
<module>v1_21_R2</module>
<module>v1_21_R3</module>
<module>all</module>
</modules>

Expand Down Expand Up @@ -132,6 +133,12 @@
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-nms-v1_21_R3</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>

Expand Down
41 changes: 41 additions & 0 deletions nms/v1_21_R3/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shopchest-nms</artifactId>
<groupId>de.epiceric</groupId>
<version>1.0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>shopchest-nms-v1_21_R3</artifactId>
<version>1.0.0</version>

<properties>
<spigot.version>1.21.4-R0.1-SNAPSHOT</spigot.version>
</properties>

<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<classifier>remapped-mojang</classifier>
</dependency>
<dependency>
<groupId>de.epiceric</groupId>
<artifactId>shopchest-nms-interface</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package de.epiceric.shopchest.nms.v1_21_R3;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Optional;

import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_21_R3.util.CraftChatMessage;
import org.bukkit.entity.Player;

import de.epiceric.shopchest.nms.FakeArmorStand;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.phys.Vec3;

public class FakeArmorStandImpl extends FakeEntityImpl<String> implements FakeArmorStand {

private final static byte INVISIBLE_FLAG = 0b100000;
private final static byte MARKER_FLAG = 0b10000;
private final static EntityDataAccessor<Byte> DATA_SHARED_FLAGS_ID;
private final static EntityDataAccessor<Optional<Component>> DATA_CUSTOM_NAME;
private final static EntityDataAccessor<Boolean> DATA_CUSTOM_NAME_VISIBLE;
private final static float MARKER_ARMOR_STAND_OFFSET = 1.975f;

static {
try {
final Field dataSharedFlagsId = Entity.class.getDeclaredField(ObfuscatedFieldNames.DATA_SHARED_FLAGS_ID);
dataSharedFlagsId.setAccessible(true);
DATA_SHARED_FLAGS_ID = forceCast(dataSharedFlagsId.get(null));
final Field dataCustomNameField = Entity.class.getDeclaredField(ObfuscatedFieldNames.DATA_CUSTOM_NAME);
dataCustomNameField.setAccessible(true);
DATA_CUSTOM_NAME = forceCast(dataCustomNameField.get(null));
final Field dataCustomNameVisibleField = Entity.class
.getDeclaredField(ObfuscatedFieldNames.DATA_CUSTOM_NAME_VISIBLE);
dataCustomNameVisibleField.setAccessible(true);
DATA_CUSTOM_NAME_VISIBLE = forceCast(dataCustomNameVisibleField.get(null));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}

public FakeArmorStandImpl() {
super();
}

@Override
public void sendData(String name, Iterable<Player> receivers) {
sendData(receivers, name);
}

@Override
protected EntityType<?> getEntityType() {
return EntityType.ARMOR_STAND;
}

@Override
protected float getSpawnOffSet() {
return MARKER_ARMOR_STAND_OFFSET;
}

@Override
protected int getDataItemCount() {
return 4;
}

@Override
protected void addSpecificData(List<SynchedEntityData.DataValue<?>> packedItems, String name) {
packedItems.add(SynchedEntityData.DataValue.create(DATA_SHARED_FLAGS_ID, INVISIBLE_FLAG));
packedItems.add(SynchedEntityData.DataValue.create(DATA_CUSTOM_NAME, Optional.ofNullable(
CraftChatMessage.fromStringOrNull(name))));
packedItems.add(SynchedEntityData.DataValue.create(DATA_CUSTOM_NAME_VISIBLE, true));
packedItems.add(SynchedEntityData.DataValue.create(ArmorStand.DATA_CLIENT_FLAGS, MARKER_FLAG));
}

@Override
public void setLocation(Location location, Iterable<Player> receivers) {
final Vec3 pos = new Vec3(location.getX(), location.getY() + MARKER_ARMOR_STAND_OFFSET, location.getZ());
final PositionMoveRotation positionMoveRotation = new PositionMoveRotation(pos, Vec3.ZERO, 0f, 0f);
final ClientboundEntityPositionSyncPacket positionPacket = new ClientboundEntityPositionSyncPacket(entityId,
positionMoveRotation, false);
sendPacket(positionPacket, receivers);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package de.epiceric.shopchest.nms.v1_21_R3;

import de.epiceric.shopchest.nms.FakeEntity;
import net.minecraft.network.protocol.Packet;
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.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.phys.Vec3;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_21_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class FakeEntityImpl<T> implements FakeEntity {

private final static AtomicInteger ENTITY_COUNTER;
private final static EntityDataAccessor<Boolean> DATA_NO_GRAVITY;
private final static EntityDataAccessor<Boolean> DATA_SILENT;

static {
try {
final Field entityCounterField = Entity.class.getDeclaredField(ObfuscatedFieldNames.ENTITY_COUNTER);
entityCounterField.setAccessible(true);
ENTITY_COUNTER = (AtomicInteger) entityCounterField.get(null);
final Field dataNoGravityField = Entity.class.getDeclaredField(ObfuscatedFieldNames.DATA_NO_GRAVITY);
dataNoGravityField.setAccessible(true);
DATA_NO_GRAVITY = forceCast(dataNoGravityField.get(null));
final Field dataSilentField = Entity.class.getDeclaredField(ObfuscatedFieldNames.DATA_SILENT);
dataSilentField.setAccessible(true);
DATA_SILENT = forceCast(dataSilentField.get(null));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}

protected final int entityId;

public FakeEntityImpl() {
entityId = ENTITY_COUNTER.incrementAndGet();
}

@SuppressWarnings("unchecked")
protected static <T> T forceCast(Object o) {
return (T) o;
}

@Override
public int getEntityId() {
return entityId;
}

protected void sendPacket(Packet<?> packet, Iterable<Player> receivers) {
for (Player receiver : receivers) {
((CraftPlayer) receiver).getHandle().connection.send(packet);
}
}

@Override
public void spawn(UUID uuid, Location location, Iterable<Player> receivers) {
final ClientboundAddEntityPacket spawnPacket = new ClientboundAddEntityPacket(
entityId,
uuid,
location.getX(),
location.getY() + getSpawnOffSet(),
location.getZ(),
0f,
0f,
getEntityType(),
0,
Vec3.ZERO,
0d
);
sendPacket(spawnPacket, receivers);
}

@Override
public void remove(Iterable<Player> receivers) {
final ClientboundRemoveEntitiesPacket removePacket = new ClientboundRemoveEntitiesPacket(entityId);
sendPacket(removePacket, receivers);
}

protected void sendData(Iterable<Player> receivers, T data) {
// Create packet
final List<SynchedEntityData.DataValue<?>> packedItems = new LinkedList<>();
final ClientboundSetEntityDataPacket dataPacket = new ClientboundSetEntityDataPacket(entityId, packedItems);

// Setup data
packedItems.add(SynchedEntityData.DataValue.create(DATA_NO_GRAVITY, true));
packedItems.add(SynchedEntityData.DataValue.create(DATA_SILENT, true));
addSpecificData(packedItems, data);

// Send packet
sendPacket(dataPacket, receivers);
}

protected abstract EntityType<?> getEntityType();

protected float getSpawnOffSet() {
return 0f;
}

protected abstract int getDataItemCount();

protected abstract void addSpecificData(List<SynchedEntityData.DataValue<?>> packedItems, T data);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package de.epiceric.shopchest.nms.v1_21_R3;

import de.epiceric.shopchest.nms.FakeItem;
import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.phys.Vec3;
import org.bukkit.craftbukkit.v1_21_R3.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.lang.reflect.Field;
import java.util.List;

public class FakeItemImpl extends FakeEntityImpl<ItemStack> implements FakeItem {

private final static EntityDataAccessor<net.minecraft.world.item.ItemStack> DATA_ITEM;

static {
try {
final Field dataItemField = ItemEntity.class.getDeclaredField(ObfuscatedFieldNames.DATA_ITEM);
dataItemField.setAccessible(true);
DATA_ITEM = forceCast(dataItemField.get(null));
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}

public FakeItemImpl() {
super();
}

@Override
public void sendData(ItemStack item, Iterable<Player> receivers) {
sendData(receivers, item);
}

@Override
public void resetVelocity(Iterable<Player> receivers) {
final ClientboundSetEntityMotionPacket velocityPacket = new ClientboundSetEntityMotionPacket(entityId, Vec3.ZERO);
sendPacket(velocityPacket, receivers);
}

@Override
protected EntityType<?> getEntityType() {
return EntityType.ITEM;
}

@Override
protected int getDataItemCount() {
return 1;
}

@Override
protected void addSpecificData(List<SynchedEntityData.DataValue<?>> packedItems, ItemStack data) {
packedItems.add(SynchedEntityData.DataValue.create(DATA_ITEM, CraftItemStack.asNMSCopy(data)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package de.epiceric.shopchest.nms.v1_21_R3;

public class ObfuscatedFieldNames {

// Entity
public static final String ENTITY_COUNTER = "c";
public static final String DATA_NO_GRAVITY = "aR";
public static final String DATA_SILENT = "aQ";
public static final String DATA_SHARED_FLAGS_ID = "am";
public static final String DATA_CUSTOM_NAME = "aO";
public static final String DATA_CUSTOM_NAME_VISIBLE = "aP";
// ItemEntity
public static final String DATA_ITEM = "c";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package de.epiceric.shopchest.nms.v1_21_R3;

import de.epiceric.shopchest.nms.FakeArmorStand;
import de.epiceric.shopchest.nms.FakeItem;
import de.epiceric.shopchest.nms.Platform;

public class PlatformImpl implements Platform {

@Override
public FakeArmorStand createFakeArmorStand() {
return new FakeArmorStandImpl();
}

@Override
public FakeItem createFakeItem() {
return new FakeItemImpl();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ private Platform getSpecificPlatform(String mappingsVersion) {
return new de.epiceric.shopchest.nms.v1_21_R1.PlatformImpl();
case "61a218cda78417b6039da56e08194083": // 1.21.3 (v1_21_R2)
return new de.epiceric.shopchest.nms.v1_21_R2.PlatformImpl();
case "60ac387ca8007aa018e6aeb394a6988c": // 1.21.4 (v1_21_R3)
return new de.epiceric.shopchest.nms.v1_21_R3.PlatformImpl();
default:
return null;
}
Expand Down

0 comments on commit 5c074ff

Please sign in to comment.