Many changes
Fix spectator race condition Refactor out cut clean into modules Add combat log module Add antixray module
This commit is contained in:
parent
a7b30f4f59
commit
7dcf7378ef
@ -0,0 +1,59 @@
|
||||
package mineplex.core.common.util;
|
||||
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
||||
public class UtilParser
|
||||
{
|
||||
public static String parseDamageCause(EntityDamageEvent.DamageCause cause)
|
||||
{
|
||||
switch (cause)
|
||||
{
|
||||
case CONTACT:
|
||||
return "Cactus";
|
||||
case ENTITY_ATTACK:
|
||||
return "Attack";
|
||||
case PROJECTILE:
|
||||
return "Ranged Weapon";
|
||||
case SUFFOCATION:
|
||||
return "Suffocation";
|
||||
case FALL:
|
||||
return "Fall";
|
||||
case FIRE:
|
||||
return "Fire";
|
||||
case FIRE_TICK:
|
||||
return "Burning";
|
||||
case MELTING:
|
||||
return "Melting";
|
||||
case LAVA:
|
||||
return "Lava";
|
||||
case DROWNING:
|
||||
return "Drowning";
|
||||
case BLOCK_EXPLOSION:
|
||||
return "Explosion";
|
||||
case ENTITY_EXPLOSION:
|
||||
return "Explosion";
|
||||
case VOID:
|
||||
return "Void";
|
||||
case LIGHTNING:
|
||||
return "Lightning";
|
||||
case SUICIDE:
|
||||
return "Suicide";
|
||||
case STARVATION:
|
||||
return "Hunger";
|
||||
case POISON:
|
||||
return "Poison";
|
||||
case MAGIC:
|
||||
return "Thrown Potion";
|
||||
case WITHER:
|
||||
return "Wither Effect";
|
||||
case FALLING_BLOCK:
|
||||
return "Falling Block";
|
||||
case THORNS:
|
||||
return "Thorns Enchantment";
|
||||
case CUSTOM:
|
||||
return "Custom";
|
||||
default:
|
||||
return "The Mighty defek7";
|
||||
}
|
||||
}
|
||||
}
|
@ -227,7 +227,8 @@ public class InventoryManager extends MiniDbClientPlugin<ClientInventory>
|
||||
event.getInventory().setItem(1, new ItemStack(Material.INK_SACK, level, (byte) 4));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
// fixme broken cast
|
||||
// @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void onBlockBreak(BlockBreakEvent event)
|
||||
{
|
||||
if (event.getBlock().getType() != Material.ENCHANTMENT_TABLE)
|
||||
|
@ -204,6 +204,7 @@ public abstract class Game implements Listener
|
||||
public boolean WorldLeavesDecay = false;
|
||||
public boolean WorldSoilTrample = false;
|
||||
public boolean WorldBoneMeal = false;
|
||||
public boolean WorldChunkUnload = false;
|
||||
|
||||
public int HungerSet = -1;
|
||||
public int HealthSet = -1;
|
||||
@ -423,13 +424,14 @@ public abstract class Game implements Listener
|
||||
System.out.println("Loading " + GetName() + "...");
|
||||
}
|
||||
|
||||
public void registerModule(Module module)
|
||||
public <T extends Module> T registerModule(T module)
|
||||
{
|
||||
if (!_modules.containsKey(module.getClass()))
|
||||
{
|
||||
module.initialize(this);
|
||||
_modules.put(module.getClass(), module);
|
||||
UtilServer.RegisterEvents(module);
|
||||
module.initialize(this);
|
||||
return module;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -437,6 +439,16 @@ public abstract class Game implements Listener
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterModule(Module module)
|
||||
{
|
||||
if (_modules.containsKey(module.getClass()) && _modules.get(module.getClass()) == module)
|
||||
{
|
||||
_modules.remove(module.getClass());
|
||||
module.cleanup();
|
||||
HandlerList.unregisterAll(module);
|
||||
}
|
||||
}
|
||||
|
||||
public void setKits(Kit[] kits)
|
||||
{
|
||||
_kits = kits;
|
||||
|
@ -1,33 +1,38 @@
|
||||
package nautilus.game.arcade.game;
|
||||
|
||||
import mineplex.core.common.util.*;
|
||||
import mineplex.core.common.util.UtilTime.*;
|
||||
import mineplex.core.updater.*;
|
||||
import mineplex.core.updater.event.*;
|
||||
import nautilus.game.arcade.*;
|
||||
import nautilus.game.arcade.events.*;
|
||||
import nautilus.game.arcade.game.GameTeam.*;
|
||||
import nautilus.game.arcade.kit.*;
|
||||
import nautilus.game.arcade.stats.TeamDeathsStatTracker;
|
||||
import nautilus.game.arcade.stats.TeamKillsStatTracker;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.NautHashMap;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.common.util.UtilTime.TimeUnit;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.PlayerStateChangeEvent;
|
||||
import nautilus.game.arcade.game.GameTeam.PlayerState;
|
||||
import nautilus.game.arcade.kit.Kit;
|
||||
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.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.*;
|
||||
import org.bukkit.event.player.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class TeamGame extends Game
|
||||
{
|
||||
public long RejoinTime = 120000;
|
||||
|
||||
protected ArrayList<GameTeam> _places = new ArrayList<GameTeam>();
|
||||
|
||||
private NautHashMap<String, Long> _rejoinTime = new NautHashMap<String, Long>();
|
||||
protected NautHashMap<String, GameTeam> RejoinTeam = new NautHashMap<String, GameTeam>();
|
||||
protected NautHashMap<String, Kit> RejoinKit = new NautHashMap<String, Kit>();
|
||||
protected NautHashMap<String, Double> RejoinHealth = new NautHashMap<String, Double>();
|
||||
|
||||
protected long RejoinTime = 120000;
|
||||
public NautHashMap<String, Long> RejoinTimes = new NautHashMap<String, Long>();
|
||||
public NautHashMap<String, GameTeam> RejoinTeam = new NautHashMap<String, GameTeam>();
|
||||
public NautHashMap<String, Kit> RejoinKit = new NautHashMap<String, Kit>();
|
||||
public NautHashMap<String, Double> RejoinHealth = new NautHashMap<String, Double>();
|
||||
|
||||
public TeamGame(ArcadeManager manager, GameType gameType, Kit[] kits, String[] gameDesc)
|
||||
{
|
||||
@ -54,7 +59,7 @@ public abstract class TeamGame extends Game
|
||||
return _places;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void PlayerQuit(PlayerQuitEvent event)
|
||||
{
|
||||
if (!InProgress())
|
||||
@ -79,7 +84,7 @@ public abstract class TeamGame extends Game
|
||||
if (!QuitOut)
|
||||
{
|
||||
//Store
|
||||
_rejoinTime.put(player.getName(), System.currentTimeMillis());
|
||||
RejoinTimes.put(player.getName(), System.currentTimeMillis());
|
||||
RejoinTeam.put(player.getName(), team);
|
||||
|
||||
if (GetKit(player) != null)
|
||||
@ -102,7 +107,7 @@ public abstract class TeamGame extends Game
|
||||
|
||||
//Rejoined
|
||||
GameTeam team = RejoinTeam.remove(event.getPlayer().getName());
|
||||
if (team != null && _rejoinTime.remove(event.getPlayer().getName()) != null)
|
||||
if (team != null && RejoinTimes.remove(event.getPlayer().getName()) != null)
|
||||
{
|
||||
team.AddPlayer(event.getPlayer(), true);
|
||||
Announce(team.GetColor() + C.Bold + event.getPlayer().getName() + " has reconnected!", false);
|
||||
@ -126,8 +131,6 @@ public abstract class TeamGame extends Game
|
||||
// }
|
||||
// }
|
||||
// }, 20);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +146,21 @@ public abstract class TeamGame extends Game
|
||||
if (RejoinHealth.containsKey(player.getName()))
|
||||
{
|
||||
double health = RejoinHealth.remove(player.getName());
|
||||
player.setHealth(health);
|
||||
if (health > 0)
|
||||
{
|
||||
getArcadeManager().runSyncLater(() ->
|
||||
{
|
||||
player.setHealth(health);
|
||||
}, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
if (GetLocationStore().containsKey(player.getName()))
|
||||
{
|
||||
getArcadeManager().runSyncLater(() ->
|
||||
{
|
||||
player.teleport(GetLocationStore().remove(player.getName()));
|
||||
}, 1L);
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,13 +170,13 @@ public abstract class TeamGame extends Game
|
||||
if (event.getType() != UpdateType.SEC || QuitOut)
|
||||
return;
|
||||
|
||||
Iterator<String> rejoinIterator = _rejoinTime.keySet().iterator();
|
||||
Iterator<String> rejoinIterator = RejoinTimes.keySet().iterator();
|
||||
|
||||
while (rejoinIterator.hasNext())
|
||||
{
|
||||
String name = rejoinIterator.next();
|
||||
|
||||
if (!UtilTime.elapsed(_rejoinTime.get(name), RejoinTime))
|
||||
if (!UtilTime.elapsed(RejoinTimes.get(name), RejoinTime))
|
||||
continue;
|
||||
|
||||
rejoinIterator.remove();
|
||||
@ -187,7 +204,7 @@ public abstract class TeamGame extends Game
|
||||
}
|
||||
else
|
||||
{
|
||||
_rejoinTime.put(toks[1], System.currentTimeMillis());
|
||||
RejoinTimes.put(toks[1], System.currentTimeMillis());
|
||||
event.getPlayer().sendMessage("Allowed " + toks[1] + " to rejoin!");
|
||||
}
|
||||
|
||||
|
@ -16,11 +16,12 @@ import mineplex.core.common.util.UtilBlock;
|
||||
import mineplex.core.common.util.UtilEvent;
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilParser;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextMiddle;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.common.util.UtilWorld;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.recharge.Recharge;
|
||||
import mineplex.core.timing.TimingManager;
|
||||
@ -38,14 +39,17 @@ import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.TeamGame;
|
||||
import nautilus.game.arcade.game.games.uhc.helpers.ChunkLoadingThread;
|
||||
import nautilus.game.arcade.game.games.uhc.helpers.WorldGenThread;
|
||||
import nautilus.game.arcade.game.modules.OreVeinEditorModule;
|
||||
import nautilus.game.arcade.game.modules.TeamModule;
|
||||
import nautilus.game.arcade.game.modules.antixray.AntiXrayModule;
|
||||
import nautilus.game.arcade.game.modules.combatlog.CombatLogModule;
|
||||
import nautilus.game.arcade.game.modules.combatlog.CombatLogNPC;
|
||||
import nautilus.game.arcade.kit.Kit;
|
||||
import net.minecraft.server.v1_8_R3.Chunk;
|
||||
import net.minecraft.server.v1_8_R3.MathHelper;
|
||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||
import net.minecraft.server.v1_8_R3.WorldServer;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Difficulty;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -54,9 +58,8 @@ import org.bukkit.World.Environment;
|
||||
import org.bukkit.WorldBorder;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@ -68,7 +71,9 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.block.BlockGrowEvent;
|
||||
import org.bukkit.event.block.BlockPistonExtendEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
||||
@ -81,6 +86,7 @@ import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerPickupItemEvent;
|
||||
@ -88,6 +94,7 @@ import org.bukkit.event.player.PlayerPortalEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.bukkit.inventory.CraftingInventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.ShapedRecipe;
|
||||
@ -96,16 +103,17 @@ import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scoreboard.DisplaySlot;
|
||||
import org.bukkit.scoreboard.Objective;
|
||||
import org.spigotmc.ActivationRange;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
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.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@ -120,12 +128,27 @@ public class UHC extends TeamGame implements NCPHook
|
||||
// The number of minutes after which PVP should be enabled
|
||||
public static final int SAFE_TIME_IN_MINUTES = 11;
|
||||
|
||||
// The number of chunks to unload per tick
|
||||
public static final int CHUNKS_UNLOAD_PER_TICK = 1;
|
||||
|
||||
// This is the region in which nothing can be done (block placing, flowing, etc)
|
||||
public static final int SAFE_REGION = 36;
|
||||
|
||||
// The amount of damage to give from hitting the world border
|
||||
public static final int WORLD_BORDER_DAMAGE = 5;
|
||||
|
||||
// The thread responsible for generating the world
|
||||
private final WorldGenThread _worldGenThread = new WorldGenThread(this);
|
||||
|
||||
// The thread responsible for loading and decorating the world
|
||||
private final ChunkLoadingThread _chunkLoadingThread = new ChunkLoadingThread(this);
|
||||
|
||||
// The chunks which we have prevented unloading
|
||||
private final Set<Chunk> _loadedChunks = new HashSet<>();
|
||||
|
||||
// The task which will unload chunks periodically
|
||||
private BukkitRunnable _chunkUnloadTask;
|
||||
|
||||
// The number of minutes passed in this game
|
||||
private int _minutesSinceStart = 0;
|
||||
|
||||
@ -139,8 +162,6 @@ public class UHC extends TeamGame implements NCPHook
|
||||
// Whether players are teleporting currently
|
||||
private volatile boolean _isTeleporting = false;
|
||||
|
||||
private boolean xrayDebug;
|
||||
|
||||
// Border
|
||||
private int _secondsSinceStart;
|
||||
private HashMap<Integer, Double> _borderPositions = new HashMap<Integer, Double>();
|
||||
@ -159,6 +180,11 @@ public class UHC extends TeamGame implements NCPHook
|
||||
DamageTaken,
|
||||
DamageDealt
|
||||
);
|
||||
|
||||
registerModule(
|
||||
new OreVeinEditorModule()
|
||||
.removeNonAirVeins()
|
||||
);
|
||||
}
|
||||
|
||||
public UHC(ArcadeManager manager, GameType type)
|
||||
@ -176,12 +202,12 @@ public class UHC extends TeamGame implements NCPHook
|
||||
"Borders shrink over time", "Last player/team alive wins!"
|
||||
});
|
||||
|
||||
_gamesRun++;
|
||||
|
||||
this.HideTeamSheep = true;
|
||||
|
||||
this.StrictAntiHack = true;
|
||||
|
||||
AnnounceStay = false;
|
||||
|
||||
this.GameTimeout = 10800000;
|
||||
|
||||
this.DamagePvP = false;
|
||||
@ -229,6 +255,10 @@ public class UHC extends TeamGame implements NCPHook
|
||||
WorldTimeSet = -1;
|
||||
|
||||
this.WorldLeavesDecay = true;
|
||||
this.WorldBlockGrow = true;
|
||||
this.WorldSoilTrample = true;
|
||||
this.WorldBoneMeal = true;
|
||||
this.WorldChunkUnload = true;
|
||||
|
||||
CraftRecipes();
|
||||
|
||||
@ -247,6 +277,31 @@ public class UHC extends TeamGame implements NCPHook
|
||||
NCPHookManager.addHook(CheckType.ALL, this);
|
||||
|
||||
registerModule(new TeamModule());
|
||||
registerModule(new AntiXrayModule())
|
||||
.setEnabled(true)
|
||||
.setUpdateOnDamage(true)
|
||||
.setAntiTexturePacksAndFreecam(false)
|
||||
.setUseProximityHider(false)
|
||||
.setEngineMode(2)
|
||||
.setInitialRadius(1)
|
||||
.setUpdateRadius(2)
|
||||
.setObfuscateBlocks(
|
||||
Material.GOLD_ORE,
|
||||
Material.IRON_ORE,
|
||||
Material.LAPIS_ORE,
|
||||
Material.DIAMOND_ORE,
|
||||
Material.REDSTONE_ORE,
|
||||
Material.GLOWING_REDSTONE_ORE,
|
||||
Material.EMERALD_ORE
|
||||
)
|
||||
.setRandomBlocks(
|
||||
Material.GOLD_ORE,
|
||||
Material.IRON_ORE,
|
||||
Material.LAPIS_ORE,
|
||||
Material.DIAMOND_ORE,
|
||||
Material.REDSTONE_ORE,
|
||||
Material.EMERALD_ORE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -345,7 +400,7 @@ public class UHC extends TeamGame implements NCPHook
|
||||
|
||||
if (Manager.IsAlive(player))
|
||||
{
|
||||
Manager.GetDamage().NewDamageEvent(player, null, null, DamageCause.CUSTOM, 10, false, false, false,
|
||||
Manager.GetDamage().NewDamageEvent(player, null, null, DamageCause.CUSTOM, WORLD_BORDER_DAMAGE, false, false, false,
|
||||
"Nether Field", "Vaporize");
|
||||
|
||||
player.getWorld().playSound(loc, Sound.NOTE_BASS, 2f, 1f);
|
||||
@ -358,6 +413,36 @@ public class UHC extends TeamGame implements NCPHook
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (getModule(CombatLogModule.class) != null)
|
||||
{
|
||||
for (CombatLogNPC npc : getModule(CombatLogModule.class).getAllNPCs())
|
||||
{
|
||||
LivingEntity ent = npc.getNPC();
|
||||
Location loc = ent.getLocation();
|
||||
|
||||
// Bump Players Back In
|
||||
if (loc.getX() > border || loc.getX() < -border || loc.getZ() > border || loc.getZ() < -border)
|
||||
{
|
||||
// Can't use recharge on entities; blame bad design (mapping by name instead of uuid)
|
||||
// if (Recharge.Instance.use(ent, "Hit by Border", 1000, false, false))
|
||||
{
|
||||
Entity bottom = ent;
|
||||
while (bottom.getVehicle() != null)
|
||||
bottom = bottom.getVehicle();
|
||||
|
||||
UtilAction
|
||||
.velocity(bottom, UtilAlg.getTrajectory2d(loc, GetSpectatorLocation()), 1.2, true, 0.4, 0, 10, true);
|
||||
|
||||
Manager.GetDamage().NewDamageEvent(ent, null, null, DamageCause.CUSTOM, WORLD_BORDER_DAMAGE, false, false, false,
|
||||
"Nether Field", "Vaporize");
|
||||
|
||||
ent.getWorld().playSound(loc, Sound.NOTE_BASS, 2f, 1f);
|
||||
ent.getWorld().playSound(loc, Sound.NOTE_BASS, 2f, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<Double> buildBorders(int seconds, double border, double leaveRemaining)
|
||||
@ -517,7 +602,70 @@ public class UHC extends TeamGame implements NCPHook
|
||||
|
||||
this.DamagePvP = true;
|
||||
this.CompassGiveItem = true;
|
||||
this.QuitOut = true;
|
||||
this.RejoinTime = 300000; // 5 minutes
|
||||
registerModule(
|
||||
new CombatLogModule()
|
||||
.setSpawnForCreative(false)
|
||||
.setCombatLogTime(300000)
|
||||
.setOnDeathAction(npc ->
|
||||
{
|
||||
if (npc.getLastDamager() instanceof Player)
|
||||
{
|
||||
Player killer = (Player) npc.getLastDamager();
|
||||
Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName()
|
||||
+ C.cGray + C.Bold + " was killed by " + getArcadeManager().GetColor(killer)
|
||||
+ C.Bold + npc.getLastDamager().getName() + C.cGray + C.Bold + " while logged out.");
|
||||
}
|
||||
else
|
||||
{
|
||||
String cause = UtilParser.parseDamageCause(npc.getLastDamageCause());
|
||||
if (npc.getLastDamager() != null)
|
||||
{
|
||||
cause = npc.getLastDamager().getName();
|
||||
}
|
||||
Announce(npc.getPlayerInfo().getTeamColor() + C.Bold + npc.getPlayerInfo().getName()
|
||||
+ C.cGray + C.Bold + " was killed by " + cause + " while logged out.");
|
||||
}
|
||||
|
||||
ItemStack stack = new ItemBuilder(Material.SKULL_ITEM)
|
||||
.setData((byte) 3)
|
||||
.setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head")
|
||||
.build();
|
||||
|
||||
SkullMeta meta = (SkullMeta) stack.getItemMeta();
|
||||
meta.setOwner(npc.getPlayerInfo().getName());
|
||||
stack.setItemMeta(meta);
|
||||
|
||||
npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack);
|
||||
|
||||
Location location = npc.getNPC().getLocation();
|
||||
|
||||
for (ItemStack item : npc.getPlayerInfo().getItems())
|
||||
{
|
||||
location.getWorld().dropItemNaturally(location, item);
|
||||
}
|
||||
})
|
||||
.setOnExpireAction(npc ->
|
||||
{
|
||||
ItemStack stack = new ItemBuilder(Material.SKULL_ITEM)
|
||||
.setData((byte) 3)
|
||||
.setTitle(npc.getPlayerInfo().getTeamColor() + npc.getPlayerInfo().getName() + "'s Head")
|
||||
.build();
|
||||
|
||||
SkullMeta meta = (SkullMeta) stack.getItemMeta();
|
||||
meta.setOwner(npc.getPlayerInfo().getName());
|
||||
stack.setItemMeta(meta);
|
||||
|
||||
npc.getNPC().getWorld().dropItemNaturally(npc.getNPC().getLocation(), stack);
|
||||
|
||||
Location location = npc.getNPC().getLocation();
|
||||
|
||||
for (ItemStack item : npc.getPlayerInfo().getItems())
|
||||
{
|
||||
location.getWorld().dropItemNaturally(location, item);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,6 +729,27 @@ public class UHC extends TeamGame implements NCPHook
|
||||
}
|
||||
HandlerList.unregisterAll(_chunkLoadingThread);
|
||||
NCPHookManager.removeHook(this);
|
||||
|
||||
if (_chunkUnloadTask != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_chunkUnloadTask.cancel();
|
||||
}
|
||||
catch (IllegalStateException ex)
|
||||
{
|
||||
// bukkit
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<Chunk> iterator = _loadedChunks.iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Chunk chunk = iterator.next();
|
||||
WorldData.World.unloadChunk(chunk.getX(), chunk.getZ());
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -592,16 +761,13 @@ public class UHC extends TeamGame implements NCPHook
|
||||
_worldGenThread.start();
|
||||
}
|
||||
|
||||
@EventHandler (priority = EventPriority.MONITOR, ignoreCancelled = false)
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void on(ChunkUnloadEvent event)
|
||||
{
|
||||
if (IsLive())
|
||||
{
|
||||
event.setCancelled(false);
|
||||
}
|
||||
else
|
||||
if (!IsLive())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
_loadedChunks.add(event.getChunk());
|
||||
}
|
||||
}
|
||||
|
||||
@ -641,11 +807,11 @@ public class UHC extends TeamGame implements NCPHook
|
||||
|
||||
Location zero = WorldData.World.getSpawnLocation();
|
||||
|
||||
// fixme if you leave while teleporting you'll rejoin at 0,0
|
||||
|
||||
for (Player player : players)
|
||||
{
|
||||
player.teleport(zero);
|
||||
player.hidePlayer(player);
|
||||
|
||||
// Heal
|
||||
player.setHealth(player.getMaxHealth());
|
||||
// Resistance and regen
|
||||
@ -711,14 +877,31 @@ public class UHC extends TeamGame implements NCPHook
|
||||
|
||||
WorldData.World.setAutoSave(true);
|
||||
|
||||
int x = 0;
|
||||
for (org.bukkit.Chunk chunk : WorldData.World.getLoadedChunks())
|
||||
_chunkUnloadTask = new BukkitRunnable()
|
||||
{
|
||||
if (WorldData.World.unloadChunkRequest(chunk.getX(), chunk.getZ()))
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
System.out.println("Requesting unload of chunk #" + (++x) + " " + chunk.getX() + " " + chunk.getZ());
|
||||
Iterator<Chunk> iterator = _loadedChunks.iterator();
|
||||
int amount = 0;
|
||||
|
||||
while (amount < CHUNKS_UNLOAD_PER_TICK && iterator.hasNext())
|
||||
{
|
||||
Chunk next = iterator.next();
|
||||
if (WorldData.World.unloadChunkRequest(next.getX(), next.getZ()))
|
||||
{
|
||||
System.out.println("Requesting unload of chunk " + next.getX() + " " + next.getZ());
|
||||
}
|
||||
iterator.remove();
|
||||
amount++;
|
||||
}
|
||||
|
||||
if (_loadedChunks.size() == 0)
|
||||
{
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}, 10 * 20L);
|
||||
}
|
||||
}, 5 * 20L);
|
||||
@ -821,17 +1004,90 @@ public class UHC extends TeamGame implements NCPHook
|
||||
return SpectatorSpawn;
|
||||
}
|
||||
|
||||
// fixme flowing water and stuff
|
||||
|
||||
@EventHandler
|
||||
public void WorldBoundaryYLimit(BlockPlaceEvent event)
|
||||
public void preventBlockPlacement(BlockPlaceEvent event)
|
||||
{
|
||||
if (event.getBlock().getX() >= -36 && event.getBlock().getX() <= 36 && event.getBlock().getZ() >= -36
|
||||
&& event.getBlock().getZ() <= 36)
|
||||
if (isInSafeZone(event.getBlock().getLocation()))
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Game", "You cannot build this high near center of map."));
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventStructureGrow(StructureGrowEvent event)
|
||||
{
|
||||
Iterator<BlockState> blocks = event.getBlocks().iterator();
|
||||
while (blocks.hasNext())
|
||||
{
|
||||
BlockState next = blocks.next();
|
||||
if (isInSafeZone(next.getLocation()))
|
||||
{
|
||||
blocks.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventBlockGrow(BlockGrowEvent event)
|
||||
{
|
||||
if (isInSafeZone(event.getBlock().getLocation()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventBoneMeal(PlayerInteractEvent event)
|
||||
{
|
||||
if (event.getAction() == Action.RIGHT_CLICK_BLOCK)
|
||||
{
|
||||
boolean isIllegal = false;
|
||||
if (!isIllegal)
|
||||
{
|
||||
isIllegal = event.getPlayer().getItemInHand().getType() == Material.INK_SACK &&
|
||||
event.getPlayer().getItemInHand().getData().getData() == (byte) 15;
|
||||
}
|
||||
if (!isIllegal)
|
||||
{
|
||||
isIllegal = event.getPlayer().getItemInHand().getType() == Material.WATER_BUCKET
|
||||
|| event.getPlayer().getItemInHand().getType() == Material.LAVA_BUCKET;
|
||||
}
|
||||
|
||||
if (isIllegal && isInSafeZone(event.getClickedBlock().getLocation()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void preventPistons(BlockPistonExtendEvent event)
|
||||
{
|
||||
boolean willBeUnsafe = false;
|
||||
for (Block block : event.getBlocks())
|
||||
{
|
||||
if (isInSafeZone(block.getRelative(event.getDirection()).getLocation()))
|
||||
{
|
||||
willBeUnsafe = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (willBeUnsafe)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isInSafeZone(Location location)
|
||||
{
|
||||
return location.getX() <= SAFE_REGION && location.getX() >= -SAFE_REGION
|
||||
&& location.getZ() < SAFE_REGION && location.getZ() >= -SAFE_REGION;
|
||||
}
|
||||
|
||||
// fixme world decoration means random spawns which were clear before might not be after
|
||||
public Location GetRandomSpawn(Location around)
|
||||
{
|
||||
// Sometimes getting a random spawn at 0,0 hangs forever
|
||||
@ -1019,7 +1275,7 @@ public class UHC extends TeamGame implements NCPHook
|
||||
if (event.getType() != UpdateType.SLOW)
|
||||
return;
|
||||
|
||||
HashMap<EntityType, ArrayList<Entity>> ents = new HashMap<EntityType, ArrayList<Entity>>();
|
||||
Map<EntityType, ArrayList<Entity>> ents = new HashMap<>();
|
||||
|
||||
for (Entity ent : WorldData.World.getEntities())
|
||||
{
|
||||
@ -1573,82 +1829,12 @@ public class UHC extends TeamGame implements NCPHook
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int _gamesRun = 0;
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerCommandPreprocessEvent event)
|
||||
{
|
||||
if (event.getMessage().equals("/uhcentities"))
|
||||
{
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
if (client.GetRank().has(Rank.DEVELOPER))
|
||||
{
|
||||
for (Entity entity : event.getPlayer().getNearbyEntities(5.0, 5.0, 5.0))
|
||||
{
|
||||
net.minecraft.server.v1_8_R3.Entity nms = ((CraftEntity) entity).getHandle();
|
||||
String debug = "Entity: " + entity.getType() + " id:" + nms.getId() + " inac:" + ActivationRange.checkIfActive(nms);
|
||||
debug += " at:" + nms.activatedTick + " dac:" + nms.defaultActivationState;
|
||||
|
||||
int x = MathHelper.floor(nms.locX);
|
||||
int z = MathHelper.floor(nms.locZ);
|
||||
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = nms.world.getChunkIfLoaded(x >> 4, z >> 4);
|
||||
debug += " c:" + chunk + " il:" + (chunk != null ? chunk.areNeighborsLoaded(1) : "null");
|
||||
event.getPlayer().sendMessage(debug);
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().equals("/uhcchunk"))
|
||||
{
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
if (client.GetRank().has(Rank.DEVELOPER))
|
||||
{
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = ((CraftChunk) event.getPlayer().getLocation().getChunk()).getHandle();
|
||||
try
|
||||
{
|
||||
Field neighbors = chunk.getClass().getDeclaredField("neighbors");
|
||||
neighbors.setAccessible(true);
|
||||
int n = neighbors.getInt(chunk);
|
||||
|
||||
for (int x = -1; x < 2; x++)
|
||||
{
|
||||
for (int z = -1; z < 2; z++)
|
||||
{
|
||||
if (x == 0 && z == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int mask = 0x1 << (x * 5 + z + 12);
|
||||
|
||||
boolean should = chunk.world.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z) != null;
|
||||
boolean is = (n & mask) == mask;
|
||||
if (is && should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.GREEN + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") is a neighbor");
|
||||
}
|
||||
else if (is && !should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.RED + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") is a neighbor but should not be");
|
||||
}
|
||||
else if (!is && should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.RED + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") is not a neighbor but should be");
|
||||
}
|
||||
else if (!is && !should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.GREEN + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") is not a neighbor");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().equals("/uhcgc"))
|
||||
if (event.getMessage().equals("/uhcgc"))
|
||||
{
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
if (client.GetRank().has(Rank.DEVELOPER))
|
||||
@ -1658,53 +1844,6 @@ public class UHC extends TeamGame implements NCPHook
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().equals("/uhcallchunks"))
|
||||
{
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
if (client.GetRank().has(Rank.DEVELOPER))
|
||||
{
|
||||
for (Chunk chunk : ((CraftWorld) event.getPlayer().getWorld()).getHandle().chunkProviderServer.chunks.values())
|
||||
{
|
||||
try
|
||||
{
|
||||
Field neighbors = chunk.getClass().getDeclaredField("neighbors");
|
||||
neighbors.setAccessible(true);
|
||||
int n = neighbors.getInt(chunk);
|
||||
|
||||
for (int x = -1; x < 2; x++)
|
||||
{
|
||||
for (int z = -1; z < 2; z++)
|
||||
{
|
||||
if (x == 0 && z == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int mask = 0x1 << (x * 5 + z + 12);
|
||||
|
||||
boolean should = chunk.world.getChunkIfLoaded(chunk.locX + x, chunk.locZ + z) != null;
|
||||
boolean is = (n & mask) == mask;
|
||||
if (is && !should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.RED + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") relative to " + (chunk.locX) + "," + chunk.locZ + " is a neighbor but should not be");
|
||||
}
|
||||
else if (!is && should)
|
||||
{
|
||||
event.getPlayer().sendMessage(ChatColor.RED + "Chunk " + (chunk.locX + x) + "," + (chunk.locZ + z) + " (" + x + "," + z + ") relative to " + (chunk.locX) + "," + chunk.locZ + " is not a neighbor but should be");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
event.getPlayer().sendMessage("Done");
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
else if (event.getMessage().equals("/uhcworlds"))
|
||||
{
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
@ -1734,183 +1873,14 @@ public class UHC extends TeamGame implements NCPHook
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void xrayBlockBreak(BlockBreakEvent event)
|
||||
{
|
||||
if (event.isCancelled())
|
||||
return;
|
||||
|
||||
if (xrayDebug)
|
||||
TimingManager.start("Block Break");
|
||||
|
||||
int range = 3;
|
||||
|
||||
// Find Nearby Ores
|
||||
ArrayList<Block> ores = findOres(event.getBlock(), range);
|
||||
|
||||
// Anti-Xray
|
||||
removeNonAirVeins(generateVeins(ores));
|
||||
|
||||
if (xrayDebug)
|
||||
TimingManager.stop("Block Break");
|
||||
}
|
||||
|
||||
private ArrayList<Block> findOres(Block source, int range)
|
||||
{
|
||||
ArrayList<Block> ores = new ArrayList<Block>();
|
||||
|
||||
for (int x = -range; x <= range; x++)
|
||||
for (int z = -range; z <= range; z++)
|
||||
for (int y = -range; y <= range; y++)
|
||||
{
|
||||
Block block = source.getRelative(x, y, z);
|
||||
|
||||
findOreFromBlock(ores, block);
|
||||
}
|
||||
|
||||
if (xrayDebug)
|
||||
for (Block debug : ores)
|
||||
System.out.println("Found " + debug.getType() + " at " + UtilWorld.locToStrClean(debug.getLocation()));
|
||||
|
||||
return ores;
|
||||
}
|
||||
|
||||
public void findOreFromBlock(ArrayList<Block> ores, Block block)
|
||||
{
|
||||
if (ores.contains(block))
|
||||
return;
|
||||
|
||||
if (isOre(block))
|
||||
else if (event.getMessage().equals("/uhcgames"))
|
||||
{
|
||||
ores.add(block);
|
||||
|
||||
for (Block neighbour : UtilBlock.getSurrounding(block, true))
|
||||
CoreClient client = getArcadeManager().GetClients().Get(event.getPlayer());
|
||||
if (client.GetRank().has(Rank.DEVELOPER))
|
||||
{
|
||||
findOreFromBlock(ores, neighbour);
|
||||
event.getPlayer().sendMessage("Games run: " + _gamesRun);
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOre(Block block)
|
||||
{
|
||||
return (block.getType() == Material.IRON_ORE || block.getType() == Material.GOLD_ORE || block.getType() == Material.DIAMOND_ORE);
|
||||
}
|
||||
|
||||
private ArrayList<ArrayList<Block>> generateVeins(ArrayList<Block> ores)
|
||||
{
|
||||
ArrayList<ArrayList<Block>> veins = new ArrayList<ArrayList<Block>>();
|
||||
|
||||
while (!ores.isEmpty())
|
||||
{
|
||||
Block block = ores.remove(0);
|
||||
|
||||
if (xrayDebug)
|
||||
System.out.println("NEW VEIN - " + block.getType());
|
||||
|
||||
// Start New Vein
|
||||
ArrayList<Block> vein = new ArrayList<Block>();
|
||||
veins.add(vein);
|
||||
vein.add(block);
|
||||
|
||||
// Find Vein Ores
|
||||
boolean addedToVein = true;
|
||||
while (addedToVein)
|
||||
{
|
||||
addedToVein = false;
|
||||
|
||||
Iterator<Block> oreIterator = ores.iterator();
|
||||
|
||||
while (oreIterator.hasNext())
|
||||
{
|
||||
Block ore = oreIterator.next();
|
||||
|
||||
boolean inVein = false;
|
||||
|
||||
// Check if in Vein
|
||||
for (Block veinOre : vein)
|
||||
{
|
||||
// if (veinOre.getType() != ore.getType())
|
||||
// continue;
|
||||
|
||||
if (UtilMath.offset(ore.getLocation(), veinOre.getLocation()) <= 2)
|
||||
{
|
||||
inVein = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to Vein
|
||||
if (inVein)
|
||||
{
|
||||
vein.add(ore);
|
||||
oreIterator.remove();
|
||||
addedToVein = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (xrayDebug)
|
||||
for (Block veinOre : vein)
|
||||
System.out.println(UtilWorld.locToStrClean(veinOre.getLocation()));
|
||||
}
|
||||
|
||||
return veins;
|
||||
}
|
||||
|
||||
private void removeNonAirVeins(ArrayList<ArrayList<Block>> oreVeins)
|
||||
{
|
||||
// Remove Non-Aired Veins
|
||||
for (ArrayList<Block> vein : oreVeins)
|
||||
{
|
||||
boolean visible = false;
|
||||
|
||||
// Check if Air is near Vein
|
||||
for (Block ore : vein)
|
||||
{
|
||||
for (Block visibleCheckBlock : UtilBlock.getSurrounding(ore, true))
|
||||
{
|
||||
if (visibleCheckBlock.getType() == Material.AIR || UtilBlock.isVisible(visibleCheckBlock))
|
||||
{
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (visible)
|
||||
break;
|
||||
}
|
||||
|
||||
if (visible)
|
||||
break;
|
||||
}
|
||||
|
||||
if (visible)
|
||||
setOreType(vein);
|
||||
|
||||
// Remove Vein
|
||||
if (!visible)
|
||||
{
|
||||
if (xrayDebug)
|
||||
System.out.println("DELETING VEIN;");
|
||||
|
||||
for (Block ore : vein)
|
||||
{
|
||||
if (xrayDebug)
|
||||
System.out.println(ore.getType() + " " + UtilWorld.locToStrClean(ore.getLocation()));
|
||||
|
||||
ore.setType(Material.STONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (xrayDebug)
|
||||
System.out.println("VALID VEIN!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOreType(ArrayList<Block> blocks)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -1,112 +1,63 @@
|
||||
package nautilus.game.arcade.game.games.uhc.modes;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.games.uhc.UHC;
|
||||
import nautilus.game.arcade.game.modules.CutCleanModule;
|
||||
import nautilus.game.arcade.game.modules.ItemGiverModule;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
/**
|
||||
* CutClean gamemode for UHC
|
||||
/*
|
||||
* The CutClean variant of UHC
|
||||
*
|
||||
* @author xXVevzZXx
|
||||
* This is identical to UHC however iron and gold ore will immediately smelt
|
||||
* and mob drops will be immediately cooked
|
||||
*/
|
||||
public class CutClean extends UHC
|
||||
{
|
||||
|
||||
private int _steakAmount;
|
||||
|
||||
private HashMap<Material, Material> _oreDrops;
|
||||
private HashMap<Material, Material> _drops;
|
||||
// The amount of steak to give at the start of the game
|
||||
private static final int STEAK_AMOUNT = 15;
|
||||
|
||||
public CutClean(ArcadeManager manager)
|
||||
{
|
||||
super(manager, GameType.Brawl);
|
||||
|
||||
_steakAmount = 15;
|
||||
registerModule(new CutCleanModule()
|
||||
.associateBlockDrop(
|
||||
Material.GOLD_ORE,
|
||||
new ItemBuilder(Material.GOLD_INGOT).build()
|
||||
)
|
||||
.associateBlockDrop(
|
||||
Material.IRON_ORE,
|
||||
new ItemBuilder(Material.IRON_INGOT).build()
|
||||
)
|
||||
.associateMobDrop(
|
||||
Material.RAW_BEEF,
|
||||
new ItemBuilder(Material.COOKED_BEEF).build()
|
||||
)
|
||||
.associateMobDrop(
|
||||
Material.RAW_CHICKEN,
|
||||
new ItemBuilder(Material.COOKED_CHICKEN).build()
|
||||
)
|
||||
.associateMobDrop(
|
||||
Material.RAW_FISH,
|
||||
new ItemBuilder(Material.COOKED_FISH).build()
|
||||
)
|
||||
.associateMobDrop(
|
||||
Material.PORK,
|
||||
new ItemBuilder(Material.GRILLED_PORK).build()
|
||||
)
|
||||
.associateMobDrop(
|
||||
Material.RABBIT,
|
||||
new ItemBuilder(Material.COOKED_RABBIT).build()
|
||||
)
|
||||
);
|
||||
|
||||
_oreDrops = new HashMap<>();
|
||||
_oreDrops.put(Material.GOLD_ORE, Material.GOLD_INGOT);
|
||||
_oreDrops.put(Material.IRON_ORE, Material.IRON_INGOT);
|
||||
|
||||
_drops = new HashMap<>();
|
||||
_drops.put(Material.RAW_BEEF, Material.COOKED_BEEF);
|
||||
_drops.put(Material.RAW_CHICKEN, Material.COOKED_CHICKEN);
|
||||
_drops.put(Material.RAW_FISH, Material.COOKED_FISH);
|
||||
_drops.put(Material.PORK, Material.GRILLED_PORK);
|
||||
_drops.put(Material.RABBIT, Material.COOKED_RABBIT);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void giveSteak(GameStateChangeEvent event)
|
||||
{
|
||||
if (event.GetState() != GameState.Live)
|
||||
return;
|
||||
|
||||
for (Player player : GetPlayers(true))
|
||||
{
|
||||
UtilInv.insert(player,
|
||||
ItemStackFactory.Instance.CreateStack(Material.COOKED_BEEF, _steakAmount));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void smeltOres(BlockBreakEvent event)
|
||||
{
|
||||
for (Material mat : _oreDrops.keySet())
|
||||
{
|
||||
if (event.getBlock().getType() == mat)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
event.getBlock().setType(Material.AIR);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(Manager.getPlugin(), new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
event.getBlock().getWorld().dropItem(
|
||||
event.getBlock().getLocation().add(0.5, 0.2, 0.5),
|
||||
new ItemStack(_oreDrops.get(mat)));
|
||||
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void smeltFood(EntityDeathEvent event)
|
||||
{
|
||||
List<ItemStack> drops = event.getDrops();
|
||||
for (Material mat : _drops.keySet())
|
||||
{
|
||||
Iterator<ItemStack> itemIterator = drops.iterator();
|
||||
while (itemIterator.hasNext())
|
||||
{
|
||||
ItemStack item = itemIterator.next();
|
||||
if (item.getType() == mat)
|
||||
{
|
||||
itemIterator.remove();
|
||||
drops.add(ItemStackFactory.Instance.CreateStack(_drops.get(mat),
|
||||
1 + UtilMath.r(3)));
|
||||
}
|
||||
}
|
||||
}
|
||||
registerModule(new ItemGiverModule()
|
||||
.withItem(new ItemStack(Material.COOKED_BEEF, STEAK_AMOUNT))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -114,5 +65,4 @@ public class CutClean extends UHC
|
||||
{
|
||||
return "Cut Clean";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,103 +1,74 @@
|
||||
package nautilus.game.arcade.game.games.uhc.modes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import mineplex.core.common.util.UtilBlock;
|
||||
import mineplex.core.common.util.UtilItem;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.GameType;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.games.uhc.UHC;
|
||||
import nautilus.game.arcade.game.modules.CutCleanModule;
|
||||
import nautilus.game.arcade.game.modules.ItemGiverModule;
|
||||
import nautilus.game.arcade.game.modules.OreVeinEditorModule;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* GodBattles gamemode for UHC
|
||||
*
|
||||
* @author xXVevzZXx
|
||||
*/
|
||||
public class GodBattles extends UHC
|
||||
{
|
||||
// The set of materials which will be considered as an ore
|
||||
private static final Set<Material> ORE_MATERIALS = Sets.newHashSet(
|
||||
Material.COAL_ORE,
|
||||
Material.REDSTONE_ORE,
|
||||
Material.IRON_ORE,
|
||||
Material.GOLD_ORE,
|
||||
Material.DIAMOND_ORE
|
||||
);
|
||||
|
||||
private ArrayList<Material> _ores;
|
||||
private HashMap<Material, Material> _oreDrops;
|
||||
// The set of materials which will act as replacements
|
||||
private static final List<Material> ORE_REPLACEMENTS = Lists.newArrayList(
|
||||
Material.GOLD_ORE,
|
||||
Material.DIAMOND_ORE
|
||||
);
|
||||
|
||||
public GodBattles(ArcadeManager manager)
|
||||
{
|
||||
super(manager, GameType.Brawl);
|
||||
|
||||
_ores = new ArrayList<>();
|
||||
registerModule(new CutCleanModule()
|
||||
.associateBlockDrop(
|
||||
Material.GOLD_ORE,
|
||||
new ItemBuilder(Material.GOLD_BLOCK).build()
|
||||
)
|
||||
);
|
||||
|
||||
_ores.add(Material.GOLD_ORE);
|
||||
_ores.add(Material.DIAMOND_ORE);
|
||||
registerModule(new ItemGiverModule()
|
||||
.withItem(UtilItem.makeUnbreakable(new ItemStack(Material.DIAMOND_PICKAXE)))
|
||||
);
|
||||
|
||||
_oreDrops = new HashMap<>();
|
||||
_oreDrops.put(Material.GOLD_ORE, Material.GOLD_BLOCK);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void blockOres(BlockBreakEvent event)
|
||||
{
|
||||
for (Material mat : _oreDrops.keySet())
|
||||
{
|
||||
if (event.getBlock().getType() == mat)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
event.getBlock().setType(Material.AIR);
|
||||
|
||||
Bukkit.getScheduler().runTaskLater(Manager.getPlugin(), new Runnable()
|
||||
registerModule(new OreVeinEditorModule()
|
||||
.useFilter(block -> ORE_MATERIALS.contains(block.getType()))
|
||||
.useEditor(vein ->
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
Material ore = ORE_REPLACEMENTS.get(UtilMath.r(ORE_REPLACEMENTS.size()));
|
||||
for (Block block : vein)
|
||||
{
|
||||
event.getBlock().getWorld().dropItem(
|
||||
event.getBlock().getLocation().add(0.5, 0.2, 0.5),
|
||||
new ItemStack(_oreDrops.get(mat)));
|
||||
|
||||
if(!ORE_REPLACEMENTS.contains(block.getType()))
|
||||
{
|
||||
if(!UtilBlock.isVisible(block))
|
||||
block.setType(ore);
|
||||
}
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void givePickaxe(GameStateChangeEvent event)
|
||||
{
|
||||
if(event.GetState() != GameState.Live)
|
||||
return;
|
||||
|
||||
for (Player player : GetPlayers(true))
|
||||
{
|
||||
player.getInventory().addItem(UtilItem.makeUnbreakable(new ItemStack(Material.DIAMOND_PICKAXE)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOreType(ArrayList<Block> blocks)
|
||||
{
|
||||
Material ore = _ores.get(UtilMath.r(_ores.size()));
|
||||
for (Block block : blocks)
|
||||
{
|
||||
if(block.getType() != Material.DIAMOND_ORE && block.getType() != Material.GOLD_ORE)
|
||||
{
|
||||
if(!UtilBlock.isVisible(block))
|
||||
block.setType(ore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOre(Block block)
|
||||
{
|
||||
return (block.getType() == Material.COAL_ORE || block.getType() == Material.REDSTONE_ORE || block.getType() == Material.IRON_ORE || block.getType() == Material.GOLD_ORE || block.getType() == Material.DIAMOND_ORE);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,5 +76,4 @@ public class GodBattles extends UHC
|
||||
{
|
||||
return "God Battles";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,107 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* This module will implement CutClean-esque features within the game.
|
||||
*
|
||||
* In particular, the CutCleanModule#associateBlockDrop and CutCleanModule#associateMobDrop methods will
|
||||
* allow you to drop different items for each block and mob killed
|
||||
*/
|
||||
public class CutCleanModule extends Module
|
||||
{
|
||||
private final EnumMap<Material, List<ItemStack>> _blockDrops = new EnumMap<>(Material.class);
|
||||
private final EnumMap<Material, List<ItemStack>> _mobDrops = new EnumMap<>(Material.class);
|
||||
|
||||
/*
|
||||
* Associates a material with a list of drops.
|
||||
*
|
||||
* Every time a block of that material is broken, the drops given will be dropped instead
|
||||
*
|
||||
* fixme does not support data ids
|
||||
*/
|
||||
public CutCleanModule associateBlockDrop(Material block, ItemStack... drops)
|
||||
{
|
||||
if (_blockDrops.containsKey(block))
|
||||
{
|
||||
throw new IllegalStateException(block + " is already registered to " + _blockDrops.get(block));
|
||||
}
|
||||
_blockDrops.put(block, new ArrayList<>(Arrays.asList(drops)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Associates a mob drop with a list of different drops
|
||||
*
|
||||
* Every time an item of the given type is dropped by a mob death, the alternative drops will be dropped instead
|
||||
*/
|
||||
public CutCleanModule associateMobDrop(Material drop, ItemStack... drops)
|
||||
{
|
||||
if (_mobDrops.containsKey(drop))
|
||||
{
|
||||
throw new IllegalStateException(drop + " is already registered to " + _mobDrops.get(drop));
|
||||
}
|
||||
_mobDrops.put(drop, new ArrayList<>(Arrays.asList(drops)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(BlockBreakEvent event)
|
||||
{
|
||||
List<ItemStack> drops = _blockDrops.get(event.getBlock().getType());
|
||||
if (drops == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
event.getBlock().setType(Material.AIR);
|
||||
|
||||
getGame().getArcadeManager().getScheduler().runTaskLater(getGame().getArcadeManager().getPlugin(), () ->
|
||||
{
|
||||
Location dropLocation = event.getBlock().getLocation().add(0.5, 0.2, 0.5);
|
||||
for (ItemStack drop : drops)
|
||||
{
|
||||
event.getBlock().getWorld().dropItem(dropLocation, drop.clone());
|
||||
}
|
||||
}, 1L);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(EntityDeathEvent event)
|
||||
{
|
||||
List<ItemStack> drops = event.getDrops();
|
||||
List<ItemStack> newDrops = new ArrayList<>();
|
||||
|
||||
Iterator<ItemStack> itemIterator = drops.iterator();
|
||||
while (itemIterator.hasNext())
|
||||
{
|
||||
ItemStack item = itemIterator.next();
|
||||
|
||||
List<ItemStack> replacements = _mobDrops.get(item.getType());
|
||||
if (replacements == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
itemIterator.remove();
|
||||
|
||||
for (ItemStack replace : replacements)
|
||||
{
|
||||
newDrops.add(replace.clone());
|
||||
}
|
||||
}
|
||||
|
||||
drops.addAll(newDrops);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilItem;
|
||||
import nautilus.game.arcade.events.GameStateChangeEvent;
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* This module will give all players specific items at the start of the game
|
||||
*/
|
||||
public class ItemGiverModule extends Module
|
||||
{
|
||||
private final List<ItemStack> _itemsToGive = new ArrayList<>();
|
||||
|
||||
public ItemGiverModule withItem(ItemStack item)
|
||||
{
|
||||
_itemsToGive.add(item.clone());
|
||||
return this;
|
||||
}
|
||||
|
||||
public ItemGiverModule withItems(ItemStack... items)
|
||||
{
|
||||
List<ItemStack> clones = new ArrayList<>();
|
||||
for (ItemStack item : items)
|
||||
{
|
||||
clones.add(item.clone());
|
||||
}
|
||||
|
||||
_itemsToGive.addAll(clones);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@EventHandler
|
||||
public void on(GameStateChangeEvent event)
|
||||
{
|
||||
if(event.GetState() != Game.GameState.Live)
|
||||
return;
|
||||
|
||||
for (Player player : getGame().GetPlayers(true))
|
||||
{
|
||||
for (ItemStack toGive : _itemsToGive)
|
||||
{
|
||||
UtilInv.insert(player, toGive.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,13 +1,34 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import nautilus.game.arcade.game.Game;
|
||||
import nautilus.game.arcade.game.TeamGame;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
/*
|
||||
* This is a Module
|
||||
*
|
||||
* A Module represents something which will enhance or change the way games can be played.
|
||||
* Modules should function independent of which specific gamemode is being played.
|
||||
* If you need game-specific features, put it into that Game implementation or refactor it into a separate class (not a module).
|
||||
*
|
||||
* Modules should never directly access other Modules via the Game instance.
|
||||
* Instead, the game which requires cross-contamination should do so itself.
|
||||
*
|
||||
* Modules should be associated per-game. Do not make them static
|
||||
*
|
||||
* If your module is able to accept custom configuration, override the configure(JsonElement) method
|
||||
* You can define the format of the json you wish to use.
|
||||
* This custom configuration will be used to dynamically adjust gamemodes via Redis if needed
|
||||
*/
|
||||
public abstract class Module implements Listener
|
||||
{
|
||||
// The game this module belongs to
|
||||
private Game _game;
|
||||
|
||||
/*
|
||||
* Initializes this module with the specific game instance. You should never do this as {@link Game} does it for you
|
||||
*/
|
||||
public void initialize(Game game)
|
||||
{
|
||||
if (_game != null)
|
||||
@ -15,13 +36,47 @@ public abstract class Module implements Listener
|
||||
throw new IllegalArgumentException("Attempting to initialize module which has already been initialized for " + _game);
|
||||
}
|
||||
this._game = game;
|
||||
this.setup();
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called once initialization is complete. Do whatever you need to do with the {@link Game} here
|
||||
*/
|
||||
protected void setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If this module can be configured via a JsonObject/JsonPrimitive, then override this method
|
||||
* to implement that feature
|
||||
*
|
||||
* You can define how the JsonElement should be formatted.
|
||||
*
|
||||
* It is recommended to have a "force" boolean which will reset this module to a clean state
|
||||
* (to allow extensive customization using json)
|
||||
*/
|
||||
public void configure(JsonElement element)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This method is called once this module is no longer needed.
|
||||
* This could be because the game is over
|
||||
* Or because this module was unregistered
|
||||
*
|
||||
* The {@link Game} will unregister this module as a listener for you.
|
||||
* All you need to do is clean up after yourself
|
||||
*/
|
||||
public void cleanup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets the game this module is associated with
|
||||
*/
|
||||
public Game getGame()
|
||||
{
|
||||
return this._game;
|
||||
|
@ -0,0 +1,219 @@
|
||||
package nautilus.game.arcade.game.modules;
|
||||
|
||||
import mineplex.core.common.util.UtilBlock;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilWorld;
|
||||
import mineplex.core.timing.TimingManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/*
|
||||
* This module will allow you to edit veins of ore live as players break them
|
||||
*/
|
||||
public class OreVeinEditorModule extends Module
|
||||
{
|
||||
// Initial range to look for veins
|
||||
// For example, if I break a block at 0,0,0 and RANGE is 3
|
||||
// Then this module will look for ores in the region of -3,-3,-3 to 3,3,3
|
||||
private static final int RANGE = 3;
|
||||
|
||||
private boolean _debug = false;
|
||||
private boolean _removeNonAirVeins = false;
|
||||
|
||||
private Predicate<Block> _predicateIsOre = block ->
|
||||
(block.getType() == Material.IRON_ORE || block.getType() == Material.GOLD_ORE || block.getType() == Material.DIAMOND_ORE);
|
||||
|
||||
private Consumer<List<Block>> _consumerOreEditor = list ->
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
public OreVeinEditorModule debug()
|
||||
{
|
||||
this._debug = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OreVeinEditorModule removeNonAirVeins()
|
||||
{
|
||||
this._removeNonAirVeins = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OreVeinEditorModule useFilter(Predicate<Block> filter)
|
||||
{
|
||||
this._predicateIsOre = filter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OreVeinEditorModule useEditor(Consumer<List<Block>> editor)
|
||||
{
|
||||
this._consumerOreEditor = editor;
|
||||
return this;
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public void on(BlockBreakEvent event)
|
||||
{
|
||||
if (_debug)
|
||||
TimingManager.start("Block Break");
|
||||
|
||||
// Find Nearby Ores
|
||||
List<Block> ores = findOres(event.getBlock(), RANGE);
|
||||
|
||||
// Anti-Xray
|
||||
removeNonAirVeins(generateVeins(ores));
|
||||
|
||||
if (_debug)
|
||||
TimingManager.stop("Block Break");
|
||||
}
|
||||
|
||||
// Searches in a range x range x range cube for ores
|
||||
private List<Block> findOres(Block source, int range)
|
||||
{
|
||||
List<Block> ores = new ArrayList<>();
|
||||
|
||||
for (int x = -range; x <= range; x++)
|
||||
for (int z = -range; z <= range; z++)
|
||||
for (int y = -range; y <= range; y++)
|
||||
findOreFromBlock(ores, source.getRelative(x, y, z));
|
||||
|
||||
if (_debug)
|
||||
for (Block debug : ores)
|
||||
System.out.println("Found " + debug.getType() + " at " + UtilWorld.locToStrClean(debug.getLocation()));
|
||||
|
||||
return ores;
|
||||
}
|
||||
|
||||
// Checks if the current block is ore
|
||||
// If so, then search all blocks around it to see if they are ores
|
||||
private void findOreFromBlock(List<Block> ores, Block block)
|
||||
{
|
||||
if (ores.contains(block))
|
||||
return;
|
||||
|
||||
if (_predicateIsOre.test(block))
|
||||
{
|
||||
ores.add(block);
|
||||
|
||||
for (Block neighbour : UtilBlock.getSurrounding(block, true))
|
||||
{
|
||||
findOreFromBlock(ores, neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<List<Block>> generateVeins(List<Block> ores)
|
||||
{
|
||||
List<List<Block>> veins = new ArrayList<>();
|
||||
|
||||
while (!ores.isEmpty())
|
||||
{
|
||||
Block block = ores.remove(0);
|
||||
|
||||
if (_debug)
|
||||
System.out.println("NEW VEIN - " + block.getType());
|
||||
|
||||
// Start New Vein
|
||||
List<Block> vein = new ArrayList<>();
|
||||
veins.add(vein);
|
||||
|
||||
vein.add(block);
|
||||
|
||||
// Find Vein Ores
|
||||
boolean addedToVein = true;
|
||||
while (addedToVein)
|
||||
{
|
||||
addedToVein = false;
|
||||
|
||||
Iterator<Block> oreIterator = ores.iterator();
|
||||
|
||||
while (oreIterator.hasNext())
|
||||
{
|
||||
Block ore = oreIterator.next();
|
||||
|
||||
boolean inVein = false;
|
||||
|
||||
// Check if in Vein
|
||||
// fixme is this a good algorithm?
|
||||
for (Block veinOre : vein)
|
||||
{
|
||||
if (UtilMath.offset(ore.getLocation(), veinOre.getLocation()) <= 2)
|
||||
{
|
||||
inVein = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to Vein
|
||||
if (inVein)
|
||||
{
|
||||
vein.add(ore);
|
||||
oreIterator.remove();
|
||||
addedToVein = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_debug)
|
||||
for (Block veinOre : vein)
|
||||
System.out.println(UtilWorld.locToStrClean(veinOre.getLocation()));
|
||||
}
|
||||
|
||||
return veins;
|
||||
}
|
||||
|
||||
private void removeNonAirVeins(List<List<Block>> oreVeins)
|
||||
{
|
||||
// Remove Non-Aired Veins
|
||||
for (List<Block> vein : oreVeins)
|
||||
{
|
||||
boolean visible = false;
|
||||
|
||||
// Check if Air is near Vein
|
||||
outer: for (Block ore : vein)
|
||||
{
|
||||
for (Block visibleCheckBlock : UtilBlock.getSurrounding(ore, true))
|
||||
{
|
||||
if (visibleCheckBlock.getType() == Material.AIR || UtilBlock.isVisible(visibleCheckBlock))
|
||||
{
|
||||
visible = true;
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (visible)
|
||||
_consumerOreEditor.accept(vein);
|
||||
|
||||
// Remove Vein
|
||||
if (!visible && _removeNonAirVeins)
|
||||
{
|
||||
if (_debug)
|
||||
System.out.println("DELETING VEIN;");
|
||||
|
||||
for (Block ore : vein)
|
||||
{
|
||||
if (_debug)
|
||||
System.out.println(ore.getType() + " " + UtilWorld.locToStrClean(ore.getLocation()));
|
||||
|
||||
ore.setType(Material.STONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_debug)
|
||||
System.out.println("VALID VEIN!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
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;
|
||||
@ -14,11 +12,14 @@ import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEntityEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TeamModule extends Module
|
||||
{
|
||||
private BiMap<UUID, UUID> _teamReqs = HashBiMap.create();
|
||||
private Map<UUID, UUID> _teamReqs = new HashMap<>();
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public void teamSelectInteract(PlayerInteractEntityEvent event)
|
||||
@ -147,8 +148,15 @@ public class TeamModule extends Module
|
||||
if (getGame().GetTeam(player) != null)
|
||||
getGame().GetTeam(player).DisbandTeam();
|
||||
|
||||
_teamReqs.remove(player.getUniqueId());
|
||||
_teamReqs.inverse().remove(player.getUniqueId());
|
||||
Iterator<Map.Entry<UUID, UUID>> iterator = _teamReqs.entrySet().iterator();
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Map.Entry<UUID, UUID> entry = iterator.next();
|
||||
if (entry.getKey().equals(player.getUniqueId()) || entry.getValue().equals(player.getUniqueId()))
|
||||
{
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GameTeam getEmptyTeam()
|
||||
|
@ -0,0 +1,111 @@
|
||||
package nautilus.game.arcade.game.modules.antixray;
|
||||
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import nautilus.game.arcade.game.modules.Module;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* This module will enable antixray for this specific game
|
||||
*
|
||||
* NOTE: The game server must also have the Mineplex Orebfuscator plugin installed
|
||||
*/
|
||||
public class AntiXrayModule extends Module
|
||||
{
|
||||
private AntiXrayService _service;
|
||||
|
||||
@Override
|
||||
protected void setup()
|
||||
{
|
||||
RegisteredServiceProvider<AntiXrayService> rsp = UtilServer.getServer().getServicesManager().getRegistration(AntiXrayService.class);
|
||||
if (rsp == null)
|
||||
{
|
||||
getGame().unregisterModule(this);
|
||||
System.out.println("!!!ERROR!!! AntiXray module was registered but the Mineplex Orebfuscator Service was not registered");
|
||||
return;
|
||||
}
|
||||
AntiXrayService service = rsp.getProvider();
|
||||
if (service == null)
|
||||
{
|
||||
getGame().unregisterModule(this);
|
||||
System.out.println("!!!ERROR!!! AntiXray module was registered but the Mineplex Orebfuscator Service was null");
|
||||
return;
|
||||
}
|
||||
_service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
_service.setEnabled(false);
|
||||
}
|
||||
|
||||
public AntiXrayModule setEnabled(boolean enabled)
|
||||
{
|
||||
_service.setEnabled(enabled);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setUpdateOnDamage(boolean updateOnDamage)
|
||||
{
|
||||
_service.setUpdateOnDamage(updateOnDamage);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setEngineMode(int engineMode)
|
||||
{
|
||||
_service.setEngineMode(engineMode);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setInitialRadius(int initialRadius)
|
||||
{
|
||||
_service.setInitialRadius(initialRadius);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setUpdateRadius(int updateRadius)
|
||||
{
|
||||
_service.setUpdateRadius(updateRadius);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setUseProximityHider(boolean useProximityHider)
|
||||
{
|
||||
_service.setUseProximityHider(useProximityHider);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setAntiTexturePacksAndFreecam(boolean antiTexturePacksAndFreecam)
|
||||
{
|
||||
_service.setAntiTexturePacksAndFreecam(antiTexturePacksAndFreecam);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setObfuscateBlocks(Material... materials)
|
||||
{
|
||||
return setObfuscateBlocks(Arrays.asList(materials));
|
||||
}
|
||||
|
||||
public AntiXrayModule setObfuscateBlocks(List<Material> materials)
|
||||
{
|
||||
_service.setObfuscateBlocks(materials);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AntiXrayModule setRandomBlocks(Material... materials)
|
||||
{
|
||||
return setRandomBlocks(Arrays.asList(materials));
|
||||
}
|
||||
|
||||
public AntiXrayModule setRandomBlocks(List<Material> materials)
|
||||
{
|
||||
_service.setRandomBlocks(materials);
|
||||
return this;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package nautilus.game.arcade.game.modules.antixray;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public interface AntiXrayService
|
||||
{
|
||||
void setEnabled(boolean enabled);
|
||||
|
||||
void setUpdateOnDamage(boolean updateOnDamage);
|
||||
|
||||
void setEngineMode(int engineMode);
|
||||
|
||||
void setInitialRadius(int initialRadius);
|
||||
|
||||
void setUpdateRadius(int updateRadius);
|
||||
|
||||
void setUseProximityHider(boolean useProximityHider);
|
||||
|
||||
void setAntiTexturePacksAndFreecam(boolean antiTexturePacksAndFreecam);
|
||||
|
||||
void setObfuscateBlocks(List<Material> materials);
|
||||
|
||||
void setRandomBlocks(List<Material> materials);
|
||||
}
|
@ -0,0 +1,339 @@
|
||||
package nautilus.game.arcade.game.modules.combatlog;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilEvent;
|
||||
import mineplex.core.common.util.UtilParser;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import nautilus.game.arcade.game.TeamGame;
|
||||
import nautilus.game.arcade.game.modules.Module;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityDeathEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.ChunkUnloadEvent;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/*
|
||||
* This module will spawn combat log NPCs for players who disconnect
|
||||
*/
|
||||
public class CombatLogModule extends Module
|
||||
{
|
||||
// The map of player UUIDs to their combat log NPCs
|
||||
private Map<UUID, CombatLogNPC> _logoutNpcs = new HashMap<>();
|
||||
|
||||
// The map of player UUIDs and who killed their combat logged NPC
|
||||
private Map<UUID, String> _killedBy = new HashMap<>();
|
||||
|
||||
// The time that combat log npcs will stay spawned for, in milliseconds
|
||||
private int _spawnTime = 60000;
|
||||
// Whether to notify the combat logged player on join if they have been killed
|
||||
private boolean _notifyPlayer = true;
|
||||
// Whether to spawn a combat log NPC for creative players
|
||||
private boolean _spawnForCreative = true;
|
||||
// The action to take once a combat logged NPC has died
|
||||
private Consumer<CombatLogNPC> _onKill = npc ->
|
||||
{
|
||||
|
||||
};
|
||||
// The action to take once a combat logged NPC has expired
|
||||
private Consumer<CombatLogNPC> _onExpire = npc ->
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
private int _locationTaskId = -1;
|
||||
|
||||
protected void setup()
|
||||
{
|
||||
_locationTaskId = Bukkit.getScheduler().runTaskTimer(getGame().getArcadeManager().getPlugin(), () ->
|
||||
{
|
||||
for (CombatLogNPC npc : _logoutNpcs.values())
|
||||
{
|
||||
getGame().GetLocationStore().put(npc.getPlayerInfo().getName(), npc.getNPC().getLocation());
|
||||
}
|
||||
}, 0L, 1L).getTaskId();
|
||||
}
|
||||
|
||||
public CombatLogModule setNotifyPlayer(boolean notifyPlayer)
|
||||
{
|
||||
this._notifyPlayer = notifyPlayer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CombatLogModule setSpawnForCreative(boolean spawnForCreative)
|
||||
{
|
||||
this._spawnForCreative = spawnForCreative;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CombatLogModule setOnDeathAction(Consumer<CombatLogNPC> action)
|
||||
{
|
||||
this._onKill = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CombatLogModule setOnExpireAction(Consumer<CombatLogNPC> action)
|
||||
{
|
||||
this._onExpire = action;
|
||||
return this;
|
||||
}
|
||||
|
||||
public CombatLogModule setCombatLogTime(int time)
|
||||
{
|
||||
this._spawnTime = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Spawns a combat log NPC for the given player if that player does not already have one
|
||||
*/
|
||||
public void spawnLogoutNpc(Player player)
|
||||
{
|
||||
if (hasLogoutNpc(player))
|
||||
return;
|
||||
if (player.getGameMode() == GameMode.CREATIVE && !_spawnForCreative)
|
||||
return;
|
||||
|
||||
CombatLogNPC npc = new CombatLogNPC(this, player, getGame().getArcadeManager());
|
||||
npc.spawn();
|
||||
_logoutNpcs.put(player.getUniqueId(), npc);
|
||||
System.out.println(String.format("Spawned combat log NPC for %s!", player.getName()));
|
||||
}
|
||||
|
||||
public boolean hasLogoutNpc(Player player)
|
||||
{
|
||||
return _logoutNpcs.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
public CombatLogNPC getLogoutNpc(Player player)
|
||||
{
|
||||
return _logoutNpcs.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void despawnLogoutNpc(Player player)
|
||||
{
|
||||
CombatLogNPC npc = getLogoutNpc(player);
|
||||
|
||||
if (npc != null)
|
||||
{
|
||||
npc.despawn();
|
||||
_logoutNpcs.remove(player.getUniqueId());
|
||||
System.out.println(String.format("Despawned combat log NPC for %s!", player.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void on(PlayerQuitEvent event)
|
||||
{
|
||||
if (getGame().InProgress() && getGame().IsAlive(event.getPlayer()))
|
||||
{
|
||||
spawnLogoutNpc(event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void on(PlayerJoinEvent event)
|
||||
{
|
||||
if (hasLogoutNpc(event.getPlayer()))
|
||||
{
|
||||
despawnLogoutNpc(event.getPlayer());
|
||||
}
|
||||
|
||||
if (_killedBy.containsKey(event.getPlayer().getUniqueId()))
|
||||
{
|
||||
String name = _killedBy.remove(event.getPlayer().getUniqueId());
|
||||
if (_notifyPlayer && name != null)
|
||||
{
|
||||
UtilPlayer.message(event.getPlayer(), F.main("Combat Log", "While you were gone, you were killed by " + ChatColor.GREEN + name + C.mBody + "."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup()
|
||||
{
|
||||
System.out.println("Killing combat log NPCs");
|
||||
|
||||
for (CombatLogNPC npc : _logoutNpcs.values())
|
||||
{
|
||||
npc.despawn();
|
||||
}
|
||||
|
||||
_logoutNpcs.clear();
|
||||
_killedBy.clear();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onChunkUnload(ChunkUnloadEvent event)
|
||||
{
|
||||
for (CombatLogNPC npc : _logoutNpcs.values())
|
||||
{
|
||||
if (npc.getNPC().getLocation().getChunk().equals(event.getChunk()))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityDeath(EntityDeathEvent event)
|
||||
{
|
||||
CombatLogNPC logoutNpc = getLogoutNpc(event.getEntity());
|
||||
|
||||
if (logoutNpc == null)
|
||||
return;
|
||||
|
||||
_onKill.accept(logoutNpc);
|
||||
logoutNpc.onDeath();
|
||||
event.getDrops().clear(); // Clear the entity's item drops. If drops are wanted they can be added
|
||||
|
||||
if (logoutNpc.getLastDamager() != null)
|
||||
{
|
||||
_killedBy.put(logoutNpc.getPlayerInfo().getUniqueId(), logoutNpc.getLastDamager().getName());
|
||||
}
|
||||
else
|
||||
{
|
||||
_killedBy.put(logoutNpc.getPlayerInfo().getUniqueId(), UtilParser.parseDamageCause(logoutNpc.getLastDamageCause()));
|
||||
}
|
||||
|
||||
|
||||
if (getGame() instanceof TeamGame)
|
||||
{
|
||||
TeamGame teamGame = (TeamGame) getGame();
|
||||
teamGame.RejoinTimes.remove(logoutNpc.getPlayerInfo().getName());
|
||||
teamGame.RejoinKit.remove(logoutNpc.getPlayerInfo().getName());
|
||||
teamGame.RejoinTeam.remove(logoutNpc.getPlayerInfo().getName());
|
||||
teamGame.RejoinHealth.remove(logoutNpc.getPlayerInfo().getName());
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onEntityDamaged(EntityDamageEvent event)
|
||||
{
|
||||
CombatLogNPC logoutNpc = getLogoutNpc(event.getEntity());
|
||||
|
||||
if (logoutNpc != null)
|
||||
{
|
||||
LivingEntity damager = UtilEvent.GetDamagerEntity(event, true);
|
||||
|
||||
Player damagerPlayer = null;
|
||||
if (damager instanceof Player)
|
||||
{
|
||||
damagerPlayer = (Player) damager;
|
||||
}
|
||||
|
||||
if (getGame() instanceof TeamGame && damagerPlayer != null)
|
||||
{
|
||||
GameTeam damagerTeam = getGame().GetTeam(damagerPlayer);
|
||||
if (damagerTeam == logoutNpc.getPlayerInfo().getTeam())
|
||||
{
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
logoutNpc.getNPC().getWorld().playSound(logoutNpc.getNPC().getLocation(), Sound.HURT_FLESH, 1, 1);
|
||||
|
||||
if (getGame() instanceof TeamGame)
|
||||
{
|
||||
getGame().getArcadeManager().runSync(() ->
|
||||
{
|
||||
((TeamGame) getGame()).RejoinHealth.put(logoutNpc.getPlayerInfo().getName(), logoutNpc.getNPC().getHealth());
|
||||
});
|
||||
}
|
||||
|
||||
logoutNpc.handleDamageEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onUpdate(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() == UpdateType.FASTER)
|
||||
{
|
||||
for (CombatLogNPC npc : _logoutNpcs.values())
|
||||
{
|
||||
npc.update();
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getType() == UpdateType.SEC)
|
||||
{
|
||||
Iterator<CombatLogNPC> iterator = _logoutNpcs.values().iterator();
|
||||
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
CombatLogNPC npc = iterator.next();
|
||||
|
||||
if (Bukkit.getPlayerExact(npc.getPlayerInfo().getName()) != null)
|
||||
{
|
||||
System.out.println("Removing NPC " + npc.getPlayerInfo().getName() + " for 1");
|
||||
npc.despawn();
|
||||
iterator.remove();
|
||||
}
|
||||
else if (!npc.isAlive())
|
||||
{
|
||||
System.out.println("Removing NPC " + npc.getPlayerInfo().getName() + " for 2");
|
||||
npc.remove();
|
||||
iterator.remove();
|
||||
}
|
||||
else if (npc.getAliveDuation() > this._spawnTime)
|
||||
{
|
||||
System.out.println("Removing NPC " + npc.getPlayerInfo().getName() + " for 3");
|
||||
_onExpire.accept(npc);
|
||||
npc.despawn();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CombatLogNPC getLogoutNpc(Entity entity)
|
||||
{
|
||||
return getLogoutNpc(entity.getEntityId());
|
||||
}
|
||||
|
||||
private CombatLogNPC getLogoutNpc(int entityId)
|
||||
{
|
||||
for (CombatLogNPC npc : _logoutNpcs.values())
|
||||
{
|
||||
if (npc.getNPC().getEntityId() == entityId)
|
||||
{
|
||||
return npc;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getSpawnTime()
|
||||
{
|
||||
return _spawnTime;
|
||||
}
|
||||
|
||||
public Collection<CombatLogNPC> getAllNPCs()
|
||||
{
|
||||
return _logoutNpcs.values();
|
||||
}
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
package nautilus.game.arcade.game.modules.combatlog;
|
||||
|
||||
import mineplex.core.common.util.UtilEnt;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.disguise.DisguiseManager;
|
||||
import mineplex.core.disguise.disguises.DisguisePlayer;
|
||||
import mineplex.core.hologram.Hologram;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Creeper;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
public class CombatLogNPC
|
||||
{
|
||||
private CombatLogModule _module;
|
||||
|
||||
private PlayerInfo _playerInfo;
|
||||
|
||||
private Hologram _hologram;
|
||||
|
||||
private DisguiseManager _disguiseManager;
|
||||
private long _spawnDate;
|
||||
private final long _endingTime;
|
||||
private double _spawnHealth;
|
||||
private double _maxHealth;
|
||||
|
||||
private LivingEntity _npc;
|
||||
|
||||
private EntityDamageEvent.DamageCause _lastDamageCause;
|
||||
private Entity _lastDamager;
|
||||
|
||||
public CombatLogNPC(CombatLogModule module, Player player, ArcadeManager arcadeManager)
|
||||
{
|
||||
this._module = module;
|
||||
|
||||
_playerInfo = new PlayerInfo(player, arcadeManager);
|
||||
|
||||
_endingTime = System.currentTimeMillis() + this._module.getSpawnTime();
|
||||
|
||||
_disguiseManager = arcadeManager.GetDisguise();
|
||||
_hologram = new Hologram(arcadeManager.getHologramManager(), player.getEyeLocation().add(0, 1, 0), "Quitting in " + UtilTime.MakeStr(Math.max(_endingTime - System.currentTimeMillis(), 0)));
|
||||
_spawnDate = 0;
|
||||
_spawnHealth = player.getHealth();
|
||||
_maxHealth = player.getMaxHealth();
|
||||
_hologram.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the {@code _npc} associated with this CombatLogNPC is killed
|
||||
* and thus drops all the owner's items.
|
||||
*/
|
||||
public void onDeath()
|
||||
{
|
||||
_disguiseManager.undisguise(_npc);
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
_hologram.setText("Quitting in " + UtilTime.MakeStr(Math.max(_endingTime - System.currentTimeMillis(), 0)));
|
||||
if (_npc != null)
|
||||
{
|
||||
_hologram.setLocation(_npc.getEyeLocation().add(0, 1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true, if the {@code _npc} associated with this CombatLogNPC is
|
||||
* alive, false otherwise.
|
||||
*/
|
||||
public boolean isAlive()
|
||||
{
|
||||
return _npc != null && !_npc.isDead();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the amount of time (in milliseconds) that this npc has been alive
|
||||
* an spawned in.
|
||||
*/
|
||||
public long getAliveDuation()
|
||||
{
|
||||
return System.currentTimeMillis() - _spawnDate;
|
||||
}
|
||||
|
||||
public void spawn()
|
||||
{
|
||||
if (_npc != null) despawn();
|
||||
|
||||
_npc = spawnNpc(getPlayer());
|
||||
_spawnDate = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void despawn()
|
||||
{
|
||||
if (_npc != null)
|
||||
{
|
||||
_npc.remove();
|
||||
_npc = null;
|
||||
_hologram.stop();
|
||||
_hologram = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void remove()
|
||||
{
|
||||
_hologram.stop();
|
||||
_hologram = null;
|
||||
}
|
||||
|
||||
public PlayerInfo getPlayerInfo()
|
||||
{
|
||||
return _playerInfo;
|
||||
}
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
return _playerInfo.getPlayer();
|
||||
}
|
||||
|
||||
private LivingEntity spawnNpc(Player player)
|
||||
{
|
||||
Location spawnLoc = player.getLocation();
|
||||
LivingEntity skel = player.getWorld().spawn(spawnLoc, Creeper.class);
|
||||
skel.setRemoveWhenFarAway(false);
|
||||
skel.setMetadata("CombatLogNPC", new FixedMetadataValue(_disguiseManager.getPlugin(), player.getUniqueId().toString()));
|
||||
skel.teleport(spawnLoc);
|
||||
skel.setMaxHealth(_maxHealth);
|
||||
skel.setHealth(_spawnHealth);
|
||||
skel.setFallDistance(player.getFallDistance());
|
||||
// fixme potion effects, mobs don't target, entity collision (setting to ghost disables arrows and fishing rods), logging while sleeping
|
||||
// best solution to spawn EntityPlayer?
|
||||
UtilEnt.Vegetate(skel);
|
||||
UtilEnt.silence(skel, true);
|
||||
|
||||
skel.getEquipment().setHelmet(player.getInventory().getHelmet());
|
||||
skel.getEquipment().setChestplate(player.getInventory().getChestplate());
|
||||
skel.getEquipment().setLeggings(player.getInventory().getLeggings());
|
||||
skel.getEquipment().setBoots(player.getInventory().getBoots());
|
||||
skel.getEquipment().setItemInHand(player.getItemInHand());
|
||||
|
||||
// Disguise
|
||||
DisguisePlayer disguise = new DisguisePlayer(skel, ((CraftPlayer) player).getHandle().getProfile());
|
||||
_disguiseManager.disguise(disguise);
|
||||
|
||||
return skel;
|
||||
}
|
||||
|
||||
public Entity getLastDamager()
|
||||
{
|
||||
return _lastDamager;
|
||||
}
|
||||
|
||||
public LivingEntity getNPC()
|
||||
{
|
||||
return this._npc;
|
||||
}
|
||||
|
||||
public void handleDamageEvent(EntityDamageEvent event)
|
||||
{
|
||||
this._lastDamageCause = event.getCause();
|
||||
if (event instanceof EntityDamageByEntityEvent)
|
||||
{
|
||||
EntityDamageByEntityEvent entityDamageByEntityEvent = (EntityDamageByEntityEvent) event;
|
||||
this._lastDamager = entityDamageByEntityEvent.getDamager();
|
||||
}
|
||||
else
|
||||
{
|
||||
this._lastDamager = null;
|
||||
}
|
||||
}
|
||||
|
||||
public EntityDamageEvent.DamageCause getLastDamageCause()
|
||||
{
|
||||
return _lastDamageCause;
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package nautilus.game.arcade.game.modules.combatlog;
|
||||
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.game.GameTeam;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerInfo
|
||||
{
|
||||
private String _playerName;
|
||||
private UUID _playerUuid;
|
||||
private List<ItemStack> _items;
|
||||
private ChatColor _teamColor = ChatColor.GRAY;
|
||||
private GameTeam _team;
|
||||
|
||||
public PlayerInfo(Player player, ArcadeManager arcadeManager)
|
||||
{
|
||||
_playerName = player.getName();
|
||||
_playerUuid = player.getUniqueId();
|
||||
_items = UtilInv.getItems(player);
|
||||
_team = arcadeManager.GetGame().GetTeam(player);
|
||||
if (_team != null)
|
||||
{
|
||||
_teamColor = _team.GetColor();
|
||||
}
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _playerName;
|
||||
}
|
||||
|
||||
public UUID getUniqueId()
|
||||
{
|
||||
return _playerUuid;
|
||||
}
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
return Bukkit.getPlayerExact(_playerName);
|
||||
}
|
||||
|
||||
public ChatColor getTeamColor()
|
||||
{
|
||||
return _teamColor;
|
||||
}
|
||||
|
||||
public GameTeam getTeam()
|
||||
{
|
||||
return _team;
|
||||
}
|
||||
|
||||
public List<ItemStack> getItems()
|
||||
{
|
||||
return this._items;
|
||||
}
|
||||
}
|
@ -1,20 +1,27 @@
|
||||
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.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextBottom;
|
||||
import mineplex.core.packethandler.IPacketHandler;
|
||||
import mineplex.core.packethandler.PacketHandler;
|
||||
import mineplex.core.packethandler.PacketInfo;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.game.Game.GameState;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.EntityTracker;
|
||||
import net.minecraft.server.v1_8_R3.EntityTrackerEntry;
|
||||
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.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Entity;
|
||||
@ -30,41 +37,37 @@ import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerToggleSneakEvent;
|
||||
import org.bukkit.event.vehicle.VehicleDamageEvent;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilMath;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilTextBottom;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import nautilus.game.arcade.ArcadeManager;
|
||||
import nautilus.game.arcade.game.Game.GameState;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
{
|
||||
private Set<UUID> _pendingSpectate = Collections.synchronizedSet(new HashSet<>());
|
||||
// A map of a player UUID to the UUID of the entity they want to spectate
|
||||
private Map<UUID, UUID> _pendingSpectate = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
ArcadeManager Manager;
|
||||
private ArcadeManager _manager;
|
||||
|
||||
public GameSpectatorManager(ArcadeManager manager)
|
||||
{
|
||||
Manager = manager;
|
||||
_manager = manager;
|
||||
|
||||
Manager.getPluginManager().registerEvents(this, Manager.getPlugin());
|
||||
_manager.getPluginManager().registerEvents(this, _manager.getPlugin());
|
||||
|
||||
Manager.getPacketHandler().addPacketHandler(this, PacketHandler.ListenerPriority.HIGH, PacketPlayOutNamedEntitySpawn.class);
|
||||
_manager.getPacketHandler().addPacketHandler(this, PacketHandler.ListenerPriority.HIGH, PacketPlayOutNamedEntitySpawn.class);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled=true)
|
||||
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
|
||||
public void interactCancel(PlayerInteractEvent event)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
if (!_manager.GetGame().IsAlive(player))
|
||||
event.setCancelled(true);
|
||||
|
||||
processClick(player, event.getAction());
|
||||
@ -72,45 +75,45 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
|
||||
public void processClick(Player player, Action action)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
if(!Manager.GetGame().AllowEntitySpectate)
|
||||
if (!_manager.GetGame().AllowEntitySpectate)
|
||||
return;
|
||||
|
||||
if(!Manager.GetGame().IsLive())
|
||||
if (!_manager.GetGame().IsLive())
|
||||
return;
|
||||
|
||||
if(player.getGameMode() != GameMode.SPECTATOR)
|
||||
if (player.getGameMode() != GameMode.SPECTATOR)
|
||||
return;
|
||||
|
||||
if(player.getSpectatorTarget() == null)
|
||||
if (player.getSpectatorTarget() == null)
|
||||
return;
|
||||
|
||||
if(!(player.getSpectatorTarget() instanceof Player))
|
||||
if (!(player.getSpectatorTarget() instanceof Player))
|
||||
return;
|
||||
|
||||
List<Player> players = Manager.GetGame().GetPlayers(true);
|
||||
List<Player> players = _manager.GetGame().GetPlayers(true);
|
||||
int currentPlayer = 0;
|
||||
for(Player otherPlayer : players)
|
||||
for (Player otherPlayer : players)
|
||||
{
|
||||
currentPlayer++;
|
||||
if(((Player) player.getSpectatorTarget()) == otherPlayer)
|
||||
if (player.getSpectatorTarget() == otherPlayer)
|
||||
break;
|
||||
}
|
||||
|
||||
if(action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK)
|
||||
if (action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK)
|
||||
currentPlayer = currentPlayer - 2;
|
||||
else
|
||||
return;
|
||||
|
||||
if(currentPlayer < 0)
|
||||
if (currentPlayer < 0)
|
||||
currentPlayer = players.size() - 1;
|
||||
|
||||
if(currentPlayer >= players.size())
|
||||
if (currentPlayer >= players.size())
|
||||
currentPlayer = 0;
|
||||
|
||||
if(players.get(currentPlayer) == null)
|
||||
if (players.get(currentPlayer) == null)
|
||||
return;
|
||||
|
||||
Player specPlayer = players.get(currentPlayer);
|
||||
@ -121,25 +124,25 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void interactEntityCancel(PlayerInteractEntityEvent event)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (Manager.GetGame().GetState() == GameState.Recruit)
|
||||
if (_manager.GetGame().GetState() == GameState.Recruit)
|
||||
{
|
||||
if (Manager.getCosmeticManager().getMountManager().isMount(event.getRightClicked()))
|
||||
if (_manager.getCosmeticManager().getMountManager().isMount(event.getRightClicked()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
if (!_manager.GetGame().IsAlive(player))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
if(Manager.GetGame().IsLive())
|
||||
if (_manager.GetGame().IsLive())
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
if (_manager.GetGame().AllowEntitySpectate)
|
||||
{
|
||||
setSpectating(player, event.getRightClicked());
|
||||
}
|
||||
@ -150,26 +153,25 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
@EventHandler
|
||||
public void updateSpecEntitys(UpdateEvent event)
|
||||
{
|
||||
if(event.getType() != UpdateType.FASTER)
|
||||
if (event.getType() != UpdateType.FASTER)
|
||||
return;
|
||||
|
||||
if(Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
if (_manager.GetGame().IsLive() || _manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
if (_manager.GetGame().AllowEntitySpectate)
|
||||
{
|
||||
for(Player player : UtilServer.getPlayers())
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
if (!_manager.GetGame().IsAlive(player))
|
||||
{
|
||||
if(player.getGameMode() == GameMode.SPECTATOR)
|
||||
if (player.getGameMode() == GameMode.SPECTATOR)
|
||||
{
|
||||
if(player.getSpectatorTarget() == null)
|
||||
if (player.getSpectatorTarget() == null)
|
||||
{
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.setAllowFlight(true);
|
||||
despectate(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,28 +183,27 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void spectatedEntityDeath(PlayerDeathEvent event)
|
||||
{
|
||||
if(Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
if (_manager.GetGame().IsLive() || _manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
if (_manager.GetGame().AllowEntitySpectate)
|
||||
{
|
||||
for(Player player : UtilServer.getPlayers())
|
||||
for (Player player : UtilServer.getPlayers())
|
||||
{
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
if (!_manager.GetGame().IsAlive(player))
|
||||
{
|
||||
if(player.getGameMode() == GameMode.SPECTATOR)
|
||||
if (player.getGameMode() == GameMode.SPECTATOR)
|
||||
{
|
||||
if(player.getSpectatorTarget() == event.getEntity())
|
||||
if (player.getSpectatorTarget() == event.getEntity())
|
||||
{
|
||||
if(Manager.GetGame().GetPlayers(true).size() >= 1)
|
||||
if (_manager.GetGame().GetPlayers(true).size() >= 1)
|
||||
{
|
||||
setSpectating(player, Manager.GetGame().GetPlayers(true).get(UtilMath.r(Manager.GetGame().GetPlayers(true).size())));
|
||||
setSpectating(player, _manager.GetGame().GetPlayers(true).get(UtilMath.r(_manager.GetGame().GetPlayers(true).size())));
|
||||
return;
|
||||
}
|
||||
player.setGameMode(GameMode.SURVIVAL);
|
||||
player.setAllowFlight(true);
|
||||
despectate(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,28 +215,53 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void dismountEntity(PlayerToggleSneakEvent event)
|
||||
{
|
||||
if(Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
if(Manager.GetGame().IsLive() || Manager.GetGame().GetState() == GameState.End)
|
||||
if (_manager.GetGame().IsLive() || _manager.GetGame().GetState() == GameState.End)
|
||||
{
|
||||
if(Manager.GetGame().AllowEntitySpectate)
|
||||
if (_manager.GetGame().AllowEntitySpectate)
|
||||
{
|
||||
if(!Manager.GetGame().IsAlive(event.getPlayer()))
|
||||
if (!_manager.GetGame().IsAlive(event.getPlayer()))
|
||||
{
|
||||
if(event.getPlayer().getGameMode() == GameMode.SPECTATOR)
|
||||
if (event.getPlayer().getGameMode() == GameMode.SPECTATOR)
|
||||
{
|
||||
event.getPlayer().setGameMode(GameMode.SURVIVAL);
|
||||
event.getPlayer().setAllowFlight(true);
|
||||
despectate(event.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* There's a reason this code is so complicated.
|
||||
*
|
||||
* Basically, when we want to set someone to spectate another entity, we send a PacketPlayOutCamera
|
||||
* However, on the client side if the entity with the id as specified in PacketPlayOutCamera doesn't exist,
|
||||
* the client simply ignores it
|
||||
* This is alright if we're talking about small games like SSM or whatever, but in bigger games like SG and UHC
|
||||
* the client does not get to keep the entire map loaded in memory
|
||||
* Therefore, there is a chance that when we call Player#setSpectatorTarget, it has no effect because the client
|
||||
* has not yet loaded the target
|
||||
*
|
||||
* To remedy this, we take a two pronged approach.
|
||||
*
|
||||
* First, we use Minecraft's internal EntityTracker to determine whether the client should have the entity loaded
|
||||
* or not (if that's out of sync we're screwed anyways so oh well)
|
||||
*
|
||||
* If the client does have it loaded, then we simply use the Bukkit API to set the spectator target
|
||||
*
|
||||
* If the client doesn't have it loaded, we add it to a map of pending spectates and let the packet handler do the rest
|
||||
*
|
||||
* If at any point the client wants to stop spectating, we immediately replace the value in the map which notifies
|
||||
* the packet handler to stop doing whatever it's doing.
|
||||
*
|
||||
* This is because the despectation code will work no matter what step of the spectating process is currently
|
||||
* being executed
|
||||
*/
|
||||
public void setSpectating(Player player, Entity target)
|
||||
{
|
||||
if (Manager.GetGame().IsAlive(player))
|
||||
if (_manager.GetGame().IsAlive(player))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -245,66 +271,78 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
if (target instanceof Player)
|
||||
{
|
||||
playerTarget = (Player) target;
|
||||
if (!Manager.GetGame().IsAlive(playerTarget))
|
||||
if (!_manager.GetGame().IsAlive(playerTarget))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_pendingSpectate.add(target.getUniqueId());
|
||||
// Not finished last spectate
|
||||
if (_pendingSpectate.containsKey(player.getUniqueId()))
|
||||
return;
|
||||
|
||||
_pendingSpectate.put(player.getUniqueId(), target.getUniqueId());
|
||||
|
||||
EntityPlayer ep = ((CraftPlayer) player).getHandle();
|
||||
EntityTracker tracker = ep.u().getTracker();
|
||||
EntityTrackerEntry entry = tracker.trackedEntities.get(target.getEntityId());
|
||||
|
||||
// If the server is tracking this entity (eg the player should have it loaded) we can spectate right away
|
||||
if (entry.trackedPlayers.contains(ep))
|
||||
{
|
||||
player.teleport(target.getLocation().add(0, 1, 0));
|
||||
|
||||
// If the player already has the entity loaded, we have to set it now
|
||||
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."));
|
||||
_pendingSpectate.remove(player.getUniqueId());
|
||||
}
|
||||
|
||||
// We still set spectating here even though it's pointless because of updateSpecEntites() above
|
||||
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)
|
||||
{
|
||||
if (Manager.GetGame() == null)
|
||||
if (_manager.GetGame() == null)
|
||||
return;
|
||||
|
||||
if (!(event.getAttacker() instanceof Player))
|
||||
return;
|
||||
|
||||
Player player = (Player)event.getAttacker();
|
||||
Player player = (Player) event.getAttacker();
|
||||
|
||||
if (!Manager.GetGame().IsAlive(player))
|
||||
if (!_manager.GetGame().IsAlive(player))
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
// Yes, there are a lot of checks for _pendingSpectate
|
||||
// This is needed because if at any point (keeping in mind this code is not executed sequentially, but with delays)
|
||||
// spectation needs to be aborted (signaled by replacing the value in _pendingSpectate)
|
||||
// Then we need to stop spectating right away
|
||||
// Otherwise the client will be out of sync
|
||||
@Override
|
||||
public void handle(PacketInfo packetInfo)
|
||||
{
|
||||
if (packetInfo.getPacket() instanceof PacketPlayOutNamedEntitySpawn)
|
||||
{
|
||||
PacketPlayOutNamedEntitySpawn packet = (PacketPlayOutNamedEntitySpawn) packetInfo.getPacket();
|
||||
if (_pendingSpectate.remove(packet.b))
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) == packet.b)
|
||||
{
|
||||
// Handle Minestrike spam race condition
|
||||
if (Manager.GetGame().IsAlive(packetInfo.getPlayer()))
|
||||
if (_manager.GetGame().IsAlive(packetInfo.getPlayer()))
|
||||
{
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
_pendingSpectate.remove(packetInfo.getPlayer().getUniqueId());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -313,31 +351,100 @@ public class GameSpectatorManager implements Listener, IPacketHandler
|
||||
EntityPlayer ep = ((CraftPlayer) packetInfo.getPlayer()).getHandle();
|
||||
NetworkManager manager = ep.playerConnection.networkManager;
|
||||
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
manager.a(packet, future ->
|
||||
{
|
||||
Manager.runSync(() ->
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(packetInfo.getPlayer(), GameMode.SPECTATOR);
|
||||
UtilServer.CallEvent(event);
|
||||
if(event.isCancelled()) {
|
||||
if (event.isCancelled())
|
||||
{
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
_pendingSpectate.remove(packetInfo.getPlayer().getUniqueId());
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
ep.playerInteractManager.setGameMode(WorldSettings.EnumGamemode.getById(GameMode.SPECTATOR.getValue()));
|
||||
ep.fallDistance = 0.0F;
|
||||
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
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);
|
||||
});
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
manager.a(new PacketPlayOutGameStateChange(3, (float) GameMode.SPECTATOR.getValue()), future2 ->
|
||||
{
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
PacketPlayOutCamera p1 = new PacketPlayOutCamera();
|
||||
p1.a = packet.a;
|
||||
|
||||
if (_pendingSpectate.get(packetInfo.getPlayer().getUniqueId()) != packet.b)
|
||||
return;
|
||||
|
||||
manager.a(p1, future3 ->
|
||||
{
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
Player playerTarget = Bukkit.getPlayer(packet.b);
|
||||
|
||||
if (playerTarget != null)
|
||||
UtilTextBottom.display(C.cGray + "You are spectating " + F.elem(_manager.GetGame().GetTeam(playerTarget).GetColor() + playerTarget.getName()) + ".", packetInfo.getPlayer());
|
||||
|
||||
UtilPlayer.message(packetInfo.getPlayer(), F.main("Game", "Sneak to stop spectating."));
|
||||
_pendingSpectate.remove(packetInfo.getPlayer().getUniqueId());
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void despectate(Player player)
|
||||
{
|
||||
// We want to override and tell any pending spectates that we are despectating now
|
||||
_pendingSpectate.put(player.getUniqueId(), player.getUniqueId());
|
||||
|
||||
PlayerGameModeChangeEvent event = new PlayerGameModeChangeEvent(player, GameMode.SURVIVAL);
|
||||
UtilServer.CallEvent(event);
|
||||
if (event.isCancelled())
|
||||
{
|
||||
_pendingSpectate.remove(player.getUniqueId());
|
||||
return;
|
||||
}
|
||||
|
||||
EntityPlayer ep = ((CraftPlayer) player).getHandle();
|
||||
ep.playerInteractManager.setGameMode(WorldSettings.EnumGamemode.getById(GameMode.SURVIVAL.getValue()));
|
||||
ep.fallDistance = 0.0F;
|
||||
NetworkManager manager = ep.playerConnection.networkManager;
|
||||
manager.a(new PacketPlayOutCamera(ep), future1 ->
|
||||
{
|
||||
manager.a(new PacketPlayOutGameStateChange(3, (float) GameMode.SURVIVAL.getValue()), future2 ->
|
||||
{
|
||||
_manager.runSync(() ->
|
||||
{
|
||||
player.setAllowFlight(true);
|
||||
_pendingSpectate.remove(player.getUniqueId());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +75,23 @@ public class GameWorldManager implements Listener
|
||||
}
|
||||
|
||||
if (Manager.GetGame() != null)
|
||||
{
|
||||
if (Manager.GetGame().WorldData != null)
|
||||
Manager.GetGame().WorldData.ChunkUnload(event);
|
||||
{
|
||||
|
||||
if (Manager.GetGame().WorldChunkUnload)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (Manager.GetGame().WorldData.World == null)
|
||||
return;
|
||||
|
||||
if (!event.getWorld().equals(Manager.GetGame().WorldData.World))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterWorld(WorldData worldData)
|
||||
|
@ -450,17 +450,6 @@ public class WorldData
|
||||
|
||||
World = null;
|
||||
}
|
||||
|
||||
public void ChunkUnload(ChunkUnloadEvent event)
|
||||
{
|
||||
if (World == null)
|
||||
return;
|
||||
|
||||
if (!event.getWorld().equals(World))
|
||||
return;
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
public void ChunkLoad(ChunkPreLoadEvent event)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user