More UHC Fixes
Fixes: PC-137 PC-138 PC-497 PC-665 PC-710 PC-719 PC-754 Also fixes chunk synchronization issue, plugs potential memory leaks Fancy spectating Use enum priorities
This commit is contained in:
parent
8cf470cfd0
commit
63b6158fe4
@ -6,6 +6,7 @@ import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.boosters.command.BoosterCommand;
|
||||
import mineplex.core.boosters.event.BoosterActivateEvent;
|
||||
import mineplex.core.boosters.event.BoosterExpireEvent;
|
||||
import mineplex.core.boosters.event.BoosterItemGiveEvent;
|
||||
import mineplex.core.boosters.event.BoosterUpdateEvent;
|
||||
import mineplex.core.boosters.gui.BoosterShop;
|
||||
import mineplex.core.boosters.redis.BoosterUpdateRepository;
|
||||
@ -14,6 +15,7 @@ import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.UtilGear;
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.inventory.InventoryManager;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
@ -361,6 +363,11 @@ public class BoosterManager extends MiniPlugin
|
||||
{
|
||||
if (_giveInterfaceItem && !UtilGear.isMat(player.getInventory().getItem(INTERFACE_SLOT), Material.EMERALD))
|
||||
{
|
||||
BoosterItemGiveEvent event = new BoosterItemGiveEvent(player);
|
||||
UtilServer.CallEvent(event);
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
player.getInventory().setItem(INTERFACE_SLOT, INTERFACE_ITEM);
|
||||
|
||||
UtilInv.Update(player);
|
||||
|
@ -0,0 +1,48 @@
|
||||
package mineplex.core.boosters.event;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Called when a player is about to receive a booster gem. If cancelled the player will not receive said gem
|
||||
*/
|
||||
public class BoosterItemGiveEvent extends Event implements Cancellable
|
||||
{
|
||||
private Player _player;
|
||||
private boolean _cancelled;
|
||||
|
||||
public BoosterItemGiveEvent(Player player)
|
||||
{
|
||||
this._player = player;
|
||||
}
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
return this._player;
|
||||
}
|
||||
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return this._cancelled;
|
||||
}
|
||||
|
||||
public void setCancelled(boolean cancelled)
|
||||
{
|
||||
this._cancelled = cancelled;
|
||||
}
|
||||
|
||||
private static final HandlerList _handlers = new HandlerList();
|
||||
|
||||
private static HandlerList getHandlerList()
|
||||
{
|
||||
return _handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return getHandlerList();
|
||||
}
|
||||
}
|
@ -1,12 +1,8 @@
|
||||
package mineplex.core.packethandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.mineplex.spigot.PacketProcessor;
|
||||
import mineplex.core.MiniPlugin;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -15,16 +11,22 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.mineplex.spigot.PacketProcessor;
|
||||
|
||||
import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.common.util.NautHashMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class PacketHandler extends MiniPlugin
|
||||
{
|
||||
private NautHashMap<Player, PacketVerifier> _playerVerifierMap = new NautHashMap<Player, PacketVerifier>();
|
||||
private HashMap<Class, ArrayList<IPacketHandler>> _forceMainThread = new HashMap<Class, ArrayList<IPacketHandler>>();
|
||||
private HashMap<Class, ArrayList<IPacketHandler>> _packetHandlers = new HashMap<Class, ArrayList<IPacketHandler>>();
|
||||
private Map<Player, PacketVerifier> _playerVerifierMap = new HashMap<>();
|
||||
|
||||
private Map<Class<? extends Packet>, Set<IPacketHandler>> _forceMainThread = new HashMap<>();
|
||||
private Map<Class<? extends Packet>, Map<ListenerPriority, List<IPacketHandler>>> _packetHandlers = new HashMap<>();
|
||||
|
||||
public PacketHandler(JavaPlugin plugin)
|
||||
{
|
||||
@ -40,18 +42,6 @@ public class PacketHandler extends MiniPlugin
|
||||
.get(event.getPlayer()));
|
||||
}
|
||||
|
||||
public boolean handlePacket(Player player, Packet packet)
|
||||
{
|
||||
if (!_playerVerifierMap.containsKey(player))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PacketVerifier verifier = _playerVerifierMap.get(player);
|
||||
|
||||
return handlePacket(new PacketInfo(player, packet, verifier));
|
||||
}
|
||||
|
||||
public boolean handlePacket(PacketInfo packetInfo)
|
||||
{
|
||||
if (!_packetHandlers.containsKey(packetInfo.getPacket().getClass()))
|
||||
@ -60,15 +50,18 @@ public class PacketHandler extends MiniPlugin
|
||||
return true;
|
||||
}
|
||||
|
||||
for (IPacketHandler handler : _packetHandlers.get(packetInfo.getPacket().getClass()))
|
||||
for (Entry<ListenerPriority, List<IPacketHandler>> entry : _packetHandlers.get(packetInfo.getPacket().getClass()).entrySet())
|
||||
{
|
||||
try
|
||||
for (IPacketHandler handler : entry.getValue())
|
||||
{
|
||||
handler.handle(packetInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
try
|
||||
{
|
||||
handler.handle(packetInfo);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,72 +83,106 @@ public class PacketHandler extends MiniPlugin
|
||||
@SafeVarargs
|
||||
public final void addPacketHandler(IPacketHandler packetHandler, Class<? extends Packet>... packetsToListen)
|
||||
{
|
||||
if (packetsToListen.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("When registering a new packet listener, add the packets its going to listen to");
|
||||
}
|
||||
|
||||
addPacketHandler(packetHandler, false, packetsToListen);
|
||||
addPacketHandler(packetHandler, ListenerPriority.NORMAL, false, packetsToListen);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be used for incoming packets
|
||||
*/
|
||||
public void addPacketHandler(IPacketHandler packetHandler, boolean forceMainThread,
|
||||
Class<? extends Packet>... packetsToListen)
|
||||
@SafeVarargs
|
||||
public final void addPacketHandler(IPacketHandler packetHandler, boolean forceMainThread, Class<? extends Packet>... packetsToListen)
|
||||
{
|
||||
if (packetsToListen.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("When registering a new packet listener, add the packets its going to listen to");
|
||||
}
|
||||
|
||||
for (Class c : packetsToListen)
|
||||
addPacketHandler(packetHandler, ListenerPriority.NORMAL, forceMainThread, packetsToListen);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public final void addPacketHandler(IPacketHandler packetHandler, ListenerPriority priority, Class<? extends Packet>... packetsToListen)
|
||||
{
|
||||
if (packetsToListen.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("When registering a new packet listener, add the packets its going to listen to");
|
||||
}
|
||||
|
||||
addPacketHandler(packetHandler, priority, false, packetsToListen);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should only be used for incoming packets
|
||||
*/
|
||||
@SafeVarargs
|
||||
public final void addPacketHandler(IPacketHandler packetHandler, ListenerPriority priority, boolean forceMainThread,
|
||||
Class<? extends Packet>... packetsToListen)
|
||||
{
|
||||
if (packetsToListen.length == 0)
|
||||
{
|
||||
throw new IllegalArgumentException("When registering a new packet listener, add the packets its going to listen to");
|
||||
}
|
||||
|
||||
for (Class<? extends Packet> c : packetsToListen)
|
||||
{
|
||||
if (forceMainThread)
|
||||
{
|
||||
if (!_forceMainThread.containsKey(c))
|
||||
{
|
||||
_forceMainThread.put(c, new ArrayList());
|
||||
}
|
||||
|
||||
_forceMainThread.get(c).add(packetHandler);
|
||||
_forceMainThread
|
||||
.computeIfAbsent(c, key -> new HashSet<>())
|
||||
.add(packetHandler);
|
||||
}
|
||||
|
||||
if (!_packetHandlers.containsKey(c))
|
||||
{
|
||||
_packetHandlers.put(c, new ArrayList());
|
||||
}
|
||||
_packetHandlers
|
||||
.computeIfAbsent(c, key -> new TreeMap<>())
|
||||
.computeIfAbsent(priority, key -> new ArrayList<>())
|
||||
.add(packetHandler);
|
||||
|
||||
_packetHandlers.get(c).add(packetHandler);
|
||||
PacketProcessor.addPacket(c, forceMainThread || _forceMainThread.containsKey(c));
|
||||
}
|
||||
}
|
||||
|
||||
public void removePacketHandler(IPacketHandler packetHandler)
|
||||
{
|
||||
Iterator<Entry<Class, ArrayList<IPacketHandler>>> itel = _packetHandlers.entrySet().iterator();
|
||||
Iterator<Entry<Class<? extends Packet>, Map<ListenerPriority, List<IPacketHandler>>>> itel = _packetHandlers.entrySet().iterator();
|
||||
|
||||
while (itel.hasNext())
|
||||
{
|
||||
Entry<Class, ArrayList<IPacketHandler>> entry = itel.next();
|
||||
Entry<Class<? extends Packet>, Map<ListenerPriority, List<IPacketHandler>>> entry = itel.next();
|
||||
|
||||
if (entry.getValue().remove(packetHandler))
|
||||
Set<ListenerPriority> removedFrom = new HashSet<>();
|
||||
|
||||
for (Entry<ListenerPriority, List<IPacketHandler>> ent : entry.getValue().entrySet())
|
||||
{
|
||||
if (_forceMainThread.containsKey(entry.getKey()) && _forceMainThread.get(entry.getKey()).remove(packetHandler))
|
||||
if (ent.getValue().remove(packetHandler))
|
||||
{
|
||||
if (_forceMainThread.get(entry.getKey()).isEmpty())
|
||||
{
|
||||
_forceMainThread.remove(entry.getKey());
|
||||
PacketProcessor.addPacket(entry.getKey(), false);
|
||||
}
|
||||
removedFrom.add(ent.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getValue().isEmpty())
|
||||
for (ListenerPriority priority : removedFrom)
|
||||
{
|
||||
if (entry.getValue().get(priority).isEmpty())
|
||||
{
|
||||
PacketProcessor.removePacket(entry.getKey());
|
||||
itel.remove();
|
||||
entry.getValue().remove(priority);
|
||||
}
|
||||
}
|
||||
|
||||
if (_forceMainThread.containsKey(entry.getKey()) && _forceMainThread.get(entry.getKey()).remove(packetHandler))
|
||||
{
|
||||
if (_forceMainThread.get(entry.getKey()).isEmpty())
|
||||
{
|
||||
_forceMainThread.remove(entry.getKey());
|
||||
PacketProcessor.addPacket(entry.getKey(), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.getValue().isEmpty())
|
||||
{
|
||||
PacketProcessor.removePacket(entry.getKey());
|
||||
itel.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum ListenerPriority
|
||||
{
|
||||
HIGH, NORMAL, LOW
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +231,9 @@ public class DamageManager extends MiniPlugin
|
||||
@EventHandler
|
||||
public void onEntityCombust(EntityCombustByEntityEvent event)
|
||||
{
|
||||
if (!_enabled)
|
||||
return;
|
||||
|
||||
if (!(event.getCombuster() instanceof Player || event.getCombuster() instanceof Arrow))
|
||||
return;
|
||||
|
||||
|
@ -172,6 +172,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation
|
||||
private KitProgressionManager _kitProgressionManager;
|
||||
private ProgressingKitManager _progressionKitManager;
|
||||
private BoosterManager _boosterManager;
|
||||
private GameSpectatorManager _spectatorManager;
|
||||
|
||||
private IncognitoManager _incognitoManager;
|
||||
|
||||
@ -290,7 +291,7 @@ public class ArcadeManager extends MiniPlugin implements IRelation
|
||||
YoutubeManager youtubeManager = new YoutubeManager(plugin, clientManager, donationManager);
|
||||
_bonusManager = new BonusManager(plugin, clientManager, serverStatusManager, donationManager, pollManager , npcManager, hologramManager, statsManager, _inventoryManager, petManager, facebookManager, youtubeManager, _cosmeticManager.getGadgetManager(), boosterManager);
|
||||
new GameLootManager(this, petManager, _bonusManager.getRewardManager());
|
||||
new GameSpectatorManager(this);
|
||||
_spectatorManager = new GameSpectatorManager(this);
|
||||
_gameWorldManager = new GameWorldManager(this);
|
||||
new MiscManager(this);
|
||||
_hologramManager = hologramManager;
|
||||
@ -1705,4 +1706,9 @@ public class ArcadeManager extends MiniPlugin implements IRelation
|
||||
{
|
||||
return _kitProgressionManager;
|
||||
}
|
||||
|
||||
public GameSpectatorManager getGameSpectatorManager()
|
||||
{
|
||||
return _spectatorManager;
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.events.PlayerGameRespawnEvent;
|
||||
import nautilus.game.arcade.events.PlayerStateChangeEvent;
|
||||
import nautilus.game.arcade.game.GameTeam.PlayerState;
|
||||
import nautilus.game.arcade.game.modules.Module;
|
||||
import nautilus.game.arcade.kit.*;
|
||||
import nautilus.game.arcade.managers.GameLobbyManager;
|
||||
import nautilus.game.arcade.managers.chat.ChatStatData;
|
||||
@ -311,8 +312,6 @@ public abstract class Game implements Listener
|
||||
|
||||
public boolean AllowEntitySpectate = true;
|
||||
|
||||
public boolean PlayerTeamSelection = false;
|
||||
|
||||
public boolean TeamMode = false;
|
||||
|
||||
public boolean TeamPerSpawn = false;
|
||||
@ -332,6 +331,8 @@ public abstract class Game implements Listener
|
||||
private NautHashMap<Player, Player> _teamReqs = new NautHashMap<Player, Player>();
|
||||
public WinEffectManager WinEffectManager = new WinEffectManager();
|
||||
|
||||
private Map<Class<? extends Module>, Module> _modules = new HashMap<>();
|
||||
|
||||
public Game(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc)
|
||||
{
|
||||
Manager = manager;
|
||||
@ -418,6 +419,20 @@ public abstract class Game implements Listener
|
||||
System.out.println("Loading " + GetName() + "...");
|
||||
}
|
||||
|
||||
public void registerModule(Module module)
|
||||
{
|
||||
if (!_modules.containsKey(module.getClass()))
|
||||
{
|
||||
module.initialize(this);
|
||||
_modules.put(module.getClass(), module);
|
||||
UtilServer.RegisterEvents(module);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Module " + module.getClass() + " is already registered");
|
||||
}
|
||||
}
|
||||
|
||||
public void setKits(Kit[] kits)
|
||||
{
|
||||
_kits = kits;
|
||||
@ -1897,157 +1912,6 @@ public abstract class Game implements Listener
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void teamSelectInteract(PlayerInteractEntityEvent event)
|
||||
{
|
||||
if (!PlayerTeamSelection)
|
||||
return;
|
||||
|
||||
if (GetState() != GameState.Recruit)
|
||||
return;
|
||||
|
||||
if (event.getRightClicked() == null)
|
||||
return;
|
||||
|
||||
if (!(event.getRightClicked() instanceof Player))
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
//Observer
|
||||
if (Manager.IsObserver(player))
|
||||
{
|
||||
UtilPlayer.message(player, F.main("Game", "Spectators cannot partake in games."));
|
||||
return;
|
||||
}
|
||||
|
||||
selectTeamMate(player, (Player) event.getRightClicked());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void teamSelectCommand(PlayerCommandPreprocessEvent event)
|
||||
{
|
||||
if (!PlayerTeamSelection)
|
||||
return;
|
||||
|
||||
if (GetState() != GameState.Recruit)
|
||||
return;
|
||||
|
||||
if (!event.getMessage().toLowerCase().startsWith("/team "))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
Player target = UtilPlayer.searchOnline(event.getPlayer(), event.getMessage().split(" ")[1],
|
||||
true);
|
||||
if (target == null)
|
||||
return;
|
||||
|
||||
//Observer
|
||||
if (Manager.IsObserver(event.getPlayer()))
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(),
|
||||
F.main("Game", "Spectators cannot partake in games."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getPlayer().equals(target))
|
||||
return;
|
||||
|
||||
selectTeamMate(event.getPlayer(), target);
|
||||
}
|
||||
|
||||
public void selectTeamMate(Player player, Player ally)
|
||||
{
|
||||
//Accept Invite
|
||||
if (_teamReqs.containsKey(ally) && _teamReqs.get(ally).equals(player))
|
||||
{
|
||||
//Remove Prefs
|
||||
_teamReqs.remove(player);
|
||||
_teamReqs.remove(ally);
|
||||
|
||||
//Inform
|
||||
UtilPlayer.message(player,
|
||||
F.main("Game", "You accepted " + ally.getName() + "'s Team Request!"));
|
||||
UtilPlayer.message(ally,
|
||||
F.main("Game", player.getName() + " accepted your Team Request!"));
|
||||
|
||||
//Leave Old Teams
|
||||
if (GetTeam(player) != null)
|
||||
GetTeam(player).DisbandTeam();
|
||||
|
||||
if (GetTeam(ally) != null)
|
||||
GetTeam(ally).DisbandTeam();
|
||||
|
||||
//Get Team
|
||||
GameTeam team = getEmptyTeam();
|
||||
if (team == null)
|
||||
return;
|
||||
|
||||
//Join Team
|
||||
SetPlayerTeam(player, team, true);
|
||||
SetPlayerTeam(ally, team, true);
|
||||
}
|
||||
//Send Invite
|
||||
else
|
||||
{
|
||||
//Already on Team with Target
|
||||
if (GetTeam(player) != null)
|
||||
if (GetTeam(player).HasPlayer(ally))
|
||||
return;
|
||||
|
||||
//Inform Player
|
||||
UtilPlayer.message(player,
|
||||
F.main("Game", "You sent a Team Request to " + ally.getName() + "!"));
|
||||
|
||||
//Inform Target
|
||||
if (Recharge.Instance.use(player, "Team Req " + ally.getName(), 2000, false, false))
|
||||
{
|
||||
UtilPlayer.message(ally,
|
||||
F.main("Game", player.getName() + " sent you a Team Request!"));
|
||||
UtilPlayer.message(ally, F.main("Game",
|
||||
"Type " + F.elem("/team " + player.getName()) + " to accept!"));
|
||||
}
|
||||
|
||||
//Add Pref
|
||||
_teamReqs.put(player, ally);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void teamQuit(PlayerQuitEvent event)
|
||||
{
|
||||
if (!PlayerTeamSelection)
|
||||
return;
|
||||
|
||||
if (GetState() != GameState.Recruit)
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (GetTeam(player) != null)
|
||||
GetTeam(player).DisbandTeam();
|
||||
|
||||
Iterator<Player> teamIter = _teamReqs.keySet().iterator();
|
||||
while (teamIter.hasNext())
|
||||
{
|
||||
Player sender = teamIter.next();
|
||||
if (sender.equals(player) || _teamReqs.get(sender).equals(player))
|
||||
teamIter.remove();
|
||||
}
|
||||
}
|
||||
|
||||
public GameTeam getEmptyTeam()
|
||||
{
|
||||
for (GameTeam team : GetTeamList())
|
||||
{
|
||||
if (team.GetPlayers(false).isEmpty())
|
||||
return team;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void CustomTeamGeneration(GameStateChangeEvent event)
|
||||
{
|
||||
@ -2271,4 +2135,17 @@ public abstract class Game implements Listener
|
||||
{
|
||||
}
|
||||
|
||||
public void cleanupModules()
|
||||
{
|
||||
for (Module module : this._modules.values())
|
||||
{
|
||||
module.cleanup();
|
||||
HandlerList.unregisterAll(module);
|
||||
}
|
||||
}
|
||||
|
||||
public <T extends Module> T getModule(Class<T> clazz)
|
||||
{
|
||||
return clazz.cast(_modules.get(clazz));
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.entity.Creature;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.scoreboard.Team;
|
||||
|
||||
public class GameTeam
|
||||
{
|
||||
@ -192,7 +193,11 @@ public class GameTeam
|
||||
{
|
||||
for(Player other : UtilServer.getPlayers())
|
||||
{
|
||||
other.getScoreboard().getTeam(Host.Manager.GetClients().Get(player).GetRank().Name + _name.toUpperCase()).removePlayer(player);
|
||||
Team team = other.getScoreboard().getTeam(Host.Manager.GetClients().Get(player).GetRank().Name + _name.toUpperCase());
|
||||
if (team != null)
|
||||
{
|
||||
team.removePlayer(player);
|
||||
}
|
||||
other.getScoreboard().getTeam(Host.Manager.GetClients().Get(player).GetRank().Name).addPlayer(player);
|
||||
}
|
||||
UtilPlayer.message(player, F.main("Team", _color + C.Bold + getDisplayName() + " Team was disbanded."));
|
||||
|
@ -5,6 +5,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import nautilus.game.arcade.game.modules.TeamModule;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
@ -40,7 +41,9 @@ public class TeamBuild extends Build
|
||||
super(manager, GameType.Brawl);
|
||||
|
||||
TeamMode = true;
|
||||
PlayerTeamSelection = true;
|
||||
|
||||
registerModule(new TeamModule());
|
||||
|
||||
TeamPerSpawn = true;
|
||||
FillTeamsInOrderToCount = 2;
|
||||
|
||||
|
@ -19,6 +19,7 @@ import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.Game.GameState;
|
||||
import nautilus.game.arcade.game.modules.TeamModule;
|
||||
import nautilus.game.arcade.stats.DeathBomberStatTracker;
|
||||
import nautilus.game.arcade.stats.SkywarsKillZombieStatTracker;
|
||||
import nautilus.game.arcade.stats.SkywarsTNTStatTracker;
|
||||
@ -78,10 +79,11 @@ public class TeamSkywars extends Skywars
|
||||
DamageTeamSelf = false;
|
||||
|
||||
DontAllowOverfill = true;
|
||||
|
||||
PlayerTeamSelection = true;
|
||||
|
||||
TeamMode = true;
|
||||
TeamPerSpawn = true;
|
||||
|
||||
registerModule(new TeamModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -15,6 +15,7 @@ import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.modules.TeamModule;
|
||||
import nautilus.game.arcade.managers.chat.ChatStatData;
|
||||
import nautilus.game.arcade.stats.FreeKitWinStatTracker;
|
||||
import nautilus.game.arcade.stats.KillFastStatTracker;
|
||||
@ -55,7 +56,8 @@ public class TeamSuperSmash extends SuperSmash
|
||||
DontAllowOverfill = true;
|
||||
|
||||
TeamMode = true;
|
||||
PlayerTeamSelection = true;
|
||||
|
||||
registerModule(new TeamModule());
|
||||
|
||||
registerStatTrackers(
|
||||
new WinWithoutDyingStatTracker(this, "MLGPro"),
|
||||
|
@ -17,6 +17,7 @@ import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.modules.TeamModule;
|
||||
import nautilus.game.arcade.managers.chat.ChatStatData;
|
||||
import nautilus.game.arcade.stats.FirstSupplyDropOpenStatTracker;
|
||||
import nautilus.game.arcade.stats.KillsWithinTimeLimitStatTracker;
|
||||
@ -59,7 +60,8 @@ public class TeamSurvivalGames extends SurvivalGames
|
||||
|
||||
DontAllowOverfill = true;
|
||||
TeamMode = true;
|
||||
PlayerTeamSelection = true;
|
||||
|
||||
registerModule(new TeamModule());
|
||||
|
||||
registerStatTrackers(new WinWithoutWearingArmorStatTracker(this),
|
||||
new KillsWithinTimeLimitStatTracker(this, 3, 60, "Bloodlust"),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,385 @@
|
||||
package nautilus.game.arcade.game.games.uhc.helpers;
|
||||
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.timing.TimingManager;
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.games.uhc.UHC;
|
||||
import net.minecraft.server.v1_8_R3.Chunk;
|
||||
import net.minecraft.server.v1_8_R3.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_8_R3.ChunkRegionLoader;
|
||||
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
||||
import net.minecraft.server.v1_8_R3.WorldServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.LongHash;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.spigotmc.AsyncCatcher;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static nautilus.game.arcade.game.games.uhc.UHC.VIEW_DISTANCE;
|
||||
|
||||
public class ChunkLoadingThread extends Thread implements Listener
|
||||
{
|
||||
private Game _game;
|
||||
|
||||
private volatile boolean _isDecorating = false;
|
||||
private AtomicInteger _actual = new AtomicInteger();
|
||||
private AtomicInteger _expected = new AtomicInteger(23000); // Most likely it'll be around 23000
|
||||
|
||||
private Set<net.minecraft.server.v1_8_R3.Entity> _entities = new HashSet<>();
|
||||
|
||||
public ChunkLoadingThread(Game game)
|
||||
{
|
||||
super("Chunk Loader");
|
||||
this._game = game;
|
||||
UtilServer.RegisterEvents(this);
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
WorldServer worldServer = ((CraftWorld) _game.WorldData.World).getHandle();
|
||||
Location spawn = _game.WorldData.World.getSpawnLocation();
|
||||
|
||||
Map<Long, Chunk> loaded = new ConcurrentHashMap<>();
|
||||
Map<Long, NBTTagCompound> compounds = new ConcurrentHashMap<>();
|
||||
|
||||
try
|
||||
{
|
||||
TimingManager.start("UHC Chunk Loading");
|
||||
|
||||
ChunkProviderServer chunkProviderServer = worldServer.chunkProviderServer;
|
||||
|
||||
Field chunkLoaderField = chunkProviderServer.getClass().getDeclaredField("chunkLoader");
|
||||
chunkLoaderField.setAccessible(true);
|
||||
|
||||
ChunkRegionLoader loader = (ChunkRegionLoader) chunkLoaderField.get(chunkProviderServer);
|
||||
|
||||
// Step 1: Read all the required chunks from the disk
|
||||
// We're going to read all the required chunks from disk async
|
||||
{
|
||||
Set<Long> coordPairs = new HashSet<>();
|
||||
|
||||
// Special case for 0, 0
|
||||
{
|
||||
int x = spawn.getBlockX() >> 4;
|
||||
int z = spawn.getBlockZ() >> 4;
|
||||
|
||||
for (int dx = -VIEW_DISTANCE; dx <= VIEW_DISTANCE; dx++)
|
||||
{
|
||||
for (int dz = -VIEW_DISTANCE; dz <= VIEW_DISTANCE; dz++)
|
||||
{
|
||||
coordPairs.add(LongHash.toLong(x + dx, z + dz));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All the team spawns
|
||||
{
|
||||
for (int i = 0; i < _game.GetTeamList().size(); i++)
|
||||
{
|
||||
GameTeam team = _game.GetTeamList().get(i);
|
||||
for (Location l : team.GetSpawns())
|
||||
{
|
||||
int x = l.getChunk().getX();
|
||||
int z = l.getChunk().getZ();
|
||||
|
||||
for (int dx = -VIEW_DISTANCE; dx <= VIEW_DISTANCE; dx++)
|
||||
{
|
||||
for (int dz = -VIEW_DISTANCE; dz <= VIEW_DISTANCE; dz++)
|
||||
{
|
||||
coordPairs.add(LongHash.toLong(x + dx, z + dz));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AtomicBoolean lockCompleted = new AtomicBoolean(false);
|
||||
Object lock = new Object();
|
||||
|
||||
// Hop back onto the main thread
|
||||
_game.getArcadeManager().runSync(() ->
|
||||
{
|
||||
for (Chunk chunk : new ArrayList<>(chunkProviderServer.chunks.values()))
|
||||
{
|
||||
chunk.bukkitChunk.unload(true, false);
|
||||
}
|
||||
lockCompleted.set(true);
|
||||
synchronized(lock)
|
||||
{
|
||||
lock.notifyAll();
|
||||
}
|
||||
});
|
||||
if (!lockCompleted.get())
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
if (!lockCompleted.get())
|
||||
{
|
||||
throw new IllegalStateException("Lock was not completed");
|
||||
}
|
||||
|
||||
|
||||
// Sigh... I don't want this to be here but it needs to be set somewhere...
|
||||
// Multiply by 3 because there are 3 stages
|
||||
_expected.set(coordPairs.size() * 3);
|
||||
|
||||
// Load them now
|
||||
ExecutorService chunkLoaders = Executors.newFixedThreadPool(UHC.THREADS_FOR_CHUNK_LOADING);
|
||||
|
||||
for (long coord : coordPairs)
|
||||
{
|
||||
chunkLoaders.submit(() ->
|
||||
{
|
||||
int x = LongHash.msw(coord);
|
||||
int z = LongHash.lsw(coord);
|
||||
try
|
||||
{
|
||||
Object[] data = loader.loadChunk(worldServer, x, z);
|
||||
if (data != null)
|
||||
{
|
||||
NBTTagCompound compound = (NBTTagCompound) data[1];
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = (net.minecraft.server.v1_8_R3.Chunk) data[0];
|
||||
loaded.put(coord, chunk);
|
||||
compounds.put(coord, compound);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("Failed to load chunk " + x + "," + z);
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_actual.getAndIncrement();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
chunkLoaders.shutdown();
|
||||
|
||||
// We've got plenty of time to wait
|
||||
System.out.println("Finished submitting tasks to executor, waiting...");
|
||||
chunkLoaders.awaitTermination(1, TimeUnit.DAYS);
|
||||
|
||||
System.out.println("Loaded: " + loaded.size() + " and coords: " + coordPairs.size());
|
||||
coordPairs.clear();
|
||||
}
|
||||
|
||||
// Step 2: Recreate structures, update neighbors, load entities
|
||||
// This step should be super quick so there's no point in scheduling it elsewhere
|
||||
// Code is plain copypasted from ChunkIOProvider
|
||||
{
|
||||
for (net.minecraft.server.v1_8_R3.Chunk chunk : loaded.values())
|
||||
{
|
||||
NBTTagCompound compound = compounds.get(LongHash.toLong(chunk.locX, chunk.locZ));
|
||||
loader.loadEntities(chunk, compound.getCompound("Level"), worldServer);
|
||||
chunk.setLastSaved(chunkProviderServer.world.getTime());
|
||||
if (chunkProviderServer.chunkProvider != null)
|
||||
{
|
||||
chunkProviderServer.chunkProvider.recreateStructures(chunk, chunk.locX, chunk.locZ);
|
||||
}
|
||||
|
||||
for (int x = -2; x < 3; ++x)
|
||||
{
|
||||
for (int z = -2; z < 3; ++z)
|
||||
{
|
||||
if (x != 0 || z != 0)
|
||||
{
|
||||
net.minecraft.server.v1_8_R3.Chunk neighbor = loaded.get(LongHash.toLong(chunk.locX + x, chunk.locZ + z));
|
||||
if (neighbor != null)
|
||||
{
|
||||
neighbor.setNeighborLoaded(-x, -z);
|
||||
chunk.setNeighborLoaded(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_actual.getAndIncrement();
|
||||
}
|
||||
}
|
||||
|
||||
AtomicBoolean lockCompleted = new AtomicBoolean(false);
|
||||
Object lock = new Object();
|
||||
|
||||
// Hop back onto the main thread
|
||||
_game.getArcadeManager().runSync(() ->
|
||||
{
|
||||
// We want to add all the chunks to the chunkmap so that the server is not out of sync
|
||||
for (Map.Entry<Long, net.minecraft.server.v1_8_R3.Chunk> ent : loaded.entrySet())
|
||||
{
|
||||
ent.getValue().addEntities();
|
||||
chunkProviderServer.chunks.put(ent.getKey(), ent.getValue());
|
||||
ChunkLoadEvent event = new ChunkLoadEvent(ent.getValue().bukkitChunk, true);
|
||||
UtilServer.CallEvent(event);
|
||||
}
|
||||
lockCompleted.set(true);
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.notifyAll();
|
||||
}
|
||||
});
|
||||
|
||||
if (!lockCompleted.get())
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
if (!lockCompleted.get())
|
||||
{
|
||||
throw new IllegalStateException("Lock was not completed");
|
||||
}
|
||||
|
||||
|
||||
// Step 3: Decorate the chunks. This step must be performed async as otherwise the server lags way too hard
|
||||
// Notes: Do not allow the server to tick the world. If this is allowed EntityTracker will raise CME
|
||||
// NextTickList will also raise errors
|
||||
// And worst case the server will crash
|
||||
{
|
||||
// Live life on the edge
|
||||
AsyncCatcher.enabled = false;
|
||||
_isDecorating = true;
|
||||
int ct = 0;
|
||||
for (net.minecraft.server.v1_8_R3.Chunk chunk : loaded.values())
|
||||
{
|
||||
chunk.loadNearby(chunkProviderServer, chunkProviderServer, chunk.locX, chunk.locZ);
|
||||
ct++;
|
||||
if (ct % 100 == 0)
|
||||
{
|
||||
System.out.println(ct);
|
||||
}
|
||||
_actual.getAndIncrement();
|
||||
}
|
||||
|
||||
TimingManager.stop("UHC Chunk Loading");
|
||||
_isDecorating = false;
|
||||
AsyncCatcher.enabled = true;
|
||||
|
||||
System.out.println("Expected: " + _expected.get() + ", actual: " + _actual.get());
|
||||
|
||||
_game.getArcadeManager().runSync(() ->
|
||||
{
|
||||
|
||||
for (Chunk chunk : chunkProviderServer.chunks.values())
|
||||
{
|
||||
// Clear
|
||||
for (int x = -2; x < 3; x++) {
|
||||
for (int z = -2; z < 3; z++) {
|
||||
if (x == 0 && z == 0) {
|
||||
continue;
|
||||
}
|
||||
chunk.setNeighborUnloaded(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Chunk chunk : chunkProviderServer.chunks.values())
|
||||
{
|
||||
// Refresh
|
||||
for (int x = -2; x < 3; x++) {
|
||||
for (int z = -2; z < 3; z++) {
|
||||
if (x == 0 && z == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Chunk neighbor = chunkProviderServer.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z);
|
||||
if (neighbor != null) {
|
||||
neighbor.setNeighborLoaded(-x, -z);
|
||||
chunk.setNeighborLoaded(x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (net.minecraft.server.v1_8_R3.Entity entity : _entities)
|
||||
{
|
||||
entity.dead = false;
|
||||
worldServer.addEntity(entity, CreatureSpawnEvent.SpawnReason.CHUNK_GEN);
|
||||
}
|
||||
|
||||
_entities.clear();
|
||||
|
||||
// You may tick again
|
||||
worldServer.getMinecraftServer().worlds.add(worldServer);
|
||||
|
||||
// Well, if they're not equal, not much we can do. We've hit the end
|
||||
_actual.set(_expected.get());
|
||||
});
|
||||
}
|
||||
|
||||
loaded.clear();
|
||||
compounds.clear();
|
||||
|
||||
UtilServer.Unregister(this);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(EntitySpawnEvent event)
|
||||
{
|
||||
// Don't allow entity spawns while decorating, period
|
||||
if (_isDecorating)
|
||||
{
|
||||
if (event.getLocation().getWorld().getUID() == _game.WorldData.World.getUID())
|
||||
{
|
||||
_entities.add(((CraftEntity) event.getEntity()).getHandle());
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void flagDone()
|
||||
{
|
||||
_actual.set(_expected.get());
|
||||
}
|
||||
|
||||
public boolean isDone()
|
||||
{
|
||||
return _actual.get() == _expected.get();
|
||||
}
|
||||
|
||||
public int getPercentageComplete()
|
||||
{
|
||||
return UtilMath.clamp((int) ((_actual.get() * 1.0 / _expected.get()) * 100), 0, 100);
|
||||
}
|
||||
|
||||
public String getProgress()
|
||||
{
|
||||
return getPercentageComplete() + "%";
|
||||
}
|
||||
|
||||
public void flagStop()
|
||||
{
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
@ -0,0 +1,239 @@
|
||||
package nautilus.game.arcade.game.games.uhc.helpers;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.timing.TimingManager;
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import nautilus.game.arcade.game.games.uhc.UHC;
|
||||
import net.minecraft.server.v1_8_R3.BiomeCache;
|
||||
import net.minecraft.server.v1_8_R3.ChunkProviderServer;
|
||||
import net.minecraft.server.v1_8_R3.FileIOThread;
|
||||
import net.minecraft.server.v1_8_R3.IChunkProvider;
|
||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||
import net.minecraft.server.v1_8_R3.WorldChunkManager;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.util.LongHash;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class WorldGenThread extends Thread
|
||||
{
|
||||
private UHC _game;
|
||||
|
||||
private volatile boolean _mapLoaded = false;
|
||||
private volatile int _chunksPerTick = 1;
|
||||
private volatile boolean _stopGen = false;
|
||||
|
||||
private int _chunkTotal;
|
||||
private int _chunkX = 0;
|
||||
private int _chunkZ = 0;
|
||||
private int _chunksLoaded = 0;
|
||||
|
||||
private int _currentBorder = 1000;
|
||||
|
||||
|
||||
public WorldGenThread(UHC game)
|
||||
{
|
||||
super("WorldGen Thread");
|
||||
this._game = game;
|
||||
|
||||
|
||||
_chunkX = (int) -(_currentBorder / 16);
|
||||
_chunkZ = (int) -(_currentBorder / 16);
|
||||
_chunkTotal = (int) ((_currentBorder * 2 / 16) * (_currentBorder * 2 / 16));
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Field fileIOThreadB = FileIOThread.class.getDeclaredField("b");
|
||||
fileIOThreadB.setAccessible(true);
|
||||
|
||||
// This list is the list of chunks to be saved on the File IO Thread
|
||||
List list = (List) fileIOThreadB.get(FileIOThread.a());
|
||||
|
||||
net.minecraft.server.v1_8_R3.WorldServer worldServer = ((CraftWorld) _game.WorldData.World).getHandle();
|
||||
|
||||
WorldChunkManager manager = worldServer.getWorldChunkManager();
|
||||
|
||||
Field biomeCacheField = manager.getClass().getDeclaredField("d");
|
||||
biomeCacheField.setAccessible(true);
|
||||
|
||||
// A thread safe BiomeCache
|
||||
// The implementation is literally a copy/paste from the original BiomeCache, but with some synchronization
|
||||
// Reason being while the server is ticking the world (for some reason, if you want to dig through the entire Arcade codebase go for it)
|
||||
// it stores stuff in the BiomeCache, and chunk gen needs that BiomeCache info too
|
||||
// Causing desynchronization in the cache
|
||||
biomeCacheField.set(manager, new BiomeCache(manager)
|
||||
{
|
||||
private final Object _lock = new Object();
|
||||
|
||||
private long _lastCleanTime; // b -> _lastCleanTime
|
||||
private Map<Long, BiomeCacheBlock> _blockByCoord = new HashMap<>(); // LongHashMap -> HashMap, c -> _blockByCoord
|
||||
private List<BiomeCache.BiomeCacheBlock> _blocks = new ArrayList<>(); // d -> _blocks
|
||||
|
||||
@Override
|
||||
public BiomeCache.BiomeCacheBlock a(int x, int z)
|
||||
{
|
||||
x >>= 4;
|
||||
z >>= 4;
|
||||
long var3 = hash(x, z);
|
||||
BiomeCache.BiomeCacheBlock var5 = this._blockByCoord.get(var3);
|
||||
if (var5 == null)
|
||||
{
|
||||
var5 = new BiomeCache.BiomeCacheBlock(x, z);
|
||||
synchronized (_lock)
|
||||
{
|
||||
this._blockByCoord.put(var3, var5);
|
||||
this._blocks.add(var5);
|
||||
}
|
||||
}
|
||||
|
||||
var5.e = MinecraftServer.az();
|
||||
return var5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void a()
|
||||
{
|
||||
long currentTime = MinecraftServer.az();
|
||||
long deltaTime = currentTime - this._lastCleanTime;
|
||||
if (deltaTime > 7500L || deltaTime < 0L)
|
||||
{
|
||||
this._lastCleanTime = currentTime;
|
||||
|
||||
synchronized (_lock)
|
||||
{
|
||||
for (int i = 0; i < this._blocks.size(); ++i)
|
||||
{
|
||||
BiomeCache.BiomeCacheBlock biomeCacheBlock = (BiomeCache.BiomeCacheBlock) this._blocks.get(i);
|
||||
long var7 = currentTime - biomeCacheBlock.e;
|
||||
if (var7 > 30000L || var7 < 0L)
|
||||
{
|
||||
this._blocks.remove(i--);
|
||||
this._blockByCoord.remove(hash(biomeCacheBlock.c, biomeCacheBlock.d));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long hash(int x, int z)
|
||||
{
|
||||
return (long) x & 4294967295L | ((long) z & 4294967295L) << 32;
|
||||
}
|
||||
});
|
||||
|
||||
ChunkProviderServer cps = worldServer.chunkProviderServer;
|
||||
IChunkProvider icp = cps.chunkProvider;
|
||||
System.out.println("Using chunk provider " + icp.getClass());
|
||||
|
||||
TimingManager.start("Map Generation");
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
long last = start;
|
||||
|
||||
while (!_stopGen)
|
||||
{
|
||||
long now = System.currentTimeMillis();
|
||||
if ((now - last) >= 10 * 1000)
|
||||
{
|
||||
_game.Announce(C.cGreen + C.Bold + "Generating Map: " + C.cWhite + getMapLoadETA() + " Remaining...", false);
|
||||
last = now;
|
||||
}
|
||||
|
||||
long hash = LongHash.toLong(_chunkX, _chunkZ);
|
||||
|
||||
// This is just a shortcut to how the Minecraft server would have generated a chunk if it doesn't exist.
|
||||
// This should always create a chunk because we're not loading any chunks beforehand...
|
||||
// /me looks at new maintainer
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = icp.getOrCreateChunk(_chunkX, _chunkZ);
|
||||
|
||||
// Run the copypasted code for chunk saving.
|
||||
cps.saveChunk(chunk);
|
||||
cps.saveChunkNOP(chunk);
|
||||
cps.unloadQueue.remove(_chunkX, _chunkZ);
|
||||
cps.chunks.remove(hash);
|
||||
|
||||
if (_chunkX < _currentBorder / 16)
|
||||
{
|
||||
_chunkX++;
|
||||
}
|
||||
else if (_chunkZ < _currentBorder / 16)
|
||||
{
|
||||
_chunkX = (int) -(_currentBorder / 16);
|
||||
_chunkZ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mapLoaded = true;
|
||||
System.out.println("Map Loading Finished! Took " + TimeUnit.MILLISECONDS.toSeconds(now - start) + " seconds");
|
||||
break;
|
||||
}
|
||||
|
||||
_chunksLoaded++;
|
||||
|
||||
_chunksPerTick = (int) (_chunksLoaded / ((now - start) / 50.0));
|
||||
}
|
||||
|
||||
TimingManager.stop("Map Generation");
|
||||
|
||||
if (_stopGen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TimingManager.start("Map Saving");
|
||||
|
||||
// Wait for all the chunks to save (but do we need this?)
|
||||
while (!list.isEmpty())
|
||||
{
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
TimingManager.stop("Map Saving");
|
||||
|
||||
_game.getArcadeManager().runSync(_game::generateSpawns);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
// todo proper exception handling
|
||||
// maybe force shutdown?
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void flagStop()
|
||||
{
|
||||
this._stopGen = true;
|
||||
}
|
||||
|
||||
public String getMapLoadETA()
|
||||
{
|
||||
int chunksToGo = _chunkTotal - _chunksLoaded;
|
||||
|
||||
return UtilTime.MakeStr((long) ((double) chunksToGo / (double) (_chunksPerTick * 20) * 1000d), 1);
|
||||
}
|
||||
|
||||
public boolean isMapLoaded()
|
||||
{
|
||||
return this._mapLoaded;
|
||||
}
|
||||
|
||||
public int getPercentageComplete()
|
||||
{
|
||||
return UtilMath.clamp((int) ((_chunksLoaded * 1.0 / _chunkTotal) * 100), 0, 100);
|
||||
}
|
||||
|
||||
public String getProgress()
|
||||
{
|
||||
return getPercentageComplete() + "%";
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
public abstract class Module implements Listener
|
||||
{
|
||||
// The game this module belongs to
|
||||
private Game _game;
|
||||
|
||||
public void initialize(Game game)
|
||||
{
|
||||
if (_game != null)
|
||||
{
|
||||
throw new IllegalArgumentException("Attempting to initialize module which has already been initialized for " + _game);
|
||||
}
|
||||
this._game = game;
|
||||
}
|
||||
|
||||
public void cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Game getGame()
|
||||
{
|
||||
return this._game;
|
||||
}
|
||||
}
|
@ -0,0 +1,164 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.recharge.Recharge;
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class TeamModule extends Module
|
||||
{
|
||||
private BiMap<UUID, UUID> _teamReqs = HashBiMap.create();
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void teamSelectInteract(PlayerInteractEntityEvent event)
|
||||
{
|
||||
if (getGame().GetState() != Game.GameState.Recruit)
|
||||
return;
|
||||
|
||||
if (event.getRightClicked() == null)
|
||||
return;
|
||||
|
||||
if (!(event.getRightClicked() instanceof Player))
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
//Observer
|
||||
if (getGame().getArcadeManager().IsObserver(player))
|
||||
{
|
||||
UtilPlayer.message(player, F.main("Game", "Spectators cannot partake in games."));
|
||||
return;
|
||||
}
|
||||
|
||||
selectTeamMate(player, (Player) event.getRightClicked());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void teamSelectCommand(PlayerCommandPreprocessEvent event)
|
||||
{
|
||||
if (!event.getMessage().toLowerCase().startsWith("/team "))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
|
||||
if (getGame().GetState() != Game.GameState.Recruit)
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Game", "You cannot send team requests while the game is live"));
|
||||
return;
|
||||
}
|
||||
|
||||
//Observer
|
||||
if (getGame().getArcadeManager().IsObserver(event.getPlayer()))
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Game", "Spectators cannot partake in games."));
|
||||
return;
|
||||
}
|
||||
|
||||
Player target = UtilPlayer.searchOnline(event.getPlayer(), event.getMessage().split(" ")[1], true);
|
||||
|
||||
if (target == null)
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Game", "That player is not online"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getPlayer().equals(target))
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Game", "You can't team with yourself!"));
|
||||
return;
|
||||
}
|
||||
|
||||
selectTeamMate(event.getPlayer(), target);
|
||||
}
|
||||
|
||||
private void selectTeamMate(Player player, Player ally)
|
||||
{
|
||||
//Accept Invite
|
||||
if (_teamReqs.containsKey(ally.getUniqueId()) && _teamReqs.get(ally.getUniqueId()).equals(player.getUniqueId()))
|
||||
{
|
||||
//Remove Prefs
|
||||
_teamReqs.remove(player.getUniqueId());
|
||||
_teamReqs.remove(ally.getUniqueId());
|
||||
|
||||
//Inform
|
||||
UtilPlayer.message(player, F.main("Game", "You accepted " + ally.getName() + "'s Team Request!"));
|
||||
UtilPlayer.message(ally, F.main("Game", player.getName() + " accepted your Team Request!"));
|
||||
|
||||
//Leave Old Teams
|
||||
if (getGame().GetTeam(player) != null)
|
||||
getGame().GetTeam(player).DisbandTeam();
|
||||
|
||||
if (getGame().GetTeam(ally) != null)
|
||||
getGame().GetTeam(ally).DisbandTeam();
|
||||
|
||||
//Get Team
|
||||
GameTeam team = getEmptyTeam();
|
||||
if (team == null)
|
||||
return;
|
||||
|
||||
team.setDisplayName(player.getName() + " & " + ally.getName());
|
||||
|
||||
//Join Team
|
||||
getGame().SetPlayerTeam(player, team, true);
|
||||
getGame().SetPlayerTeam(ally, team, true);
|
||||
}
|
||||
//Send Invite
|
||||
else
|
||||
{
|
||||
//Already on Team with Target
|
||||
if (getGame().GetTeam(player) != null)
|
||||
if (getGame().GetTeam(player).HasPlayer(ally))
|
||||
return;
|
||||
|
||||
//Inform Player
|
||||
UtilPlayer.message(player, F.main("Game", "You sent a Team Request to " + ally.getName() + "!"));
|
||||
|
||||
//Inform Target
|
||||
if (Recharge.Instance.use(player, "Team Req " + ally.getName(), 2000, false, false))
|
||||
{
|
||||
UtilPlayer.message(ally, F.main("Game", player.getName() + " sent you a Team Request!"));
|
||||
UtilPlayer.message(ally, F.main("Game", "Type " + F.elem("/team " + player.getName()) + " to accept!"));
|
||||
}
|
||||
|
||||
//Add Pref
|
||||
_teamReqs.put(player.getUniqueId(), ally.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void teamQuit(PlayerQuitEvent event)
|
||||
{
|
||||
if (getGame().GetState() != Game.GameState.Recruit)
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (getGame().GetTeam(player) != null)
|
||||
getGame().GetTeam(player).DisbandTeam();
|
||||
|
||||
_teamReqs.remove(player.getUniqueId());
|
||||
_teamReqs.inverse().remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
private GameTeam getEmptyTeam()
|
||||
{
|
||||
for (GameTeam team : getGame().GetTeamList())
|
||||
{
|
||||
if (team.GetPlayers(false).isEmpty())
|
||||
return team;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -41,18 +41,7 @@ public class SpectatorButton implements IButton
|
||||
if(clickType == ClickType.RIGHT)
|
||||
{
|
||||
_player.closeInventory();
|
||||
_player.teleport(_target.getLocation().add(0, 1, 0));
|
||||
_arcadeManager.runSyncLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
_player.setGameMode(GameMode.SPECTATOR);
|
||||
_player.setSpectatorTarget(_target);
|
||||
UtilTextBottom.display(C.cYellow + "You are spectating " + F.game(_target.getName()), player);
|
||||
UtilPlayer.message(_player, F.main("Game", "Sneak to stop spectating"));
|
||||
}
|
||||
}, 3);
|
||||
_arcadeManager.getGameSpectatorManager().setSpectating(_player, _target);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -105,6 +105,7 @@ public class GameCreationManager implements Listener
|
||||
{
|
||||
Game game = gameIterator.next();
|
||||
|
||||
game.cleanupModules();
|
||||
game.disable();
|
||||
|
||||
HandlerList.unregisterAll(game);
|
||||
|
@ -948,7 +948,8 @@ public class GameLobbyManager implements Listener
|
||||
public void Combust(EntityCombustEvent event)
|
||||
{
|
||||
for (LobbyEnt ent : _kits.values())
|
||||
if (event.getEntity().equals(ent.GetEnt()))
|
||||
if (event.getEntity().getWorld().getUID().equals(ent.GetEnt().getWorld().getUID()) &&
|
||||
event.getEntity().equals(ent.GetEnt()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
|
@ -1,8 +1,22 @@
|
||||
package nautilus.game.arcade.managers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import mineplex.core.packethandler.IPacketHandler;
|
||||
import mineplex.core.packethandler.PacketHandler;
|
||||
import mineplex.core.packethandler.PacketInfo;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.NetworkManager;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutCamera;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutGameStateChange;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutNamedEntitySpawn;
|
||||
import net.minecraft.server.v1_8_R3.WorldSettings;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -10,6 +24,7 @@ import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
@ -26,8 +41,10 @@ import mineplex.core.updater.event.UpdateEvent;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.game.Game.GameState;
|
||||
|
||||
public class GameSpectatorManager implements Listener
|
||||
public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
{
|
||||
private Set<UUID> _pendingSpectate = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
ArcadeManager Manager;
|
||||
|
||||
public GameSpectatorManager(ArcadeManager manager)
|
||||
@ -35,11 +52,13 @@ public class GameSpectatorManager implements Listener
|
||||
Manager = manager;
|
||||
|
||||
Manager.getPluginManager().registerEvents(this, Manager.getPlugin());
|
||||
|
||||
Manager.getPacketHandler().addPacketHandler(this, PacketHandler.ListenerPriority.HIGH, PacketPlayOutNamedEntitySpawn.class);
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
|
||||
public void interactCancel(PlayerInteractEvent event)
|
||||
{
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
@ -47,30 +66,30 @@ public class GameSpectatorManager implements Listener
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
event.setCancelled(true);
|
||||
|
||||
|
||||
processClick(player, event.getAction());
|
||||
}
|
||||
|
||||
|
||||
public void processClick(Player player, Action action)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
|
||||
if(!Manager.GetGame().AllowEntitySpectate)
|
||||
return;
|
||||
|
||||
|
||||
if(!Manager.GetGame().IsLive())
|
||||
return;
|
||||
|
||||
|
||||
if(player.getGameMode() != GameMode.SPECTATOR)
|
||||
return;
|
||||
|
||||
|
||||
if(player.getSpectatorTarget() == null)
|
||||
return;
|
||||
|
||||
|
||||
if(!(player.getSpectatorTarget() instanceof Player))
|
||||
return;
|
||||
|
||||
|
||||
List<Player> players = Manager.GetGame().GetPlayers(true);
|
||||
int currentPlayer = 0;
|
||||
for(Player otherPlayer : players)
|
||||
@ -79,32 +98,32 @@ public class GameSpectatorManager implements Listener
|
||||
if(((Player) player.getSpectatorTarget()) == otherPlayer)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK)
|
||||
currentPlayer = currentPlayer - 2;
|
||||
else
|
||||
return;
|
||||
|
||||
|
||||
if(currentPlayer < 0)
|
||||
currentPlayer = players.size() - 1;
|
||||
|
||||
|
||||
if(currentPlayer >= players.size())
|
||||
currentPlayer = 0;
|
||||
|
||||
|
||||
if(players.get(currentPlayer) == null)
|
||||
return;
|
||||
|
||||
|
||||
Player specPlayer = players.get(currentPlayer);
|
||||
|
||||
|
||||
setSpectating(player, specPlayer);
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void interactEntityCancel(PlayerInteractEntityEvent event)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (Manager.GetGame().GetState() == GameState.Recruit)
|
||||
@ -114,7 +133,7 @@ public class GameSpectatorManager implements Listener
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
@ -127,7 +146,7 @@ public class GameSpectatorManager implements Listener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void updateSpecEntitys(UpdateEvent event)
|
||||
{
|
||||
@ -136,7 +155,7 @@ public class GameSpectatorManager implements Listener
|
||||
|
||||
if(Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
@ -158,13 +177,13 @@ public class GameSpectatorManager implements Listener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void spectatedEntityDeath(PlayerDeathEvent event)
|
||||
{
|
||||
if(Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
@ -191,13 +210,13 @@ public class GameSpectatorManager implements Listener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void dismountEntity(PlayerToggleSneakEvent event)
|
||||
{
|
||||
if(Manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
@ -213,41 +232,53 @@ public class GameSpectatorManager implements Listener
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setSpectating(Player player, Entity target)
|
||||
{
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.teleport(target.getLocation().add(0, 1, 0));
|
||||
player.getInventory().setHeldItemSlot(5);
|
||||
Manager.runSyncLater(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (Manager.GetGame().IsAlive(player))
|
||||
return;
|
||||
|
||||
Player ptarget = null;
|
||||
if (target instanceof Player)
|
||||
ptarget = (Player) target;
|
||||
|
||||
if (ptarget != null)
|
||||
{
|
||||
if (!Manager.GetGame().IsAlive(ptarget))
|
||||
return;
|
||||
}
|
||||
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
player.setSpectatorTarget(target);
|
||||
|
||||
if (ptarget != null)
|
||||
UtilTextBottom.display(C.cGray + "You are spectating " + F.elem(Manager.GetGame().GetTeam(ptarget).GetColor() + ptarget.getName()) + ".", player);
|
||||
|
||||
UtilPlayer.message(player, F.main("Game", "Sneak to stop spectating."));
|
||||
public void setSpectating(Player player, Entity target)
|
||||
{
|
||||
if (Manager.GetGame().IsAlive(player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Player playerTarget = null;
|
||||
|
||||
if (target instanceof Player)
|
||||
{
|
||||
playerTarget = (Player) target;
|
||||
if (!Manager.GetGame().IsAlive(playerTarget))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
_pendingSpectate.add(target.getUniqueId());
|
||||
|
||||
player.teleport(target.getLocation().add(0, 1, 0));
|
||||
|
||||
// If the player already has the entity loaded, we have to set it now
|
||||
|
||||
// todo
|
||||
// In the future, we could do some really cool stuff where we listen to all incoming and outgoing
|
||||
// spawn/destroy packets and track whether the client has loaded the entity in memory
|
||||
// However, that approach has the risk of desynchronization at which point we're screwed
|
||||
player.setGameMode(GameMode.SPECTATOR);
|
||||
player.setSpectatorTarget(target);
|
||||
|
||||
if (playerTarget != null)
|
||||
UtilTextBottom.display(C.cGray + "You are spectating " + F.elem(Manager.GetGame().GetTeam(playerTarget).GetColor() + playerTarget.getName()) + ".", player);
|
||||
|
||||
UtilPlayer.message(player, F.main("Game", "Sneak to stop spectating."));
|
||||
|
||||
// And if the player did have the entity loaded, we also need to clean up after ourselves
|
||||
// 20 ticks should be more than enough time considering we're just waiting for the server to attempt to
|
||||
// send the packet
|
||||
// and even if the server was lagging, the scheduler should be lagging too
|
||||
Manager.runSyncLater(() ->
|
||||
{
|
||||
_pendingSpectate.remove(target.getUniqueId());
|
||||
}, 20L);
|
||||
}
|
||||
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void vehicleDamage(VehicleDamageEvent event)
|
||||
{
|
||||
@ -256,10 +287,57 @@ public class GameSpectatorManager implements Listener
|
||||
|
||||
if (!(event.getAttacker() instanceof Player))
|
||||
return;
|
||||
|
||||
|
||||
Player player = (Player)event.getAttacker();
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(PacketInfo packetInfo)
|
||||
{
|
||||
if (packetInfo.getPacket() instanceof PacketPlayOutNamedEntitySpawn)
|
||||
{
|
||||
PacketPlayOutNamedEntitySpawn packet = (PacketPlayOutNamedEntitySpawn) packetInfo.getPacket();
|
||||
if (_pendingSpectate.remove(packet.b))
|
||||
{
|
||||
// Handle Minestrike spam race condition
|
||||
if (Manager.GetGame().IsAlive(packetInfo.getPlayer()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
packetInfo.setCancelled(true);
|
||||
|
||||
EntityPlayer ep = ((CraftPlayer) packetInfo.getPlayer()).getHandle();
|
||||
NetworkManager manager = ep.playerConnection.networkManager;
|
||||
|
||||
manager.a(packet, future ->
|
||||
{
|
||||
Manager.runSync(() ->
|
||||
{
|
||||
PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(packetInfo.getPlayer(), GameMode.SPECTATOR);
|
||||
UtilServer.CallEvent(event);
|
||||
if(event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ep.playerInteractManager.setGameMode(WorldSettings.EnumGamemode.getById(GameMode.SPECTATOR.getValue()));
|
||||
ep.fallDistance = 0.0F;
|
||||
manager.a(new PacketPlayOutCamera(ep), future1 ->
|
||||
{
|
||||
manager.a(new PacketPlayOutGameStateChange(3, (float)GameMode.SPECTATOR.getValue()), future2 ->
|
||||
{
|
||||
PacketPlayOutCamera p1 = new PacketPlayOutCamera();
|
||||
p1.a = packet.a;
|
||||
manager.handle(p1);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user