From 14c4152248e75603ea3f0229dcd04a7c598898af Mon Sep 17 00:00:00 2001 From: Jonathan Williams Date: Fri, 12 Sep 2014 10:03:33 -1000 Subject: [PATCH] Fixed CustomTagFix. Updated ServerData ServerGroup and SErverMonitor for new flags in Arcade. --- .../src/mineplex/core/CustomTagFix.java | 57 +++++++----- .../core/disguise/DisguiseManager.java | 36 ++++--- .../mineplex/core/friend/FriendManager.java | 19 ++-- .../core/packethandler/IPacketHandler.java | 6 ++ .../core/packethandler/PacketHandler.java | 26 +++++- ...PlayerPacketEvent.java => PacketInfo.java} | 16 +--- .../core/packethandler/PacketVerifier.java | 61 +++++++----- .../Mineplex.Hub/src/mineplex/hub/Hub.java | 6 +- .../src/mineplex/serverdata/ServerGroup.java | 88 ++++++++++++++---- .../mineplex/servermonitor/ServerMonitor.java | 4 +- .../src/nautilus/game/arcade/Arcade.java | 10 +- .../nautilus/game/arcade/ArcadeManager.java | 6 +- .../arcade/managers/GameLobbyManager.java | 23 ++--- Website/LOCWebsite.suo | Bin 474624 -> 474624 bytes 14 files changed, 232 insertions(+), 126 deletions(-) create mode 100644 Plugins/Mineplex.Core/src/mineplex/core/packethandler/IPacketHandler.java rename Plugins/Mineplex.Core/src/mineplex/core/packethandler/{PlayerPacketEvent.java => PacketInfo.java} (66%) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/CustomTagFix.java b/Plugins/Mineplex.Core/src/mineplex/core/CustomTagFix.java index 91a9e1600..e9aa2cd90 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/CustomTagFix.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/CustomTagFix.java @@ -5,8 +5,10 @@ import java.util.List; import mineplex.core.common.DummyEntity; import mineplex.core.common.util.NautHashMap; +import mineplex.core.packethandler.IPacketHandler; +import mineplex.core.packethandler.PacketHandler; import mineplex.core.packethandler.PacketVerifier; -import mineplex.core.packethandler.PlayerPacketEvent; +import mineplex.core.packethandler.PacketInfo; import net.minecraft.server.v1_7_R4.DataWatcher; import net.minecraft.server.v1_7_R4.EnumEntitySize; import net.minecraft.server.v1_7_R4.MathHelper; @@ -20,23 +22,23 @@ import net.minecraft.server.v1_7_R4.WatchableObject; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_7_R4.CraftWorld; import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; -import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; -public class CustomTagFix extends MiniPlugin +public class CustomTagFix extends MiniPlugin implements IPacketHandler { private static int _fakeIdCounter = 455000; - private NautHashMap _entityMap = new NautHashMap(); + private NautHashMap> _entityMap = new NautHashMap>(); private Field _destroyId; - public CustomTagFix(JavaPlugin plugin) + public CustomTagFix(JavaPlugin plugin, PacketHandler packetHandler) { super("Custom Tag Fix", plugin); + packetHandler.addPacketHandler(this); try { @@ -50,16 +52,27 @@ public class CustomTagFix extends MiniPlugin } } - @SuppressWarnings("unchecked") - @EventHandler(priority = EventPriority.HIGHEST) - public void handlePackets(PlayerPacketEvent event) + @EventHandler + public void playerQuit(PlayerQuitEvent event) { - Packet packet = event.getPacket(); - Player owner = event.getPlayer(); - PacketVerifier verifier = event.getVerifier(); + _entityMap.remove(event.getPlayer()); + } + + @SuppressWarnings("unchecked") + public void handle(PacketInfo packetInfo) + { + if (packetInfo.isCancelled()) + return; + + Packet packet = packetInfo.getPacket(); + Player owner = packetInfo.getPlayer(); + PacketVerifier verifier = packetInfo.getVerifier(); if (((CraftPlayer)owner).getHandle().playerConnection.networkManager.getVersion() >= 47) { + if (owner.isOnline() && !_entityMap.containsKey(owner)) + _entityMap.put(owner, new NautHashMap()); + if (packet instanceof PacketPlayOutSpawnEntityLiving) { PacketPlayOutSpawnEntityLiving spawnPacket = (PacketPlayOutSpawnEntityLiving)packet; @@ -68,14 +81,14 @@ public class CustomTagFix extends MiniPlugin if (spawnPacket.l.getByte(11) == 1 || spawnPacket.l.getByte(3) == 1) { - if (_entityMap.containsKey(spawnPacket.a)) + if (_entityMap.get(owner).containsKey(spawnPacket.a)) { - verifier.bypassProcess(new PacketPlayOutEntityDestroy(_entityMap.get(spawnPacket.a))); + verifier.bypassProcess(new PacketPlayOutEntityDestroy(_entityMap.get(owner).get(spawnPacket.a))); } int newId = _fakeIdCounter++; sendProtocolPackets(owner, spawnPacket.a, newId, entityName, verifier); - _entityMap.put(spawnPacket.a, newId); + _entityMap.get(owner).put(spawnPacket.a, newId); } } @@ -83,7 +96,7 @@ public class CustomTagFix extends MiniPlugin { PacketPlayOutEntityMetadata metaPacket = (PacketPlayOutEntityMetadata)packet; - if (!_entityMap.containsKey(metaPacket.a) && metaPacket.a != 777777) + if (!_entityMap.get(owner).containsKey(metaPacket.a) && metaPacket.a != 777777) { String entityName = ""; for (WatchableObject watchable : (List)metaPacket.b) @@ -98,7 +111,7 @@ public class CustomTagFix extends MiniPlugin { int newId = _fakeIdCounter++; sendProtocolPackets(owner, metaPacket.a, newId, entityName, verifier); - _entityMap.put(metaPacket.a, newId); + _entityMap.get(owner).put(metaPacket.a, newId); } } } @@ -108,10 +121,10 @@ public class CustomTagFix extends MiniPlugin { for (int id : (int[])_destroyId.get(packet)) { - if (_entityMap.containsKey(id)) + if (_entityMap.get(owner).containsKey(id)) { - verifier.bypassProcess(new PacketPlayOutEntityDestroy(_entityMap.get(id))); - _entityMap.remove(id); + verifier.bypassProcess(new PacketPlayOutEntityDestroy(_entityMap.get(owner).get(id))); + _entityMap.get(owner).remove(id); } } } @@ -126,7 +139,7 @@ public class CustomTagFix extends MiniPlugin if (attachPacket.c == owner.getEntityId()) { - event.setCancelled(true); + packetInfo.setCancelled(true); //verifier.bypassProcess(new PacketPlayOutEntityDestroy(attachPacket.b)); /* System.out.println("Adding patch item."); @@ -302,7 +315,7 @@ public class CustomTagFix extends MiniPlugin packet.l = watcher; - packetList.bypassProcess(packet); + packetList.bypassProcess(packet); PacketPlayOutAttachEntity vehiclePacket = new PacketPlayOutAttachEntity(); vehiclePacket.a = 0; diff --git a/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java b/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java index e2e57be28..19c3fb90a 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/disguise/DisguiseManager.java @@ -40,13 +40,15 @@ import mineplex.core.common.util.NautHashMap; import mineplex.core.disguise.disguises.DisguiseBase; import mineplex.core.disguise.disguises.DisguiseBlock; import mineplex.core.disguise.disguises.DisguiseInsentient; +import mineplex.core.packethandler.IPacketHandler; +import mineplex.core.packethandler.PacketHandler; import mineplex.core.packethandler.PacketVerifier; -import mineplex.core.packethandler.PlayerPacketEvent; +import mineplex.core.packethandler.PacketInfo; import mineplex.core.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; -public class DisguiseManager extends MiniPlugin +public class DisguiseManager extends MiniPlugin implements IPacketHandler { private NautHashMap _spawnPacketMap = new NautHashMap(); private NautHashMap _movePacketMap = new NautHashMap(); @@ -64,10 +66,12 @@ public class DisguiseManager extends MiniPlugin private Field _soundC; private Field _soundD; - public DisguiseManager(JavaPlugin plugin) + public DisguiseManager(JavaPlugin plugin, PacketHandler packetHandler) { super("Disguise Manager", plugin); + packetHandler.addPacketHandler(this); + try { _attributesA = PacketPlayOutUpdateAttributes.class.getDeclaredField("a"); @@ -173,6 +177,8 @@ public class DisguiseManager extends MiniPlugin entityPlayer.playerConnection.sendPacket(new PacketPlayOutSpawnEntityLiving(((CraftLivingEntity)entity).getHandle())); } } + + _disguisePlayerMap.remove(disguise); } public void reApplyDisguise(final DisguiseBase disguise) @@ -347,6 +353,7 @@ public class DisguiseManager extends MiniPlugin _entityDisguiseMap.clear(); _addTempList.clear(); _delTempList.clear(); + _disguisePlayerMap.clear(); } @EventHandler @@ -360,15 +367,14 @@ public class DisguiseManager extends MiniPlugin } } - @EventHandler - public void handlePackets(PlayerPacketEvent event) + public void handle(PacketInfo packetInfo) { if (_handlingPacket) return; - final Packet packet = event.getPacket(); - Player owner = event.getPlayer(); - final PacketVerifier packetVerifier = event.getVerifier(); + final Packet packet = packetInfo.getPacket(); + Player owner = packetInfo.getPlayer(); + final PacketVerifier packetVerifier = packetInfo.getVerifier(); if (packet instanceof PacketPlayOutNamedEntitySpawn) { @@ -377,7 +383,7 @@ public class DisguiseManager extends MiniPlugin if (_spawnPacketMap.containsKey(entityId) && (_spawnPacketMap.get(entityId).Global || _disguisePlayerMap.get(_spawnPacketMap.get(entityId)).contains(owner))) { handlePacket(_spawnPacketMap.get(entityId).GetSpawnPacket(), packetVerifier); - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutSpawnEntity) @@ -387,7 +393,7 @@ public class DisguiseManager extends MiniPlugin if (_spawnPacketMap.containsKey(entityId) && (_spawnPacketMap.get(entityId).Global || _disguisePlayerMap.get(_spawnPacketMap.get(entityId)).contains(owner))) { handlePacket(_spawnPacketMap.get(entityId).GetSpawnPacket(), packetVerifier); - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutUpdateAttributes) @@ -411,7 +417,7 @@ public class DisguiseManager extends MiniPlugin { // Crash clients with meta to a block id. if (_spawnPacketMap.get(entityId) instanceof DisguiseBlock) - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutAnimation) @@ -420,7 +426,7 @@ public class DisguiseManager extends MiniPlugin if (containsSpawnDisguise(owner, entityId) && owner.getEntityId() != entityId) { - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutEntityMetadata) @@ -430,7 +436,7 @@ public class DisguiseManager extends MiniPlugin if (containsSpawnDisguise(owner, entityId) && owner.getEntityId() != entityId) { handlePacket(_spawnPacketMap.get(entityId).GetMetaDataPacket(), packetVerifier); - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutEntityEquipment) @@ -441,7 +447,7 @@ public class DisguiseManager extends MiniPlugin { if (!((DisguiseInsentient)_spawnPacketMap.get(entityId)).armorVisible() && ((PacketPlayOutEntityEquipment)packet).b != 0) { - event.setCancelled(true); + packetInfo.setCancelled(true); } } } @@ -461,7 +467,7 @@ public class DisguiseManager extends MiniPlugin } else if (_spawnPacketMap.containsKey(velocityPacket.a)) { - event.setCancelled(true); + packetInfo.setCancelled(true); } } else if (packet instanceof PacketPlayOutRelEntityMove) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/friend/FriendManager.java b/Plugins/Mineplex.Core/src/mineplex/core/friend/FriendManager.java index 99b6ea971..8d4cb8a8f 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/friend/FriendManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/friend/FriendManager.java @@ -20,22 +20,26 @@ import mineplex.core.friend.command.DeleteFriend; import mineplex.core.friend.data.FriendData; import mineplex.core.friend.data.FriendRepository; import mineplex.core.friend.ui.FriendTabList; -import mineplex.core.packethandler.PlayerPacketEvent; +import mineplex.core.packethandler.IPacketHandler; +import mineplex.core.packethandler.PacketHandler; +import mineplex.core.packethandler.PacketInfo; import mineplex.core.timing.TimingManager; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; -public class FriendManager extends MiniClientPlugin +public class FriendManager extends MiniClientPlugin implements IPacketHandler { private FriendRepository _repository; private NautHashMap _playerTabMap; private boolean _sendingPackets = false; - public FriendManager(JavaPlugin plugin) + public FriendManager(JavaPlugin plugin, PacketHandler packetHandler) { super("Friends", plugin); + packetHandler.addPacketHandler(this); + _repository = new FriendRepository(plugin); _playerTabMap = new NautHashMap(); } @@ -134,15 +138,14 @@ public class FriendManager extends MiniClientPlugin _playerTabMap.remove(event.getPlayer()); } - @EventHandler - public void handleFriendPackets(PlayerPacketEvent event) + public void handle(PacketInfo packetInfo) { - if (event.isCancelled()) + if (packetInfo.isCancelled()) return; - if (event.getPacket() instanceof PacketPlayOutPlayerInfo) + if (packetInfo.getPacket() instanceof PacketPlayOutPlayerInfo) { - event.setCancelled(_sendingPackets); + packetInfo.setCancelled(_sendingPackets); } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/IPacketHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/IPacketHandler.java new file mode 100644 index 000000000..3ce1c5563 --- /dev/null +++ b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/IPacketHandler.java @@ -0,0 +1,6 @@ +package mineplex.core.packethandler; + +public interface IPacketHandler +{ + void handle(PacketInfo packetInfo); +} diff --git a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketHandler.java b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketHandler.java index b26b88406..5ee3adc78 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketHandler.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketHandler.java @@ -1,6 +1,9 @@ package mineplex.core.packethandler; +import java.util.HashSet; + import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.player.PlayerJoinEvent; @@ -8,9 +11,13 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.java.JavaPlugin; import mineplex.core.MiniPlugin; +import mineplex.core.common.util.NautHashMap; public class PacketHandler extends MiniPlugin { + private NautHashMap _playerVerifierMap = new NautHashMap(); + private HashSet _packetHandlers = new HashSet(); + public PacketHandler(JavaPlugin plugin) { super("PacketHandler", plugin); @@ -19,12 +26,29 @@ public class PacketHandler extends MiniPlugin @EventHandler(priority = EventPriority.MONITOR) public void onPlayerJoin(PlayerJoinEvent event) { - ((CraftPlayer) event.getPlayer()).getHandle().playerConnection.PacketVerifier.addPacketVerifier(new PacketVerifier(event.getPlayer())); + _playerVerifierMap.put(event.getPlayer(), new PacketVerifier(event.getPlayer())); + ((CraftPlayer) event.getPlayer()).getHandle().playerConnection.PacketVerifier.addPacketVerifier(_playerVerifierMap.get(event.getPlayer())); + + for (IPacketHandler packetHandler : _packetHandlers) + { + _playerVerifierMap.get(event.getPlayer()).addPacketHandler(packetHandler); + } } @EventHandler(priority = EventPriority.MONITOR) public void onPlayerQuit(PlayerQuitEvent event) { ((CraftPlayer) event.getPlayer()).getHandle().playerConnection.PacketVerifier.clearVerifiers(); + _playerVerifierMap.remove(event.getPlayer()).clearHandlers(); } + + public void addPacketHandler(IPacketHandler packetHandler) + { + _packetHandlers.add(packetHandler); + + for (PacketVerifier verifier : _playerVerifierMap.values()) + { + verifier.addPacketHandler(packetHandler); + } + } } diff --git a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PlayerPacketEvent.java b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketInfo.java similarity index 66% rename from Plugins/Mineplex.Core/src/mineplex/core/packethandler/PlayerPacketEvent.java rename to Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketInfo.java index c85d82402..06ededb58 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PlayerPacketEvent.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketInfo.java @@ -6,32 +6,20 @@ import org.bukkit.entity.Player; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -public class PlayerPacketEvent extends Event +public class PacketInfo { - private static final HandlerList handlers = new HandlerList(); - private Player _player; private Packet _packet; private PacketVerifier _verifier; private boolean _cancelled = false; - public PlayerPacketEvent(Player player, Packet packet, PacketVerifier verifier) + public PacketInfo(Player player, Packet packet, PacketVerifier verifier) { _player = player; _packet = packet; _verifier = verifier; } - - public HandlerList getHandlers() - { - return handlers; - } - - public static HandlerList getHandlerList() - { - return handlers; - } public Packet getPacket() { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketVerifier.java b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketVerifier.java index 4d9bcb082..f318ac341 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketVerifier.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/packethandler/PacketVerifier.java @@ -1,5 +1,9 @@ package mineplex.core.packethandler; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + import net.minecraft.server.v1_7_R4.IPacketVerifier; import net.minecraft.server.v1_7_R4.Packet; import net.minecraft.server.v1_7_R4.PacketPlayOutAnimation; @@ -23,38 +27,41 @@ import org.bukkit.entity.Player; public class PacketVerifier implements IPacketVerifier { + private static Field _destroyId; private Player _owner; + + private List _packetHandlers = new ArrayList(); public PacketVerifier(Player owner) { _owner = owner; + + if (_destroyId == null) + { + try + { + _destroyId = PacketPlayOutEntityDestroy.class.getDeclaredField("a"); + _destroyId.setAccessible(true); + } + catch (Exception exception) + { + System.out.println("Field exception in CustomTagFix : "); + exception.printStackTrace(); + } + } } @Override public boolean verify(Packet o) { - if (o instanceof PacketPlayOutNamedEntitySpawn - || o instanceof PacketPlayOutSpawnEntity - || o instanceof PacketPlayOutSpawnEntityLiving - || o instanceof PacketPlayOutUpdateAttributes - || o instanceof PacketPlayOutAnimation - || o instanceof PacketPlayOutEntityMetadata - || o instanceof PacketPlayOutEntityEquipment - || o instanceof PacketPlayOutEntityVelocity - || o instanceof PacketPlayOutRelEntityMove - || o instanceof PacketPlayOutRelEntityMoveLook - || o instanceof PacketPlayOutPlayerInfo - || o instanceof PacketPlayOutEntityDestroy - || o instanceof PacketPlayOutAttachEntity) - { - PlayerPacketEvent event = new PlayerPacketEvent(_owner, o, this); - - Bukkit.getServer().getPluginManager().callEvent(event); - - return !event.isCancelled(); - } - - return true; + PacketInfo packetInfo = new PacketInfo(_owner, o, this); + + for (IPacketHandler handler : _packetHandlers) + { + handler.handle(packetInfo); + } + + return !packetInfo.isCancelled(); } public void bypassProcess(Packet packet) @@ -71,4 +78,14 @@ public class PacketVerifier implements IPacketVerifier { ((CraftPlayer)_owner).getHandle().playerConnection.sendPacket(packet); } + + public void clearHandlers() + { + _packetHandlers.clear(); + } + + public void addPacketHandler(IPacketHandler packetHandler) + { + _packetHandlers.add(packetHandler); + } } diff --git a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java index d565f52bb..62055c56c 100644 --- a/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java +++ b/Plugins/Mineplex.Hub/src/mineplex/hub/Hub.java @@ -95,7 +95,8 @@ public class Hub extends JavaPlugin implements IRelation PartyManager partyManager = new PartyManager(this, clientManager, preferenceManager); Portal portal = new Portal(this, serverStatusManager.getCurrentServerName()); AntiHack.Initialize(this, punish, portal); - DisguiseManager disguiseManager = new DisguiseManager(this); + PacketHandler packetHandler = new PacketHandler(this); + DisguiseManager disguiseManager = new DisguiseManager(this, packetHandler); HubManager hubManager = new HubManager(this, new BlockRestore(this), clientManager, donationManager, new ConditionManager(this), disguiseManager, new TaskManager(this, webServerAddress), portal, partyManager, preferenceManager, petManager, pollManager); new PlayerTracker(this, serverStatusManager.getCurrentServerName(), serverStatusManager.getUs()); @@ -105,8 +106,7 @@ public class Hub extends JavaPlugin implements IRelation new Chat(this, clientManager, preferenceManager, serverStatusManager.getCurrentServerName()); new MemoryFix(this); new FileUpdater(this, portal); - new CustomTagFix(this); - new PacketHandler(this); + new CustomTagFix(this, packetHandler); CombatManager combatManager = new CombatManager(this); BlockRestore blockRestore = new BlockRestore(this); diff --git a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerGroup.java b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerGroup.java index a07e52ba4..232347e58 100644 --- a/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerGroup.java +++ b/Plugins/Mineplex.ServerData/src/mineplex/serverdata/ServerGroup.java @@ -71,6 +71,42 @@ public class ServerGroup private boolean _tournament; public boolean getTournament() { return _tournament; } + private boolean _teamRejoin; + public boolean getTeamRejoin() { return _teamRejoin; } + + private boolean _teamAutoJoin; + public boolean getTeamAutoJoin() { return _teamAutoJoin; } + + private boolean _teamForceBalance; + public boolean getTeamForceBalance() { return _teamForceBalance; } + + private boolean _gameAutoStart; + public boolean getGameAutoStart() { return _gameAutoStart; } + + private boolean _gameTimeout; + public boolean getGameTimeout() { return _gameTimeout; } + + private boolean _rewardGems; + public boolean getRewardGems() { return _rewardGems; } + + private boolean _rewardItems; + public boolean getRewardItems() { return _rewardItems; } + + private boolean _rewardStats; + public boolean getRewardStats() { return _rewardStats; } + + private boolean _rewardAchievements; + public boolean getRewardAchievements() { return _rewardAchievements; } + + private boolean _hotbarInventory; + public boolean getHotbarInventory() { return _hotbarInventory; } + + private boolean _hotbarHubClock; + public boolean getHotbarHubClock() { return _hotbarHubClock; } + + private boolean _playerKickIdle; + public boolean getPlayerKickIdle() { return _playerKickIdle; } + private boolean _generateFreeVersions; public boolean getGenerateFreeVersions() { return _generateFreeVersions; } @@ -95,26 +131,38 @@ public class ServerGroup */ public ServerGroup(Map data, Region region) { - this._name = data.get("name"); - this._prefix = data.get("prefix"); - this._scriptName = data.get("scriptName"); - this._requiredRam = Integer.valueOf(data.get("ram")); - this._requiredCpu = Integer.valueOf(data.get("cpu")); - this._requiredTotalServers = Integer.valueOf(data.get("totalServers")); - this._requiredJoinableServers = Integer.valueOf(data.get("joinableServers")); - this._portSection = Integer.valueOf(data.get("portSection")); - this._arcadeGroup = Boolean.valueOf(data.get("arcadeGroup")); - this._worldZip = data.get("worldZip"); - this._plugin = data.get("plugin"); - this._configPath = data.get("configPath"); - this._minPlayers = Integer.valueOf(data.get("minPlayers")); - this._maxPlayers = Integer.valueOf(data.get("maxPlayers")); - this._pvp = Boolean.valueOf(data.get("pvp")); - this._tournament = Boolean.valueOf(data.get("tournament")); - this._generateFreeVersions = Boolean.valueOf(data.get("generateFreeVersions")); - this._games = data.get("games"); - this._serverType = data.get("serverType"); - this._addNoCheat = Boolean.valueOf(data.get("addNoCheat")); + _name = data.get("name"); + _prefix = data.get("prefix"); + _scriptName = data.get("scriptName"); + _requiredRam = Integer.valueOf(data.get("ram")); + _requiredCpu = Integer.valueOf(data.get("cpu")); + _requiredTotalServers = Integer.valueOf(data.get("totalServers")); + _requiredJoinableServers = Integer.valueOf(data.get("joinableServers")); + _portSection = Integer.valueOf(data.get("portSection")); + _arcadeGroup = Boolean.valueOf(data.get("arcadeGroup")); + _worldZip = data.get("worldZip"); + _plugin = data.get("plugin"); + _configPath = data.get("configPath"); + _minPlayers = Integer.valueOf(data.get("minPlayers")); + _maxPlayers = Integer.valueOf(data.get("maxPlayers")); + _pvp = Boolean.valueOf(data.get("pvp")); + _tournament = Boolean.valueOf(data.get("tournament")); + _generateFreeVersions = Boolean.valueOf(data.get("generateFreeVersions")); + _games = data.get("games"); + _serverType = data.get("serverType"); + _addNoCheat = Boolean.valueOf(data.get("addNoCheat")); + _teamRejoin = Boolean.valueOf(data.get("teamRejoin")); + _teamAutoJoin = Boolean.valueOf(data.get("teamAutoJoin")); + _teamForceBalance = Boolean.valueOf(data.get("teamForceBalance")); + _gameAutoStart = Boolean.valueOf(data.get("gameAutoStart")); + _gameTimeout = Boolean.valueOf(data.get("gameTimeout")); + _rewardGems = Boolean.valueOf(data.get("rewardGems")); + _rewardItems = Boolean.valueOf(data.get("rewardItems")); + _rewardStats = Boolean.valueOf(data.get("rewardStats")); + _rewardAchievements = Boolean.valueOf(data.get("rewardAchievements")); + _hotbarInventory = Boolean.valueOf(data.get("hotbarInventory")); + _hotbarHubClock = Boolean.valueOf(data.get("hotbarHubClock")); + _playerKickIdle = Boolean.valueOf(data.get("playerKickIdle")); fetchServers(region); } diff --git a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java index 29bd07db9..d271edc74 100644 --- a/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java +++ b/Plugins/Mineplex.ServerMonitor/src/mineplex/servermonitor/ServerMonitor.java @@ -380,12 +380,12 @@ public class ServerMonitor private static void startServer(final DedicatedServer serverSpace, final ServerGroup serverGroup, final int serverNum, final boolean free) { - String cmd = "/home/mineplex/easyRemoteStartServerCustom.sh"; + String cmd = "/home/mineplex/easyRemoteStartServer.sh"; final String groupPrefix = serverGroup.getPrefix(); final String serverName = serverSpace.getName(); final String serverAddress = serverSpace.getPublicAddress(); - ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverAddress, serverSpace.getPrivateAddress(), (serverGroup.getPortSection() + serverNum) + "", serverGroup.getRequiredRam() + "", serverGroup.getWorldZip(), serverGroup.getPlugin(), serverGroup.getConfigPath(), serverGroup.getName(), serverGroup.getPrefix() + "-" + serverNum, serverGroup.getMinPlayers() + "", serverGroup.getMaxPlayers() + "", serverGroup.getPvp() + "", serverGroup.getTournament() + "", free + "", serverSpace.isUsRegion() ? "true" : "false", serverGroup.getArcadeGroup() + "", serverGroup.getGames(), serverGroup.getServerType(), serverGroup.getAddNoCheat() + ""}); + ProcessRunner pr = new ProcessRunner(new String[] {"/bin/sh", cmd, serverAddress, serverSpace.getPrivateAddress(), (serverGroup.getPortSection() + serverNum) + "", serverGroup.getRequiredRam() + "", serverGroup.getWorldZip(), serverGroup.getPlugin(), serverGroup.getConfigPath(), serverGroup.getName(), serverGroup.getPrefix() + "-" + serverNum, serverGroup.getMinPlayers() + "", serverGroup.getMaxPlayers() + "", serverGroup.getPvp() + "", serverGroup.getTournament() + "", free + "", serverSpace.isUsRegion() ? "true" : "false", serverGroup.getArcadeGroup() + "", serverGroup.getGames(), serverGroup.getServerType(), serverGroup.getAddNoCheat() + "", serverGroup.getTeamAutoJoin() + "", serverGroup.getTeamForceBalance() + "", serverGroup.getTeamRejoin() + "", serverGroup.getGameAutoStart() + "", serverGroup.getGameTimeout() + "", serverGroup.getHotbarHubClock() + "", serverGroup.getHotbarInventory() + "", serverGroup.getPlayerKickIdle() + "", serverGroup.getRewardGems() + "", serverGroup.getRewardItems() + "", serverGroup.getRewardAchievements() + "", serverGroup.getRewardStats() + ""}); pr.start(new GenericRunnable() { public void run(Boolean error) diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java index dd25b37b9..1eaf1d90c 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/Arcade.java @@ -96,8 +96,9 @@ public class Arcade extends JavaPlugin ServerStatusManager serverStatusManager = new ServerStatusManager(this, new LagMeter(this, _clientManager)); Portal portal = new Portal(this, serverStatusManager.getCurrentServerName()); new FileUpdater(this, portal); - - DisguiseManager disguiseManager = new DisguiseManager(this); + PacketHandler packetHandler = new PacketHandler(this); + + DisguiseManager disguiseManager = new DisguiseManager(this, packetHandler); _damageManager = new DamageManager(this, new CombatManager(this), new NpcManager(this, creature), disguiseManager); @@ -115,11 +116,10 @@ public class Arcade extends JavaPlugin GadgetManager gadgetManager = new GadgetManager(this, _clientManager, _donationManager, inventoryManager, mountManager, petManager, preferenceManager, disguiseManager, blockRestore, projectileManager); CosmeticManager cosmeticManager = new CosmeticManager(this, _clientManager, _donationManager, inventoryManager, gadgetManager, mountManager, petManager, true); cosmeticManager.setInterfaceSlot(7); - new CustomTagFix(this); - new PacketHandler(this); + new CustomTagFix(this, packetHandler); //Arcade Manager - _gameManager = new ArcadeManager(this, serverStatusManager, ReadServerConfig(), _clientManager, _donationManager, _damageManager, disguiseManager, creature, teleport, new Blood(this), antistack, portal, preferenceManager, inventoryManager, cosmeticManager, projectileManager, webServerAddress); + _gameManager = new ArcadeManager(this, serverStatusManager, ReadServerConfig(), _clientManager, _donationManager, _damageManager, disguiseManager, creature, teleport, new Blood(this), antistack, portal, preferenceManager, inventoryManager, packetHandler, cosmeticManager, projectileManager, webServerAddress); new PlayerTracker(this, serverStatusManager.getCurrentServerName(), serverStatusManager.getUs()); new MemoryFix(this); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java index a778ebc43..bd450a768 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/ArcadeManager.java @@ -72,6 +72,7 @@ import mineplex.core.movement.Movement; import mineplex.core.elo.EloManager; import mineplex.core.energy.Energy; import mineplex.core.explosion.Explosion; +import mineplex.core.packethandler.PacketHandler; import mineplex.core.portal.Portal; import mineplex.core.preferences.PreferencesManager; import mineplex.core.projectile.ProjectileManager; @@ -139,7 +140,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation public ArcadeManager(Arcade plugin, ServerStatusManager serverStatusManager, GameServerConfig serverConfig, CoreClientManager clientManager, DonationManager donationManager, DamageManager damageManager, DisguiseManager disguiseManager, Creature creature, Teleport teleport, Blood blood, AntiStack antistack, - Portal portal, PreferencesManager preferences, InventoryManager inventoryManager, + Portal portal, PreferencesManager preferences, InventoryManager inventoryManager, PacketHandler packetHandler, CosmeticManager cosmeticManager, ProjectileManager projectileManager, String webAddress) { super("Game Manager", plugin); @@ -227,7 +228,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation _gameCreationManager = new GameCreationManager(this); _gameGemManager = new GameGemManager(this); _gameManager = new GameManager(this); - _gameLobbyManager = new GameLobbyManager(this); + _gameLobbyManager = new GameLobbyManager(this, packetHandler); new GameFlagManager(this); _gamePlayerManager = new GamePlayerManager(this); new GameAchievementManager(this); @@ -236,7 +237,6 @@ public class ArcadeManager extends MiniPlugin implements IRelation new IdleManager(this); _leaderboardRepository = new LeaderboardRepository(plugin); - // Game Addons new CompassAddon(plugin, this); new SoupAddon(plugin, this); diff --git a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameLobbyManager.java b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameLobbyManager.java index e9b20582d..12590bdb9 100644 --- a/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameLobbyManager.java +++ b/Plugins/Nautilus.Game.Arcade/src/nautilus/game/arcade/managers/GameLobbyManager.java @@ -52,8 +52,10 @@ import mineplex.core.common.util.UtilTime; import mineplex.core.common.util.UtilWorld; import mineplex.core.cosmetic.event.ActivateGemBoosterEvent; import mineplex.core.donation.Donor; +import mineplex.core.packethandler.IPacketHandler; +import mineplex.core.packethandler.PacketHandler; import mineplex.core.packethandler.PacketVerifier; -import mineplex.core.packethandler.PlayerPacketEvent; +import mineplex.core.packethandler.PacketInfo; import mineplex.core.updater.UpdateType; import mineplex.core.updater.event.UpdateEvent; import mineplex.minecraft.game.core.damage.CustomDamageEvent; @@ -66,13 +68,11 @@ import nautilus.game.arcade.game.GameTeam; import nautilus.game.arcade.kit.Kit; import nautilus.game.arcade.kit.KitAvailability; import nautilus.game.arcade.kit.KitSorter; -import net.minecraft.server.v1_7_R4.DataWatcher; import net.minecraft.server.v1_7_R4.Packet; import net.minecraft.server.v1_7_R4.PacketPlayOutEntityMetadata; -import net.minecraft.server.v1_7_R4.PacketPlayOutSpawnEntityLiving; import net.minecraft.server.v1_7_R4.WatchableObject; -public class GameLobbyManager implements Listener +public class GameLobbyManager implements Listener, IPacketHandler { public ArcadeManager Manager; @@ -107,10 +107,12 @@ public class GameLobbyManager implements Listener private boolean _handlingPacket = false; - public GameLobbyManager(ArcadeManager manager) + public GameLobbyManager(ArcadeManager manager, PacketHandler packetHandler) { Manager = manager; + packetHandler.addPacketHandler(this); + World world = UtilWorld.getWorld("world"); spawn = new Location(world, 0, 104, 0); @@ -1031,15 +1033,14 @@ public class GameLobbyManager implements Listener } @SuppressWarnings("unchecked") - @EventHandler - public void handlePacket(PlayerPacketEvent event) + public void handle(PacketInfo packetInfo) { if (_handlingPacket) return; - Packet packet = event.getPacket(); - Player owner = event.getPlayer(); - PacketVerifier packetVerifier = event.getVerifier(); + Packet packet = packetInfo.getPacket(); + Player owner = packetInfo.getPlayer(); + PacketVerifier packetVerifier = packetInfo.getVerifier(); int entityId = -1; @@ -1090,7 +1091,7 @@ public class GameLobbyManager implements Listener packetVerifier.process(newPacket); _handlingPacket = false; - event.setCancelled(true); + packetInfo.setCancelled(true); } } catch (IllegalArgumentException e) diff --git a/Website/LOCWebsite.suo b/Website/LOCWebsite.suo index 60dbf9eda671c99414bd1595844a97ebc439622d..6a1f5de2e4ce72304d0adaab701e1170d325e563 100644 GIT binary patch delta 14888 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 Tx_sCuiM;)xGM>F+qz?OkvfwjP delta 14964 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