Skip to content

Commit

Permalink
1.19.4 support
Browse files Browse the repository at this point in the history
  • Loading branch information
cerus committed Mar 14, 2023
1 parent 5c6be9b commit 5dbea8c
Show file tree
Hide file tree
Showing 15 changed files with 330 additions and 14 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ of <a href="https://github.com/cerus/packet-maps">packet-maps</a>.</p>
• Advanced engine features
like [alpha compositing](https://en.wikipedia.org/wiki/Alpha_compositing) ([Image](https://cerus.dev/img/maps_alpha_composition.png))\
• Efficient click handling\
• Supports 1.16.5 - 1.19.3
• Supports 1.16.5 - 1.19.4

**What is the point of the plugin module?**\
See [FAQ](#FAQ)
Expand All @@ -50,7 +50,7 @@ See [FAQ](#FAQ)
<dependency>
<groupId>dev.cerus.maps</groupId>
<artifactId>common</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<scope>provided</scope> <!-- "provided" if the maps plugin is on the server, "compile" if not -->
</dependency>

Expand All @@ -59,7 +59,7 @@ See [FAQ](#FAQ)
<dependency>
<groupId>dev.cerus.maps</groupId>
<artifactId>plugin</artifactId>
<version>3.5.0</version>
<version>3.5.1</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down Expand Up @@ -136,7 +136,7 @@ public class MyPlugin extends JavaPlugin {

### Building

Requirements: Java 16, Git, Maven, CraftBukkit 1.16.5, 1.17.1, 1.18.1, 1.18.2, 1.19.1 and 1.19.3 installed in local Maven repo
Requirements: Java 16, Git, Maven, CraftBukkit 1.16.5, 1.17.1, 1.18.1, 1.18.2, 1.19.1, 1.19.3 and 1.19.4 installed in local Maven repo

Simply clone the repository, navigate into the directory and run `mvn clean package`. The plugin will be in `plugin/target` and the api
in `common/target`.
Expand Down
2 changes: 1 addition & 1 deletion bukkit-16_R3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-17_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-18_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-18_R2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-19_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-19_R2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.5.0</version>
<version>3.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
34 changes: 34 additions & 0 deletions bukkit-19_R3/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
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>
<parent>
<groupId>dev.cerus.maps</groupId>
<artifactId>parent</artifactId>
<version>3.5.1</version>
</parent>

<artifactId>bukkit-19_R3</artifactId>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>dev.cerus.maps</groupId>
<artifactId>common</artifactId>
<version>${parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>craftbukkit</artifactId>
<version>1.19.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package dev.cerus.maps.version;

import dev.cerus.maps.api.version.PacketListener;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import java.lang.reflect.Field;
import java.util.Arrays;
import net.minecraft.network.protocol.game.ClientboundBlockChangedAckPacket;
import net.minecraft.network.protocol.game.PacketPlayInBlockDig;
import net.minecraft.network.protocol.game.PacketPlayInBlockPlace;
import net.minecraft.network.protocol.game.PacketPlayInUseEntity;
import net.minecraft.network.protocol.game.PacketPlayInUseItem;
import net.minecraft.world.EnumHand;
import net.minecraft.world.phys.MovingObjectPositionBlock;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_19_R3.block.CraftBlock;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;

public class PacketHandler19R3 extends ChannelDuplexHandler {

private static final Field actionField;
private static final Object attackAction;

static {
try {
actionField = PacketPlayInUseEntity.class.getDeclaredField("b");
actionField.setAccessible(true);
final Field attackActionField = PacketPlayInUseEntity.class.getDeclaredField("d");
attackActionField.setAccessible(true);
attackAction = attackActionField.get(null);
} catch (final NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private final Player player;
private final PacketListener listener;
private final JavaPlugin plugin;

public PacketHandler19R3(final Player player, final PacketListener listener, final JavaPlugin plugin) {
this.player = player;
this.listener = listener;
this.plugin = plugin;
}

private static Object getAction(final PacketPlayInUseEntity packet) {
try {
return actionField.get(packet);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
}

private static EnumHand getHand(final PacketPlayInUseEntity packet) {
try {
final Object action = getAction(packet);
final Field handField = Arrays.stream(action.getClass().getDeclaredFields())
.filter(field -> field.getType() == EnumHand.class)
.findAny().orElse(null);
if (handField == null) {
return null;
}
handField.setAccessible(true);
return (EnumHand) handField.get(action);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
}

@Override
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
if ((((msg instanceof PacketPlayInUseItem useItem && useItem.a() != EnumHand.b) || msg instanceof PacketPlayInBlockPlace)
&& this.listener.handlePlayerRightClick(this.player)) || (msg instanceof PacketPlayInUseEntity useEntity && getHand(useEntity) != EnumHand.b
&& (getAction(useEntity) == attackAction ? this.listener.handlePlayerLeftClick(this.player)
: this.listener.handlePlayerRightClick(this.player))) || (msg instanceof PacketPlayInBlockDig
&& this.listener.handlePlayerLeftClick(this.player))) {
if (msg instanceof PacketPlayInBlockDig dig) {
// To prevent de-syncs we need to tell the client that the block has not changed
final Location location = new Location(
this.player.getWorld(),
dig.a().u(),
dig.a().v(),
dig.a().w()
);
// If we don't acknowledge the client's block change it won't accept further block change packets
((CraftPlayer) this.player).getHandle().b.a(new ClientboundBlockChangedAckPacket(dig.e()));
Bukkit.getScheduler().runTask(this.plugin, () -> this.player.sendBlockChange(location, location.getBlock().getBlockData()));
}
if (msg instanceof PacketPlayInUseItem useItem) {
// To prevent de-syncs we need to tell the client that the block has not changed
final MovingObjectPositionBlock pos = useItem.c();
if (pos != null && pos.a() != null) {
final Location location = new Location(
this.player.getWorld(),
pos.a().u(),
pos.a().v(),
pos.a().w()
).getBlock().getRelative(CraftBlock.notchToBlockFace(pos.b())).getLocation();
// If we don't acknowledge the client's block change it won't accept further block change packets
((CraftPlayer) this.player).getHandle().b.a(new ClientboundBlockChangedAckPacket(useItem.d()));
Bukkit.getScheduler().runTask(this.plugin, () -> this.player.sendBlockChange(location, location.getBlock().getBlockData()));
}
}
return;
}
super.channelRead(ctx, msg);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
package dev.cerus.maps.version;

import dev.cerus.maps.api.ClientsideMap;
import dev.cerus.maps.api.Frame;
import dev.cerus.maps.api.version.PacketListener;
import dev.cerus.maps.api.version.VersionAdapter;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.stream.Collectors;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.chat.IChatBaseComponent;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.PacketPlayOutEntityDestroy;
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
import net.minecraft.network.protocol.game.PacketPlayOutMap;
import net.minecraft.network.protocol.game.PacketPlayOutSpawnEntity;
import net.minecraft.network.syncher.DataWatcher;
import net.minecraft.network.syncher.DataWatcherRegistry;
import net.minecraft.server.network.PlayerConnection;
import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.level.saveddata.maps.MapIcon;
import net.minecraft.world.level.saveddata.maps.WorldMap;
import net.minecraft.world.phys.Vec3D;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack;
import org.bukkit.entity.Player;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.plugin.java.JavaPlugin;

public class VersionAdapter19R3 implements VersionAdapter {

private Field netManField;

@Override
public Object makeMapPacket(final boolean ignoreBounds, final ClientsideMap map) {
final int x = ignoreBounds ? 0 : map.getX();
final int y = ignoreBounds ? 0 : map.getY();
final int w = ignoreBounds ? 128 : Math.max(1, map.getWidth());
final int h = ignoreBounds ? 128 : Math.max(1, map.getHeight());

final byte[] data;
if (ignoreBounds) {
data = map.getData();
} else {
data = new byte[w * h];
for (int xx = 0; xx < w; ++xx) {
for (int yy = 0; yy < h; ++yy) {
data[xx + yy * w] = map.getData()[x + xx + (y + yy) * 128];
}
}
}

return new PacketPlayOutMap(
map.getId(),
(byte) 0,
true,
map.getMarkers().stream()
.map(cursor -> new MapIcon(
MapIcon.Type.a(cursor.getType()),
cursor.getCompressedX(),
cursor.getCompressedY(),
cursor.getDirection(),
!cursor.hasCaption() ? null : IChatBaseComponent.ChatSerializer.a(cursor.getCaptionString())
))
.collect(Collectors.toList()),
new WorldMap.b(
x,
y,
w,
h,
data
)
);
}

@Override
public Object makeFramePacket(final int frameId, final boolean visible, final ClientsideMap map) {
final org.bukkit.inventory.ItemStack mapItem = new org.bukkit.inventory.ItemStack(Material.FILLED_MAP, 1);
final MapMeta mapMeta = (MapMeta) mapItem.getItemMeta();
mapMeta.setMapId(map.getId());
mapItem.setItemMeta(mapMeta);

final List<DataWatcher.b<?>> dwItems = Arrays.asList(
new DataWatcher.b<>(8, DataWatcherRegistry.h, CraftItemStack.asNMSCopy(mapItem)),
new DataWatcher.b<>(0, DataWatcherRegistry.a, (byte) (visible ? 0 : 0x20))
);
return new PacketPlayOutEntityMetadata(frameId, dwItems);
}

@Override
public Object makeFrameSpawnPacket(final Frame frame) {
return new PacketPlayOutSpawnEntity(
frame.getEntityId(),
UUID.randomUUID(),
frame.getPosX(),
frame.getPosY(),
frame.getPosZ(),
frame.getFacing() == BlockFace.DOWN ? 90 : frame.getFacing() == BlockFace.UP ? -90 : 0,
switch (frame.getFacing()) {
case NORTH -> -180;
case EAST -> -90;
case WEST -> 90;
default -> 0;
},
EntityTypes.af,
switch (frame.getFacing()) {
case UP -> 1;
case NORTH -> 2;
case SOUTH -> 3;
case WEST -> 4;
case EAST -> 5;
default -> 0;
},
new Vec3D(0, 0, 0),
switch (frame.getFacing()) {
case NORTH -> -180;
case EAST -> -90;
case WEST -> 90;
default -> 0;
}
);
}

@Override
public Object makeFrameDespawnPacket(final Frame frame) {
return new PacketPlayOutEntityDestroy(frame.getEntityId());
}

@Override
public void sendPacket(final Player player, final Object packet) {
((CraftPlayer) player).getHandle().b.a((Packet<?>) packet);
}

@Override
public void inject(final Player player, final PacketListener listener, final JavaPlugin plugin) {
final NetworkManager networkManager;
try {
networkManager = this.getNetworkManager(((CraftPlayer) player).getHandle().b);
} catch (final IllegalAccessException | NoSuchFieldException e) {
plugin.getLogger().log(Level.WARNING, "Failed to inject packet handler into player %s".formatted(player.getName()), e);
return;
}
networkManager.m.pipeline().addBefore("packet_handler", "maps_listener", new PacketHandler19R3(player, listener, plugin));
}

private NetworkManager getNetworkManager(final PlayerConnection b) throws IllegalAccessException, NoSuchFieldException {
if (this.netManField == null) {
this.netManField = PlayerConnection.class.getDeclaredField("h");
this.netManField.setAccessible(true);
}
return (NetworkManager) this.netManField.get(b);
}

}
Loading

0 comments on commit 5dbea8c

Please sign in to comment.