Added 1.21 to legacy NMS branch (untested)
This commit is contained in:
parent
4f187b92bb
commit
39dcfc8b31
6 changed files with 583 additions and 0 deletions
2
.idea/encodings.xml
generated
2
.idea/encodings.xml
generated
|
@ -29,6 +29,8 @@
|
|||
<file url="file://$PROJECT_DIR$/NMS-v1_20_R2/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS-v1_20_R3/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS-v1_20_R3/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS-v1_21_R1/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/NMS-v1_21_R1/src/main/resources" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
|
||||
</component>
|
||||
|
|
72
NMS-v1_21_R1/pom.xml
Normal file
72
NMS-v1_21_R1/pom.xml
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ This file is part of MapReflectionAPI.
|
||||
~ Copyright (c) 2022-2023 inventivetalent / SBDevelopment - All Rights Reserved
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<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">
|
||||
<parent>
|
||||
<artifactId>MapReflectionAPI</artifactId>
|
||||
<groupId>tech.sbdevelopment</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>MapReflectionAPI-NMS-v1_21_R1</artifactId>
|
||||
|
||||
<properties>
|
||||
<NMSVersion>1.21-R0.1-SNAPSHOT</NMSVersion>
|
||||
<jdk.version>21</jdk.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<release>${jdk.version}</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>craftbukkit</artifactId>
|
||||
<version>${NMSVersion}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.sbdevelopment</groupId>
|
||||
<artifactId>MapReflectionAPI-API</artifactId>
|
||||
<version>${revision}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* This file is part of MapReflectionAPI.
|
||||
* Copyright (c) 2022-2023 inventivetalent / SBDevelopment - All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package tech.sbdevelopment.mapreflectionapi.nms;
|
||||
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutMap;
|
||||
import net.minecraft.world.level.saveddata.maps.MapId;
|
||||
import net.minecraft.world.level.saveddata.maps.WorldMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.ArrayImage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The {@link MapSender_v1_21_R1} sends the Map packets to players.
|
||||
*/
|
||||
public class MapSender_v1_21_R1 {
|
||||
private static final List<QueuedMap> sendQueue = new ArrayList<>();
|
||||
private static int senderID = -1;
|
||||
|
||||
private MapSender_v1_21_R1() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a map to the send queue
|
||||
*
|
||||
* @param id The ID of the map
|
||||
* @param content The {@link ArrayImage} to view on the map
|
||||
* @param player The {@link Player} to view for
|
||||
*/
|
||||
public static void addToQueue(final int id, final ArrayImage content, final Player player) {
|
||||
QueuedMap toSend = new QueuedMap(id, content, player);
|
||||
if (sendQueue.contains(toSend)) return;
|
||||
sendQueue.add(toSend);
|
||||
|
||||
runSender();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a senderID in the sender queue
|
||||
*
|
||||
* @param s The senderID to cancel
|
||||
*/
|
||||
public static void cancelID(int s) {
|
||||
sendQueue.removeIf(queuedMap -> queuedMap.id == s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the sender task
|
||||
*/
|
||||
private static void runSender() {
|
||||
if (Bukkit.getScheduler().isQueued(senderID) || Bukkit.getScheduler().isCurrentlyRunning(senderID) || sendQueue.isEmpty())
|
||||
return;
|
||||
|
||||
senderID = Bukkit.getScheduler().scheduleSyncRepeatingTask(MapReflectionAPI.getInstance(), () -> {
|
||||
if (sendQueue.isEmpty()) return;
|
||||
|
||||
for (int i = 0; i < Math.min(sendQueue.size(), 10 + 1); i++) {
|
||||
QueuedMap current = sendQueue.get(0);
|
||||
if (current == null) return;
|
||||
|
||||
sendMap(current.id, current.image, current.player);
|
||||
|
||||
if (!sendQueue.isEmpty()) sendQueue.remove(0);
|
||||
}
|
||||
}, 0, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a map to a player
|
||||
*
|
||||
* @param id0 The ID of the map
|
||||
* @param content The {@link ArrayImage} to view on the map
|
||||
* @param player The {@link Player} to view for
|
||||
*/
|
||||
public static void sendMap(final int id0, final ArrayImage content, final Player player) {
|
||||
if (player == null || !player.isOnline()) {
|
||||
List<QueuedMap> toRemove = new ArrayList<>();
|
||||
for (QueuedMap qMap : sendQueue) {
|
||||
if (qMap == null) continue;
|
||||
|
||||
if (qMap.player == null || !qMap.player.isOnline()) {
|
||||
toRemove.add(qMap);
|
||||
}
|
||||
}
|
||||
Bukkit.getScheduler().cancelTask(senderID);
|
||||
sendQueue.removeAll(toRemove);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final MapId id = new MapId(-id0);
|
||||
Bukkit.getScheduler().runTaskAsynchronously(MapReflectionAPI.getInstance(), () -> {
|
||||
try {
|
||||
WorldMap.b updateData = new WorldMap.b(
|
||||
content.minX, //X pos
|
||||
content.minY, //Y pos
|
||||
content.maxX, //X size (2nd X pos)
|
||||
content.maxY, //Y size (2nd Y pos)
|
||||
content.array //Data
|
||||
);
|
||||
|
||||
PacketPlayOutMap packet = new PacketPlayOutMap(
|
||||
id, //ID
|
||||
(byte) 0, //Scale
|
||||
false, //Show icons
|
||||
new ArrayList<>(), //Icons
|
||||
updateData
|
||||
);
|
||||
|
||||
((CraftPlayer) player).getHandle().c.a(packet); //connection send()
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
record QueuedMap(int id, ArrayImage image, Player player) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* This file is part of MapReflectionAPI.
|
||||
* Copyright (c) 2022-2023 inventivetalent / SBDevelopment - All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package tech.sbdevelopment.mapreflectionapi.nms;
|
||||
|
||||
import net.minecraft.core.component.DataComponentType;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutSetSlot;
|
||||
import net.minecraft.network.syncher.DataWatcher;
|
||||
import net.minecraft.resources.MinecraftKey;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.decoration.EntityItemFrame;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.ArrayImage;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.MapController;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.MapWrapper;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MapWrapper_v1_21_R1 extends MapWrapper {
|
||||
protected MapController controller = new MapController() {
|
||||
private final Map<UUID, Integer> viewers = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void addViewer(Player player) throws MapLimitExceededException {
|
||||
if (!isViewing(player)) {
|
||||
viewers.put(player.getUniqueId(), MapReflectionAPI.getMapManager().getNextFreeIdFor(player));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeViewer(OfflinePlayer player) {
|
||||
viewers.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearViewers() {
|
||||
for (UUID uuid : viewers.keySet()) {
|
||||
viewers.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewing(OfflinePlayer player) {
|
||||
if (player == null) return false;
|
||||
return viewers.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMapId(OfflinePlayer player) {
|
||||
if (isViewing(player)) {
|
||||
return viewers.get(player.getUniqueId());
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(ArrayImage content) {
|
||||
MapWrapper duplicate = MapReflectionAPI.getMapManager().getDuplicate(content);
|
||||
if (duplicate != null) {
|
||||
MapWrapper_v1_21_R1.this.content = duplicate.getContent();
|
||||
return;
|
||||
}
|
||||
|
||||
MapWrapper_v1_21_R1.this.content = content;
|
||||
|
||||
for (UUID id : viewers.keySet()) {
|
||||
sendContent(Bukkit.getPlayer(id));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendContent(Player player) {
|
||||
sendContent(player, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendContent(Player player, boolean withoutQueue) {
|
||||
if (!isViewing(player)) return;
|
||||
|
||||
int id = getMapId(player);
|
||||
if (withoutQueue) {
|
||||
MapSender_v1_21_R1.sendMap(id, MapWrapper_v1_21_R1.this.content, player);
|
||||
} else {
|
||||
MapSender_v1_21_R1.addToQueue(id, MapWrapper_v1_21_R1.this.content, player);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelSend() {
|
||||
for (int s : viewers.values()) {
|
||||
MapSender_v1_21_R1.cancelID(s);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInInventory(Player player, int slot, boolean force) {
|
||||
if (!isViewing(player)) return;
|
||||
|
||||
if (player.getGameMode() == GameMode.CREATIVE && !force) return;
|
||||
|
||||
if (slot < 9) {
|
||||
slot += 36;
|
||||
} else if (slot > 35 && slot != 45) {
|
||||
slot = 8 - (slot - 36);
|
||||
}
|
||||
|
||||
CraftPlayer craftPlayer = (CraftPlayer) player;
|
||||
int windowId = craftPlayer.getHandle().cc.j; //inventoryMenu containerId
|
||||
int stateId = craftPlayer.getHandle().cc.j(); //inventoryMenu getStateId()
|
||||
|
||||
ItemStack stack = new ItemStack(Material.FILLED_MAP, 1);
|
||||
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
|
||||
|
||||
PacketPlayOutSetSlot packet = new PacketPlayOutSetSlot(windowId, stateId, slot, nmsStack);
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInInventory(Player player, int slot) {
|
||||
showInInventory(player, slot, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInHand(Player player, boolean force) {
|
||||
if (player.getInventory().getItemInMainHand().getType() != Material.FILLED_MAP && !force) return;
|
||||
showInInventory(player, player.getInventory().getHeldItemSlot(), force);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInHand(Player player) {
|
||||
showInHand(player, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInFrame(Player player, ItemFrame frame) {
|
||||
showInFrame(player, frame, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInFrame(Player player, ItemFrame frame, boolean force) {
|
||||
if (frame.getItem().getType() != Material.FILLED_MAP && !force) return;
|
||||
showInFrame(player, frame.getEntityId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInFrame(Player player, int entityId) {
|
||||
showInFrame(player, entityId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showInFrame(Player player, int entityId, String debugInfo) {
|
||||
if (!isViewing(player)) return;
|
||||
|
||||
ItemStack stack = new ItemStack(Material.FILLED_MAP, 1);
|
||||
if (debugInfo != null) {
|
||||
ItemMeta itemMeta = stack.getItemMeta();
|
||||
itemMeta.setDisplayName(debugInfo);
|
||||
stack.setItemMeta(itemMeta);
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTask(MapReflectionAPI.getInstance(), () -> {
|
||||
ItemFrame frame = getItemFrameById(player.getWorld(), entityId);
|
||||
if (frame != null) {
|
||||
frame.removeMetadata("MAP_WRAPPER_REF", MapReflectionAPI.getInstance());
|
||||
frame.setMetadata("MAP_WRAPPER_REF", new FixedMetadataValue(MapReflectionAPI.getInstance(), MapWrapper_v1_21_R1.this));
|
||||
}
|
||||
|
||||
sendItemFramePacket(player, entityId, stack, getMapId(player));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFrame(Player player, int entityId) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearFrame(Player player, ItemFrame frame) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemFrame getItemFrameById(World world, int entityId) {
|
||||
CraftWorld craftWorld = (CraftWorld) world;
|
||||
|
||||
Entity entity = craftWorld.getHandle().a(entityId);
|
||||
if (entity == null) return null;
|
||||
|
||||
if (entity instanceof ItemFrame) return (ItemFrame) entity;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendItemFramePacket(Player player, int entityId, ItemStack stack, int mapId) {
|
||||
net.minecraft.world.item.ItemStack nmsStack = CraftItemStack.asNMSCopy(stack);
|
||||
nmsStack.a().a(BuiltInRegistries.aq.a(MinecraftKey.a("minecraft:map_id")), mapId); //getOrCreateTag putInt
|
||||
|
||||
List<DataWatcher.c<?>> list = new ArrayList<>();
|
||||
DataWatcher.c<?> dataWatcherItem = DataWatcher.c.a(EntityItemFrame.f, nmsStack);
|
||||
list.add(dataWatcherItem);
|
||||
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(entityId, list);
|
||||
|
||||
((CraftPlayer) player).getHandle().c.a(packet);
|
||||
}
|
||||
};
|
||||
|
||||
public MapWrapper_v1_21_R1(ArrayImage image) {
|
||||
super(image);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MapController getController() {
|
||||
return controller;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* This file is part of MapReflectionAPI.
|
||||
* Copyright (c) 2022-2023 inventivetalent / SBDevelopment - All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package tech.sbdevelopment.mapreflectionapi.nms;
|
||||
|
||||
import io.netty.channel.*;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInSetCreativeSlot;
|
||||
import net.minecraft.network.protocol.game.PacketPlayInUseEntity;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutMap;
|
||||
import net.minecraft.world.EnumHand;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.phys.Vec3D;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftPlayer;
|
||||
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.events.CreateInventoryMapUpdateEvent;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.events.MapCancelEvent;
|
||||
import tech.sbdevelopment.mapreflectionapi.api.events.MapInteractEvent;
|
||||
import tech.sbdevelopment.mapreflectionapi.listeners.PacketListener;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil.*;
|
||||
|
||||
public class PacketListener_v1_21_R1 extends PacketListener {
|
||||
@Override
|
||||
protected void injectPlayer(Player p) {
|
||||
ChannelDuplexHandler channelDuplexHandler = new ChannelDuplexHandler() {
|
||||
@Override
|
||||
//On send packet
|
||||
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
|
||||
if (packet instanceof PacketPlayOutMap packetPlayOutMap) {
|
||||
int id = (int) getDeclaredField(packetPlayOutMap, "a");
|
||||
|
||||
if (id < 0) {
|
||||
//It's one of our maps, invert ID and let through!
|
||||
int newId = -id;
|
||||
setDeclaredField(packetPlayOutMap, "a", newId); //mapId
|
||||
} else {
|
||||
boolean async = !plugin.getServer().isPrimaryThread();
|
||||
MapCancelEvent event = new MapCancelEvent(p, id, async);
|
||||
if (MapReflectionAPI.getMapManager().isIdUsedBy(p, id)) event.setCancelled(true);
|
||||
if (event.getHandlers().getRegisteredListeners().length > 0)
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
|
||||
if (event.isCancelled()) return;
|
||||
}
|
||||
}
|
||||
|
||||
super.write(ctx, packet, promise);
|
||||
}
|
||||
|
||||
@Override
|
||||
//On receive packet
|
||||
public void channelRead(ChannelHandlerContext ctx, Object packet) throws Exception {
|
||||
if (packet instanceof PacketPlayInUseEntity packetPlayInUseEntity) {
|
||||
int entityId = (int) getDeclaredField(packetPlayInUseEntity, "a"); //entityId
|
||||
Object action = getDeclaredField(packetPlayInUseEntity, "b"); //action
|
||||
Enum<?> actionEnum = (Enum<?>) callDeclaredMethod(action, "a"); //action type
|
||||
EnumHand hand = hasField(action, "a") ? (EnumHand) getDeclaredField(action, "a") : null; //hand
|
||||
Vec3D pos = hasField(action, "b") ? (Vec3D) getDeclaredField(action, "b") : null; //pos
|
||||
|
||||
if (Bukkit.getScheduler().callSyncMethod(plugin, () -> {
|
||||
boolean async = !plugin.getServer().isPrimaryThread();
|
||||
MapInteractEvent event = new MapInteractEvent(p, entityId, actionEnum.ordinal(), pos != null ? vec3DToVector(pos) : null, hand != null ? hand.ordinal() : 0, async);
|
||||
if (event.getFrame() != null && event.getMapWrapper() != null) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
return event.isCancelled();
|
||||
}
|
||||
return false;
|
||||
}).get(1, TimeUnit.SECONDS)) return;
|
||||
} else if (packet instanceof PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot) {
|
||||
int slot = packetPlayInSetCreativeSlot.b();
|
||||
ItemStack item = packetPlayInSetCreativeSlot.e();
|
||||
|
||||
boolean async = !plugin.getServer().isPrimaryThread();
|
||||
CreateInventoryMapUpdateEvent event = new CreateInventoryMapUpdateEvent(p, slot, CraftItemStack.asBukkitCopy(item), async);
|
||||
if (event.getMapWrapper() != null) {
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if (event.isCancelled()) return;
|
||||
}
|
||||
}
|
||||
|
||||
super.channelRead(ctx, packet);
|
||||
}
|
||||
};
|
||||
|
||||
//The connection is private since 1.19.4 :|
|
||||
NetworkManager networkManager = (NetworkManager) getField(((CraftPlayer) p).getHandle().c, "h");
|
||||
ChannelPipeline pipeline = networkManager.n.pipeline(); //connection channel
|
||||
pipeline.addBefore("packet_handler", p.getName(), channelDuplexHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePlayer(Player p) {
|
||||
//The connection is private since 1.19.4 :|
|
||||
NetworkManager networkManager = (NetworkManager) getField(((CraftPlayer) p).getHandle().c, "h");
|
||||
Channel channel = networkManager.n; //connection channel
|
||||
channel.eventLoop().submit(() -> channel.pipeline().remove(p.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Vector vec3DToVector(Object vec3d) {
|
||||
if (!(vec3d instanceof Vec3D vec3dObj)) return new Vector(0, 0, 0);
|
||||
return new Vector(vec3dObj.c, vec3dObj.d, vec3dObj.e); //x, y, z
|
||||
}
|
||||
}
|
1
pom.xml
1
pom.xml
|
@ -40,6 +40,7 @@
|
|||
<modules>
|
||||
<module>API</module>
|
||||
<module>Dist</module>
|
||||
<module>NMS-v1_21_R1</module>
|
||||
<module>NMS-v1_20_R3</module>
|
||||
<module>NMS-v1_20_R2</module>
|
||||
<module>NMS-v1_20_R1</module>
|
||||
|
|
Loading…
Add table
Reference in a new issue