Use Abstraction (part 1)

This commit is contained in:
Eric 2019-12-15 14:27:51 +01:00
parent ed1ab126af
commit 5e479d65c2
8 changed files with 416 additions and 0 deletions

18
nms/interfaces/pom.xml Normal file
View File

@ -0,0 +1,18 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms-interfaces</artifactId>
<version>1.13-SNAPSHOT</version>
<name>ShopChest NMS Interfaces</name>
<parent>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms</artifactId>
<version>1.13-SNAPSHOT</version>
</parent>
</project>

View File

@ -0,0 +1,18 @@
package de.epiceric.shopchest.shop.hologram;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public interface IHologramLine {
void setLocation(Location location);
void setText(String text);
void showPlayer(Player player);
void hidePlayer(Player player);
void destroy();
}

35
nms/pom.xml Normal file
View File

@ -0,0 +1,35 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms</artifactId>
<version>1.13-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>interfaces</module>
<module>v8r1</module>
<!-- <module>v8r2</module>
<module>v8r3</module>
<module>v9r1</module>
<module>v9r2</module>
<module>v10r1</module>
<module>v11r1</module>
<module>v12r1</module>
<module>v13r1</module>
<module>v13r2</module>
<module>v14r1</module> -->
<module>v15r1</module>
</modules>
<name>ShopChest NMS</name>
<parent>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-parent</artifactId>
<version>1.13-SNAPSHOT</version>
</parent>
</project>

34
nms/v15r1/pom.xml Normal file
View File

@ -0,0 +1,34 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms-v15r1</artifactId>
<version>1.13-SNAPSHOT</version>
<name>ShopChest NMS v1.15-R1</name>
<parent>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms</artifactId>
<version>1.13-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms-interfaces</artifactId>
<version>1.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.15-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,162 @@
package de.epiceric.shopchest.shop.hologram;
import java.io.IOException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_15_R1.DataWatcher;
import net.minecraft.server.v1_15_R1.DataWatcherObject;
import net.minecraft.server.v1_15_R1.Entity;
import net.minecraft.server.v1_15_R1.EntityArmorStand;
import net.minecraft.server.v1_15_R1.EntityTypes;
import net.minecraft.server.v1_15_R1.IChatBaseComponent;
import net.minecraft.server.v1_15_R1.IRegistry;
import net.minecraft.server.v1_15_R1.Packet;
import net.minecraft.server.v1_15_R1.PacketDataSerializer;
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityDestroy;
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityMetadata;
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityTeleport;
import net.minecraft.server.v1_15_R1.PacketPlayOutSpawnEntity;
import net.minecraft.server.v1_15_R1.PlayerConnection;
import net.minecraft.server.v1_15_R1.IChatBaseComponent.ChatSerializer;
public class HologramLine implements IHologramLine {
private PacketPlayOutSpawnEntity packet;
private DataWatcher dataWatcher;
private DataWatcherObject<Boolean> nameVisible;
private DataWatcherObject<Optional<IChatBaseComponent>> customName;
private int id;
private Location location;
private String text;
public HologramLine(Location location, String text) {
this.id = 5;
this.location = location.clone();
this.text = text;
this.packet = new PacketPlayOutSpawnEntity();
this.dataWatcher = createDataWatcher();
updatePacket();
}
@Override
public void setLocation(Location location) {
this.location = location.clone();
updatePacket();
PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport();
location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet));
}
@Override
public void setText(String text) {
this.text = text;
dataWatcher.register(nameVisible, !text.isEmpty());
dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text)));
location.getWorld().getPlayers()
.forEach(player -> sendPackets(player, new PacketPlayOutEntityMetadata(id, dataWatcher, true)));
}
@Override
public void showPlayer(Player player) {
if (player == null || !player.isOnline()) {
return;
}
sendPackets(player, packet, new PacketPlayOutEntityMetadata(id, dataWatcher, true));
}
@Override
public void hidePlayer(Player player) {
if (player == null || !player.isOnline()) {
return;
}
sendPackets(player, new PacketPlayOutEntityDestroy(id));
}
@Override
public void destroy() {
location.getWorld().getPlayers().forEach(player -> hidePlayer(player));
}
private void sendPackets(Player player, Packet<?>... packets) {
PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection;
Arrays.stream(packets).forEach(packet -> con.sendPacket(packet));
}
public void updatePacket() {
PacketDataSerializer s = new PacketDataSerializer(Unpooled.buffer());
s.d(id); // id
s.a(UUID.randomUUID()); // uuid
s.d(IRegistry.ENTITY_TYPE.a(EntityTypes.ARMOR_STAND)); // type
s.writeDouble(location.getX()); // x
s.writeDouble(location.getY()); // y
s.writeDouble(location.getZ()); // z
s.writeByte(0); // pitch
s.writeByte(0); // yaw
s.writeInt(0); // ?
s.writeShort(0); // mot x
s.writeShort(0); // mot y
s.writeShort(0); // mot z
try {
packet.a(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
s.release();
}
}
@SuppressWarnings("unchecked")
public DataWatcher createDataWatcher() {
try {
Field fEntityFlags = Entity.class.getDeclaredField("T");
Field fAirTicks = Entity.class.getDeclaredField("AIR_TICKS");
Field fNameVisible = Entity.class.getDeclaredField("aA");
Field fCustomName = Entity.class.getDeclaredField("az");
Field fNoGravity = Entity.class.getDeclaredField("aC");
setAccessible(fEntityFlags, fAirTicks, fNameVisible, fCustomName, fNoGravity);
nameVisible = (DataWatcherObject<Boolean>) fNameVisible.get(null);
customName = (DataWatcherObject<Optional<IChatBaseComponent>>) fCustomName.get(null);
DataWatcherObject<Byte> entityFlags = (DataWatcherObject<Byte>) fEntityFlags.get(null);
DataWatcherObject<Integer> airTicks = (DataWatcherObject<Integer>) fAirTicks.get(null);
DataWatcherObject<Boolean> noGravity = (DataWatcherObject<Boolean>) fNoGravity.get(null);
DataWatcherObject<Byte> armorStandFlags = EntityArmorStand.b;
DataWatcher dataWatcher = new DataWatcher(null);
dataWatcher.register(entityFlags, (byte) 0b100000);
dataWatcher.register(airTicks, 300);
dataWatcher.register(nameVisible, !text.isEmpty());
dataWatcher.register(customName, Optional.ofNullable(ChatSerializer.b(text)));
dataWatcher.register(noGravity, true);
dataWatcher.register(armorStandFlags, (byte) 0b10000);
return dataWatcher;
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
return null;
}
void setAccessible(AccessibleObject... args) {
Arrays.stream(args).forEach(arg -> arg.setAccessible(true));
}
}

34
nms/v8r1/pom.xml Normal file
View File

@ -0,0 +1,34 @@
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms-v8r1</artifactId>
<version>1.13-SNAPSHOT</version>
<name>ShopChest NMS v1.8-R1</name>
<parent>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms</artifactId>
<version>1.13-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>de.epiceric.shopchest</groupId>
<artifactId>shopchest-nms-interfaces</artifactId>
<version>1.13-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,114 @@
package de.epiceric.shopchest.shop.hologram;
import java.util.Arrays;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;
import io.netty.buffer.Unpooled;
import net.minecraft.server.v1_8_R1.DataWatcher;
import net.minecraft.server.v1_8_R1.MathHelper;
import net.minecraft.server.v1_8_R1.Packet;
import net.minecraft.server.v1_8_R1.PacketDataSerializer;
import net.minecraft.server.v1_8_R1.PacketPlayOutEntityDestroy;
import net.minecraft.server.v1_8_R1.PacketPlayOutEntityMetadata;
import net.minecraft.server.v1_8_R1.PacketPlayOutEntityTeleport;
import net.minecraft.server.v1_8_R1.PacketPlayOutSpawnEntity;
import net.minecraft.server.v1_8_R1.PlayerConnection;
public class HologramLine implements IHologramLine {
private PacketPlayOutSpawnEntity packet;
private DataWatcher dataWatcher;
private int id;
private Location location;
private String text;
public HologramLine(Location location, String text) {
this.id = 5;
this.location = location.clone();
this.text = text == null ? "" : text;
this.packet = new PacketPlayOutSpawnEntity();
this.dataWatcher = createDataWatcher();
updatePacket();
}
@Override
public void setLocation(Location location) {
this.location = location.clone();
updatePacket();
int x = MathHelper.floor(location.getX() * 32d);
int y = MathHelper.floor(location.getY() * 32d);
int z = MathHelper.floor(location.getZ() * 32d);
Packet packet = new PacketPlayOutEntityTeleport(id, x, y, z, (byte) 0, (byte) 0, true);
location.getWorld().getPlayers().forEach(player -> sendPackets(player, packet));
}
@Override
public void setText(String text) {
this.text = text == null ? "" : text;
dataWatcher.a(2, this.text); // custom name
dataWatcher.a(3, (byte) (this.text.isEmpty() ? 0 : 1)); // name visible
location.getWorld().getPlayers()
.forEach(player -> sendPackets(player, new PacketPlayOutEntityMetadata(id, dataWatcher, true)));
}
@Override
public void showPlayer(Player player) {
if (player == null || !player.isOnline()) {
return;
}
sendPackets(player, packet, new PacketPlayOutEntityMetadata(id, dataWatcher, true));
}
@Override
public void hidePlayer(Player player) {
if (player == null || !player.isOnline()) {
return;
}
sendPackets(player, new PacketPlayOutEntityDestroy(id));
}
@Override
public void destroy() {
location.getWorld().getPlayers().forEach(player -> hidePlayer(player));
}
private void sendPackets(Player player, Packet... packets) {
PlayerConnection con = ((CraftPlayer) player).getHandle().playerConnection;
Arrays.stream(packets).forEach(packet -> con.sendPacket(packet));
}
private void updatePacket() {
PacketDataSerializer serializer = new PacketDataSerializer(Unpooled.buffer());
serializer.b(id); // id
serializer.writeByte(78); // entity type
serializer.writeInt(MathHelper.floor(location.getX() * 32d)); // x
serializer.writeInt(MathHelper.floor(location.getY() * 32d)); // y
serializer.writeInt(MathHelper.floor(location.getZ() * 32d)); // z
serializer.writeByte(0); // pitch
serializer.writeByte(0); // yaw
serializer.writeInt(0); // has motion (?)
this.packet.a(serializer);
serializer.release();
}
private DataWatcher createDataWatcher() {
DataWatcher dataWatcher = new DataWatcher(null);
dataWatcher.a(0, 0b100000); // entity flags
dataWatcher.a(1, (short) 300); // air ticks
dataWatcher.a(2, text); // custom name
dataWatcher.a(3, (byte) (text.isEmpty() ? 0 : 1)); // name visible
dataWatcher.a(10, (byte) 0b1100); // armor stand flags
return dataWatcher;
}
}

View File

@ -13,6 +13,7 @@
<module>api</module>
<module>implementation</module>
<module>new-implementation</module>
<module>nms</module>
</modules>
<properties>