Merge branch 'project-cosmetics' of https://github.com/Mineplex-LLC/Minecraft-PC into project-cosmetics

This commit is contained in:
LCastr0 2016-05-25 12:20:18 -03:00
commit e52ff13712
54 changed files with 1929 additions and 859 deletions

View File

@ -0,0 +1,111 @@
package mineplex.core.common.util;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* Utilities for interleaving Bukkit scheduler operations as
* intermediate and terminal operations in a {@link CompletionStage}
* pipeline.
* <p>
* Any {@link Function}s returned by methods are suitable for use
* in {@link CompletionStage#thenCompose(Function)}
*
* @see CompletableFuture#thenCompose(Function)
*/
public class BukkitFuture
{
private static final Plugin LOADING_PLUGIN = JavaPlugin.getProvidingPlugin(BukkitFuture.class);
private static void runBlocking(Runnable action)
{
Bukkit.getScheduler().runTask(LOADING_PLUGIN, action);
}
/**
* Finalize a {@link CompletionStage} by consuming its value
* on the main thread.
*
* @param action the {@link Consumer} to call on the main thread
* @return a {@link Function} to be passed as an argument to
* {@link CompletionStage#thenCompose(Function)}
* @see CompletableFuture#thenCompose(Function)
*/
public static <T> Function<T, CompletionStage<Void>> accept(Consumer<? super T> action)
{
return val ->
{
CompletableFuture<Void> future = new CompletableFuture<>();
runBlocking(() ->
{
action.accept(val);
future.complete(null);
});
return future;
};
}
/**
* Finalize a {@link CompletionStage} by executing code on the
* main thread after its completion.
*
* @param action the {@link Runnable} that will execute
* @return a {@link Function} to be passed as an argument to
* {@link CompletionStage#thenCompose(Function)}
* @see CompletableFuture#thenCompose(Function)
*/
public static <T> Function<T, CompletionStage<Void>> run(Runnable action)
{
return val ->
{
CompletableFuture<Void> future = new CompletableFuture<>();
runBlocking(() ->
{
action.run();
future.complete(null);
});
return future;
};
}
/**
* Transform a value contained within a {@link CompletionStage}
* by executing a mapping {@link Function} on the main thread.
*
* @param fn the {@link Function} used to transform the value
* @return a {@link Function} to be passed as an argument to
* {@link CompletionStage#thenCompose(Function)}
* @see CompletableFuture#thenCompose(Function)
*/
public static <T,U> Function<T, CompletionStage<U>> map(Function<? super T,? extends U> fn)
{
return val ->
{
CompletableFuture<U> future = new CompletableFuture<>();
runBlocking(() -> future.complete(fn.apply(val)));
return future;
};
}
/**
* Create a {@link CompletionStage} from a supplier executed on the
* main thread.
*
* @param supplier the supplier to run on the main thread
* @return a {@link CompletionStage} whose value will be supplied
* during the next Minecraft tick
*/
public static <T> CompletionStage<T> supply(Supplier<T> supplier)
{
CompletableFuture<T> future = new CompletableFuture<>();
runBlocking(() -> future.complete(supplier.get()));
return future;
}
}

View File

@ -10,6 +10,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.entity.CraftEntity;
import org.bukkit.entity.Entity;
import org.bukkit.util.Vector;
import com.google.common.collect.Lists;
@ -28,7 +30,12 @@ public class UtilWorld
if (chunk == null)
return "";
return chunk.getWorld().getName() + "," + chunk.getX() + "," + chunk.getZ();
return chunkToStr(chunk.getWorld().getName(), chunk.getX(), chunk.getZ());
}
public static String chunkToStr(String world, int x, int z)
{
return world + "," + x + "," + z;
}
public static String chunkToStrClean(Chunk chunk)
@ -289,4 +296,15 @@ public class UtilWorld
return startX >= minX && startZ <= maxX && endX >= minZ && endZ <= maxZ;
}
public static double distanceSquared(Entity a, Entity b)
{
if (a.getWorld() != b.getWorld())
throw new IllegalArgumentException("Different worlds: " + a.getWorld().getName() + " and " + b.getWorld().getName());
net.minecraft.server.v1_8_R3.Entity entityA = ((CraftEntity) a).getHandle();
net.minecraft.server.v1_8_R3.Entity entityB = ((CraftEntity) b).getHandle();
double dx = entityA.locX - entityB.locX;
double dy = entityA.locY - entityB.locY;
double dz = entityA.locZ - entityB.locZ;
return (dx * dx) + (dy * dy) + (dz * dz);
}
}

View File

@ -491,7 +491,7 @@ public class CoreClientManager extends MiniPlugin
}
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.MONITOR)
public void Quit(PlayerQuitEvent event)
{
// When an account is logged in to this server and the same account name logs in

View File

@ -103,6 +103,11 @@ public class Creature extends MiniPlugin
event.setDroppedExp(0);
List<ItemStack> drops = event.getDrops();
if (event.getEntity().hasMetadata("Creature.DoNotDrop"))
{
drops.clear();
return;
}
if (event.getEntityType() == EntityType.PLAYER)
drops.add(ItemStackFactory.Instance.CreateStack(Material.BONE, 1));

View File

@ -0,0 +1,291 @@
package mineplex.core.database;
import com.google.common.collect.ImmutableMap;
import mineplex.serverdata.database.DBPool;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
/**
* A SQL-backed repository supporting {@link String} keys and
* values of type {@link V}
* <p>
* Each java primitive (sans char) and String are supported by default.
* Serializing functions for any additional types can be supplied
* to {@link PlayerKeyValueRepository(String, Serializer, Deserializer)}.
* For example, if {@link String} was not supported, one could use:
* <p>
* {@code new PlayerKeyValueRepository("tableName", PreparedStatement::setString, ResultSet::getString, "VARCHAR(255)")}
* <p>
* NOTE: EACH CONSTRUCTOR IS BLOCKING, and initializes a backing table
* if one does not yet exist
*
* @param <V> The value type to use for this repository
*/
public class PlayerKeyValueRepository<V>
{
private static final ImmutableMap<Class<?>, ValueMapper<?>> PRIM_MAPPERS = ImmutableMap.<Class<?>, ValueMapper<?>>builder()
.put(String.class, new ValueMapper<>(PreparedStatement::setString, ResultSet::getString, "VARCHAR(255)"))
.put(Boolean.class, new ValueMapper<>(PreparedStatement::setBoolean, ResultSet::getBoolean, "BOOL"))
.put(Byte.class, new ValueMapper<>(PreparedStatement::setByte, ResultSet::getByte, "TINYINT"))
.put(Short.class, new ValueMapper<>(PreparedStatement::setShort, ResultSet::getShort, "SMALLINT"))
.put(Integer.class, new ValueMapper<>(PreparedStatement::setInt, ResultSet::getInt, "INTEGER"))
.put(Long.class, new ValueMapper<>(PreparedStatement::setLong, ResultSet::getLong, "BIGINT"))
.put(Float.class, new ValueMapper<>(PreparedStatement::setFloat, ResultSet::getFloat, "REAL"))
.put(Double.class, new ValueMapper<>(PreparedStatement::setDouble, ResultSet::getDouble, "DOUBLE"))
.build();
private final String _tableName;
private final ValueMapper<V> _mapper;
/**
* Build a PlayerKeyValueRepository with the given class'
* built-in deserializer.
*
* @param tableName the underlying table's name
* @param clazz the type of values to used
* @throws IllegalArgumentException if the provided class isn't a supported type
*/
@SuppressWarnings("unchecked") // java's generics are garbage.
public PlayerKeyValueRepository(String tableName, Class<V> clazz) // we could infer the type parameter at runtime, but it's super ugly
{
this(tableName, (ValueMapper<V>) PRIM_MAPPERS.get(clazz));
}
/**
* Build a PlayerKeyValueRepository with an explicit deserializer.
* This is the constructor to use if the type you're deserializing
* isn't supported by default.
*
* @param tableName the underlying table's name
* @param serializer the serializing function used to insert values
* @param deserializer the deserializing function used to retrieve
* values
* @param columnDef the value type's SQL datatype declaration, e.g., {@code "VARCHAR(255)"} for Strings.
*/
public PlayerKeyValueRepository(String tableName, Serializer<V> serializer, Deserializer<V> deserializer, String columnDef)
{
this(tableName, new ValueMapper<V>(serializer, deserializer, columnDef));
}
private PlayerKeyValueRepository(String tableName, ValueMapper<V> mapper)
{
this._tableName = tableName;
this._mapper = mapper;
// Create a table to back this repository
try (Connection conn = DBPool.getAccount().getConnection())
{
Statement stmt = conn.createStatement();
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS " + _tableName + "("
+ "accountId INT NOT NULL,"
+ "kvKey VARCHAR(255) NOT NULL,"
+ "kvValue " + _mapper._columnDef + ","
+ "PRIMARY KEY (accountId,kvKey),"
+ "INDEX acc_ind (accountId),"
+ "FOREIGN KEY (accountId) REFERENCES accounts(id) ON DELETE NO ACTION ON UPDATE NO ACTION"
+ ")");
}
catch (SQLException e)
{
e.printStackTrace();
}
}
/**
* Get all value for a player's key
*
* @param uuid the {@link UUID} of the player
* @return a CompletableFuture containing all key/value pairs
* associated with the player
*/
public CompletableFuture<V> get(UUID uuid, String key)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("SELECT kvValue FROM " + _tableName + " WHERE accountId = (SELECT id FROM accounts WHERE uuid=?) AND kvKey=?");
stmt.setString(1, uuid.toString());
stmt.setString(2, key);
ResultSet set = stmt.executeQuery();
if (set.next())
{
return _mapper._deserializer.read(set, 1);
}
return null;
} catch (SQLException ignored) {}
return null; // yuck
});
}
/**
* Get all key/value pairs for a player
*
* @param uuid the {@link UUID} of the player
* @return a CompletableFuture containing all key/value pairs
* associated with the player
*/
public CompletableFuture<Map<String,V>> getAll(UUID uuid)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("SELECT kvKey, kvValue FROM " + _tableName + " WHERE accountId = (SELECT id FROM accounts WHERE uuid=?)");
stmt.setString(1, uuid.toString());
ResultSet set = stmt.executeQuery();
Map<String, V> results = new HashMap<>();
while (set.next())
{
results.put(set.getString(1), _mapper._deserializer.read(set, 2));
}
return results;
} catch (SQLException ignored) {}
return new HashMap<>(); // yuck
});
}
/**
* Insert a key/value pair for a player
*
* @param uuid the {@link UUID} of the player
* @param key the key to insert
* @param value the value to insert
* @return a {@link CompletableFuture} whose value indicates
* success or failure
*/
public CompletableFuture<Boolean> put(UUID uuid, String key, V value)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("REPLACE INTO " + _tableName + " (accountId, kvKey, kvValue) SELECT accounts.id, ?, ? FROM accounts WHERE uuid=?");
stmt.setString(1, key);
_mapper._serializer.write(stmt, 2, value);
stmt.setString(3, uuid.toString());
stmt.executeUpdate();
return true;
} catch (SQLException ignored) {}
return false;
});
}
/**
* Insert many key/value pairs for a player
*
* @param uuid the {@link UUID} of the player
* @param values the map whose entries will be inserted for the
* player
* @return a {@link CompletableFuture} whose value indicates
* success or failure
*/
public CompletableFuture<Boolean> putAll(UUID uuid, Map<String,V> values)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("REPLACE INTO " + _tableName + " (accountId, kvKey, kvValue) SELECT accounts.id, ?, ? FROM accounts WHERE uuid=?");
stmt.setString(3, uuid.toString());
for (Map.Entry<String, V> entry : values.entrySet())
{
stmt.setString(1, entry.getKey());
_mapper._serializer.write(stmt, 2, entry.getValue());
stmt.addBatch();
}
stmt.executeBatch();
return true;
} catch (SQLException ignored) {}
return false;
});
}
/**
* Remove a key's value for a player
*
* @param uuid the {@link UUID} of the player
* @param key the key to remove
* @return a {@link CompletableFuture} whose value indicates
* success or failure
*/
public CompletableFuture<Boolean> remove(UUID uuid, String key)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("DELETE FROM " + _tableName + " WHERE accountId=(SELECT id FROM accounts WHERE uuid=?) AND kvKey=?");
stmt.setString(1, uuid.toString());
stmt.setString(2, key);
stmt.executeUpdate();
return true;
} catch (SQLException ignored) {}
return false;
});
}
/**
* Remove all key/value pairs for a player
*
* @param uuid the {@link UUID} of the player
* @return a {@link CompletableFuture} whose value indicates
* success or failure
*/
public CompletableFuture<Boolean> removeAll(UUID uuid)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = DBPool.getAccount().getConnection())
{
PreparedStatement stmt = conn.prepareStatement("DELETE FROM " + _tableName + " WHERE accountId=(SELECT id FROM accounts WHERE uuid=?)");
stmt.setString(1, uuid.toString());
stmt.executeUpdate();
return true;
} catch (SQLException ignored) {}
return false;
});
}
private static class ValueMapper<V>
{
private final Serializer<V> _serializer;
private final Deserializer<V> _deserializer;
private final String _columnDef;
private ValueMapper(Serializer<V> serializer, Deserializer<V> deserializer, String columnDef)
{
_serializer = serializer;
_deserializer = deserializer;
_columnDef = columnDef;
}
}
@FunctionalInterface
public interface Serializer<V>
{
void write(PreparedStatement statement, int index, V value) throws SQLException;
}
@FunctionalInterface
public interface Deserializer<V>
{
V read(ResultSet resultSet, int index) throws SQLException;
}
}

View File

@ -1,47 +0,0 @@
package mineplex.core.incognito.events;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/**
* Called when an Incognito player is getting hidden from all other players.
*/
public class IncognitoHidePlayerEvent extends Event
{
private static final HandlerList handlers = new HandlerList();
private Player _player;
private boolean _cancelled;
public IncognitoHidePlayerEvent(Player player)
{
_player = player;
}
public Player getPlayer()
{
return _player;
}
public void setCancelled(boolean cancelled)
{
_cancelled = cancelled;
}
public boolean isCancelled()
{
return _cancelled;
}
public HandlerList getHandlers()
{
return handlers;
}
public static HandlerList getHandlerList()
{
return handlers;
}
}

View File

@ -1,73 +1,72 @@
package mineplex.game.clans;
import com.google.common.collect.Sets;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.UtilItem;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.Set;
public class Farming extends MiniPlugin
{
private static final Set<Material> PLANTABLE = Sets.newHashSet(
Material.WHEAT,
Material.SUGAR_CANE_BLOCK,
Material.PUMPKIN_STEM,
Material.MELON_STEM,
Material.COCOA,
Material.CARROT,
Material.POTATO
);
public Farming(JavaPlugin plugin)
{
super("Farming", plugin);
}
@EventHandler
@EventHandler (ignoreCancelled = true)
public void BlockBreak(BlockBreakEvent event)
{
if (event.isCancelled())
return;
if (event.getBlock().getType() != Material.LEAVES)
return;
if (event.getPlayer().getItemInHand() != null)
if (event.getPlayer().getItemInHand().getType() == Material.SHEARS)
return;
if (UtilItem.matchesMaterial(event.getPlayer().getItemInHand(), Material.SHEARS))
return;
Location dropLocation = event.getBlock().getLocation().add(0.5, 0.5, 0.5);
if (Math.random() > 0.9)
event.getBlock().getWorld().dropItemNaturally(
event.getBlock().getLocation().add(0.5, 0.5, 0.5),
ItemStackFactory.Instance.CreateStack(Material.APPLE));
event.getBlock().getWorld().dropItemNaturally(dropLocation, ItemStackFactory.Instance.CreateStack(Material.APPLE));
if (Math.random() > 0.999)
event.getBlock().getWorld().dropItemNaturally(
event.getBlock().getLocation().add(0.5, 0.5, 0.5),
ItemStackFactory.Instance.CreateStack(Material.GOLDEN_APPLE));
event.getBlock().getWorld().dropItemNaturally(dropLocation, ItemStackFactory.Instance.CreateStack(Material.GOLDEN_APPLE));
}
@SuppressWarnings("deprecation")
@EventHandler
@EventHandler (ignoreCancelled = true)
public void BlockPlace(BlockPlaceEvent event)
{
if (event.isCancelled())
if (!PLANTABLE.contains(event.getBlock().getType()))
return;
if (
event.getBlock().getTypeId() != 59 &&
event.getBlock().getTypeId() != 83 &&
event.getBlock().getTypeId() != 104 &&
event.getBlock().getTypeId() != 105 &&
event.getBlock().getTypeId() != 127 &&
event.getBlock().getTypeId() != 141 &&
event.getBlock().getTypeId() != 142
)
return;
double blockY = event.getBlock().getLocation().getY();
double seaLevel = event.getBlock().getWorld().getSeaLevel();
if (event.getBlock().getLocation().getY() < event.getBlock().getWorld().getSeaLevel() - 12)
if (blockY < seaLevel - 12)
{
UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot plant " +
F.item(ItemStackFactory.Instance.GetName(event.getPlayer().getItemInHand(), true)) + " this deep underground."));
event.setCancelled(true);
}
else if (event.getBlock().getLocation().getY() > event.getBlock().getWorld().getSeaLevel() + 24)
else if (blockY > seaLevel + 24)
{
UtilPlayer.message(event.getPlayer(), F.main(getName(), "You cannot plant " +
F.item(ItemStackFactory.Instance.GetName(event.getPlayer().getItemInHand(), true)) + " at this altitude."));

View File

@ -114,7 +114,6 @@ public class ClansAdmin
UtilPlayer.message(caller, F.help("/c x demote <player>", "Demote Player in Mimic", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x kick <player>", "Kick Player from Mimic", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x ally <clan>", "Send Alliance to Mimic", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x trust <clan>", "Give Trust to Clan", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x neutral <clan>", "Set Neutrality", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x enemy <clan>", "Start Invasion", Rank.CMOD));
UtilPlayer.message(caller, F.help("/c x rename <name>", "Change the name of Mimic", Rank.CMOD));
@ -379,12 +378,6 @@ public class ClansAdmin
if (target == null)
return;
if (target.getName().equals(caller.getName()))
{
UtilPlayer.message(caller, F.main("Clans Admin", "You cannot invite yourself."));
return;
}
//Inform
clan.inform(caller.getName() + " invited " + target.getName() + " to join Clan " + clan.getName() + ".", caller.getName());
UtilPlayer.message(caller, F.main("Clans Admin", "You invited " + target.getName() + " to join " + F.elem("Clan " + clan.getName()) + "."));

View File

@ -303,16 +303,40 @@ public class ClansGame extends MiniPlugin
UtilPlayer.message(player, F.main("Clans", "You cannot place blocks in " + F.elem("Borderlands") + "."));
return;
}
// Banners/String
if (player.getGameMode() != GameMode.CREATIVE && player.getItemInHand() != null)
{
if (player.getItemInHand().getType() == Material.BANNER || player.getItemInHand().getType() == Material.STRING)
{
Location destLocation = event.getClickedBlock().getRelative(event.getBlockFace()).getLocation();
ClanTerritory territory = _clans.getClanUtility().getClaim(destLocation);
if (territory != null)
{
if (territory.Owner.equals("Shops") || territory.Owner.equals("Fields") || territory.Owner.equals("Spawn") || territory.Owner.equals("Borderlands")) {
// Disallow
event.setCancelled(true);
// Inform
UtilPlayer.message(player, F.main("Clans", "You cannot place that in " + F.elem(_clans.getClanUtility().getOwnerStringRel(destLocation, player)) + "."));
return;
}
}
}
}
ClanRelation access = _clans.getClanUtility().getAccess(player, loc);
ClanInfo clan = _clans.getClan(player);
ClanInfo mimicClan = _clans.getClanAdmin().getMimic(player, false);
ClanInfo blockClan = _clans.getClanUtility().getClaim(loc) == null ? null : _clans.getClan(_clans.getClanUtility().getClaim(loc).Owner);
if (blockClan.equals(mimicClan)) access = ClanRelation.SELF;
// Doors, chests, & furnaces
if (blockClan != null && !blockClan.equals(clan) && (event.getAction() == Action.RIGHT_CLICK_BLOCK && (loc.getBlock().getType().name().contains("DOOR") || UtilItem.doesHaveGUI(loc.getBlock().getType()))))
if (blockClan != null && (!blockClan.equals(clan) && !blockClan.equals(mimicClan)) && (event.getAction() == Action.RIGHT_CLICK_BLOCK && (loc.getBlock().getType().name().contains("DOOR") || UtilItem.doesHaveGUI(loc.getBlock().getType()))))
{
UtilPlayer.message(player, F.main("Clans", "You are not allowed to use that here."));
event.setCancelled(true);
return;
}
// Hoe Return

View File

@ -44,7 +44,7 @@ import mineplex.game.clans.clans.commands.*;
import mineplex.game.clans.clans.data.PlayerClan;
import mineplex.game.clans.clans.event.ClansPlayerDeathEvent;
import mineplex.game.clans.clans.gui.ClanShop;
import mineplex.game.clans.clans.invsee.Invsee;
import mineplex.game.clans.clans.invsee.InvseeManager;
import mineplex.game.clans.clans.loot.LootManager;
import mineplex.game.clans.clans.map.ItemMapManager;
import mineplex.game.clans.clans.nameblacklist.ClansBlacklist;
@ -260,7 +260,7 @@ public class ClansManager extends MiniClientPlugin<ClientClan>implements IRelati
new TntGeneratorManager(plugin, this);
new SupplyDropManager(plugin, this);
new Invsee(this);
new InvseeManager(this);
_explosion = new Explosion(plugin, blockRestore);
_warPointEvasion = new WarPointEvasion(plugin);
@ -555,19 +555,6 @@ public class ClansManager extends MiniClientPlugin<ClientClan>implements IRelati
_classManager.GetRepository().SaveCustomBuild(activeBuild);
}
}
@EventHandler
public void onPlayerKick(PlayerKickEvent event)
{
// Players using wind blade should not get kicked
if (event.getPlayer().getItemInHand() != null && event.getPlayer().getItemInHand().getItemMeta() != null && (C.cGold + "Wind Blade").equals(event.getPlayer().getItemInHand().getItemMeta().getDisplayName()))
{
if (event.getReason().contains("flying is not enabled"))
{
event.setCancelled(true);
}
}
}
@EventHandler
public void StaffIncognito(IncognitoStatusChangeEvent event)
@ -1175,7 +1162,7 @@ public class ClansManager extends MiniClientPlugin<ClientClan>implements IRelati
@EventHandler
public void hubCommand(PlayerCommandPreprocessEvent event)
{
if (event.getMessage().toLowerCase().startsWith("/lobby") || event.getMessage().toLowerCase().startsWith("/hub") || event.getMessage().toLowerCase().startsWith("/leave"))
if (event.getMessage().toLowerCase().equals("/lobby") || event.getMessage().toLowerCase().equals("/hub") || event.getMessage().toLowerCase().equals("/leave"))
{
Portal.getInstance().sendPlayerToServer(event.getPlayer(), "Lobby");
event.setCancelled(true);

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
@ -28,6 +29,11 @@ import mineplex.game.clans.spawn.Spawn;
public class ClansUtility
{
// The maximum number of clans to search before exiting early. Inclusive
private static final int MAX_CLAN_SEARCH = 10;
// The maximum number of players to search before exiting early. Inclusive
private static final int MAX_PLAYER_SEARCH = 10;
private ClansManager _clansManager;
public ClansUtility(ClansManager clans)
@ -113,55 +119,79 @@ public class ClansUtility
public ClanInfo searchClanPlayer(Player caller, String name, boolean inform)
{
// CLAN
LinkedList<ClanInfo> clanMatchList = new LinkedList<ClanInfo>();
List<ClanInfo> clanMatchList = new ArrayList<>(MAX_CLAN_SEARCH);
for (ClanInfo cur : _clansManager.getClanMap().values())
{
if (cur.getName().equalsIgnoreCase(name)) return cur;
if (cur.getName().toLowerCase().contains(name.toLowerCase())) clanMatchList.add(cur);
if (clanMatchList.size() > MAX_CLAN_SEARCH) break;
}
if (clanMatchList.size() == 1) return clanMatchList.get(0);
// No / Non-Unique
String clanMatchString = "None";
if (clanMatchList.size() > 1)
{
for (ClanInfo cur : clanMatchList)
clanMatchString += cur.getName() + " ";
}
// PLAYER
LinkedList<ClanInfo> playerMatchList = new LinkedList<ClanInfo>();
for (ClanInfo clanInfo : _clansManager.getClanMap().values())
List<ClanInfo> playerMatchList = new ArrayList<>(MAX_PLAYER_SEARCH);
outer: for (ClanInfo clanInfo : _clansManager.getClanMap().values())
{
for (ClansPlayer player : clanInfo.getMembers().values())
{
if (player.getPlayerName().equalsIgnoreCase(name)) return clanInfo;
if (player.getPlayerName().toLowerCase().contains(name.toLowerCase())) playerMatchList.add(clanInfo);
if (player.getPlayerName().toLowerCase().contains(name.toLowerCase()))
{
playerMatchList.add(clanInfo);
// No duplicate results please
continue outer;
}
if (playerMatchList.size() > MAX_PLAYER_SEARCH) break outer;
}
}
if (playerMatchList.size() == 1) return playerMatchList.get(0);
// No / Non-Unique
String playerMatchString = "None";
if (playerMatchList.size() > 1)
{
for (ClanInfo cur : playerMatchList)
playerMatchString += cur.getName() + " ";
}
if (inform)
{
UtilPlayer.message(caller, F.main("Clan Search", "" + C.mCount + (clanMatchList.size() + playerMatchList.size()) + C.mBody + " matches for [" + C.mElem + name + C.mBody + "]."));
UtilPlayer.message(caller, F.desc("Matches via Clan", clanMatchString));
UtilPlayer.message(caller, F.desc("Matches via Player", playerMatchString));
if (clanMatchList.size() > MAX_CLAN_SEARCH)
{
UtilPlayer.message(caller, F.main("Clan Search", "Too many clans matched. Try a more specific search"));
}
else if (clanMatchList.size() == 0)
{
UtilPlayer.message(caller, F.main("Clan Search", "No clans matched. Try a more specific search"));
}
else
{
StringBuilder clanMatchString = new StringBuilder();
for (ClanInfo clanInfo : clanMatchList)
{
clanMatchString.append(clanInfo.getName()).append(" ");
}
UtilPlayer.message(caller, F.desc("Matches via Clan", clanMatchString.toString()));
}
if (playerMatchList.size() > MAX_PLAYER_SEARCH)
{
UtilPlayer.message(caller, F.main("Clan Search", "Too many players matched. Try a more specific search"));
}
else if (playerMatchList.size() == 0)
{
UtilPlayer.message(caller, F.main("Clan Search", "No players matched. Try a more specific search"));
}
else
{
StringBuilder playerMatchString = new StringBuilder();
for (ClanInfo clanInfo : playerMatchList)
{
playerMatchString.append(clanInfo.getName()).append(" ");
}
UtilPlayer.message(caller, F.desc("Matches via Player", playerMatchString.toString()));
}
}
return null;
@ -259,9 +289,15 @@ public class ClansUtility
public boolean isSafe(Location loc)
{
if (!_clansManager.getClaimMap().containsKey(UtilWorld.chunkToStr(loc.getChunk()))) return false;
// Fix for PC-279
// Do not change to getChunk
// PlayerList#updatePlayers -> iterator -> PlayerVelocityEvent -> getChunk -> loadChunk -> loadPersistentEntities -> addTracker -> ITERATE ON SAME SET
int chunkX = loc.getBlockX() >> 4;
int chunkZ = loc.getBlockZ() >> 4;
String chunkStr = UtilWorld.chunkToStr(loc.getWorld().getName(), chunkX, chunkZ);
if (!_clansManager.getClaimMap().containsKey(chunkStr)) return false;
return _clansManager.getClaimMap().get(UtilWorld.chunkToStr(loc.getChunk())).isSafe(loc);
return _clansManager.getClaimMap().get(chunkStr).isSafe(loc);
}
public boolean isChunkHome(ClanInfo clan, Chunk chunk)

View File

@ -233,7 +233,6 @@ public class ClansCommand extends CommandBase<ClansManager>
UtilPlayer.message(caller, F.help("/c neutral <clan>", "Request Neutrality with Clan", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/c enemy <clan>", "Declare ClanWar with Clan", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/c ally <clan>", "Send Alliance to Clan", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/c trust <clan>", "Give Trust to Clan", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/c claim", "Claim Territory", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/c unclaim (all)", "Unclaim Territory", Rank.ADMIN));

View File

@ -269,26 +269,33 @@ public class ClanMainPage extends ClanPageBase
{
String enemyName = clanWar.getClanA().equals(clan.getName()) ? clanWar.getClanB() : clanWar.getClanA();
final ClanInfo enemy = getPlugin().getClan(enemyName);
String itemName = enemyName;
Material material = USE_RESOURCE_ICONS ? ClanIcon.WAR.getMaterial() : Material.DIAMOND_SWORD;
byte data = USE_RESOURCE_ICONS ? ClanIcon.WAR.getData() : 0;
int warPoints = clanWar.getPoints(clan.getName());
ArrayList<String> lore = new ArrayList<String>(5);
lore.add(" ");
lore.add(C.Reset + C.cYellow + "War Points " + clan.getFormattedWarPoints(enemy));
lore.add(" ");
lore.add(ChatColor.RESET + C.cGray + "Left Click " + C.cWhite + "Clan Info");
ShopItem shopItem = new ShopItem(material, data, itemName, lore.toArray(new String[0]), 0, false, false);
addButtonFakeCount(slot, shopItem, new IButton()
if (enemy != null)
{
@Override
public void onClick(Player player, ClickType clickType)
String itemName = enemyName;
Material material = USE_RESOURCE_ICONS ? ClanIcon.WAR.getMaterial() : Material.DIAMOND_SWORD;
byte data = USE_RESOURCE_ICONS ? ClanIcon.WAR.getData() : 0;
int warPoints = clanWar.getPoints(clan.getName());
ArrayList<String> lore = new ArrayList<String>(5);
lore.add(" ");
lore.add(C.Reset + C.cYellow + "War Points " + clan.getFormattedWarPoints(enemy));
lore.add(" ");
lore.add(ChatColor.RESET + C.cGray + "Left Click " + C.cWhite + "Clan Info");
ShopItem shopItem = new ShopItem(material, data, itemName, lore.toArray(new String[0]), 0, false, false);
addButtonFakeCount(slot, shopItem, new IButton()
{
getShop().openPageForPlayer(player, new ClanWhoPage(getPlugin(), getShop(), getClientManager(), getDonationManager(), player, enemy, true));
}
}, warPoints);
@Override
public void onClick(Player player, ClickType clickType)
{
getShop().openPageForPlayer(player, new ClanWhoPage(getPlugin(), getShop(), getClientManager(), getDonationManager(), player, enemy, true));
}
}, warPoints);
}
else
{
System.err.println("Could not find enemy clan: " + enemyName);
}
}
private void addAllyButton(int slot, final ClanInfo ally)

View File

@ -1,23 +0,0 @@
package mineplex.game.clans.clans.invsee;
import mineplex.core.MiniPlugin;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.invsee.commands.InvseeCommand;
public class Invsee extends MiniPlugin
{
private ClansManager _clansManager;
public Invsee(ClansManager clansManager)
{
super("Inventory Viewer", clansManager.getPlugin());
_clansManager = clansManager;
}
public void addCommands()
{
addCommand(new InvseeCommand(this));
}
}

View File

@ -0,0 +1,63 @@
package mineplex.game.clans.clans.invsee;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.UtilServer;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.invsee.commands.InvseeCommand;
import mineplex.game.clans.clans.invsee.ui.InvseeInventory;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class InvseeManager extends MiniPlugin
{
private final Map<UUID, InvseeInventory> _viewing = new HashMap<>();
public InvseeManager(ClansManager manager)
{
super("Invsee Manager", manager.getPlugin());
}
@Override
public void addCommands()
{
addCommand(new InvseeCommand(this));
}
public void doInvsee(OfflinePlayer target, Player requester)
{
InvseeInventory invseeInventory = _viewing.computeIfAbsent(target.getUniqueId(), key -> new InvseeInventory(this, target));
invseeInventory.addAndShowViewer(requester);
}
public boolean isBeingInvseen(OfflinePlayer player)
{
return _viewing.containsKey(player.getUniqueId());
}
public boolean isInvseeing(Player player)
{
for (InvseeInventory invseeInventory : _viewing.values())
{
if (invseeInventory.isViewer(player))
{
return true;
}
}
return false;
}
public void close(UUID target)
{
InvseeInventory invseeInventory = _viewing.remove(target);
if (invseeInventory == null)
{
log("Expected non-null inventory when closing " + target);
return;
}
UtilServer.Unregister(invseeInventory);
}
}

View File

@ -1,50 +1,94 @@
package mineplex.game.clans.clans.invsee.commands;
import com.mojang.authlib.GameProfile;
import mineplex.core.command.CommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.game.clans.clans.invsee.Invsee;
import mineplex.game.clans.clans.invsee.ui.InvseeInventory;
import mineplex.game.clans.clans.invsee.InvseeManager;
import net.minecraft.server.v1_8_R3.MinecraftServer;
import net.minecraft.server.v1_8_R3.NBTTagCompound;
import net.minecraft.server.v1_8_R3.WorldNBTStorage;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
public class InvseeCommand extends CommandBase<Invsee>
import java.util.UUID;
public class InvseeCommand extends CommandBase<InvseeManager>
{
public InvseeCommand(Invsee plugin)
public InvseeCommand(InvseeManager plugin)
{
super(plugin, Rank.ADMIN, "invsee");
}
@SuppressWarnings("deprecation")
@Override
public void Execute(Player caller, String[] args)
{
if (args.length == 0)
{
UtilPlayer.message(caller, F.help("/invsee <Player>", "View a player's inventory", Rank.ADMIN));
UtilPlayer.message(caller, F.help("/invsee <playername/playeruuid>", "View a player's inventory", Rank.ADMIN));
return;
}
else
UUID uuid = null;
try
{
String name = args[0];
uuid = UUID.fromString(args[0]);
}
catch (IllegalArgumentException failed)
{
}
OfflinePlayer player = Bukkit.getServer().getPlayer(name);
if (player == null)
OfflinePlayer exactPlayer = Bukkit.getServer().getPlayerExact(args[0]);
if (exactPlayer == null)
{
if (uuid == null)
{
player = Bukkit.getServer().getOfflinePlayer(name);
// We don't want to open the wrong OfflinePlayer's inventory, so if we can't fetch the UUID then abort
GameProfile gameProfile = MinecraftServer.getServer().getUserCache().getProfile(args[0]);
if (gameProfile == null)
{
UtilPlayer.message(caller, F.main("Invsee", "Player is offline and we could not find the UUID. Aborting"));
return;
}
uuid = gameProfile.getId();
}
if (player == null)
if (uuid == null)
{
UtilPlayer.message(caller, F.main("Clans", "Specified player is neither online nor offline. Perhaps they changed their name?"));
UtilPlayer.message(caller, F.main("Invsee", "Something has gone very wrong. Please report the username/uuid you tried to look up"));
return;
}
new InvseeInventory(player).ShowTo(caller);
// We need to check if we actually have data on this player
// fixme main thread file IO but it's what the server does...?
NBTTagCompound compound = ((WorldNBTStorage) MinecraftServer.getServer().worlds.get(0).getDataManager()).getPlayerData(uuid.toString());
if (compound == null)
{
UtilPlayer.message(caller, F.main("Invsee", "The player exists, but has never joined this server. No inventory to show"));
return;
}
exactPlayer = Bukkit.getServer().getOfflinePlayer(uuid);
}
if (exactPlayer == null)
{
UtilPlayer.message(caller, F.main("Invsee", "Could not load offline player data. Does the player exist?"));
return;
}
if (exactPlayer.getUniqueId().equals(caller.getUniqueId()))
{
UtilPlayer.message(caller, F.main("Invsee", "You cannot invsee yourself!"));
return;
}
if (Plugin.isBeingInvseen(caller))
{
UtilPlayer.message(caller, F.main("Invsee", "You cannot use invsee right now. Someone is invseeing you!"));
return;
}
if (exactPlayer.isOnline() && Plugin.isInvseeing((Player) exactPlayer))
{
UtilPlayer.message(caller, F.main("Invsee", "You cannot use invsee right now. That person is currently using invsee!"));
return;
}
Plugin.doInvsee(exactPlayer, caller);
}
}

View File

@ -1,99 +1,407 @@
package mineplex.game.clans.clans.invsee.ui;
import mineplex.core.common.util.*;
import mineplex.core.itemstack.ItemStackFactory;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.invsee.InvseeManager;
import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftInventory;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.*;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilCollections;
import mineplex.core.common.util.UtilServer;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
public class InvseeInventory implements Listener
{
private OfflinePlayer _player;
private final InvseeManager _invseeManager;
// This is the UUID of the target player. This should stay constant. Use this for comparison
private final UUID _uuid;
// This is the current player. It will switch when the player joins/quits
private OfflinePlayer _targetPlayer;
// This is the inventory of said player. If the player is not online then this inventory is a fake PlayerInventory
private net.minecraft.server.v1_8_R3.PlayerInventory _playerInventory;
// This is the set of all admins viewing this player
private Set<Player> _viewers = new HashSet<>();
// This is the inventory that all admins will be looking at
private Inventory _inventory;
private boolean _online;
private Player _admin;
public InvseeInventory(OfflinePlayer player)
// This is whether the target player should be allowed to open any inventories
private boolean _canOpenInventory = true;
public InvseeInventory(InvseeManager manager, OfflinePlayer player)
{
_online = (_player = player) instanceof Player;
_inventory = UtilServer.getServer().createInventory(null, 54, player.getName() + " " + (_online ? C.cGreen + "ONLINE" : C.cRed + "OFFLINE"));
_invseeManager = manager;
_uuid = player.getUniqueId();
_targetPlayer = player;
_inventory = UtilServer.getServer().createInventory(null, 6 * 9, player.getName());
for (int index = 38; index < 45; index++)
{
_inventory.setItem(index, ItemStackFactory.Instance.CreateStack(Material.STAINED_GLASS_PANE, (byte) 14, 1, C.Bold));
}
_inventory.setItem(47, ItemStackFactory.Instance.CreateStack(Material.STONE_BUTTON, (byte) 0, 1, C.cGreenB + "Inventory Control", generateLore(_canOpenInventory)));
_inventory.setItem(48, ItemStackFactory.Instance.CreateStack(Material.STAINED_GLASS_PANE, (byte) 14, 1, C.Bold));
UtilServer.RegisterEvents(this);
updateInventory();
update(true);
}
public void ShowTo(Player admin)
private String[] generateLore(boolean canOpenInventory)
{
_admin = admin;
admin.openInventory(_inventory);
return UtilText.splitLinesToArray(new String[]{
C.cYellow + "Left-Click" + C.cWhite + " to force close any open inventories the target has open",
"",
C.cYellow + "Right-Click" + C.cWhite + " to " + (canOpenInventory ? "disable inventory opening" : "enable inventory opening")
}, LineFormat.LORE);
}
@EventHandler
public void quit(PlayerQuitEvent event)
/*
* Add the player to the list of viewers and open the inventory for him
*/
public void addAndShowViewer(Player requester)
{
if (_online && event.getPlayer().equals(_player))
_viewers.add(requester);
requester.openInventory(_inventory);
}
/*
* Check whether the given player is currently viewing this InvseeInventory
*/
public boolean isViewer(Player check)
{
return _viewers.contains(check);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void on(PlayerJoinEvent event)
{
if (_uuid.equals(event.getPlayer().getUniqueId()))
{
_admin.closeInventory();
_targetPlayer = event.getPlayer();
updateInventory();
}
}
@EventHandler
public void update(UpdateEvent event)
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void on(PlayerQuitEvent event)
{
if (event.getType() != UpdateType.TICK)
// If a viewer quit, this will clean it up
_viewers.remove(event.getPlayer());
if (_viewers.size() == 0)
{
return;
_invseeManager.close(_uuid);
}
if (_online)
else
{
if (!UtilCollections.equal(_inventory.getContents(), ((Player) _player).getInventory().getContents()))
// This should always work
_targetPlayer = Bukkit.getOfflinePlayer(_uuid);
updateInventory();
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true)
public void on(InventoryOpenEvent event)
{
if (event.getPlayer().getUniqueId().equals(_targetPlayer.getUniqueId()) && !_canOpenInventory)
{
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void on(InventoryCloseEvent event)
{
if (_inventory.equals(event.getInventory()))
{
_viewers.remove(event.getPlayer());
if (_viewers.size() == 0)
{
_inventory.setContents(((Player) _player).getInventory().getContents());
}
}
}
@EventHandler
public void inventoryClick(InventoryClickEvent event)
{
if (event.getClickedInventory().equals(((Player) _player).getInventory()))
{
_inventory.setContents(((Player) _player).getInventory().getContents());
}
else if (event.getClickedInventory().equals(_inventory))
{
if (_online)
{
((Player) _player).getInventory().setContents(_inventory.getContents());
}
}
}
@EventHandler
public void closeInventory(InventoryCloseEvent event)
{
if (event.getInventory().equals(_inventory))
{
UtilServer.Unregister(this);
if (!_online)
{
// save offline inv
_invseeManager.close(_uuid);
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void on(InventoryDragEvent event)
{
if (_inventory.equals(event.getInventory()))
{
ClansManager.getInstance().runSync(() ->
{
update(false);
saveInventory();
});
}
else if (event.getWhoClicked().getUniqueId().equals(_targetPlayer.getUniqueId()))
{
ClansManager.getInstance().runSync(() ->
{
update(true);
saveInventory();
});
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void on(InventoryClickEvent event)
{
if (_inventory.equals(event.getClickedInventory()))
{
if (event.getCurrentItem() != null && event.getCurrentItem().getType() == Material.STAINED_GLASS_PANE
&& event.getCurrentItem().getItemMeta() != null
&& event.getCurrentItem().getItemMeta().getDisplayName() != null
&& event.getCurrentItem().getItemMeta().getDisplayName().equals(C.Bold))
{
event.setCancelled(true);
return;
}
if (event.getCurrentItem() != null && event.getCurrentItem().getType() == Material.STONE_BUTTON
&& event.getCurrentItem().getItemMeta() != null
&& event.getCurrentItem().getItemMeta().getDisplayName() != null
&& event.getCurrentItem().getItemMeta().getDisplayName().equals(C.cGreenB + "Inventory Control"))
{
event.setCancelled(true);
if (event.getClick() == ClickType.LEFT)
{
if (_targetPlayer.isOnline())
{
((Player) _targetPlayer).closeInventory();
}
}
else if (event.getClick() == ClickType.RIGHT)
{
if (_targetPlayer.isOnline())
{
_canOpenInventory = !_canOpenInventory;
ItemMeta meta = event.getCurrentItem().getItemMeta();
meta.setLore(Arrays.asList(generateLore(_canOpenInventory)));
event.getCurrentItem().setItemMeta(meta);
if (!_canOpenInventory)
{
((Player) _targetPlayer).closeInventory();
}
}
}
return;
}
if (MAPPING_INVENTORY_REVERSE.containsKey(event.getRawSlot()))
{
ClansManager.getInstance().runSync(() ->
{
update(false);
saveInventory();
});
}
else if (MAPPING_CRAFTING_REVERSE.containsKey(event.getRawSlot()))
{
if (_targetPlayer.isOnline())
{
ClansManager.getInstance().runSync(() ->
{
update(false);
});
}
}
else if (event.getRawSlot() == 49)
{
if (_targetPlayer.isOnline())
{
ClansManager.getInstance().runSync(() ->
{
update(false);
});
}
}
}
else
{
if (event.getWhoClicked().getUniqueId().equals(_targetPlayer.getUniqueId()))
{
ClansManager.getInstance().runSync(() ->
{
update(true);
});
}
}
}
/*
* Updates the inventory instance
*/
private void updateInventory()
{
if (_targetPlayer.isOnline())
{
_playerInventory = ((CraftPlayer) _targetPlayer).getHandle().inventory;
}
else
{
NBTTagCompound compound = ((WorldNBTStorage) MinecraftServer.getServer().worlds.get(0).getDataManager()).getPlayerData(_uuid.toString());
// Should not matter if null
_playerInventory = new PlayerInventory(null);
if (compound.hasKeyOfType("Inventory", 9))
{
_playerInventory.b(compound.getList("Inventory", 10));
}
}
}
private void saveInventory()
{
if (!_targetPlayer.isOnline())
{
try
{
WorldNBTStorage worldNBTStorage = ((WorldNBTStorage) MinecraftServer.getServer().worlds.get(0).getDataManager());
NBTTagCompound compound = worldNBTStorage.getPlayerData(_uuid.toString());
compound.set("Inventory", new NBTTagList());
_playerInventory.a(compound.getList("Inventory", 10));
File file = new File(worldNBTStorage.getPlayerDir(), _targetPlayer.getUniqueId().toString() + ".dat.tmp");
File file1 = new File(worldNBTStorage.getPlayerDir(), _targetPlayer.getUniqueId().toString() + ".dat");
NBTCompressedStreamTools.a(compound, new FileOutputStream(file));
if (file1.exists())
{
file1.delete();
}
file.renameTo(file1);
}
catch (Exception var5)
{
_invseeManager.log("Failed to save player inventory for " + _targetPlayer.getName());
for (Player player : _viewers)
{
UtilPlayer.message(player, F.main("Invsee", "Could not save inventory for " + _targetPlayer.getName()));
}
var5.printStackTrace(System.out);
}
}
}
/*
* Update the player inventory and invsee inventory.
*
* @param targetClick If true, then it means the player being invseen has modified their inventory. Otherwise, it's the admin who has modified something
*/
private void update(boolean targetClick)
{
IInventory iInventoryThis = ((CraftInventory) _inventory).getInventory();
if (targetClick)
{
// Update items on hotbar
for (int otherSlot = 0; otherSlot < 9; otherSlot++)
{
iInventoryThis.setItem(MAPPING_INVENTORY.get(otherSlot), _playerInventory.getItem(otherSlot));
}
// Update main inventory
for (int otherSlot = 9; otherSlot < 36; otherSlot++)
{
iInventoryThis.setItem(MAPPING_INVENTORY.get(otherSlot), _playerInventory.getItem(otherSlot));
}
// Update armor
for (int otherSlot = 36; otherSlot < 40; otherSlot++)
{
iInventoryThis.setItem(MAPPING_INVENTORY.get(otherSlot), _playerInventory.getItem(otherSlot));
}
if (_targetPlayer.isOnline())
{
ContainerPlayer containerPlayer = (ContainerPlayer) ((CraftPlayer) _targetPlayer).getHandle().defaultContainer;
for (int craftingIndex = 0; craftingIndex < 4; craftingIndex++)
{
iInventoryThis.setItem(MAPPING_CRAFTING.get(craftingIndex), containerPlayer.craftInventory.getItem(craftingIndex));
}
}
iInventoryThis.setItem(49, _playerInventory.getCarried());
}
else
{
// Update items on hotbar
for (int otherSlot = 0; otherSlot < 9; otherSlot++)
{
_playerInventory.setItem(otherSlot, iInventoryThis.getItem(MAPPING_INVENTORY.get(otherSlot)));
}
// Update main inventory
for (int otherSlot = 9; otherSlot < 36; otherSlot++)
{
_playerInventory.setItem(otherSlot, iInventoryThis.getItem(MAPPING_INVENTORY.get(otherSlot)));
}
// Update armor
for (int otherSlot = 36; otherSlot < 40; otherSlot++)
{
_playerInventory.setItem(otherSlot, iInventoryThis.getItem(MAPPING_INVENTORY.get(otherSlot)));
}
if (_targetPlayer.isOnline())
{
ContainerPlayer containerPlayer = (ContainerPlayer) ((CraftPlayer) _targetPlayer).getHandle().defaultContainer;
for (int craftingIndex = 0; craftingIndex < 4; craftingIndex++)
{
containerPlayer.craftInventory.setItem(craftingIndex, iInventoryThis.getItem(MAPPING_CRAFTING.get(craftingIndex)));
}
}
_playerInventory.setCarried(iInventoryThis.getItem(49));
}
for (Player viewing : _viewers)
{
viewing.updateInventory();
}
if (_targetPlayer.isOnline())
{
((Player) _targetPlayer).updateInventory();
}
}
// Maps slot indices of player inventories to slot indices of double chests
private static final Map<Integer, Integer> MAPPING_INVENTORY = new HashMap<>();
private static final Map<Integer, Integer> MAPPING_INVENTORY_REVERSE = new HashMap<>();
// Maps slot indices of player inventories to slot indices of crafting window
private static final Map<Integer, Integer> MAPPING_CRAFTING = new HashMap<>();
private static final Map<Integer, Integer> MAPPING_CRAFTING_REVERSE = new HashMap<>();
static
{
int[] inventoryMapping = new int[]
{
27, 28, 29, 30, 31, 32, 33, 34, 35, //Hotbar
0, 1, 2, 3, 4, 5, 6, 7, 8, // Top row inventory
9, 10, 11, 12, 13, 14, 15, 16, 17, //Second row inventory
18, 19, 20, 21, 22, 23, 24, 25, 26, //Third row inventory
53, 52, 51, 50 //Armor
};
int[] craftingMapping = new int[]
{
36, 37, //Top crafting
45, 46 //Bottom crafting
};
for (int i = 0; i < inventoryMapping.length; i++)
{
MAPPING_INVENTORY.put(i, inventoryMapping[i]);
MAPPING_INVENTORY_REVERSE.put(inventoryMapping[i], i);
}
for (int i = 0; i < craftingMapping.length; i++)
{
MAPPING_CRAFTING.put(i, craftingMapping[i]);
MAPPING_CRAFTING_REVERSE.put(craftingMapping[i], i);
}
}
}

View File

@ -1,30 +1,26 @@
package mineplex.game.clans.clans.map;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.*;
import java.util.Map.Entry;
import mineplex.core.common.util.*;
import mineplex.game.clans.tutorial.TutorialManager;
import mineplex.game.clans.tutorial.map.TutorialMapManager;
import net.minecraft.server.v1_8_R3.*;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_8_R3.util.LongHash;
import org.bukkit.craftbukkit.v1_8_R3.util.LongObjectHashMap;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.ItemSpawnEvent;
import org.bukkit.event.entity.PlayerDeathEvent;
@ -35,6 +31,8 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.map.MapRenderer;
@ -46,13 +44,6 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Multisets;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilInv;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilTextBottom;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.core.itemstack.ItemBuilder;
import mineplex.core.portal.ServerTransferEvent;
@ -62,82 +53,119 @@ import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.ClansUtility;
import mineplex.game.clans.clans.map.events.PlayerGetMapEvent;
import mineplex.game.clans.clans.worldevent.WorldEventManager;
import net.minecraft.server.v1_8_R3.Block;
import net.minecraft.server.v1_8_R3.BlockPosition;
import net.minecraft.server.v1_8_R3.Blocks;
import net.minecraft.server.v1_8_R3.IBlockData;
import net.minecraft.server.v1_8_R3.MaterialMapColor;
import net.minecraft.server.v1_8_R3.PersistentCollection;
/*
* This class manages what the Clans map will show.
* It will scan all relevant chunks (eg players nearby) every <x> ticks
*/
public class ItemMapManager extends MiniPlugin
{
private int _blocksScan = 16 * 3;
// Every BLOCK_SCAN_INTERVAL we add as a new region to scan
private static final int BLOCK_SCAN_INTERVAL = 16 * 3;
// 1536 is the width of the entire world from one borderland to the other
private static final int HALF_WORLD_SIZE = 1536 / 2;
// This slot is where the Clans Map will go by default
private static final int CLANS_MAP_SLOT = 8;
private static final String[] ZOOM_INFO;
static
{
ZOOM_INFO = new String[4];
for (int zoomLevel = 0; zoomLevel <= 3; zoomLevel++)
{
StringBuilder progressBar = new StringBuilder(C.cBlue);
boolean colorChange = false;
for (int i = 2; i >= 0; i--)
{
if (!colorChange && i < zoomLevel)
{
progressBar.append(C.cGray);
colorChange = true;
}
char c;
switch (i)
{
case 0:
c = '█';
break;
case 1:
c = '▆';
break;
default:
c = '▄';
break;
}
for (int a = 0; a < 4; a++)
{
progressBar.append(c);
}
if (i > 0)
{
progressBar.append(" ");
}
}
ZOOM_INFO[zoomLevel] = progressBar.toString();
}
}
private ClansUtility _clansUtility;
private Comparator<Entry<Integer, Integer>> _comparator;
private int _halfMapSize = 1536 / 2;
private int[][] _heightMap = new int[(_halfMapSize * 2) + 16][];
private boolean _loadWorld = true;
private int[][] _heightMap = new int[(HALF_WORLD_SIZE * 2) + 16][];
private HashMap<Integer, Byte[][]> _map = new HashMap<Integer, Byte[][]>();
private short _mapId = -1;
private HashMap<String, MapInfo> _mapInfo = new HashMap<String, MapInfo>();
private HashMap<Integer, Integer> _scale = new HashMap<Integer, Integer>();
private ArrayList<Entry<Integer, Integer>> _scanList = new ArrayList<Entry<Integer, Integer>>();
// Use LinkedList because operations are either add(Entry) which is O(1) and remove(0) which is O(1) on LinkedList but O(n) on ArrayList
private LinkedList<Entry<Integer, Integer>> _scanList = new LinkedList<Entry<Integer, Integer>>();
private World _world;
private WorldServer _nmsWorld;
private ChunkProviderServer _chunkProviderServer;
private ChunkRegionLoader _chunkRegionLoader;
private WorldEventManager _eventManager;
private TutorialManager _tutorial;
public ItemMapManager(ClansManager clansManager, TutorialManager tutorial, WorldEventManager eventManager)
{
super("ItemMapManager", clansManager.getPlugin());
_clansUtility = clansManager.getClanUtility();
_eventManager = eventManager;
_tutorial = tutorial;
_comparator = new Comparator<Entry<Integer, Integer>>()
_comparator = (o1, o2) ->
{
// Render the places outside the map first to speed up visual errors fixing
int outsideMap = Boolean.compare(o1.getValue() < -HALF_WORLD_SIZE, o2.getValue() < -HALF_WORLD_SIZE);
@Override
public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2)
if (outsideMap != 0)
{
// Render the places outside the map first to speed up visual errors fixing
int outsideMap = Boolean.compare(o1.getValue() < -_halfMapSize, o2.getValue() < -_halfMapSize);
return -outsideMap;
}
if (outsideMap != 0)
{
return -outsideMap;
}
double dist1 = 0;
double dist2 = 0;
double dist1 = 0;
double dist2 = 0;
for (Player player : UtilServer.getPlayers())
{
dist1 += getDistance(o1, player.getLocation().getX(), player.getLocation().getZ());
dist2 += getDistance(o2, player.getLocation().getX(), player.getLocation().getZ());
}
if (dist1 != dist2)
{
return Double.compare(dist1, dist2);
}
dist1 = getDistance(o1, 0, 0);
dist2 = getDistance(o2, 0, 0);
for (Player player : UtilServer.getPlayers())
{
dist1 += getDistance(o1, player.getLocation().getX(), player.getLocation().getZ());
dist2 += getDistance(o2, player.getLocation().getX(), player.getLocation().getZ());
}
if (dist1 != dist2)
{
return Double.compare(dist1, dist2);
}
dist1 = getDistance(o1, 0, 0);
dist2 = getDistance(o2, 0, 0);
return Double.compare(dist1, dist2);
};
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
{
for (int z = -_halfMapSize - 16; z < _halfMapSize; z += (z < -_halfMapSize ? 16 : _blocksScan))
{
_scanList.add(new HashMap.SimpleEntry(x, z));
}
}
_scale.put(0, 1);
// _scale.put(1, 2);
_scale.put(1, 4);
@ -147,7 +175,7 @@ public class ItemMapManager extends MiniPlugin
for (Entry<Integer, Integer> entry : _scale.entrySet())
{
int size = (_halfMapSize * 2) / entry.getValue();
int size = (HALF_WORLD_SIZE * 2) / entry.getValue();
Byte[][] bytes = new Byte[size][];
for (int i = 0; i < size; i++)
@ -165,6 +193,23 @@ public class ItemMapManager extends MiniPlugin
_world = Bukkit.getWorld("world");
try
{
Field chunkLoader = ChunkProviderServer.class.getDeclaredField("chunkLoader");
chunkLoader.setAccessible(true);
_nmsWorld = ((CraftWorld) _world).getHandle();
_chunkProviderServer = _nmsWorld.chunkProviderServer;
_chunkRegionLoader = (ChunkRegionLoader) chunkLoader.get(_chunkProviderServer);
if (_chunkRegionLoader == null)
{
throw new RuntimeException("Did not expect null chunkLoader");
}
}
catch (ReflectiveOperationException e)
{
throw new RuntimeException("Could not reflectively access ChunkRegionLoader", e);
}
try
{
File file = new File("world/clans_map_id");
@ -238,6 +283,58 @@ public class ItemMapManager extends MiniPlugin
}
rebuildScan();
initialScan();
}
private void initialScan()
{
System.out.println("Beginning initial scan. There are " + _scanList.size() + " regions to scan");
// How many regions before logging an update (Currently set to every 20%)
int logPer = _scanList.size() / 5;
while (!_scanList.isEmpty())
{
Entry<Integer, Integer> entry = _scanList.remove(0);
if (_scanList.size() % logPer == 0)
{
System.out.println("Running initial render... " + _scanList.size() + " sections to go");
}
int startingX = entry.getKey();
int startingZ = entry.getValue();
boolean outsideMap = startingZ < -HALF_WORLD_SIZE;
scanWorldMap(startingX, startingZ, !outsideMap, true);
if (outsideMap)
{
continue;
}
for (int scale = 1; scale < _scale.size(); scale++)
{
if (scale == 3)
continue;
drawWorldScale(scale, startingX, startingZ);
colorWorldHeight(scale, startingX, startingZ);
}
colorWorldHeight(0, startingX, startingZ);
}
for (int x = -HALF_WORLD_SIZE; x < HALF_WORLD_SIZE; x += BLOCK_SCAN_INTERVAL)
{
for (int z = -HALF_WORLD_SIZE; z < HALF_WORLD_SIZE; z += BLOCK_SCAN_INTERVAL)
{
drawWorldScale(3, x, z);
colorWorldHeight(3, x, z);
}
}
System.out.println("Finished first map scan and render");
}
private void setupRenderer(MapView view)
@ -256,10 +353,7 @@ public class ItemMapManager extends MiniPlugin
if (!(event.getRightClicked() instanceof ItemFrame))
return;
ItemStack item = event.getPlayer().getItemInHand();
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|| item.getDurability() > _mapId + 100)
if (!isItemClansMap(event.getPlayer().getItemInHand()))
return;
event.setCancelled(true);
@ -270,7 +364,7 @@ public class ItemMapManager extends MiniPlugin
*/
public int calcMapCenter(int zoom, int cord)
{
int mapSize = _halfMapSize / zoom; // This is how large the map is in pixels
int mapSize = HALF_WORLD_SIZE / zoom; // This is how large the map is in pixels
int mapCord = cord / zoom; // This is pixels from true center of map, not held map
@ -309,7 +403,7 @@ public class ItemMapManager extends MiniPlugin
Byte[][] map = _map.get(scale);
int zoom = getZoom(scale);
for (int x = startingX; x < startingX + _blocksScan; x += zoom)
for (int x = startingX; x < startingX + BLOCK_SCAN_INTERVAL; x += zoom)
{
double d0 = 0;
@ -319,10 +413,10 @@ public class ItemMapManager extends MiniPlugin
{
for (int addZ = 0; addZ < zoom; addZ++)
{
int hX = x + addX + _halfMapSize;
int hZ = (startingZ - zoom) + addZ + _halfMapSize;
int hX = x + addX + HALF_WORLD_SIZE;
int hZ = (startingZ - zoom) + addZ + HALF_WORLD_SIZE;
if (hX >= _halfMapSize * 2 || hZ >= _halfMapSize * 2)
if (hX >= HALF_WORLD_SIZE * 2 || hZ >= HALF_WORLD_SIZE * 2)
{
continue;
}
@ -331,7 +425,7 @@ public class ItemMapManager extends MiniPlugin
}
}
for (int z = startingZ; z < startingZ + _blocksScan; z += zoom)
for (int z = startingZ; z < startingZ + BLOCK_SCAN_INTERVAL; z += zoom)
{
// Water depth colors not included
double d1 = 0;
@ -340,10 +434,10 @@ public class ItemMapManager extends MiniPlugin
{
for (int addZ = 0; addZ < zoom; addZ++)
{
int hX = x + addX + _halfMapSize;
int hZ = z + addZ + _halfMapSize;
int hX = x + addX + HALF_WORLD_SIZE;
int hZ = z + addZ + HALF_WORLD_SIZE;
if (hX >= _halfMapSize * 2 || hZ >= _halfMapSize * 2)
if (hX >= HALF_WORLD_SIZE * 2 || hZ >= HALF_WORLD_SIZE * 2)
{
continue;
}
@ -370,7 +464,7 @@ public class ItemMapManager extends MiniPlugin
b0 = 0;
}
int origColor = map[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] - 1;
int origColor = map[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] - 1;
/*if (color < 4)
{
@ -388,7 +482,7 @@ public class ItemMapManager extends MiniPlugin
}*/
byte color = (byte) (origColor + b0);
map[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] = color;
map[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] = color;
}
}
}
@ -399,9 +493,9 @@ public class ItemMapManager extends MiniPlugin
Byte[][] second = _map.get(scale);
int zoom = getZoom(scale);
for (int x = startingX; x < startingX + _blocksScan; x += zoom)
for (int x = startingX; x < startingX + BLOCK_SCAN_INTERVAL; x += zoom)
{
for (int z = startingZ; z < startingZ + _blocksScan; z += zoom)
for (int z = startingZ; z < startingZ + BLOCK_SCAN_INTERVAL; z += zoom)
{
HashMultiset<Byte> hashmultiset = HashMultiset.create();
@ -409,8 +503,8 @@ public class ItemMapManager extends MiniPlugin
{
for (int addZ = 0; addZ < zoom; addZ++)
{
int pX = x + addX + _halfMapSize;
int pZ = z + addZ + _halfMapSize;
int pX = x + addX + HALF_WORLD_SIZE;
int pZ = z + addZ + HALF_WORLD_SIZE;
if (pX >= first.length || pZ >= first.length)
{
@ -432,7 +526,7 @@ public class ItemMapManager extends MiniPlugin
{
color = (byte) 0;
}
second[(x + _halfMapSize) / zoom][(z + _halfMapSize) / zoom] = color;
second[(x + HALF_WORLD_SIZE) / zoom][(z + HALF_WORLD_SIZE) / zoom] = color;
}
}
}
@ -440,25 +534,16 @@ public class ItemMapManager extends MiniPlugin
@EventHandler
public void dropItem(ItemSpawnEvent event)
{
ItemStack item = event.getEntity().getItemStack();
if (item != null && item.getType() == Material.MAP && item.getDurability() >= _mapId
&& item.getDurability() <= _mapId + 100)
{
if (isItemClansMap(event.getEntity().getItemStack()))
event.getEntity().remove();
}
}
public void removeMap(Player player)
{
for (int slot = 0; slot < player.getInventory().getSize(); slot++)
{
ItemStack item = player.getInventory().getItem(slot);
if (item != null && item.getType() == Material.MAP && item.getDurability() >= _mapId && item.getDurability() <= _mapId + 100)
{
if (isItemClansMap(player.getInventory().getItem(slot)))
player.getInventory().setItem(slot, null);
}
}
}
@ -477,7 +562,7 @@ public class ItemMapManager extends MiniPlugin
private double getDistance(Entry<Integer, Integer> entry, double x1, double z1)
{
return getDistance(x1, z1, entry.getKey() + (_blocksScan / 2), entry.getValue() + (_blocksScan / 2));
return getDistance(x1, z1, entry.getKey() + (BLOCK_SCAN_INTERVAL / 2), entry.getValue() + (BLOCK_SCAN_INTERVAL / 2));
}
public Byte[][] getMap(int scale)
@ -492,7 +577,7 @@ public class ItemMapManager extends MiniPlugin
public int getMapSize()
{
return _halfMapSize;
return HALF_WORLD_SIZE;
}
public int getZoom(int scale)
@ -500,35 +585,7 @@ public class ItemMapManager extends MiniPlugin
return _scale.get(scale);
}
@EventHandler
public void preventMapMoveInventories(InventoryClickEvent event)
{
Inventory inv = event.getClickedInventory();
if (inv == null)
return;
// Yeah, the loop looks a little weird..
for (ItemStack item : new ItemStack[]
{
event.getCurrentItem(), event.getCursor()
})
{
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|| item.getDurability() > _mapId + 100)
continue;
if (inv.getHolder() instanceof Player ? !event.isShiftClick() : Objects.equal(event.getCurrentItem(), item))
continue;
event.setCancelled(true);
UtilPlayer.message(event.getWhoClicked(),
F.main("Inventory", "You cannot move " + F.item("Clans Map") + " between inventories."));
return;
}
}
//fixme So what appears to happen is that after you die, if your map is is the same then the map is frozen
@EventHandler
public void onDeath(PlayerDeathEvent event)
{
@ -542,14 +599,10 @@ public class ItemMapManager extends MiniPlugin
{
Player player = event.getPlayer();
ItemStack item = player.getInventory().getItem(event.getNewSlot());
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|| item.getDurability() > _mapId + 100)
if (!isItemClansMap(player.getInventory().getItem(event.getNewSlot())))
return;
showZoom(player, getMap(player));
}
@EventHandler
@ -558,10 +611,7 @@ public class ItemMapManager extends MiniPlugin
if (event.getAction() == Action.PHYSICAL)
return;
ItemStack item = event.getItem();
if (item == null || item.getType() != Material.MAP || item.getDurability() < _mapId
|| item.getDurability() > _mapId + 100)
if (!isItemClansMap(event.getItem()))
return;
event.setCancelled(true);
@ -666,36 +716,11 @@ public class ItemMapManager extends MiniPlugin
private void rebuildScan()
{
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
for (int x = -HALF_WORLD_SIZE; x < HALF_WORLD_SIZE; x += BLOCK_SCAN_INTERVAL)
{
for (int z = -_halfMapSize - 16; z < _halfMapSize; z += (z < -_halfMapSize ? 16 : _blocksScan))
for (int z = -HALF_WORLD_SIZE - 16; z < HALF_WORLD_SIZE; z += (z < -HALF_WORLD_SIZE ? 16 : BLOCK_SCAN_INTERVAL))
{
_scanList.add(new HashMap.SimpleEntry(x, z));
}
}
if (!_loadWorld)
{
Iterator<Entry<Integer, Integer>> itel = _scanList.iterator();
while (itel.hasNext())
{
Entry<Integer, Integer> entry = itel.next();
boolean removeEntry = true;
for (Player player : UtilServer.getPlayers())
{
if (Math.sqrt(getDistance(entry, player.getLocation().getX(), player.getLocation().getZ())) < 200)
{
removeEntry = false;
break;
}
}
if (removeEntry)
{
itel.remove();
}
_scanList.add(new HashMap.SimpleEntry<>(x, z));
}
}
@ -744,101 +769,117 @@ public class ItemMapManager extends MiniPlugin
if (event.getType() != UpdateType.FAST)
return;
if (_scanList.isEmpty())
if (_scanList.isEmpty() && UtilServer.getPlayers().length > 0)
{
if (_loadWorld)
{
for (int x = -_halfMapSize; x < _halfMapSize; x += _blocksScan)
{
for (int z = -_halfMapSize; z < _halfMapSize; z += _blocksScan)
{
drawWorldScale(3, x, z);
colorWorldHeight(3, x, z);
}
}
System.out.print("Finished first map scan and render");
}
_loadWorld = false;
if (UtilServer.getPlayers().length == 0)
return;
rebuildScan();
}
else if (_scanList.size() % 20 == 0)
if (_scanList.size() % 20 == 0)
{
Collections.sort(_scanList, _comparator);
}
if (_scanList.isEmpty())
{
return;
}
Entry<Integer, Integer> entry = _scanList.remove(0);
int startingX = entry.getKey();
int startingZ = entry.getValue();
boolean outsideMap = startingZ < -_halfMapSize;
boolean outsideMap = startingZ < -HALF_WORLD_SIZE;
scanWorldMap(startingX, startingZ, !outsideMap, false);
scanWorldMap(startingX, startingZ, !outsideMap);
if (outsideMap)
{
return;
}
for (int scale = 1; scale < _scale.size(); scale++)
{
if (scale == 3 && _loadWorld)
continue;
if (!outsideMap)
{
drawWorldScale(scale, startingX, startingZ);
}
drawWorldScale(scale, startingX, startingZ);
colorWorldHeight(scale, startingX, startingZ);
}
colorWorldHeight(0, startingX, startingZ);
}
public void scanWorldMap(int startingX, int startingZ, boolean setColors)
// Let's not create hundreds of thousands of BlockPositions
// Single thread = should be thread safe
private BlockPosition.MutableBlockPosition _blockPosition = new BlockPosition.MutableBlockPosition();
// Maps the cached chunks which were loaded from disk to save IO operations
private LongObjectHashMap<Chunk> _chunkCache = new LongObjectHashMap<>();
/*
* Remove the cached chunks when the real chunks are loaded in
*/
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void LoadChunk(ChunkLoadEvent event)
{
_chunkCache.remove(LongHash.toLong(event.getChunk().getX(), event.getChunk().getZ()));
}
/*
* Given a particular coordinate, this method will scan up to BLOCK_SCAN_INTERVAL and record the color of ever 16th block
* If a chunk has not been loaded, the following steps will be taken:
* * Attempt to load the chunk from disk.
* * If the chunk could not be loaded, generate it froms scratch
* Otherwise, the loaded chunk will be used
*/
public void scanWorldMap(int startingX, int startingZ, boolean setColors, boolean isFirstScan)
{
Byte[][] map = _map.get(0);
for (int beginX = startingX; beginX < startingX + _blocksScan; beginX += 16)
for (int beginX = startingX; beginX < startingX + BLOCK_SCAN_INTERVAL; beginX += 16)
{
for (int beginZ = startingZ - (startingZ > -_halfMapSize ? 16 : 0); beginZ < startingZ
+ (setColors ? _blocksScan : 16); beginZ += 16)
for (int beginZ = startingZ - (startingZ > -HALF_WORLD_SIZE ? 16 : 0); beginZ < startingZ
+ (setColors ? BLOCK_SCAN_INTERVAL : 16); beginZ += 16)
{
Chunk chunk = _world.getChunkAt(beginX / 16, beginZ / 16);
boolean loaded = false;
if (!chunk.isLoaded())
int chunkX = beginX / 16;
int chunkZ = beginZ / 16;
net.minecraft.server.v1_8_R3.Chunk nmsChunk = _chunkProviderServer.getChunkIfLoaded(chunkX, chunkZ);
if (nmsChunk == null)
{
if (_loadWorld)
long key = LongHash.toLong(chunkX, chunkZ);
nmsChunk = _chunkCache.get(key);
if (nmsChunk == null)
{
loaded = chunk.load();
}
else
{
continue;
if (!isFirstScan)
{
continue;
}
try
{
Object[] data = _chunkRegionLoader.loadChunk(_nmsWorld, chunkX, chunkZ);
if (data == null)
{
// Something is wrong with the chunk
System.out.println("Chunk is not generated or missing level/block data. Regenerating (" + chunkX + "," + chunkZ + ")");
nmsChunk = ((CraftChunk) _world.getChunkAt(chunkX, chunkZ)).getHandle();
}
else
{
nmsChunk = (net.minecraft.server.v1_8_R3.Chunk) data[0];
}
}
catch (IOException e)
{
throw new RuntimeException("Chunk is corrupt or not readable!", e);
}
_chunkCache.put(key, nmsChunk);
}
}
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
for (int x = beginX; x < beginX + 16; x++)
if (!nmsChunk.isEmpty())
{
for (int z = beginZ; z < beginZ + 16; z++)
for (int x = beginX; x < beginX + 16; x++)
{
int color = 0;
if (!nmsChunk.isEmpty())
for (int z = beginZ; z < beginZ + 16; z++)
{
int color = 0;
int k3 = x & 0xF;
int l3 = z & 0xF;
@ -850,7 +891,8 @@ public class ItemMapManager extends MiniPlugin
do
{
l4--;
iblockdata= nmsChunk.getBlockData(new BlockPosition(k3, l4, l3));
_blockPosition.c(k3, l4, l3);
iblockdata = nmsChunk.getBlockData(_blockPosition);
}
while (iblockdata.getBlock().g(iblockdata) == MaterialMapColor.b && (l4 > 0));
@ -860,34 +902,31 @@ public class ItemMapManager extends MiniPlugin
Block block1;
do
{
block1 = nmsChunk.getType(new BlockPosition(k3, j5--, l3));
_blockPosition.c(k3, j5--, l3);
block1 = nmsChunk.getType(_blockPosition);
}
while ((j5 > 0) && (block1.getMaterial().isLiquid()));
}
}
_heightMap[x + _halfMapSize + 16][z + _halfMapSize + 16] = l4;
_heightMap[x + HALF_WORLD_SIZE + 16][z + HALF_WORLD_SIZE + 16] = l4;
if (setColors)
{
//color = block.f(i5).M;
IBlockData data = nmsChunk.getBlockData(new BlockPosition(k3, l4, l3));
_blockPosition.c(k3, l4, l3);
IBlockData data = nmsChunk.getBlockData(_blockPosition);
color = data.getBlock().g(data).M;
color = (byte) ((color * 4) + 1);
}
}
if (setColors && beginZ >= startingZ)
{
map[x + _halfMapSize][z + _halfMapSize] = (byte) color;
if (setColors && beginZ >= startingZ)
{
map[x + HALF_WORLD_SIZE][z + HALF_WORLD_SIZE] = (byte) color;
}
}
}
if (loaded)
{
chunk.unload();
}
}
}
}
@ -898,10 +937,10 @@ public class ItemMapManager extends MiniPlugin
PlayerGetMapEvent event = UtilServer.CallEvent(new PlayerGetMapEvent(player));
if (event.isCancelled())
return;
for (ItemStack item : UtilInv.getItems(player))
{
if (item.getType() == Material.MAP && (item.getDurability() >= _mapId && item.getDurability() <= _mapId + 100))
if (isItemClansMap(item))
{
return;
}
@ -909,62 +948,38 @@ public class ItemMapManager extends MiniPlugin
ItemStack item = new ItemBuilder(Material.MAP, 1, (short) getMap(player).getMap()).setTitle("Clans Map").build();
int slot = player.getInventory().firstEmpty();
int slot = CLANS_MAP_SLOT;
ItemStack mapSlot = player.getInventory().getItem(slot);
if (mapSlot != null && mapSlot.getType() != Material.AIR)
{
slot = player.getInventory().firstEmpty();
}
if (slot >= 0)
{
ItemStack mapSlot = player.getInventory().getItem(8);
if (mapSlot == null || mapSlot.getType() == Material.AIR)
{
slot = 8;
}
player.getInventory().setItem(slot, item);
}
}
/*
* Displays the action bar to a player given their zoom level. Implementation may change
*/
private void showZoom(Player player, MapInfo info)
{
String progressBar = C.cBlue + "";
boolean colorChange = false;
for (int i = 2; i >= 0; i--)
{
if (!colorChange && i < info.getScale())
{
progressBar += C.cGray;
colorChange = true;
}
char c;
switch (i)
{
case 0:
c = '█';
break;
case 1:
c = '▆';
break;
default:
c = '▄';
break;
}
for (int a = 0; a < 4; a++)
{
progressBar += c;
}
if (i > 0)
{
progressBar += " ";
}
}
UtilTextBottom.display(progressBar, player);
UtilTextBottom.display(ZOOM_INFO[info.getScale()], player);
}
/*
* Check whether an {@link ItemStack} is also a Clans Map
*
* @param itemStack The {@link ItemStack} to check
* @returns Whether the {@link ItemStack} is also a Clans Map
*/
private boolean isItemClansMap(ItemStack itemStack)
{
return UtilItem.matchesMaterial(itemStack, Material.MAP)
&& itemStack.getDurability() >= _mapId
&& itemStack.getDurability() <= _mapId + 100;
}
}

View File

@ -50,7 +50,7 @@ public class ItemMapRenderer extends MapRenderer
// }
// else
// {
renderNormalMap(mapView, canvas, player);
renderNormalMap(mapView, canvas, player);
// }
}
@ -135,7 +135,7 @@ public class ItemMapRenderer extends MapRenderer
if (_manager.getClansUtility().relPT(player, chunk) == ClansUtility.ClanRelation.SAFE)
clanColor2 = new Color(50, 150, 255);
}
else if (owningClan.getName().equals("Spawn"))
else if (owningClan.getName().equals("Spawn"))
{
clanColor = Color.WHITE;
clanColor2 = new Color(0, 255, 100);

View File

@ -4,6 +4,9 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
/*
* This event is called when a Player is about to receive a Clans Map
*/
public class PlayerGetMapEvent extends Event
{
private static final HandlerList handlers = new HandlerList();

View File

@ -73,7 +73,7 @@ public class MurderManager extends MiniClientPlugin<ClientMurder>
}
}
@EventHandler
@EventHandler (ignoreCancelled = true)
public void onPickup(PlayerPickupItemEvent event)
{
refreshClient(event.getPlayer());

View File

@ -131,7 +131,7 @@ public class ObserverManager extends MiniPlugin
}
}
@EventHandler
@EventHandler (priority = EventPriority.LOWEST)
public void onPickup(PlayerPickupItemEvent event)
{
ObserverData data = _observerMap.get(event.getPlayer());

View File

@ -197,18 +197,7 @@ public class ClansRegions extends MiniPlugin
{
int x = chunkX + xOffset;
int z = chunkZ + zOffset;
Chunk chunk;
try
{ //Corrupted chunk will hold up whole server
chunk = location.getWorld().getChunkAt(x, z);
}
catch(Exception e)
{
System.out.println("UNABLE TO LOAD CHUNK AT " + x + " , " + z);
e.printStackTrace();
continue;
}
String chunkStr = UtilWorld.chunkToStr(chunk);
String chunkStr = location.getWorld().getName() + "," + x + "," + z;
if (addNegative)
{

View File

@ -132,7 +132,7 @@ public class SiegeWeaponRepository extends MinecraftRepository
public void updateWeapon(SiegeWeaponToken token)
{
System.out.println("Siege Repo> Updating weapon " + token.UniqueId);
// System.out.println("Siege Repo> Updating weapon " + token.UniqueId);
_siegeManager.runAsync(() ->
executeUpdate(UPDATE_WEAPON,

View File

@ -27,6 +27,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.ChunkUnloadEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.metadata.FixedMetadataValue;
import org.bukkit.util.EulerAngle;
import org.spigotmc.event.entity.EntityDismountEvent;
@ -559,6 +560,7 @@ public abstract class SiegeWeapon implements Listener
{
entity.setCustomName(Integer.toString(_uniqueId));
entity.setCustomNameVisible(false);
entity.setMetadata("Creature.DoNotDrop", new FixedMetadataValue(_clans.getPlugin(), true));
_comprisedOf.add(entity);
@ -569,6 +571,8 @@ public abstract class SiegeWeapon implements Listener
{
Entity entity = _entityMapping.get(uniqueName);
entity.removeMetadata("Creature.DoNotDrop", _clans.getPlugin());
_entityMapping.remove(uniqueName);
_comprisedOf.remove(entity);

View File

@ -113,7 +113,7 @@ public class GoldManager extends MiniPlugin
}
}
@EventHandler
@EventHandler (ignoreCancelled = true)
public void onPickup(PlayerPickupItemEvent event)
{
if (_itemSet.contains(event.getItem()))

View File

@ -867,6 +867,12 @@ public class Gameplay extends MiniPlugin
return;
}
}
if (_blockRestore.contains(event.getClickedBlock()))
{
UtilPlayer.message(player, F.main("Repair", "You cannot repair using that anvil"));
return;
}
// Repair!
UtilPlayer.message(player, F.main("Repair", "You repaired " + F.item(item.getItemMeta().getDisplayName()) + "."));

View File

@ -29,7 +29,7 @@ import mineplex.minecraft.game.core.damage.CustomDamageEvent;
* @author MrTwiggy
*
*/
public class CustomItem
public class CustomItem implements Listener
{
private static final ChatColor TITLE_COLOR = ChatColor.GOLD; // Chat color
@ -73,6 +73,7 @@ public class CustomItem
_material = material;
_attributes = new AttributeContainer();
_uuid = UUID.randomUUID().toString();
UtilServer.RegisterEvents(this);
}
public CustomItem(Material material)

View File

@ -1,8 +1,12 @@
package mineplex.game.clans.items.attributes;
import mineplex.game.clans.clans.ClansManager;
import mineplex.game.clans.clans.ClansUtility;
import mineplex.game.clans.items.generation.ValueDistribution;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@ -127,4 +131,21 @@ public abstract class ItemAttribute
}
return s;
}
protected boolean isTeammate(Entity attacker, Entity defender)
{
if (attacker == null || defender == null) return false;
// Don't count attacks towards teammates
if (attacker instanceof Player && defender instanceof Player)
{
ClansUtility.ClanRelation relation = ClansManager.getInstance().getRelation((Player) attacker, (Player) defender);
if (relation == ClansUtility.ClanRelation.ALLY
|| relation == ClansUtility.ClanRelation.SAFE
|| relation == ClansUtility.ClanRelation.SELF)
{
return true;
}
}
return false;
}
}

View File

@ -41,6 +41,7 @@ public class FlamingAttribute extends AttackAttribute
if(attacker instanceof Player && ClansManager.getInstance().isSafe((Player) attacker)) return;
if(defender instanceof Player && ClansManager.getInstance().isSafe((Player) defender)) return;
if(attacker instanceof Player && ((Player)attacker).getGameMode().equals(GameMode.CREATIVE)) return;
if (isTeammate(attacker, defender)) return;
defender.setFireTicks(_fireDuration);
}

View File

@ -54,6 +54,7 @@ public class FrostedAttribute extends ItemAttribute
if (victim != null)
{
if (isTeammate(event.GetDamagerPlayer(true), victim)) return;
victim.addPotionEffect(generateSlowEffect()); // Slow attacking player
}
}

View File

@ -42,6 +42,7 @@ public class HasteAttribute extends AttackAttribute
@Override
public void triggerAttack(Entity attacker, Entity defender)
{
if (isTeammate(attacker, defender)) return;
if (attacker instanceof Player)
{
Player player = (Player) attacker;

View File

@ -28,6 +28,7 @@ public class JaggedAttribute extends AttackAttribute {
@Override
public void triggerAttack(Entity attacker, Entity defender) {
if (isTeammate(attacker, defender)) return;
defender.setVelocity(new Vector(0, 0, 0));
if (defender instanceof LivingEntity)
((LivingEntity) defender).addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20, 1, false, false));

View File

@ -37,6 +37,8 @@ public class VampiricAttribute extends ItemAttribute
public void onAttack(CustomDamageEvent event)
{
Player damager = event.GetDamagerPlayer(false);
if (isTeammate(damager, event.GetDamageePlayer())) return;
double damage = event.GetDamage();
double healAmount = damage * (_healPercent / 100d);

View File

@ -1,5 +1,6 @@
package mineplex.game.clans.items.legendaries;
import mineplex.core.recharge.Recharge;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Player;
@ -14,7 +15,7 @@ import mineplex.minecraft.game.core.damage.CustomDamageEvent;
public class GiantsBroadsword extends LegendaryItem
{
public static final int SLOW_AMPLIFIER = 43;
public static final int REGEN_AMPLIFIER = 3;
public static final int REGEN_AMPLIFIER = 1;
public GiantsBroadsword()
{
@ -60,6 +61,7 @@ public class GiantsBroadsword extends LegendaryItem
private void buffPlayer(Player player)
{
grantPotionEffect(player, PotionEffectType.SLOW, 40, SLOW_AMPLIFIER);
grantPotionEffect(player, PotionEffectType.REGENERATION, 2, REGEN_AMPLIFIER); //Regen
if (Recharge.Instance.use(player, "Giants Broadsword Regen", 250L, false, false, false))
grantPotionEffect(player, PotionEffectType.REGENERATION, 5, REGEN_AMPLIFIER); //Regen
}
}

View File

@ -31,7 +31,7 @@ public class HyperAxe extends LegendaryItem
C.cWhite + "blade can rip through any opponent.",
C.cWhite + " ",
C.cWhite + "Hit delay is reduced by " + C.cYellow + "50%",
C.cWhite + "Deals " + C.cYellow + "10 Damage" + C.cWhite + " with attack",
C.cWhite + "Deals " + C.cYellow + "3 Damage" + C.cWhite + " with attack",
C.cYellow + "Right-Click" + C.cWhite + " to use " + C.cGreen + "Dash",
}, Material.RECORD_3);
_speedAmount = amountGen.generateIntValue();

View File

@ -1,11 +1,6 @@
package mineplex.game.clans.items.legendaries;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilAction;
import mineplex.core.common.util.UtilAlg;
import mineplex.core.common.util.UtilMath;
@ -18,6 +13,12 @@ import mineplex.core.common.util.UtilWorld;
import mineplex.game.clans.clans.ClansManager;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
public class MagneticMaul extends LegendaryItem
{
public static final double PULL_RANGE = 10d;
@ -27,9 +28,11 @@ public class MagneticMaul extends LegendaryItem
public MagneticMaul()
{
super("Magnetic Maul", new String[]{
}, Material.RECORD_5);
super("Magnetic Maul", new String[] {
C.cWhite + "This brutal weapon allows you to pull your enemies towards you with magnetic force!"
+ " ",
C.cYellow + "Right-Click" + C.cWhite + " to use Maul."
}, Material.RECORD_5);
}
@Override

View File

@ -1,17 +1,6 @@
package mineplex.game.clans.items.legendaries;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import java.util.HashMap;
import mineplex.core.common.util.C;
import mineplex.core.common.util.F;
@ -20,26 +9,37 @@ import mineplex.core.common.util.RGBData;
import mineplex.core.common.util.UtilBlock;
import mineplex.core.common.util.UtilCollections;
import mineplex.core.common.util.UtilColor;
import mineplex.core.common.util.UtilEnt;
import mineplex.core.common.util.UtilParticle;
import mineplex.core.common.util.UtilParticle.ParticleType;
import mineplex.core.common.util.UtilParticle.ViewDist;
import mineplex.core.incognito.IncognitoManager;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.common.util.UtilShapes;
import mineplex.core.common.util.UtilText;
import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.core.recharge.Recharge;
import mineplex.game.clans.clans.ClansManager;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
public class MeridianScepter extends LegendaryItem
{
private long _lastFire = System.currentTimeMillis();
private long _interactWait;
private RGBData[] colors = { UtilColor.RgbPurple, UtilColor.RgbPurple.Lighten(), UtilColor.RgbPurple.Darken() };
private int _witherDamageTimes = 5;
private HashMap<AttackAnimation, Integer> _animations = new HashMap<AttackAnimation, Integer>();
public MeridianScepter()
{
@ -100,21 +100,14 @@ public class MeridianScepter extends LegendaryItem
// If they are less than 0.5 blocks away
if (player.getEyeLocation().subtract(0, .3, 0).distance(projectile) <= 2)
{
player.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, 20 * _witherDamageTimes, 0));
{
AttackAnimation aa = new AttackAnimation(player, shooter);
int i = UtilServer.getServer().getScheduler().scheduleSyncRepeatingTask(UtilServer.getPlugin(), () -> {
aa.update();
}, 0, 1);
_animations.put(aa, i);
int time = 0;
for (int i = 0; i < _witherDamageTimes; i++)
{
UtilServer.getServer().getScheduler().scheduleSyncDelayedTask(UtilServer.getPlugin(), () -> {
ClansManager.getInstance().getDamageManager().NewDamageEvent(player, shooter, null,
DamageCause.CUSTOM, 1.75, false, true, true,
shooter.getName(), "Meridian Scepter");
}, ++time * 20);
}
UtilPlayer.message(player, F.main("Clans", F.elem(player.getName()) + " hit you with a " + F.elem("Meridian Scepter") + C.mBody + "."));
UtilPlayer.message(player, F.main("Clans", F.elem(shooter.getName()) + " hit you with a " + F.elem("Meridian Scepter") + C.mBody + "."));
UtilPlayer.message(shooter, F.main("Clans", "You hit " + F.elem(player.getName()) + " with your " + F.elem("Meridian Scepter") + C.mBody + "."));
}
}
@ -258,4 +251,68 @@ public class MeridianScepter extends LegendaryItem
UtilParticle.PlayParticleToAll(ParticleType.RED_DUST, loc, UtilCollections.random(colors).ToVector(), 1f, 0, ViewDist.LONG);
}
}
private class AttackAnimation
{
private Player _hit, _shooter;
private double _step;
private double _radius;
private long _start, _lastStepIncrease;
public AttackAnimation(Player hit, Player shooter)
{
_step = 0;
_start = System.currentTimeMillis();
_lastStepIncrease = System.currentTimeMillis();
_hit = hit;
_shooter = shooter;
_radius = 2;
}
public void update()
{
if (_hit == null)
{
end();
return;
}
if (UtilTime.elapsed(_lastStepIncrease, UtilTime.convert(1, TimeUnit.SECONDS, TimeUnit.MILLISECONDS)))
{
_step++;
_lastStepIncrease = System.currentTimeMillis();
}
drawHelix();
if (UtilTime.elapsed(_start, 4000))
{
_hit.getWorld().strikeLightningEffect(_hit.getLocation());
ClansManager.getInstance().getDamageManager().NewDamageEvent(_hit, _shooter, null,
DamageCause.CUSTOM, 6, false, true, true,
_shooter.getName(), "Meridian Scepter");
ClansManager.getInstance().getCondition().Factory().Blind("Meridian Scepter", _hit, _shooter, 1, 0, true, true, true);
end();
return;
}
}
private void end()
{
int id = _animations.remove(this);
Bukkit.getScheduler().cancelTask(id);
}
private void drawHelix()
{
double height = Math.min(_step * 2, 8D);
for (double y = 0; y <= height; y += .5)
{
double x = _radius * Math.cos(y);
double z = _radius * Math.sin(y);
Location play = _hit.getLocation().add(x, y, z);
UtilParticle.PlayParticleToAll(ParticleType.WITCH_MAGIC, play, null, 0, 3, ViewDist.MAX);
}
}
}
}

View File

@ -1,9 +1,14 @@
package mineplex.game.clans.items.legendaries;
import mineplex.game.clans.items.GearManager;
import mineplex.game.clans.items.PlayerGear;
import net.minecraft.server.v1_8_R3.PlayerConnection;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.EventHandler;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.util.Vector;
import mineplex.core.common.util.C;
@ -16,85 +21,101 @@ import mineplex.core.common.util.UtilParticle.ParticleType;
import mineplex.core.common.util.UtilParticle.ViewDist;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilTextBottom;
import mineplex.core.common.util.UtilTextMiddle;
import mineplex.core.common.util.UtilTime;
import mineplex.core.recharge.Recharge;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import java.lang.reflect.Field;
public class WindBlade extends LegendaryItem
{
private static final Field G_FIELD;
static
{
try
{
G_FIELD = PlayerConnection.class.getDeclaredField("g");
G_FIELD.setAccessible(true);
}
catch (ReflectiveOperationException exception)
{
throw new RuntimeException("Could not reflectively access field", exception);
}
}
public static final double FLIGHT_VELOCITY = 0.75d;
private double _power;
private double _burnoutThreshold;
private int _messageTimer;
public WindBlade()
{
super("Wind Blade", new String[] {
super("Wind Blade", new String[]{
C.cWhite + "Long ago, a race of cloud dwellers",
C.cWhite + "terrorized the skies. A remnant of",
C.cWhite + "their tyranny, this airy blade is",
C.cWhite + "the last surviving memorium from",
C.cWhite + "their final battle against the Titans.",
" ",
C.cYellow + "Right-Click" + C.cWhite + " to use" + C.cGreen + " Fly",
C.cYellow + "Right-Click" + C.cWhite + " to use" + C.cGreen + " Fly",
}, Material.GREEN_RECORD);
}
@Override
public void update(Player wielder)
{
long burnoutRemaining = -1L;
if (Recharge.Instance.Get(wielder) != null && Recharge.Instance.Get(wielder).containsKey("clans_legendary_windblade_burnout"))
{
burnoutRemaining = Recharge.Instance.Get(wielder).get("clans_legendary_windblade_burnout").GetRemaining();
}
// Check if player is attempting to fly and activate
if (isHoldingRightClick())
{
if (canPropel(wielder))
{
wielder.setFallDistance(0f);
if (burnoutRemaining > 0)
{
_messageTimer++;
if (_messageTimer % 4 == 0)
{
UtilParticle.PlayParticle(ParticleType.SMOKE, wielder.getLocation(), 0.f, 0.f, 0.f, .1f, 1, ViewDist.NORMAL);
wielder.playSound(wielder.getLocation(), Sound.FIZZ, .5f, 1.f);
removePower(0.15);
_burnoutThreshold = 0;
}
if (_messageTimer % 5 == 0)
{
UtilPlayer.message(wielder, F.main("Wind Blade", "Flight power damaged whilst scraping the ground! Repairs will be finish in " + F.time(UtilTime.MakeStr(burnoutRemaining)) + "."));
}
if (_messageTimer % 10 == 0)
{
wielder.playSound(wielder.getLocation(), Sound.ANVIL_USE, .5f, 1.5f);
}
return;
}
removePower(UtilEnt.isGrounded(wielder) ? 1.17 : .88);
propelPlayer(wielder);
UtilParticle.PlayParticle(ParticleType.EXPLODE, wielder.getLocation().add(0, 1, 0), 0, 0, 0, .1f, 3, ViewDist.NORMAL);
wielder.playSound(wielder.getLocation(), Sound.FIRE, .25f, 1.75f);
}
if (UtilEnt.isGrounded(wielder))
{
_burnoutThreshold++;
@ -109,44 +130,67 @@ public class WindBlade extends LegendaryItem
{
_burnoutThreshold = UtilMath.clamp(_burnoutThreshold - .5, 0, _burnoutThreshold);
}
if (UtilEnt.isGrounded(wielder, wielder.getLocation()) || UtilEnt.isGrounded(wielder, wielder.getLocation().subtract(0, 1, 0)))
{
addPower(0.65);
}
if (_burnoutThreshold > 15 && burnoutRemaining <= 0)
{
Recharge.Instance.use(wielder, "clans_legendary_windblade_burnout", 2500, false, false);
}
UtilTextBottom.displayProgress(UtilMath.clamp(_power, .0, 80.) / 80., wielder);
}
@Override
public void onAttack(CustomDamageEvent event, Player wielder)
{
event.AddMod("Wind Blade", 6);
}
@EventHandler
public void onFall(CustomDamageEvent event)
{
if (event.GetDamageePlayer() != null && event.GetCause() == EntityDamageEvent.DamageCause.FALL)
{
PlayerGear playerGear = GearManager.getInstance().getPlayerGear(event.GetDamageePlayer());
if (playerGear.getWeapon() instanceof WindBlade)
{
event.SetCancelled("Wind Blade No Fall Damage");
}
}
}
private void propelPlayer(Player player)
{
Vector direction = player.getLocation().getDirection().normalize();
direction.multiply(FLIGHT_VELOCITY);
player.setVelocity(direction);
PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
try
{
G_FIELD.set(connection, 0);
}
catch (IllegalAccessException e)
{
new RuntimeException("Could not update g field", e).printStackTrace();
}
}
private boolean canPropel(Player player)
{
return _power > 0 && !UtilItem.isLiquid(player.getLocation().getBlock().getType());
}
private void addPower(double power)
{
_power = UtilMath.clamp(_power + power, -20, 80);
}
private void removePower(double power)
{
_power = UtilMath.clamp(_power - power, -20, 80);

View File

@ -213,6 +213,15 @@ public class Spawn extends MiniPlugin
}
}
@EventHandler
public void ignoreVelocity(PlayerVelocityEvent event)
{
if (_clansManager.getClanUtility().isSafe(event.getPlayer()))
{
event.setCancelled(true);
}
}
@EventHandler
public void onSkill(SkillTriggerEvent event)
{
@ -391,13 +400,13 @@ public class Spawn extends MiniPlugin
if (isInSpawn(victim))
{
event.SetCancelled("Safe Zone");
attemptNotify(attacker, "You cannot attack players who are in spawn!");
attemptNotify(attacker, "You cannot attack players who are in a safe zone!");
return;
}
else if (isInSpawn(attacker) && !isCombatTagged(attacker))
{
event.SetCancelled("Safe Zone");
attemptNotify(attacker, "You cannot attack untagged players while in spawn!");
attemptNotify(attacker, "You cannot attack untagged players while in a safe zone!");
return;
}
}

View File

@ -2,6 +2,7 @@ package mineplex.game.clans.tutorial;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Stack;
import org.bukkit.Bukkit;
@ -25,7 +26,7 @@ public class TutorialWorldManager extends MiniPlugin
private final World _tutorialWorld;
private final Schematic _schematic;
private Stack<TutorialRegion> _regionStack;
private LinkedList<TutorialRegion> _regionStack;
private TutorialRegion _centerRegion;
public TutorialWorldManager(JavaPlugin plugin, String worldName, String schematicName) throws IOException
@ -56,7 +57,7 @@ public class TutorialWorldManager extends MiniPlugin
private void populateRegionStack()
{
_regionStack = new Stack<>();
_regionStack = new LinkedList<>();
// Populate the stack with 100 available tutorial regions
for (int x = 0; x < 10; x++)

View File

@ -10,14 +10,16 @@ public class FinishCommand extends CommandBase<TutorialManager>
{
public FinishCommand(TutorialManager plugin)
{
super(plugin, Rank.JNR_DEV, "finish", "end");
super(plugin, Rank.ALL, "finish", "end");
}
@Override
public void Execute(Player caller, String[] args)
{
Plugin.finishTutorial(caller);
boolean testServer = Plugin.getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
if (_commandCenter.GetClientManager().hasRank(caller, testServer ? Rank.ALL : Rank.JNR_DEV))
{
Plugin.finishTutorial(caller);
}
}
}

View File

@ -1,19 +1,17 @@
package mineplex.game.clans.tutorial.command;
import org.bukkit.entity.Player;
import mineplex.core.command.CommandBase;
import mineplex.core.command.MultiCommandBase;
import mineplex.core.common.Rank;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import mineplex.game.clans.tutorial.TutorialManager;
import org.bukkit.entity.Player;
public class TutorialCommand extends MultiCommandBase<TutorialManager>
{
public TutorialCommand(TutorialManager plugin)
{
super(plugin, Rank.JNR_DEV, "tutorial", "tut");
super(plugin, Rank.ALL, "tutorial", "tut");
AddCommand(new StartCommand(plugin));
AddCommand(new FinishCommand(plugin));
@ -24,4 +22,14 @@ public class TutorialCommand extends MultiCommandBase<TutorialManager>
{
UtilPlayer.message(caller, F.main("Tutorial", "/tutorial start <name>"));
}
@Override
public void Execute(Player caller, String[] args)
{
boolean testServer = Plugin.getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
if (_commandCenter.GetClientManager().hasRank(caller, testServer ? Rank.ALL : Rank.JNR_DEV))
{
super.Execute(caller, args);
}
}
}

View File

@ -1,5 +1,7 @@
package mineplex.game.clans.tutorial.tutorials.clans.objective.goals.attackenemy;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilPlayer;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -8,6 +10,8 @@ import mineplex.core.common.util.UtilInv;
import mineplex.game.clans.clans.siege.events.LoadSiegeWeaponEvent;
import mineplex.game.clans.tutorial.objective.ObjectiveGoal;
import mineplex.game.clans.tutorial.tutorials.clans.objective.AttackEnemyObjective;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockPlaceEvent;
public class LoadCannonGoal extends ObjectiveGoal<AttackEnemyObjective>
{
@ -43,4 +47,15 @@ public class LoadCannonGoal extends ObjectiveGoal<AttackEnemyObjective>
finish(event.getPlayer());
}
@EventHandler (priority = EventPriority.MONITOR)
public void onBlockPlace(BlockPlaceEvent event)
{
if (!contains(event.getPlayer()))
{
return;
}
UtilPlayer.message(event.getPlayer(), F.main("Clans", "Are you sure? That's the only TNT you have!"));
event.setCancelled(true);
}
}

View File

@ -1,150 +1,151 @@
package mineplex.game.clans.world;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.*;
import org.bukkit.Bukkit;
import mineplex.core.common.util.UtilWorld;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.plugin.java.JavaPlugin;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.UtilMath;
import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.game.clans.clans.ClansManager;
public class WorldManager extends MiniPlugin
{
public WorldManager(JavaPlugin plugin)
{
private static final Map<EntityType, Integer> CULL_LIMITS = new HashMap<>();
private static final Set<EntityType> MINECART_TYPES = new HashSet<>();
private static final int MIN_RANGE = 64;
private static final int MIN_RANGE_SQUARED = MIN_RANGE * MIN_RANGE;
static
{
// Animals
CULL_LIMITS.put(EntityType.BAT, 50);
CULL_LIMITS.put(EntityType.CHICKEN, 150);
CULL_LIMITS.put(EntityType.COW, 150);
CULL_LIMITS.put(EntityType.HORSE, 50);
CULL_LIMITS.put(EntityType.IRON_GOLEM, 50);
CULL_LIMITS.put(EntityType.MUSHROOM_COW, 50);
CULL_LIMITS.put(EntityType.OCELOT, 50);
CULL_LIMITS.put(EntityType.PIG, 150);
CULL_LIMITS.put(EntityType.RABBIT, 50);
CULL_LIMITS.put(EntityType.SHEEP, 150);
CULL_LIMITS.put(EntityType.WOLF, 150);
// Monsters
CULL_LIMITS.put(EntityType.CAVE_SPIDER, 100);
CULL_LIMITS.put(EntityType.CREEPER, 100);
CULL_LIMITS.put(EntityType.ENDERMAN, 50);
CULL_LIMITS.put(EntityType.ENDERMITE, 50);
CULL_LIMITS.put(EntityType.SILVERFISH, 50);
CULL_LIMITS.put(EntityType.SKELETON, 100);
CULL_LIMITS.put(EntityType.SLIME, 50);
CULL_LIMITS.put(EntityType.SPIDER, 100);
CULL_LIMITS.put(EntityType.ZOMBIE, 100);
// Nether
CULL_LIMITS.put(EntityType.BLAZE, 50);
CULL_LIMITS.put(EntityType.GHAST, 50);
CULL_LIMITS.put(EntityType.MAGMA_CUBE, 50);
CULL_LIMITS.put(EntityType.PIG_ZOMBIE, 50);
MINECART_TYPES.add(EntityType.MINECART);
MINECART_TYPES.add(EntityType.MINECART_CHEST);
MINECART_TYPES.add(EntityType.MINECART_COMMAND);
MINECART_TYPES.add(EntityType.MINECART_FURNACE);
MINECART_TYPES.add(EntityType.MINECART_HOPPER);
MINECART_TYPES.add(EntityType.MINECART_MOB_SPAWNER);
MINECART_TYPES.add(EntityType.MINECART_TNT);
}
public WorldManager(JavaPlugin plugin)
{
super("Clan World Manager", plugin);
}
@EventHandler
public void cullMobs(UpdateEvent event)
{
if (event.getType() != UpdateType.SLOW)
return;
for (World world : getPlugin().getServer().getWorlds())
{
HashMap<EntityType, ArrayList<Entity>> _ents = new HashMap<EntityType, ArrayList<Entity>>();
for (EntityType type : EntityType.values())
_ents.put(type, new ArrayList<Entity>());
for (Entity ent : world.getEntities())
List<Player> players = world.getPlayers();
Map<EntityType, Set<Entity>> entities = new HashMap<>();
for (Entity entity : world.getEntities())
{
if (ent.getCustomName() == null)
if (entity.getCustomName() != null)
{
continue;
}
EntityType entityType = entity.getType();
if (entityType == EntityType.ARROW)
{
if (entity.getTicksLived() > 800)
{
entity.remove();
}
}
else if (entityType == EntityType.DROPPED_ITEM)
{
if (entity.getTicksLived() > 2400)
{
entity.remove();
}
}
else if (CULL_LIMITS.containsKey(entityType))
{
boolean cull = true;
for (Player player : world.getPlayers())
for (Player player : players)
{
if (player.getLocation().distance(ent.getLocation()) <= 64)
// Using NMS because this is going to be called quite a few times
// and each getLocation() call creates a new Location object
if (UtilWorld.distanceSquared(player, entity) <= MIN_RANGE_SQUARED)
{
cull = false;
break;
}
}
if (cull)
{
_ents.get(ent.getType()).add(ent);
entities.computeIfAbsent(entityType, key -> new HashSet<>()).add(entity);
}
}
else if (MINECART_TYPES.contains(entityType))
{
if (entity.getTicksLived() > 800)
{
entity.remove();
}
}
}
for (EntityType type : _ents.keySet())
for (Map.Entry<EntityType, Set<Entity>> entry : entities.entrySet())
{
ArrayList<Entity> ents = _ents.get(type);
//Clean Old Arrows
if (type == EntityType.ARROW)
{
for (Entity ent : ents)
if (ent.getTicksLived() > 800)
ent.remove();
}
//Clean Old Items
if (type == EntityType.DROPPED_ITEM)
{
for (Entity ent : ents)
if (ent.getTicksLived() > 2400)
ent.remove();
}
//Animals
else if (type == EntityType.BAT) cull(ents, 50);
else if (type == EntityType.CHICKEN) cull(ents, 150);
else if (type == EntityType.COW) cull(ents, 150);
else if (type == EntityType.HORSE) cull(ents, 50);
else if (type == EntityType.IRON_GOLEM) cull(ents, 50);
else if (type == EntityType.MUSHROOM_COW) cull(ents, 50);
else if (type == EntityType.OCELOT) cull(ents, 50);
else if (type == EntityType.PIG) cull(ents, 150);
else if (type == EntityType.RABBIT) cull(ents, 50);
else if (type == EntityType.SHEEP) cull(ents, 150);
else if (type == EntityType.WOLF) cull(ents, 150);
//Monster
else if (type == EntityType.CAVE_SPIDER) cull(ents, 100);
else if (type == EntityType.CREEPER) cull(ents, 100);
else if (type == EntityType.ENDERMAN) cull(ents, 50);
else if (type == EntityType.ENDERMITE) cull(ents, 50);
else if (type == EntityType.SILVERFISH) cull(ents, 50);
else if (type == EntityType.SKELETON) cull(ents, 100);
else if (type == EntityType.SLIME) cull(ents, 50);
else if (type == EntityType.SPIDER) cull(ents, 100);
else if (type == EntityType.ZOMBIE) cull(ents, 100);
//Nether
else if (type == EntityType.BLAZE) cull(ents, 50);
else if (type == EntityType.GHAST) cull(ents, 50);
else if (type == EntityType.MAGMA_CUBE) cull(ents, 50);
else if (type == EntityType.PIG_ZOMBIE) cull(ents, 50);
//Clean Old Minecarts
if (type == EntityType.MINECART ||
type == EntityType.MINECART_CHEST ||
type == EntityType.MINECART_COMMAND ||
type == EntityType.MINECART_FURNACE ||
type == EntityType.MINECART_HOPPER ||
type == EntityType.MINECART_MOB_SPAWNER ||
type == EntityType.MINECART_TNT)
{
for (Entity ent : ents)
if (ent.getTicksLived() > 800)
ent.remove();
}
cull(entry.getKey(), entry.getValue(), CULL_LIMITS.get(entry.getKey()));
}
}
}
public void cull(ArrayList<Entity> ents, int limit)
{
int culled = 0;
EntityType type = null;
while (ents.size() > limit)
{
Entity ent = ents.remove(UtilMath.r(ents.size()));
type = ent.getType();
ent.remove();
private void cull(EntityType type, Set<Entity> ents, int limit)
{
Iterator<Entity> iterator = ents.iterator();
int culled = 0;
while (iterator.hasNext() && ents.size() > limit)
{
Entity entity = iterator.next();
entity.remove();
iterator.remove();
culled++;
}
if (type != null)
{
System.out.println("Culled " + culled + " " + type);
}
log("Culled " + culled + " " + type);
}
}

View File

@ -78,7 +78,7 @@ public class Leap extends SkillActive
{
//Action
if (!wallkick)
UtilAction.velocity(player, 1.2, 0.2, 1, true);
UtilAction.velocity(player, 1 + 0.15 * level, 0.2, 1, true);
else
{
Vector vec = player.getLocation().getDirection();

View File

@ -59,12 +59,7 @@ public class Recall extends Skill
public void use(PlayerDropItemEvent event)
{
Player player = event.getPlayer();
if (!(player.getOpenInventory().getTopInventory() instanceof CraftInventoryCrafting))
{
return;
}
int level = getLevel(player);
if (level == 0)
return;
@ -87,49 +82,40 @@ public class Recall extends Skill
LinkedList<Location> locs = _locMap.remove(player);
if (locs == null)
return;
LinkedList<Double> health = _healthMap.remove(player);
if (health == null)
return;
//Heal
double newHealth = Math.min(health.getLast(), player.getHealth() + 3 + level);
player.setHealth(newHealth);
//Effect
player.getWorld().playSound(player.getLocation(), Sound.ZOMBIE_UNFECT, 2f, 2f);
//Teleport
Location current = player.getLocation();
Location target = locs.getLast();
player.teleport(target);
//Inform
UtilPlayer.message(player, F.main(GetClassType().name(), "You used " + F.skill(GetName(level)) + "."));
//Effect
player.getWorld().playSound(player.getLocation(), Sound.ZOMBIE_UNFECT, 2f, 2f);
while (UtilMath.offset(current, target) > 0.5)
{
UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, current, 0, 1f, 0, 0, 1,
ViewDist.LONGER, UtilServer.getPlayers());
current = current.add(UtilAlg.getTrajectory(current, target).multiply(0.1));
}
}
@EventHandler
public void closeInv(InventoryCloseEvent event)
{
if (getLevel(event.getPlayer()) == 0)
{
return;
}
event.getPlayer().getInventory().addItem(event.getPlayer().getItemOnCursor());
event.getPlayer().setItemOnCursor(null);
Factory.runSync(() -> {
//Heal
double newHealth = Math.min(health.getLast(), player.getHealth() + 3 + level);
player.setHealth(newHealth);
//Effect
player.getWorld().playSound(player.getLocation(), Sound.ZOMBIE_UNFECT, 2f, 2f);
//Teleport
Location current = player.getLocation();
Location target = locs.getLast();
player.teleport(target);
//Inform
UtilPlayer.message(player, F.main(GetClassType().name(), "You used " + F.skill(GetName(level)) + "."));
//Effect
player.getWorld().playSound(player.getLocation(), Sound.ZOMBIE_UNFECT, 2f, 2f);
while (UtilMath.offset(current, target) > 0.5)
{
UtilParticle.PlayParticle(ParticleType.WITCH_MAGIC, current, 0, 1f, 0, 0, 1,
ViewDist.LONGER, UtilServer.getPlayers());
current = current.add(UtilAlg.getTrajectory(current, target).multiply(0.1));
}
});
}
@EventHandler
public void storeLocation(UpdateEvent event)

View File

@ -2,6 +2,7 @@ package mineplex.minecraft.game.classcombat.Skill.Brute;
import java.util.HashMap;
import mineplex.minecraft.game.core.damage.CustomDamageEvent;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -34,21 +35,21 @@ public class Takedown extends SkillActive
{
private HashMap<LivingEntity, Long> _live = new HashMap<LivingEntity, Long>();
public Takedown(SkillFactory skills, String name, ClassType classType, SkillType skillType,
int cost, int levels,
int energy, int energyMod,
long recharge, long rechargeMod, boolean rechargeInform,
Material[] itemArray,
Action[] actionArray)
public Takedown(SkillFactory skills, String name, ClassType classType, SkillType skillType,
int cost, int levels,
int energy, int energyMod,
long recharge, long rechargeMod, boolean rechargeInform,
Material[] itemArray,
Action[] actionArray)
{
super(skills, name, classType, skillType,
cost, levels,
energy, energyMod,
recharge, rechargeMod, rechargeInform,
energy, energyMod,
recharge, rechargeMod, rechargeInform,
itemArray,
actionArray);
SetDesc(new String[]
SetDesc(new String[]
{
"Hurl yourself towards an opponent.",
"If you collide with them, you deal",
@ -58,7 +59,7 @@ public class Takedown extends SkillActive
}
@Override
public boolean CustomCheck(Player player, int level)
public boolean CustomCheck(Player player, int level)
{
if (player.getLocation().getBlock().getTypeId() == 8 || player.getLocation().getBlock().getTypeId() == 9)
{
@ -76,7 +77,7 @@ public class Takedown extends SkillActive
}
@Override
public void Skill(Player player, int level)
public void Skill(Player player, int level)
{
//Action
Vector vec = player.getLocation().getDirection();
@ -108,11 +109,11 @@ public class Takedown extends SkillActive
int level = getLevel(player);
if (level == 0) continue;
if (!UtilTime.elapsed(_live.get(player), 1000))
if (!UtilTime.elapsed(_live.get(player), 1000))
continue;
_live.remove(player);
}
_live.remove(player);
}
//Collide
for (Player player : GetUsers())
@ -167,25 +168,28 @@ public class Takedown extends SkillActive
int damage = 3 + (level);
//Damage Event
Factory.Damage().NewDamageEvent(damagee, damager, null,
CustomDamageEvent customDamageEvent = Factory.Damage().NewDamageEvent(damagee, damager, null,
DamageCause.CUSTOM, damage, false, true, false,
damager.getName(), GetName());
damager.getName(), GetName());
//Damage Event
Factory.Damage().NewDamageEvent(damager, damagee, null,
DamageCause.CUSTOM, damage/2, false, true, false,
damager.getName(), GetName() + " Recoil");
if (!customDamageEvent.IsCancelled())
{
//Damage Event
Factory.Damage().NewDamageEvent(damager, damagee, null,
DamageCause.CUSTOM, damage / 2, false, true, false,
damager.getName(), GetName() + " Recoil");
//Conditions
Factory.Condition().Factory().Slow(GetName(), damagee, damager, 2.5 + 0.5*level, 3, false, true, true, true);
Factory.Condition().Factory().Slow(GetName(), damager, damager, 2.5 + 0.5*level, 3, false, true, true, true);
//Conditions
Factory.Condition().Factory().Slow(GetName(), damagee, damager, 2.5 + 0.5 * level, 3, false, true, true, true);
Factory.Condition().Factory().Slow(GetName(), damager, damager, 2.5 + 0.5 * level, 3, false, true, true, true);
//Inform
UtilPlayer.message(damager, F.main(GetClassType().name(), "You hit " + F.name(UtilEnt.getName(damagee)) + " with " + F.skill(GetName(level)) + "."));
UtilPlayer.message(damagee, F.main(GetClassType().name(), F.name(damager.getName()) + " hit you with " + F.skill(GetName(level)) + "."));
//Inform
UtilPlayer.message(damager, F.main(GetClassType().name(), "You hit " + F.name(UtilEnt.getName(damagee)) + " with " + F.skill(GetName(level)) + "."));
UtilPlayer.message(damagee, F.main(GetClassType().name(), F.name(damager.getName()) + " hit you with " + F.skill(GetName(level)) + "."));
//Sound
damager.getWorld().playSound(damager.getLocation(), Sound.ZOMBIE_WOOD, 1f, 0.5f);
//Sound
damager.getWorld().playSound(damager.getLocation(), Sound.ZOMBIE_WOOD, 1f, 0.5f);
}
}
@EventHandler

View File

@ -1,5 +1,6 @@
package mineplex.minecraft.game.classcombat.Skill.Knight;
import mineplex.minecraft.game.core.condition.events.ConditionExpireEvent;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -22,6 +23,10 @@ import mineplex.core.updater.UpdateType;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.minecraft.game.classcombat.Skill.SkillActive;
import mineplex.minecraft.game.classcombat.Skill.SkillFactory;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.Map;
public class HoldPosition extends SkillActive
{
@ -47,10 +52,13 @@ public class HoldPosition extends SkillActive
});
}
private final Map<Player, Integer> _foodLevel = new HashMap<>();
@Override
public boolean CustomCheck(Player player, int level)
{
if (player.getLocation().getBlock().getTypeId() == 8 || player.getLocation().getBlock().getTypeId() == 9)
Material type = player.getLocation().getBlock().getType();
if (type == Material.WATER || type == Material.STATIONARY_WATER)
{
UtilPlayer.message(player, F.main("Skill", "You cannot use " + F.skill(GetName()) + " in water."));
return false;
@ -75,6 +83,8 @@ public class HoldPosition extends SkillActive
//Effect
player.getWorld().playSound(player.getLocation(), Sound.ENDERMAN_SCREAM, 1.5f, 0f);
player.getWorld().playEffect(player.getLocation(), Effect.STEP_SOUND, 49);
_foodLevel.put(player, player.getFoodLevel());
}
@EventHandler(priority = EventPriority.HIGH)
@ -123,8 +133,32 @@ public class HoldPosition extends SkillActive
}
}
@EventHandler
public void on(ConditionExpireEvent event)
{
if (event.getCondition().GetReason().equals(GetName()) && event.getCondition().GetEnt() instanceof Player)
{
if (event.getCondition().GetType() == ConditionType.DAMAGE_RESISTANCE)
{
Player player = ((Player) event.getCondition().GetEnt());
if (_foodLevel.get(player) != null)
{
player.setFoodLevel(_foodLevel.get(player));
}
// Could be null value. Sanity check
_foodLevel.remove(player);
}
}
}
@EventHandler
public void on(PlayerQuitEvent event)
{
_foodLevel.remove(event.getPlayer());
}
@Override
public void Reset(Player player)
public void Reset(Player player)
{
player.setFoodLevel(20);
}

View File

@ -7,6 +7,7 @@ import java.util.Map.Entry;
import java.util.WeakHashMap;
import mineplex.core.MiniPlugin;
import mineplex.core.common.util.UtilServer;
import mineplex.core.recharge.Recharge;
import mineplex.core.updater.event.UpdateEvent;
import mineplex.core.updater.UpdateType;
@ -18,6 +19,7 @@ import mineplex.core.common.util.UtilTime;
import mineplex.core.common.util.UtilTime.TimeUnit;
import mineplex.minecraft.game.core.condition.Condition.ConditionType;
import mineplex.minecraft.game.core.condition.events.ConditionApplyEvent;
import mineplex.minecraft.game.core.condition.events.ConditionExpireEvent;
import mineplex.minecraft.game.core.damage.DamageManager;
import org.bukkit.Material;
@ -189,7 +191,11 @@ public class ConditionManager extends MiniPlugin
Condition cond = conditionIterator.next();
if (cond.Tick())
{
ConditionExpireEvent conditionExpireEvent = new ConditionExpireEvent(cond);
UtilServer.CallEvent(conditionExpireEvent);
conditionIterator.remove();
}
}
}

View File

@ -0,0 +1,33 @@
package mineplex.minecraft.game.core.condition.events;
import mineplex.minecraft.game.core.condition.Condition;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
public class ConditionExpireEvent extends Event
{
private static final HandlerList handlers = new HandlerList();
private Condition _cond;
public ConditionExpireEvent(Condition cond)
{
_cond = cond;
}
public HandlerList getHandlers()
{
return handlers;
}
public static HandlerList getHandlerList()
{
return handlers;
}
public Condition getCondition()
{
return _cond;
}
}

View File

@ -171,37 +171,39 @@ public class DamageManager extends MiniPlugin
}
*/
public void NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj,
public CustomDamageEvent NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj,
DamageCause cause, double damage, boolean knockback, boolean ignoreRate, boolean ignoreArmor,
String source, String reason)
{
NewDamageEvent(damagee, damager, proj,
return NewDamageEvent(damagee, damager, proj,
cause, damage, knockback, ignoreRate, ignoreArmor,
source, reason, false);
}
public void NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj,
public CustomDamageEvent NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj,
DamageCause cause, double damage, boolean knockback, boolean ignoreRate, boolean ignoreArmor,
String source, String reason, boolean cancelled)
{
NewDamageEvent(damagee, damager, proj, null, cause, damage, knockback, ignoreRate, ignoreArmor, source, reason, cancelled);
return NewDamageEvent(damagee, damager, proj, null, cause, damage, knockback, ignoreRate, ignoreArmor, source, reason, cancelled);
}
public void NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj, Location knockbackOrigin,
public CustomDamageEvent NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj, Location knockbackOrigin,
DamageCause cause, double damage, boolean knockback, boolean ignoreRate, boolean ignoreArmor,
String source, String reason)
{
NewDamageEvent(damagee, damager, proj, knockbackOrigin, cause, damage, knockback, ignoreRate, ignoreArmor, source,
return NewDamageEvent(damagee, damager, proj, knockbackOrigin, cause, damage, knockback, ignoreRate, ignoreArmor, source,
reason, false);
}
public void NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj, Location knockbackOrigin,
public CustomDamageEvent NewDamageEvent(LivingEntity damagee, LivingEntity damager, Projectile proj, Location knockbackOrigin,
DamageCause cause, double damage, boolean knockback, boolean ignoreRate, boolean ignoreArmor,
String source, String reason, boolean cancelled)
{
_plugin.getServer().getPluginManager().callEvent(new CustomDamageEvent(damagee, damager, proj, knockbackOrigin, cause,
damage, knockback, ignoreRate, ignoreArmor, source, reason, cancelled));
}
{
CustomDamageEvent customDamageEvent = new CustomDamageEvent(damagee, damager, proj, knockbackOrigin, cause,
damage, knockback, ignoreRate, ignoreArmor, source, reason, cancelled);
_plugin.getServer().getPluginManager().callEvent(customDamageEvent);
return customDamageEvent;
}
@EventHandler(priority = EventPriority.LOW)
public void CancelDamageEvent(CustomDamageEvent event)
@ -282,21 +284,21 @@ public class DamageManager extends MiniPlugin
if (e.equals(Enchantment.PROTECTION_ENVIRONMENTAL))
event.AddMod("Ench Prot", damagee.getName(), 0.5 * (double)enchants.get(e), false);
else if (e.equals(Enchantment.PROTECTION_FIRE) &&
else if (e.equals(Enchantment.PROTECTION_FIRE) &&
event.GetCause() == DamageCause.FIRE &&
event.GetCause() == DamageCause.FIRE_TICK &&
event.GetCause() == DamageCause.LAVA)
event.AddMod("Ench Prot", damagee.getName(), 0.5 * (double)enchants.get(e), false);
else if (e.equals(Enchantment.PROTECTION_FALL) &&
else if (e.equals(Enchantment.PROTECTION_FALL) &&
event.GetCause() == DamageCause.FALL)
event.AddMod("Ench Prot", damagee.getName(), 0.5 * (double)enchants.get(e), false);
else if (e.equals(Enchantment.PROTECTION_EXPLOSIONS) &&
else if (e.equals(Enchantment.PROTECTION_EXPLOSIONS) &&
event.GetCause() == DamageCause.ENTITY_EXPLOSION)
event.AddMod("Ench Prot", damagee.getName(), 0.5 * (double)enchants.get(e), false);
else if (e.equals(Enchantment.PROTECTION_PROJECTILE) &&
else if (e.equals(Enchantment.PROTECTION_PROJECTILE) &&
event.GetCause() == DamageCause.PROJECTILE)
event.AddMod("Ench Prot", damagee.getName(), 0.5 * (double)enchants.get(e), false);
}
@ -322,7 +324,7 @@ public class DamageManager extends MiniPlugin
else if (e.equals(Enchantment.FIRE_ASPECT))
if (_conditionManager != null)
_conditionManager.Factory().Ignite("Ench Fire", event.GetDamageeEntity(), damager,
_conditionManager.Factory().Ignite("Ench Fire", event.GetDamageeEntity(), damager,
4 * (double)enchants.get(e), false, false);
}
}
@ -351,8 +353,15 @@ public class DamageManager extends MiniPlugin
}
}
}
//Debug
}
/*
* Should only be used to debug the damage event
* No modification of the event should take place
*/
@EventHandler (priority = EventPriority.MONITOR)
public void debugDamageEvent(CustomDamageEvent event)
{
DisplayDamage(event);
}
@ -529,7 +538,7 @@ public class DamageManager extends MiniPlugin
}
}
@EventHandler
@EventHandler (priority = EventPriority.MONITOR)
public void DamageSound(CustomDamageEvent event)
{
if (event.IsCancelled())

View File

@ -1,8 +1,5 @@
package nautilus.game.arcade;
import java.util.AbstractMap;
import java.util.Map.Entry;
import mineplex.core.common.MinecraftVersion;
import mineplex.core.common.Pair;
import mineplex.core.game.GameCategory;
@ -74,7 +71,6 @@ import nautilus.game.arcade.game.games.valentines.Valentines;
import nautilus.game.arcade.game.games.wither.WitherGame;
import nautilus.game.arcade.game.games.wizards.Wizards;
import nautilus.game.arcade.game.games.zombiesurvival.ZombieSurvival;
import org.bukkit.Material;
public enum GameType
@ -100,7 +96,7 @@ public enum GameType
DragonsTeams(DragonsTeams.class, GameDisplay.DragonsTeams),
Draw(Draw.class, GameDisplay.Draw, new Pair[]
{
Pair.create(MinecraftVersion.ALL, "http://chivebox.com/mineplex/ResDrawMyThing.zip")
Pair.create(MinecraftVersion.ALL, "http://file.mineplex.com/ResDrawMyThing.zip")
}, true),
ElytraRings(ElytraRings.class, GameDisplay.ElytraRings),
Evolution(Evolution.class, GameDisplay.Evolution),
@ -117,8 +113,8 @@ public enum GameType
MilkCow(MilkCow.class, GameDisplay.MilkCow),
MineStrike(MineStrike.class, GameDisplay.MineStrike, new Pair[]
{
Pair.create(MinecraftVersion.Version1_8, "http://chivebox.com/mineplex/ResMinestrike.zip"),
Pair.create(MinecraftVersion.Version1_9, "http://chivebox.com/mineplex/ResMinestrike19.zip")
Pair.create(MinecraftVersion.Version1_8, "http://file.mineplex.com/ResMinestrike.zip"),
Pair.create(MinecraftVersion.Version1_9, "http://file.mineplex.com/ResMinestrike19.zip")
}, true),
MineWare(MineWare.class, GameDisplay.MineWare),
MinecraftLeague(MinecraftLeague.class, GameDisplay.Minecraft_League),

View File

@ -140,7 +140,7 @@ public class MiscManager implements Listener
@EventHandler
public void HubCommand(PlayerCommandPreprocessEvent event)
{
if (event.getMessage().toLowerCase().startsWith("/lobby") || event.getMessage().toLowerCase().startsWith("/hub") || event.getMessage().toLowerCase().startsWith("/leave"))
if (event.getMessage().toLowerCase().equals("/lobby") || event.getMessage().toLowerCase().equals("/hub") || event.getMessage().toLowerCase().equals("/leave"))
{
Manager.GetPortal().sendPlayerToServer(event.getPlayer(), "Lobby");
event.setCancelled(true);