Merge branch 'develop' of github.com:Mineplex-LLC/Minecraft-PC into update/basketball-game
This commit is contained in:
commit
ab315627ad
@ -16,6 +16,10 @@
|
||||
<groupId>com.mineplex</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -1,29 +1,40 @@
|
||||
package mineplex.core.common;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import org.bukkit.Material;
|
||||
|
||||
public enum CurrencyType
|
||||
{
|
||||
Tokens("Tokens", Material.EMERALD),
|
||||
Coins("Treasure Shards", Material.PRISMARINE_SHARD),
|
||||
Gems("Gems", Material.EMERALD),
|
||||
Gold("Gold", Material.GOLD_NUGGET);
|
||||
|
||||
private String _prefix;
|
||||
TOKEN("Tokens", "Token", C.cWhite, Material.EMERALD),
|
||||
TREASURE_SHARD("Treasure Shards", "Treasure Shard", C.cAqua, Material.PRISMARINE_SHARD),
|
||||
GEM("Gems", "Gem", C.cGreen, Material.EMERALD),
|
||||
GOLD("Gold", "Gold", C.cGold, Material.GOLD_NUGGET);
|
||||
|
||||
private String _plural;
|
||||
private String _single;
|
||||
private String _color;
|
||||
private Material _displayMaterial;
|
||||
|
||||
CurrencyType(String prefix, Material displayMaterial)
|
||||
CurrencyType(String plural, String single, String color, Material displayMaterial)
|
||||
{
|
||||
_prefix = prefix;
|
||||
_plural = plural;
|
||||
_single = single;
|
||||
_color = color;
|
||||
_displayMaterial = displayMaterial;
|
||||
}
|
||||
|
||||
public String Prefix()
|
||||
|
||||
@Deprecated
|
||||
public String getPrefix()
|
||||
{
|
||||
return _prefix;
|
||||
return _plural;
|
||||
}
|
||||
|
||||
public String getString(int amount)
|
||||
{
|
||||
return _color + amount + " " + (amount == 1 ? _single : _plural);
|
||||
}
|
||||
|
||||
public Material GetDisplayMaterial()
|
||||
public Material getDisplayMaterial()
|
||||
{
|
||||
return _displayMaterial;
|
||||
}
|
||||
|
@ -23,6 +23,16 @@ public class MaterialData
|
||||
return new MaterialData(material, data);
|
||||
}
|
||||
|
||||
public Material getMaterial()
|
||||
{
|
||||
return _material;
|
||||
}
|
||||
|
||||
public byte getData()
|
||||
{
|
||||
return _data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
|
@ -0,0 +1,48 @@
|
||||
package mineplex.core.common;
|
||||
|
||||
import mineplex.core.common.block.schematic.Schematic;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
/**
|
||||
* Loads schematics based on an ordered input value. A good example of usage would be to load schematics in the
|
||||
* ordering of a progress bar.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class SortedSchematicLoader<T>
|
||||
{
|
||||
private final TreeMap<T, Schematic> _schematicMap;
|
||||
private final Location _pasteLocation;
|
||||
private T _currentValue = null;
|
||||
|
||||
public SortedSchematicLoader(Location pasteLocation)
|
||||
{
|
||||
this(pasteLocation, null);
|
||||
}
|
||||
|
||||
public SortedSchematicLoader(Location pasteLocation, Comparator<T> comparator)
|
||||
{
|
||||
_schematicMap = new TreeMap<>(comparator);
|
||||
_pasteLocation = pasteLocation;
|
||||
}
|
||||
|
||||
public void addSchematic(T minValue, Schematic schematic)
|
||||
{
|
||||
_schematicMap.put(minValue, schematic);
|
||||
}
|
||||
|
||||
public void update(T value)
|
||||
{
|
||||
Map.Entry<T, Schematic> entry = _schematicMap.floorEntry(value);
|
||||
|
||||
if (entry != null && !entry.getKey().equals(_currentValue))
|
||||
{
|
||||
_currentValue = entry.getKey();
|
||||
entry.getValue().paste(_pasteLocation, false);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package mineplex.core.common.animation;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class AnimationPoint
|
||||
{
|
||||
|
||||
private final int _tick;
|
||||
private final Vector _move;
|
||||
private final Vector _dir;
|
||||
|
||||
public AnimationPoint(int tick, Vector move, Vector dir)
|
||||
{
|
||||
_tick = tick;
|
||||
_move = move.clone();
|
||||
_dir = dir.clone();
|
||||
}
|
||||
|
||||
public Vector getMove()
|
||||
{
|
||||
return _move.clone();
|
||||
}
|
||||
|
||||
public Vector getDirection()
|
||||
{
|
||||
return _dir.clone();
|
||||
}
|
||||
|
||||
public int getTick()
|
||||
{
|
||||
return _tick;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(obj instanceof AnimationPoint) {
|
||||
AnimationPoint point = (AnimationPoint) obj;
|
||||
return point._tick == _tick && point._move.equals(_move);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(_tick, _move);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
package mineplex.core.common.animation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* Self sufficient animator to animate task with steps using local vector logic
|
||||
*/
|
||||
|
||||
public abstract class Animator
|
||||
{
|
||||
private final Plugin _plugin;
|
||||
|
||||
// private TreeSet<AnimationPoint> _points = new TreeSet<>((a, b) -> Integer.compare(a.getTick(), b.getTick()));
|
||||
private Set<AnimationPoint> _points = new HashSet<>();
|
||||
private PriorityQueue<AnimationPoint> _queue = new PriorityQueue<>((a, b) -> Integer.compare(a.getTick(), b.getTick()));
|
||||
|
||||
private AnimationPoint _prev;
|
||||
private AnimationPoint _next;
|
||||
private Location _baseLoc;
|
||||
private int _tick = -1;
|
||||
|
||||
private boolean _repeat = false;
|
||||
|
||||
private BukkitTask _task;
|
||||
|
||||
public Animator(Plugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
public void addPoint(AnimationPoint point) {
|
||||
_points.add(point);
|
||||
}
|
||||
|
||||
public void removePoint(AnimationPoint point) {
|
||||
_points.remove(point);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns a cloned list of the animator points for this instance.
|
||||
*/
|
||||
public Set<AnimationPoint> getSet() {
|
||||
return new HashSet<AnimationPoint>(_points);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the actual list of animator points used by this instance. As this is not a copy, editing this list will apply
|
||||
* changes to the current instance.
|
||||
*/
|
||||
public Set<AnimationPoint> getSetRaw() {
|
||||
return _points;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the animation at the given location. If the animator is already running then this call will be silently ignored.
|
||||
* @param loc Location the animation will start relative too. The vector poitns will be added to relative to this location.
|
||||
*/
|
||||
public void start(Location loc)
|
||||
{
|
||||
if(isRunning()) return;
|
||||
|
||||
_queue.clear();
|
||||
_queue.addAll(_points);
|
||||
|
||||
if(_queue.isEmpty()) return;
|
||||
|
||||
_baseLoc = loc.clone();
|
||||
_next = _queue.peek();
|
||||
_prev = new AnimationPoint(0, _next.getMove().clone(), _next.getDirection().clone());
|
||||
|
||||
_task = new BukkitRunnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
_tick++;
|
||||
|
||||
if(_next.getTick() < _tick)
|
||||
{
|
||||
_queue.remove();
|
||||
_prev = _next;
|
||||
_next = _queue.peek();
|
||||
}
|
||||
|
||||
if(_queue.isEmpty())
|
||||
{
|
||||
if(_repeat)
|
||||
{
|
||||
Location clone = _baseLoc.clone();
|
||||
stop();
|
||||
start(clone);
|
||||
}
|
||||
else
|
||||
{
|
||||
finish(_baseLoc);
|
||||
stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Location prev = _baseLoc.clone().add(_prev.getMove());
|
||||
Location next = _baseLoc.clone().add(_next.getMove());
|
||||
prev.setDirection(_prev.getDirection());
|
||||
|
||||
double diff = ((double)_tick-_prev.getTick())/(_next.getTick()-_prev.getTick());
|
||||
prev.add(next.clone().subtract(prev).toVector().multiply(diff));
|
||||
|
||||
Vector dirDiff = _next.getDirection().subtract(prev.getDirection());
|
||||
dirDiff.multiply(diff);
|
||||
prev.setDirection(prev.getDirection().add(dirDiff));
|
||||
|
||||
tick(prev);
|
||||
}
|
||||
}.runTaskTimer(_plugin, 0, 1);
|
||||
}
|
||||
|
||||
public boolean isRunning()
|
||||
{
|
||||
return _task != null;
|
||||
}
|
||||
|
||||
public void stop()
|
||||
{
|
||||
if(!isRunning()) return;
|
||||
_task.cancel();
|
||||
_task = null;
|
||||
_tick = -1;
|
||||
_baseLoc = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true if the animation should repeat.
|
||||
* @see #setRepeat(boolean)
|
||||
*/
|
||||
public boolean isRepeat()
|
||||
{
|
||||
return _repeat;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the last animation point does not make the animation end up at the exact same location as the start
|
||||
* then it might lead to unexpected results as it will re-start the animation from the end of the animation.
|
||||
*/
|
||||
public void setRepeat(boolean repeat)
|
||||
{
|
||||
_repeat = repeat;
|
||||
}
|
||||
|
||||
protected abstract void tick(Location loc);
|
||||
|
||||
|
||||
protected abstract void finish(Location loc);
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package mineplex.core.common.animation;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link Animator} which will teleport the provided entity along the animation path each tick.
|
||||
*/
|
||||
|
||||
public class AnimatorEntity extends Animator
|
||||
{
|
||||
|
||||
private final Entity _ent;
|
||||
|
||||
public AnimatorEntity(Plugin plugin, Entity ent)
|
||||
{
|
||||
super(plugin);
|
||||
_ent = ent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tick(Location loc)
|
||||
{
|
||||
if(!_ent.isValid())
|
||||
{
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
_ent.setVelocity(new Vector(0,0,0));
|
||||
_ent.teleport(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finish(Location loc) {}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ApiEndpoint
|
||||
{
|
||||
private static final String API_HOST = "10.33.53.12";
|
||||
// private static final String API_HOST = "localhost";
|
||||
// private static final int API_PORT = 3000;
|
||||
private static final int API_PORT = 7979;
|
||||
|
||||
private Gson _gson;
|
||||
private ApiWebCall _webCall;
|
||||
|
||||
public ApiEndpoint(String path, Gson gson)
|
||||
{
|
||||
String url = "http://" + API_HOST + ":" + API_PORT + path;
|
||||
_webCall = new ApiWebCall(url, gson);
|
||||
_gson = gson;
|
||||
}
|
||||
|
||||
protected ApiWebCall getWebCall()
|
||||
{
|
||||
return _webCall;
|
||||
}
|
||||
|
||||
public Gson getGson()
|
||||
{
|
||||
return _gson;
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
import com.google.gson.FieldNamingStrategy;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ApiFieldNamingStrategy implements FieldNamingStrategy
|
||||
{
|
||||
@Override
|
||||
public String translateName(Field field)
|
||||
{
|
||||
return (field.getName().startsWith("_") ? field.getName().substring(1) : field.getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ApiResponse implements HttpStatusCode
|
||||
{
|
||||
// These do not have _ prefix because of gson. Please do not add underscores!
|
||||
private int statusCode;
|
||||
private boolean success;
|
||||
private String error;
|
||||
|
||||
public ApiResponse()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return success;
|
||||
}
|
||||
|
||||
public String getError()
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ApiResponse{" +
|
||||
"success=" + success +
|
||||
", error='" + error + '\'' +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatusCode()
|
||||
{
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatusCode(int statusCode)
|
||||
{
|
||||
this.statusCode = statusCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ApiWebCall
|
||||
{
|
||||
private String _url;
|
||||
private Gson _gson;
|
||||
private PoolingHttpClientConnectionManager _cm;
|
||||
private CloseableHttpClient _httpClient;
|
||||
|
||||
public ApiWebCall(String url, Gson gson)
|
||||
{
|
||||
_url = url;
|
||||
_gson = gson;
|
||||
|
||||
_cm = new PoolingHttpClientConnectionManager();
|
||||
_cm.setMaxTotal(200);
|
||||
_cm.setDefaultMaxPerRoute(20);
|
||||
_httpClient = HttpClients.custom().setConnectionManager(_cm).build();
|
||||
}
|
||||
|
||||
public <T> T get(String resource, Class<T> clazz)
|
||||
{
|
||||
return get(resource, (Type)clazz);
|
||||
}
|
||||
|
||||
public <T> T get(String resource, Type type)
|
||||
{
|
||||
T returnData = null;
|
||||
|
||||
HttpGet httpGet = new HttpGet(_url + resource);
|
||||
try (CloseableHttpResponse response = _httpClient.execute(httpGet)) {
|
||||
returnData = parseResponse(response, type);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
public <T> T post(String resource, Class<T> clazz, Object data)
|
||||
{
|
||||
T returnData = null;
|
||||
|
||||
HttpPost httpPost = new HttpPost(_url + resource);
|
||||
try
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
StringEntity params = new StringEntity(_gson.toJson(data));
|
||||
params.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
|
||||
httpPost.setEntity(params);
|
||||
}
|
||||
|
||||
try (CloseableHttpResponse response = _httpClient.execute(httpPost))
|
||||
{
|
||||
returnData = parseResponse(response, clazz);
|
||||
} catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} catch (UnsupportedEncodingException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
private <T> T parseResponse(CloseableHttpResponse response, Type type) throws IOException
|
||||
{
|
||||
HttpEntity entity = response.getEntity();
|
||||
T parsed = _gson.fromJson(new InputStreamReader(entity.getContent()), type);
|
||||
if (parsed instanceof HttpStatusCode && response.getStatusLine() != null)
|
||||
{
|
||||
((HttpStatusCode) parsed).setStatusCode(response.getStatusLine().getStatusCode());
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
/**
|
||||
* Interface used to also grab status code from ApiWebCall
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public interface HttpStatusCode
|
||||
{
|
||||
public int getStatusCode();
|
||||
|
||||
public void setStatusCode(int statusCode);
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package mineplex.core.common.api;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ListResponseType<Data> implements ParameterizedType
|
||||
{
|
||||
private Class<Data> _wrapped;
|
||||
|
||||
public ListResponseType(Class<Data> wrapped)
|
||||
{
|
||||
_wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments()
|
||||
{
|
||||
return new Type[] { _wrapped };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType()
|
||||
{
|
||||
return List.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,126 @@
|
||||
package mineplex.core.common.block;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.BlockVector;
|
||||
|
||||
import mineplex.core.common.util.MapUtil;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import net.minecraft.server.v1_8_R3.Chunk;
|
||||
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMultiBlockChange;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMultiBlockChange.MultiBlockChangeInfo;
|
||||
|
||||
/**
|
||||
* An agent used to easily record and send multi-block update packets to players. The agent handles if the packet should be a
|
||||
* MultiBlock packet or a chunk update. It also supports blocks across multiple chunks.
|
||||
*/
|
||||
|
||||
public class MultiBlockUpdaterAgent
|
||||
{
|
||||
|
||||
private Map<Chunk, List<BlockVector>> _chunks = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Add a block to the list of blocks to send to the player. The agent supports blocks across different chunks and
|
||||
* will not send duplicates.
|
||||
* @param block The block to send. The block is stored using a BlockVector, meaning that when the send method is called, it will use
|
||||
* the material and data found for the block at the moment you call the send method.
|
||||
* @see #send(Collection)
|
||||
*/
|
||||
public void addBlock(Block block)
|
||||
{
|
||||
Chunk c = ((CraftChunk)block.getChunk()).getHandle();
|
||||
List<BlockVector> list = _chunks.computeIfAbsent(c,chunk -> new ArrayList<>());
|
||||
|
||||
if(list.size() >= 64) return;
|
||||
|
||||
BlockVector bv = block.getLocation().toVector().toBlockVector();
|
||||
if(list.contains(bv)) return;
|
||||
list.add(bv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends all the record blocks to all online players. Players out of range will not receive packets.
|
||||
* @see #send(Collection)
|
||||
*/
|
||||
public void send()
|
||||
{
|
||||
send(UtilServer.getPlayersCollection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all blocks for this agent.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
_chunks.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send all the recorded blocks to the provided players. This will only send packets to players in range. If the blocks span multiple
|
||||
* chunks then players will only receive block updates for chunks close to them.
|
||||
* @param players The players which will the packets will be sent to.
|
||||
*/
|
||||
public void send(Collection<? extends Player> players)
|
||||
{
|
||||
for(Player p : players)
|
||||
{
|
||||
for(Chunk c : _chunks.keySet())
|
||||
{
|
||||
if(!p.getWorld().equals(c.bukkitChunk.getWorld())) continue;
|
||||
|
||||
int x = p.getLocation().getChunk().getX();
|
||||
int z = p.getLocation().getChunk().getZ();
|
||||
|
||||
int chunkDist = Math.max(Math.abs(c.locX-x), Math.abs(c.locZ-z));
|
||||
|
||||
if(chunkDist > Bukkit.getViewDistance()) continue;
|
||||
|
||||
sendPacket(c, players);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket(Chunk c, Collection<? extends Player> players)
|
||||
{
|
||||
List<BlockVector> list = _chunks.get(c);
|
||||
|
||||
if(list == null) return;
|
||||
|
||||
if(list.size() >= 64)
|
||||
{
|
||||
for(Player p : players)
|
||||
{
|
||||
MapUtil.SendChunkForPlayer(c, p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange();
|
||||
packet.a = new ChunkCoordIntPair(c.locX, c.locZ);
|
||||
packet.b = new MultiBlockChangeInfo[list.size()];
|
||||
for(int i = 0; i < list.size(); i++)
|
||||
{
|
||||
BlockVector bv = list.get(i);
|
||||
short xyz = (short)((bv.getBlockX() & 0xF) << 12 | (bv.getBlockZ() & 0xF) << 8 | bv.getBlockY());
|
||||
packet.b[i] = packet.new MultiBlockChangeInfo(xyz, c);
|
||||
}
|
||||
|
||||
for(Player p : players)
|
||||
{
|
||||
UtilPlayer.sendPacket(p, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,9 @@ package mineplex.core.common.block.schematic;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.mysql.jdbc.Util;
|
||||
|
||||
import mineplex.core.common.block.DataLocationMap;
|
||||
import mineplex.core.common.util.UtilBlock;
|
||||
@ -14,23 +17,46 @@ public class Schematic
|
||||
private final short _length;
|
||||
private final short[] _blocks;
|
||||
private final byte[] _blockData;
|
||||
private final Vector _weOffset;
|
||||
|
||||
public Schematic(short width, short height, short length, short[] blocks, byte[] blockData)
|
||||
public Schematic(short width, short height, short length, short[] blocks, byte[] blockData, Vector worldEditOffset)
|
||||
{
|
||||
_width = width;
|
||||
_height = height;
|
||||
_length = length;
|
||||
_blocks = blocks;
|
||||
_blockData = blockData;
|
||||
_weOffset = worldEditOffset;
|
||||
}
|
||||
|
||||
|
||||
public Schematic(short width, short height, short length, short[] blocks, byte[] blockData)
|
||||
{
|
||||
this(width, height, length, blocks, blockData, null);
|
||||
}
|
||||
|
||||
public DataLocationMap paste(Location originLocation)
|
||||
{
|
||||
return paste(originLocation, false);
|
||||
}
|
||||
|
||||
public DataLocationMap paste(Location originLocation, boolean ignoreAir)
|
||||
{
|
||||
return paste(originLocation, ignoreAir, false);
|
||||
}
|
||||
|
||||
public DataLocationMap paste(Location originLocation, boolean ignoreAir, boolean worldEditOffset)
|
||||
{
|
||||
if(worldEditOffset && hasWorldEditOffset())
|
||||
{
|
||||
originLocation = originLocation.clone().add(_weOffset);
|
||||
}
|
||||
DataLocationMap locationMap = new DataLocationMap();
|
||||
|
||||
int startX = originLocation.getBlockX();
|
||||
int startY = originLocation.getBlockY();
|
||||
int startZ = originLocation.getBlockZ();
|
||||
|
||||
UtilBlock.startQuickRecording();
|
||||
|
||||
for (int x = 0; x < _width; x++)
|
||||
{
|
||||
@ -86,6 +112,8 @@ public class Schematic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UtilBlock.stopQuickRecording();
|
||||
|
||||
return locationMap;
|
||||
}
|
||||
@ -141,6 +169,11 @@ public class Schematic
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasWorldEditOffset()
|
||||
{
|
||||
return _weOffset != null;
|
||||
}
|
||||
|
||||
public int getSize()
|
||||
{
|
||||
|
@ -6,8 +6,11 @@ import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.java.sk89q.jnbt.ByteArrayTag;
|
||||
import com.java.sk89q.jnbt.CompoundTag;
|
||||
import com.java.sk89q.jnbt.IntTag;
|
||||
import com.java.sk89q.jnbt.NBTInputStream;
|
||||
import com.java.sk89q.jnbt.NamedTag;
|
||||
import com.java.sk89q.jnbt.ShortTag;
|
||||
@ -36,6 +39,15 @@ public class UtilSchematic
|
||||
byte[] addId = new byte[0];
|
||||
short[] blocks = new short[blockId.length];
|
||||
byte[] blockData = getChildTag(schematic, "Data", ByteArrayTag.class).getValue();
|
||||
|
||||
Vector weOffset = null;
|
||||
if(schematic.containsKey("WEOffsetX") && schematic.containsKey("WEOffsetY") && schematic.containsKey("WEOffsetZ"))
|
||||
{
|
||||
int x = getChildTag(schematic, "WEOffsetX", IntTag.class).getValue();
|
||||
int y = getChildTag(schematic, "WEOffsetY", IntTag.class).getValue();
|
||||
int z = getChildTag(schematic, "WEOffsetZ", IntTag.class).getValue();
|
||||
weOffset = new Vector(x, y, z);
|
||||
}
|
||||
|
||||
if (schematic.containsKey("AddBlocks"))
|
||||
{
|
||||
@ -56,7 +68,7 @@ public class UtilSchematic
|
||||
}
|
||||
|
||||
|
||||
return new Schematic(width, height, length, blocks, blockData);
|
||||
return new Schematic(width, height, length, blocks, blockData, weOffset);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,16 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* Interface used by classes which can display visuals at provided locations.
|
||||
*/
|
||||
public interface CosmeticShape
|
||||
{
|
||||
/**
|
||||
* Display a visual at the given location
|
||||
* @param loc The location to display the visual at
|
||||
*/
|
||||
void display(Location loc);
|
||||
|
||||
}
|
@ -0,0 +1,189 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* A simple 3D vector stored shape
|
||||
*/
|
||||
|
||||
public class Shape
|
||||
{
|
||||
|
||||
protected final static double DEFAULT_DENSITY = 1;
|
||||
|
||||
protected HashSet<Vector> _points = new HashSet<>();
|
||||
|
||||
public Shape(){}
|
||||
|
||||
public Shape(Collection<Vector> points){
|
||||
this._points.addAll(points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate this shape along the X-axis
|
||||
* @param radians Radians to rotate the shape
|
||||
*/
|
||||
public void rotateOnXAxis(double radians)
|
||||
{
|
||||
for(Vector v : _points)
|
||||
{
|
||||
double y = v.getY();
|
||||
double z = v.getZ();
|
||||
v.setY(y * Math.cos(radians) - z * Math.sin(radians));
|
||||
v.setZ(y * Math.sin(radians) + z * Math.cos(radians));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate this shape along the Y-axis
|
||||
* @param radians Radians to rotate the shape
|
||||
*/
|
||||
public void rotateOnYAxis(double radians)
|
||||
{
|
||||
for(Vector v : _points)
|
||||
{
|
||||
double x = v.getX();
|
||||
double z = v.getZ();
|
||||
v.setX(x * Math.cos(radians) - z * Math.sin(radians));
|
||||
v.setZ(x * Math.sin(radians) + z * Math.cos(radians));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate this shape along the Z-axis
|
||||
* @param radians Radians to rotate the shape
|
||||
*/
|
||||
public void rotateOnZAxis(double radians)
|
||||
{
|
||||
for(Vector v : _points)
|
||||
{
|
||||
double x = v.getX();
|
||||
double y = v.getY();
|
||||
v.setX(x * Math.cos(radians) - y * Math.sin(radians));
|
||||
v.setY(x * Math.sin(radians) + y * Math.cos(radians));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets all the points based on the given vector
|
||||
* @param v
|
||||
*/
|
||||
public void add(Vector v)
|
||||
{
|
||||
for(Vector p : _points) p.add(v);
|
||||
}
|
||||
|
||||
public void addPoint(Vector v)
|
||||
{
|
||||
_points.add(v);
|
||||
}
|
||||
|
||||
public boolean removePoint(Vector v)
|
||||
{
|
||||
return _points.remove(v);
|
||||
}
|
||||
|
||||
public Set<Vector> getPoints()
|
||||
{
|
||||
return new HashSet<>(_points);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply all the points by m.
|
||||
* If m > 1 then the shape will become larger.
|
||||
* If m < 1 then the shape will become smaller.
|
||||
* If m = 1 then the shape will stay the same.
|
||||
* If m < 0 then the shape will become inverted.
|
||||
* @param m
|
||||
*/
|
||||
public void multiply(double m)
|
||||
{
|
||||
for(Vector v : _points) v.multiply(m);
|
||||
}
|
||||
|
||||
public Shape clone() {
|
||||
List<Vector> list = new ArrayList<>();
|
||||
for(Vector p : _points)
|
||||
{
|
||||
list.add(p.clone());
|
||||
}
|
||||
return new Shape(list);
|
||||
}
|
||||
|
||||
public Vector getMidPoint()
|
||||
{
|
||||
return getMaxAABBCorner().subtract(getMinAABBCorner()).multiply(0.5);
|
||||
}
|
||||
|
||||
public Vector getMaxAABBCorner()
|
||||
{
|
||||
Vector max = null;
|
||||
for(Vector v : _points)
|
||||
{
|
||||
if(max == null)
|
||||
{
|
||||
max = v.clone();
|
||||
continue;
|
||||
}
|
||||
if(v.getX() > max.getX()) max.setX(v.getX());
|
||||
if(v.getY() > max.getY()) max.setY(v.getY());
|
||||
if(v.getZ() > max.getZ()) max.setZ(v.getZ());
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public Vector getMinAABBCorner()
|
||||
{
|
||||
Vector min = null;
|
||||
for(Vector v : _points)
|
||||
{
|
||||
if(min == null)
|
||||
{
|
||||
min = v.clone();
|
||||
continue;
|
||||
}
|
||||
if(v.getX() < min.getX()) min.setX(v.getX());
|
||||
if(v.getY() < min.getY()) min.setY(v.getY());
|
||||
if(v.getZ() < min.getZ()) min.setZ(v.getZ());
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest length which will be a factor of the provided length, but not longer then max
|
||||
* E.g. You want to split a length of 9 into even peaces, but the peaces should not be longer than the max 5, then this will
|
||||
* return 4.5, as 4.5 goes 2 times to make up precisely 9.
|
||||
* @param length The length which the returned factor should fit into
|
||||
* @param max The max distance of the returned length
|
||||
* @return The closest to length to be a factor of the provided length which is <= max
|
||||
*/
|
||||
|
||||
public static double getRoundFactor(double length, double max)
|
||||
{
|
||||
return length/Math.ceil(length/max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the closest RoundFactor length applied to a vector, using the vector as the max length. The returned vector is a cloned
|
||||
* parallel vector to the provided length
|
||||
* @param length The vector used as length and direction
|
||||
* @param maxLength The max length of the new returned vector
|
||||
* @return Returns a parallel vector to the given length vector which is also a factor of the provided vector, but not longer
|
||||
* then maxLength
|
||||
*
|
||||
* @see #getRoundFactor(double, double)
|
||||
*/
|
||||
public static Vector getVectorFactor(Vector length, double maxLength)
|
||||
{
|
||||
return length.clone().multiply(getRoundFactor(length.length(), maxLength));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* An extension of {@link Shape} creating a simple box
|
||||
*/
|
||||
|
||||
public class ShapeBox extends Shape
|
||||
{
|
||||
|
||||
/**
|
||||
* Define a parallelepiped using three vectors using default density {@link Shape#DefaultDensity} and is not hollow
|
||||
* @param localx The first vector to use as local x direction, does not have to align to global x direction
|
||||
* @param localy The second vector to use as local y direction, does not have to align to global y direction
|
||||
* @param localz The third vector to use as local z direction, does not have to align to global z direction
|
||||
*/
|
||||
|
||||
public ShapeBox(Vector localx, Vector localy, Vector localz)
|
||||
{
|
||||
this(localx, localy, localz, false, DEFAULT_DENSITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a parallelepiped using three vectors using default density {@link Shape#DefaultDensity}
|
||||
* @param localx The first vector to use as local x direction, does not have to align to global x direction
|
||||
* @param localy The second vector to use as local y direction, does not have to align to global y direction
|
||||
* @param localz The third vector to use as local z direction, does not have to align to global z direction
|
||||
* @param hollow If the parallelepiped box should be hollow or not
|
||||
*/
|
||||
|
||||
public ShapeBox(Vector localx, Vector localy, Vector localz, boolean hollow)
|
||||
{
|
||||
this(localx, localy, localz, hollow, DEFAULT_DENSITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a parallelepiped using three vectors
|
||||
* @param localx The first vector to use as local x direction, does not have to align to global x direction
|
||||
* @param localy The second vector to use as local y direction, does not have to align to global y direction
|
||||
* @param localz The third vector to use as local z direction, does not have to align to global z direction
|
||||
* @param hollow If the parallelepiped box should be hollow or not
|
||||
* @param density The density of the vector points
|
||||
*/
|
||||
public ShapeBox(Vector localx, Vector localy, Vector localz, boolean hollow, double density)
|
||||
{
|
||||
Vector x = Shape.getVectorFactor(localx, density);
|
||||
Vector y = Shape.getVectorFactor(localx, density);
|
||||
Vector z = Shape.getVectorFactor(localx, density);
|
||||
|
||||
int xm = (int) Math.sqrt(localx.lengthSquared()/x.lengthSquared());
|
||||
int ym = (int) Math.sqrt(localy.lengthSquared()/y.lengthSquared());
|
||||
int zm = (int) Math.sqrt(localz.lengthSquared()/z.lengthSquared());
|
||||
|
||||
for(int ix = 0; ix < xm; ix++)
|
||||
{
|
||||
for(int iy = 0; iy < ym; iy++)
|
||||
{
|
||||
for(int iz = 0; iz < zm; iz++)
|
||||
{
|
||||
if(hollow)
|
||||
{
|
||||
if(!(ix == 0 || ix == xm-1 || iy == 0 || iy == ym-1 || iz == 0 || iz == zm-1)) continue;
|
||||
}
|
||||
_points.add(x.clone().multiply(ix).add(y.clone().multiply(iy)).add(z.clone().multiply(iz)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* A simple grid shape which uses string inputs to define points
|
||||
*/
|
||||
|
||||
public class ShapeGrid extends Shape
|
||||
{
|
||||
|
||||
/**
|
||||
* Each string in the array represents a layer on the XY-plane, meaning the layers moves towards positive Z.
|
||||
* Each line in the string represents a line on parallel with the X-axis, where the first line is on the top of the shape.
|
||||
* Use '#' for each point and anything else for each "non-point".
|
||||
* The finished shape will then be centered afterwards.
|
||||
*/
|
||||
public ShapeGrid(String... input)
|
||||
{
|
||||
this(DEFAULT_DENSITY, '#', input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each string in the array represents a layer on the XY-plane, meaning the layers moves towards positive Z.
|
||||
* Each line in the string represents a line on parallel with the X-axis, where the first line is on the top of the shape.
|
||||
* Use the <code>read</code> char for each point and anything else for each "non-point".
|
||||
* The finished shape will then be centered afterwards.
|
||||
*/
|
||||
public ShapeGrid(char read, String...input)
|
||||
{
|
||||
this(DEFAULT_DENSITY, read, input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Each string in the array represents a layer on the XY-plane, meaning the layers moves towards positive Z.
|
||||
* Each line in the string represents a line on parallel with the X-axis.
|
||||
* Use the <code>read</code> char for each point and anything else for each "non-point".
|
||||
* The finished shape will then be centered afterwards.
|
||||
*/
|
||||
public ShapeGrid(double density, char read, String...input)
|
||||
{
|
||||
int lx = 0;
|
||||
int ly = 0;
|
||||
int lz = 0;
|
||||
for(int y = 0; y < input.length; y++)
|
||||
{
|
||||
String[] lines = input[y].split("\n");
|
||||
for(int z = 0; z < lines.length; z++)
|
||||
{
|
||||
String line = lines[z];
|
||||
for(int x = 0; x < line.length(); x++)
|
||||
{
|
||||
if(line.charAt(x) == read) addPoint(new Vector(-x,-y+input.length,-z).multiply(density));
|
||||
if(x > lx) lx = x;
|
||||
if(-y+input.length > ly) ly = -y+input.length;
|
||||
if(z > lz) lz= z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add(new Vector(-lx,ly,-lz).multiply(-0.5*density));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* A bag collection of several shapes. This will add all the points from the given shapes into a new shape
|
||||
*/
|
||||
|
||||
public class ShapeMulti extends Shape
|
||||
{
|
||||
|
||||
/**
|
||||
* @param shapes Shapes which points will be added to this instance of a shape
|
||||
*/
|
||||
public ShapeMulti(Collection<Shape> shapes)
|
||||
{
|
||||
for(Shape shape : shapes) addShape(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shapes Shapes which points will be added to this instance of a shape
|
||||
*/
|
||||
public ShapeMulti(Shape... shapes)
|
||||
{
|
||||
for(Shape shape : shapes) addShape(shape);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all the points from the given shape to this shape
|
||||
* @param shape
|
||||
*/
|
||||
public void addShape(Shape shape) {
|
||||
for(Vector v : shape._points) add(v);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
/**
|
||||
* A simple sphere defined using vector points extending {@link Shape}
|
||||
*/
|
||||
|
||||
public class ShapeSphere extends Shape
|
||||
{
|
||||
|
||||
/**
|
||||
* Define a sphere with radius r that is not hollow and using default density {@link Shape#DefaultDensity}
|
||||
* @param r Radius for the sphere
|
||||
*/
|
||||
public ShapeSphere(double r)
|
||||
{
|
||||
this(r,r,r);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sphere with different radiuses on different planes that is not hollow and using default density {@link Shape#DefaultDensity}
|
||||
* @param x Radius in x direction
|
||||
* @param y Radius in y direction
|
||||
* @param z Radius in z direction
|
||||
*/
|
||||
public ShapeSphere(double x, double y, double z)
|
||||
{
|
||||
this(x, y, z, false, DEFAULT_DENSITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sphere with different radiuses on different planes using default density {@link Shape#DefaultDensity}
|
||||
* @param x Radius in x direction
|
||||
* @param y Radius in y direction
|
||||
* @param z Radius in z direction
|
||||
* @param hollow If the sphere should be hollow or not
|
||||
*/
|
||||
public ShapeSphere(double x, double y, double z, boolean hollow)
|
||||
{
|
||||
this(x, y, z, hollow, DEFAULT_DENSITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* A sphere with different radiuses on different planes
|
||||
* @param x Radius in x direction
|
||||
* @param y Radius in y direction
|
||||
* @param z Radius in z direction
|
||||
* @param hollow If the sphere should be hollow or not
|
||||
* @param density Density between points
|
||||
*/
|
||||
public ShapeSphere(double x, double y, double z, boolean hollow, double density)
|
||||
{
|
||||
for(double px = -x; px <= x; x += Shape.getRoundFactor(2*x, density))
|
||||
{
|
||||
for(double py = -y; py <= y; y += Shape.getRoundFactor(2*y, density))
|
||||
{
|
||||
for(double pz = -z; pz <= z; z += Shape.getRoundFactor(2*z, density))
|
||||
{
|
||||
if( hollow && px*px/x*x + py*py/y*y + pz*pz/z*z == 1) _points.add(new Vector(px,py,pz));
|
||||
else if(!hollow && px*px/x*x + py*py/y*y + pz*pz/z*z <= 1) _points.add(new Vector(px,py,pz));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
package mineplex.core.common.shape;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import mineplex.core.common.util.UtilParticle;
|
||||
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||
import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||
|
||||
/**
|
||||
* Some simple wing shapes implementing {@link ICosmeticShape} storing additional particle information
|
||||
*/
|
||||
|
||||
public class ShapeWings extends ShapeGrid implements CosmeticShape
|
||||
{
|
||||
public static final String[] ANGEL_WING_PATTERN = new String[]
|
||||
{
|
||||
"000$$0000000000$$000",
|
||||
"00$##$00000000$##$00",
|
||||
"0$####$000000$####$0",
|
||||
"$#####$000000$#####$",
|
||||
"$#####$000000$#####$",
|
||||
"$######$0000$######$",
|
||||
"$######$0000$######$",
|
||||
"$######$0000$######$",
|
||||
"$######$$$$$$######$",
|
||||
"$##################$",
|
||||
"0$################$0",
|
||||
"00$####$$$$$$####$00",
|
||||
"00$####$0000$####$00",
|
||||
"000$##$000000$##$000",
|
||||
"000$##$000000$##$000",
|
||||
"000$#$00000000$#$000",
|
||||
"00$#$0000000000$#$00",
|
||||
"00$#$0000000000$#$00",
|
||||
"000$000000000000$000",
|
||||
};
|
||||
|
||||
public static final String[] BUTTERFLY_WING_PATTERN = new String[]
|
||||
{
|
||||
"0$$0000000000000000$$0",
|
||||
"$##$00000000000000$##$",
|
||||
"0$##$000000000000$##$0",
|
||||
"00$##$0000000000$##$00",
|
||||
"00$###$00000000$###$00",
|
||||
"000$####$0000$####$000",
|
||||
"000$######$$#####$0000",
|
||||
"0000$############$0000",
|
||||
"00000$##########$00000",
|
||||
"00000$##########$00000",
|
||||
"00000$####$$$###$00000",
|
||||
"00000$###$000$###$0000",
|
||||
"00000$##$00000$##$0000",
|
||||
"000000$000000000$00000"
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Default rotation to give the wings a little tilt when displayed on players for instance
|
||||
*/
|
||||
public static double DEFAULT_ROTATION = Math.PI/0.05;
|
||||
|
||||
|
||||
private String _particle;
|
||||
private Vector _offsetData;
|
||||
private float _speed;
|
||||
private int _count;
|
||||
|
||||
/**
|
||||
* A simple non-edge wing shape using the default butterfly pattern {@link ShapeWings#BUTTERFLY_WING_PATTERN}
|
||||
* and x-rotation {@link #DEFAULT_ROTATION}. It also uses default redstone dust particle with offset of 0, speed of 0 and count 1
|
||||
*/
|
||||
public ShapeWings()
|
||||
{
|
||||
this(ParticleType.RED_DUST.particleName);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple non-edge wing shape using the default butterfly pattern {@link ShapeWings#BUTTERFLY_WING_PATTERN}
|
||||
* and x-rotation {@link #DEFAULT_ROTATION}
|
||||
* @param particle The particle to display at each point in the wing shape. Using offset of 0, speed of 0 and count 1
|
||||
*/
|
||||
public ShapeWings(String particle)
|
||||
{
|
||||
this(particle, null, 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple non-edge wing shape using the default butterfly pattern {@link ShapeWings#BUTTERFLY_WING_PATTERN}
|
||||
* and x-rotation {@link #DEFAULT_ROTATION}
|
||||
* @param particle The particle to display at each point in the wing shape
|
||||
* @param offsetData Particle data
|
||||
* @param speed Particle speed
|
||||
* @param count Particle count
|
||||
*/
|
||||
public ShapeWings(String particle, Vector offsetData, float speed, int count)
|
||||
{
|
||||
this(particle, offsetData, speed, count, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wing shape using the default butterfly pattern {@link ShapeWings#BUTTERFLY_WING_PATTERN}
|
||||
* and x-rotation {@link #DEFAULT_ROTATION}
|
||||
* @param particle The particle to display at each point in the wing shape
|
||||
* @param offsetData Particle data
|
||||
* @param speed Particle speed
|
||||
* @param count Particle count
|
||||
* @param edge If this is the edge of the wings or not
|
||||
*/
|
||||
public ShapeWings(String particle, Vector offsetData, float speed, int count, boolean edge)
|
||||
{
|
||||
this(particle, offsetData, speed, count, edge, DEFAULT_ROTATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wing shape using the default butterfly pattern {@link ShapeWings#BUTTERFLY_WING_PATTERN}
|
||||
* @param particle The particle to display at each point in the wing shape
|
||||
* @param offsetData Particle data
|
||||
* @param speed Particle speed
|
||||
* @param count Particle count
|
||||
* @param edge If this is the edge of the wings or not
|
||||
* @param xRotation Rotation on the x axis
|
||||
*/
|
||||
public ShapeWings(String particle, Vector offsetData, float speed, int count, boolean edge, double xRotation)
|
||||
{
|
||||
this(particle, offsetData, speed, count, edge, xRotation, BUTTERFLY_WING_PATTERN);
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple wing shape
|
||||
* @param particle The particle to display at each point in the wing shape
|
||||
* @param offsetData Particle data
|
||||
* @param speed Particle speed
|
||||
* @param count Particle count
|
||||
* @param edge If this is the edge of the wings or not
|
||||
* @param xRotation Rotation on the x axis
|
||||
* @param pattern Pattern to use as wing shape
|
||||
*/
|
||||
public ShapeWings(String particle, Vector offsetData, float speed, int count, boolean edge, double xRotation, String... pattern)
|
||||
{
|
||||
super(0.15, edge? '$' : '#',
|
||||
pattern
|
||||
);
|
||||
|
||||
_particle = particle;
|
||||
_offsetData = offsetData;
|
||||
_speed = speed;
|
||||
_count = count;
|
||||
|
||||
rotateOnXAxis(xRotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(Location loc)
|
||||
{
|
||||
Shape clone = clone();
|
||||
clone.rotateOnYAxis(Math.toRadians(loc.getYaw()));
|
||||
for(Vector v : clone._points)
|
||||
{
|
||||
Location ploc = loc.clone().add(v);
|
||||
displayParticle(ploc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a single particle of the type provided to this shape at the given location.
|
||||
*/
|
||||
public void displayParticle(Location loc)
|
||||
{
|
||||
UtilParticle.PlayParticleToAll(_particle, loc, _offsetData, _speed, _count, ViewDist.NORMAL);
|
||||
}
|
||||
|
||||
}
|
@ -19,21 +19,27 @@ import net.minecraft.server.v1_8_R3.NBTTagString;
|
||||
|
||||
public class SkinData
|
||||
{
|
||||
private static long _nameCount = -99999999999999L;
|
||||
|
||||
public final static SkinData MOOSHROOM = new SkinData("eyJ0aW1lc3RhbXAiOjE0NDk4NzI0OTU0MTcsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzIxOWJlYTU0Y2FkN2Q1OGFiNWRhNDA2YjBhOTJhYjNhODI0MjI1MjY2Nzc3ZTUzNGI3ZGI2YzM3MmRkZmY3ZiJ9fX0=","UoSif81+UyvkcaanU8KAMYBpw9mefAmWehE2liDUFvk+y0X/9NovsxTYVpIDCltTSpLW3sNgamvbj4Ybs+s6DbudPiEkvh0ER7Bv2v29UJw7RzIdr6/1g548X12zcnh5iPGz/P75uNRnSfTFQx0ed8P/GNkPIjWpDuJFxEj6KcPzrCAGMx+BVw1VwryBIYf9cCDHky8z0bxR89rjiIvPTBFI6MRhqI3vgpEBTySHDS+Ki0Hwl5oa3PwS6+jgYx/4RSfFsb+BawcvDk2Xpkt5UimvqZ5BceYLIfCt4KbShYipgLXLfYUZrntjPemd3SxthjxUuA07i44UxRdiC8uqy1twLT/HUS28gpk68lA/id9tKFwu1CUzshgcmvQPt3ghtNViNziR/2t7D/+5D31Vzmhf6n7Pnpdirt/5frMi2BKMMs7pLa0EF8CrrDU7QCwPav+EZVGFvVZbxSkCDq+n3IQ3PUWSCzy6KPxpdOlUjD0pAfLoiNj0P8u4+puQtID76r/St8ExchYl2dodUImu1ZETWeFUClF3ZGat62evx8uRQEI2W4dsVwj40VUfjaAuvyDzuouaKTrCzJXLQZZjR1B8URvuK61fGX0nhW607mEi6DE+nxP2ZoBrROEX4e37Ap6+TQn9Q8tKDPdcxtwSOpPO4Qkncjn/mGtP9lZU/DQ=");
|
||||
public final static SkinData SNOWMAN = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk4Nzk5NDIsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzEzMTgxYWViODQzODk3NzM1ZDQwMmIyNDk2OTQxNmZkYjBjZTM0YTZiOTM3ODE2MjQzNzU2ZTlkYWU1OGUzIn19fQ==","NZvsNu+HQ5uvGWq6O8VNDGq9A145bmk2IkHiz916uRVPMRqqCI/zwhKWNLlFACE/feuLkhYAois29ec6sVVOtHIoNA+S5q1Mb/Vjc3TJQxzqmx2FZOhJiIttFwYuo9WomQKBqrPMSJ9tpQig4wzoqldeeTjWC3dLz7JeX+gkzinryVjG7NNN9L5hXK5/BBxRcrtwmXJfUlSANyrd8RZW7mEUgU8yxlzdqTu0w7bZLjQNd4vciwoF3NelXDorMIIqiHTkuQesG91Njtu25VCUDK3nXbqEnZw2ZtxB5fT5G2Omm/vkNSRXc0P7iqchVowdYQcMlQUsp65xpkBbFS4LwjzDkYIfLmF++hePb8z72Gz77FxhO5sRLGreSH227McyL/0CtWNKm9ZZIfQtZZjEZTj9+eiJMCloCMg3yWa1VBOiLHzz0wY6gGklccIImPyXEg7E0dIK8qYseJMhmmBNZ8pDOkbUDp3mRlrQ2iyClgQkbuR63j79IBUaCxmsa3NnrAtaJklzd9mzkHXfMBh2XT7Gl8AhJS6JK5kCvip1rBBI8yjrsjE/E+lyJFIbC4rXxyMDGZWkcdrd7U4ZFYKiLHbzdFRqX+11qs9xO2BvomGXkATCzYmOf2kQ86R6rNN0+JfE4QpKzj2WWt3C8ky2qpuXZz29p0816E3/qseYtgg=");
|
||||
public final static SkinData SANTA = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk3OTM3NTgsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2MyNTM5ZGFkZDUxYmE5ZTg0YzFhOTE1OTY3NWUxZTJiYWM1NmFlNmFlNTMxNTQyZDI1YTlkM2Q1YzQ2ODZmNiJ9fX0=","gvLc0Vo6+1vl17vrFCbK1eNqa4/ix4xiwcWae7WOCvqiVIX4sdIPagOGUrKsDdEhuWCKkTWILGP1K3wYfC9v/0mXZvbu0sRln+APTOsswMkQmbKcA1zTFTMpwEI+nIMzYJSbIx5wjz28K5hDf/umtHH2GADTENdJGGUtU4CyEdeHTzcqIAEV3bcMLkfTKvwKUWqI5gZbbercqmDeGkmXVS9297a9paRX1NfEL9pFT0pjdH3tCjgvvKfAwGC6tYtvTFbfcJocqgI+PI2f5OFf62A4XjWwWFi4wxCHVYNpqs/XTbfF64K7KVE0d9gsLjJoB8DMZPxlNpMFA0R5OIW6Q7Qjyz9IKxUqEYRCQbuUKpHyNDcmVKcTJRwBpCHeqAbTbweZHd5tzrT/terWhLEMsK1+lH2KBfIRIRB9kd3epyShNjSEKoly6uRXVxU+IJtfcq0aFVZlwgG3c1Ds9jbsNJV158e1n6WCmvT00RLdvpcIekwUKODhi3zFeFkrVvV50tGYqXLRZenitLJvDzx4c0IGK4krALrUS0oybinBS7/GmW3Ktz3xbGKZSzzaDw0EKB7Y6XHdb4yqR1xS7lAWgv4cNDEIUSzUDJ7HpmDCIF2A5kPS4XVYFCclyR6qPGD5e+9apVhBMz4lfYlT1IfRAUQlucO4UpAlkXs7ho3pQXU=");
|
||||
private static long _nameCount = -99999999999999L;
|
||||
|
||||
public final static SkinData FREEDOM_CHEST = new SkinData("eyJ0aW1lc3RhbXAiOjE0NjY1NzA5NDAzODcsInByb2ZpbGVJZCI6IjQwZWQ5NzU1OWIzNTQ1M2Q4NjU1ZmMwMDM5OGRiNmI5IiwicHJvZmlsZU5hbWUiOiJTcG9vYm5jb29iciIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjc4N2Q4OGNlYzNmOWI0M2RiNDg1YTU0Mjc2YTQ1MjQzNGFiZDI2ZDMzY2QzZmZhMTM2N2ZiMzVmOWUzODQifX19", "UgsQyW/HJ/jmDzfI1d7RWFbhKi8PeJAKBuAOk7ajS5dzH5od301KfcmiT2X3TU7cBbUswcKtDb2F/m7gNrg/t+pU7Bi9UKzyALEu9HRjd4s1uKbqGkBip1z5Qycp4fhkSyKvtvTnA2fhpP9oHtE5FxGXdMhZXyFkLrli4Hyxp1BI0N4h7pgbcMaISPS0ZYzDRNxkrSnl3y3KyKn5Rl5qH7utmQtAjoyx9aueMZxG3tg/igfYF7uAvvmuYKsSiTZWZOOuSh+U1dkP+ZE/cQANfryXkLJSJHa9YZPCMJHXe4mMoAyu0/quwZCW9NlW3P30XeCfZ87IxfKxISIP0dLgY8hUJyCuI2u5U7TEDrDggPKr6XTcIbX2kFKOsYSeovsAgjC+1UKFH4Ba0jTbRmqzPK49fk/jU8XqRP2Gl9UZDIVbc0dMEXNOeJ0e0wejDtSyX8flBk9sIKYwqeB9ns4cFqSyTI5tKnNin12BNTFRK/bDp8dN7nloyQvhDGlW88UlnJmOFhR6R0naP89VM04VCLaYCr6jyv/ZwV88uPvL2kjhx14qSFfgqJI5ORhFgYkuc+nhyQaD8+y2t3ZMs0HAfoujmq98lp2ECLWyI0ATUcXjUyNYadLj4valS/m0jl7U2fwzcmVMQqOC3ddu6mHbt871hIkG2X4v6kEcVAtKmkg=");
|
||||
public final static SkinData COMPANION_CUBE = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMDk5NjI0NjEsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2MyMTVkYmRhNTY1ZjVjYjhlYjEyZjU1NWY1ZTNkYTBlYTVmNTUxOTg5MWNjNWM1ZDY3NmZkODJjNjIifX19", "vaAQbhnhnTOs64ToFWLg7o4JmqkIl07HWJ6l7xibfISaOcU4BvYBxsfGvmoxlVdsUeCunAJ8/05qVLl5zZYd8Dt+To6JSY0RlqV8piRaaj3FztYWV2ZvG3YZxPxiD3HRJTAQnDobSuxHyPa1e3khjAFp9xJo4q1oqQ28oI2WDuoT+IHqxwkKVbGzO7UD5lzz5chjQC46E8SxddNKp9aqwbbccrkHYT4gteoonOXu4MFxZniJN12LqUCb6+G15rU8MijlBkWx0xE5NMUloeTGuJZItbHun9fysLk/+HE5xJOKYtpZNMuWX+DB/O5ds9dXrOoSAg+Vn0QU4CZbwcxzLii5ILOfEEBtePuEAgzROri+iCKp59CqlEMBrCsd3Um0MCdbuOfvkXGBHBz+bqX7VJY1ujlSdMefmbJtHAkDANnsaaVb+eli9Dk6139041sptsLytD+EfJzaitX6crBwKZ2WDx2P6LHo8B+iSOzOJxjf/08zlXqFw1vsk62IN6lisuZ89QyZw23RvOx3obLAGYs1GxAlMl9qQdpXcmuE1+lPR3g8gZ0BfnTeYwflC2wbR1tuwGG98lyUGCvGLyqNKAQTN87XV4IFQWR81mi1c5CcasoWhKf9D9nAik9aK7A915fEE5IvpeuUdZseDxDVVN5dBIs5q2PIHFAS0rDsDBc=");
|
||||
public final static SkinData THE_GRINCH = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTYxNDMwMDQsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWRlOTI3ZDQzOWVmMzliMzFhYzFkYzJhODM5NGZlNzlhY2U4NDMyNzBjYmUxMjg2ZGM3NTE3ZjMxYTk2In19fQ==","ELo594vTzPq9ZmPYOtVr4kim/k19gzmoxEIK1ehS87gwgag5HcgM+P1FMnHIyrmSvTVaMh0NxwXmNS+JETFL7OrmgRYNpkxkkO4VBA0pfSn3dA9ujnXpDnDiWEPxKdMgQspIOOI0Z3esNt3pj8qIj6dWPtGwtso48tjHl2o/kazfa82yvGORlFhGkeEJKQMno/Buc12C0foQw39XI8GjvlSkFN2eH4Fp16RLu8/hf7SqJQC3L1KacvzMW1d8BWEIgACCJDni29+YqxflSqSyYrV4Z+D66S0jYvUUL/vM4/q/p/YWX/vs/FtMtHQTj4PCpAmMNTgfkahuhb6rCvKHukbjA+WhUdwyxSqXU5YnpXCu1M2dzZgiXjIi+fnyn4CmXKindWCQtSwu+mCA2ILv/6vEHoYJgdlz+DXyRkFx+DH4Sl74HBCOXTOq5AGjq5h3LYfsre+UjCCUv8VgxbVprOyj35So7K0m+6faCFVSt35T3RgicDQfdiWUrW7kmHQVvJpvaq9Vu+63F/0X93cwqwaR0buMirxRx7qkFrRunSI4T+9fsN02t1fAieeu80lBSv83wr7BFneSsLsdVAND9xttTb6fClg7anr8/XVEVIkylB4B+ZcWQbH61XP1nn7oFP2VBg1h6XuuLp8FGSgYf/LW+54/KZci/MnanqQE6QQ=");
|
||||
public final static SkinData LOVESTRUCK = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMTAyNDMyNjUsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzczMTY5YWQwZTUyYjM1N2NiZGYxZDU0NGVkNGNmOWJmOTI4YmI0ZWNlMDhlY2YyY2M0YmYyYTlmMjJhODI4MmQifX19", "LL4RiSKQoTZamRQ4QG6izpvhgFu5gAqW4eZxcWAihk7GkhyxifpJpBTOzKrj5hH9fCUfYkkijVWUYTEcVSVRWhocp2HXW59TbKfxOeMvHU5vTMwgpwm6PnUfwuTsRPSLC7WMnEreI3cjOxPVmXbTniOSd+o8j4oOIgwFS+VLPiYLh5Jl16i5I/9ekafl3/x41NISKWl62geqO2jPWehlk+r3soiRJsxaKw20T61GSNLu19iA96Rz2T2tUHB4opm8hbLgoiNL2g1affTjq3cZPLHH4JWF3vPhqLB5uw6xb55vFLM/PP0YiEMIi7YZOfRGeaPp7uXbXgHeew+7PG9UDVMfqbwANQY4ndECijZoei54+xX3MDXkMhQsc5S+FLnGH6e4d008v81eEOyzJUPkKbGxLCBgTUb1s4IHwomCr30twPlo1IuFBOY1qeVvZUfAfPJsREuj5q/oCAoYFgupmb3ClWECnwwaH/T4wdHjfSBHoZQdLzcgDOAl0b5EXxWmYBECqk/WA4TrYIDVGdwkqjI0RkPLUoxTj6135KO+F7P7PwhU9WBGeW8hHq918DBL0fjQVHjrzvolTqwmw6nySSePnPOxFX/iwtHWzpBa9V6kUNNN+V7OGTgRr0H/yUxB+oq1F8UBqyqT4YpqxXCSD36derF/Xt5IdpTbEbGBpm0=");
|
||||
public final static SkinData PRESENT = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk3MDIxNjIsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2U2YzRkZWQwNTdjMjhiMTU0NjVkYzQzNmFmODIyYTNkZTY4NzgyZTZjMzgyOGMzMmFhYWE4ZjRiOTIzOWVjIn19fQ==","rJNlxTqHHmOoWwbXdMQLcj0P9w/PIr/hWKXH0nbhm/S2CFo/zfefffZlnQmpKCgn1Y8tXvcRwLGQ4CLpm9m2ZrKprSWRhrnOtZWYabrhExQESEammS3TY81VoNt+4On0pAGBippz/bRfWLuDne2rDbhuljnqvxjROmxpky7gRCU06VMlm2WLFC5XYJkiAaOXBqzpiHMMRPNnCvtcbtpILKi/Luj302eyN8nRKjHHbbiDmttwvlshxZ8UxJHvALtM506IUHba10Q6QX2zCeDAU5/WYRKa6e19r8plROcgGbKYFSq8JW5cWuWT3/rveZM6FnU6ABn9DWsCyfQ5wr2jdBd+xaevGTAScRHA5J493GqL1bBZYKj9yhQFtxJHCAf0++raAVPCZgyPtwTth4TAQisn8gnhM5R+txnW6xK+oflLy0dwEN1YdPLN/h7yuDnyjSMDe9RZT2NKMjok2C6Kux4WBI0KFXKC5Gqwa3Htku4v3WEOWMaVoWOtchQ9BzpQ/etD0ylmzjALQLB+HtndEEm1Jd3tmob42X4hBE8hCce7C3EtGINB33dlx4CK1xBqyGTJEqi69DJRzVL99u98+7kJ1Db9+MaPOfI4B2RY3XbvnSYwecandY//A3bb19FGSdl299ZXbp4zpm8fivzeB1rUAhhmtaA3Iwu/nEQNMkU=");
|
||||
public final static SkinData RUDOLPH = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk1NjgxODIsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2IzZjdlMjhiNTJkZjJjZjhlZWM2NDk2ZmM0NWFlMGQ2NTM0Njc5OGIxYWRjNzM3ZDcxYzBmOTRlNDIyMSJ9fX0=","uUBOTe63CL+qRvtsb2g4AjB2YzxE3N6AUqIsTv8n0jYyPsuXpuOmZPSMEdgDVONywEJ1L4XRx05sjnGu56A8vuXmGI/uHQWuMZzbOSjiFfT3DkEm8zEl5AWpH9dz/t8nZ1WYUIwy0pN5VrZqIr1DAkF6AMh/Qy+FGDw1GG9ReRr80eJ0JiRskpkCpCZIGGjrgwNKAM8JOuNZ4gCQOTRC3etrcfls3qmUMFcVlhuB4bydxSR01i2w0A4b5KpufsJjLKw4InWn2+m/druo8hl9sYuusTeItW0MQmZqCAqXCc9YBnRPQ0hDXFgnPxOh3RwGWiZvL4MnWUVmLwZWh/Fk9QmyVbd7zVao0lxS8YNsKtP8j5B+hs4l9qNohhf0A07bt4oPeTtd5fQeOU5N87fUGuUAcpC4gP9U5WpVY5FFPBvLvGbXdV5jpuAQz4lLSoo1grsP9baR2IBvdN/0awjQWoPJfGOttegubkBHwz3LNcVqvZLtX/M13IDHZa6zQZEX0wsnMX60LeWgBWfTON1l2cSgaPTerHFS2EifJ2LvTBife3s9/4XR6Zth3FLFqxI3MSlqT2hVFRPLke6rBqfqPoWOj2MCykQ70IAwb3oTHcJDJ86V2DdNaU2bZ8V4TjaP+nRobsLJOImoPYEPq23MP36X8gbXEIjmuu8S5xRlrrc=");
|
||||
public final static SkinData THE_GRINCH = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTYxNDMwMDQsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWRlOTI3ZDQzOWVmMzliMzFhYzFkYzJhODM5NGZlNzlhY2U4NDMyNzBjYmUxMjg2ZGM3NTE3ZjMxYTk2In19fQ==","ELo594vTzPq9ZmPYOtVr4kim/k19gzmoxEIK1ehS87gwgag5HcgM+P1FMnHIyrmSvTVaMh0NxwXmNS+JETFL7OrmgRYNpkxkkO4VBA0pfSn3dA9ujnXpDnDiWEPxKdMgQspIOOI0Z3esNt3pj8qIj6dWPtGwtso48tjHl2o/kazfa82yvGORlFhGkeEJKQMno/Buc12C0foQw39XI8GjvlSkFN2eH4Fp16RLu8/hf7SqJQC3L1KacvzMW1d8BWEIgACCJDni29+YqxflSqSyYrV4Z+D66S0jYvUUL/vM4/q/p/YWX/vs/FtMtHQTj4PCpAmMNTgfkahuhb6rCvKHukbjA+WhUdwyxSqXU5YnpXCu1M2dzZgiXjIi+fnyn4CmXKindWCQtSwu+mCA2ILv/6vEHoYJgdlz+DXyRkFx+DH4Sl74HBCOXTOq5AGjq5h3LYfsre+UjCCUv8VgxbVprOyj35So7K0m+6faCFVSt35T3RgicDQfdiWUrW7kmHQVvJpvaq9Vu+63F/0X93cwqwaR0buMirxRx7qkFrRunSI4T+9fsN02t1fAieeu80lBSv83wr7BFneSsLsdVAND9xttTb6fClg7anr8/XVEVIkylB4B+ZcWQbH61XP1nn7oFP2VBg1h6XuuLp8FGSgYf/LW+54/KZci/MnanqQE6QQ=");
|
||||
public final static SkinData TEDDY_BEAR = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMDkzOTE4MjYsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzQ0OTU4ZDdjNjlhZTQ4NGM2NWYzMTM0N2NkY2M5MmM2OWY1NDA2ODA1YjUzNjUyYTc1YThlZDc5OWRmNyJ9fX0=", "sNTRV9jTjLszUmyaqyEG7N8d5RM1jbwMSXi34S2EkVmIjWsowfSMnHRQqqgZfxcyqBM5I7MljtB84IeQWu4rqhyFrM9blWvtowjijFIOgKCs97q2sswv9iauU6ohvgTpgN5B0Q16MJmMIgZU8d8TATtEaIzq2eg6Ve1AJlNnW4huGNsoNfm8WdVU1tZmsYAwtVP/ryvhyj7mHyVF27m0Sm4fZRf/lHH5gEJYB4JHSAoEhjPIQOdkgRMJRrWGOfhhiGs3kEWmsRGfIPFo2ZJfcu+TFV2rd4Q+A1LmY8kimnzdKX3InXeKbk8qzcgqGNro4XFnSiHo1d6/B+N0JeYOTITYRQ6u24rNSUh5ezbG01iikVFCfrgb7UR6utoLK15F4/fmhpex+BJpmyZoXAqk08tZws/5wsIWQ1okrGcbBKWEHhw2ekUc82US21/W53vd657UBg7FuqM4FhkAqmsYPvYLMpNYxxmDJaI8uJyU7cnGFYyBaFlqUxfJUfcFTwWo10JO3yp5FjqeCQa7rFvfpsqw3w2mBpJmlZ5HRjfS5pmhk0QiY0TRfwZfFemkuZYnNbO82qLUm+6zTm0fbC90Swt8nNr/42ajzEoUjnL6VsERIXS5/fPwjftbQAC60ujy8yo66Sp3sSAALNg5zjM+Uizkq2f9Axc+kind22hp10M=");
|
||||
public final static SkinData COMPANION_CUBE = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMDk5NjI0NjEsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2MyMTVkYmRhNTY1ZjVjYjhlYjEyZjU1NWY1ZTNkYTBlYTVmNTUxOTg5MWNjNWM1ZDY3NmZkODJjNjIifX19", "vaAQbhnhnTOs64ToFWLg7o4JmqkIl07HWJ6l7xibfISaOcU4BvYBxsfGvmoxlVdsUeCunAJ8/05qVLl5zZYd8Dt+To6JSY0RlqV8piRaaj3FztYWV2ZvG3YZxPxiD3HRJTAQnDobSuxHyPa1e3khjAFp9xJo4q1oqQ28oI2WDuoT+IHqxwkKVbGzO7UD5lzz5chjQC46E8SxddNKp9aqwbbccrkHYT4gteoonOXu4MFxZniJN12LqUCb6+G15rU8MijlBkWx0xE5NMUloeTGuJZItbHun9fysLk/+HE5xJOKYtpZNMuWX+DB/O5ds9dXrOoSAg+Vn0QU4CZbwcxzLii5ILOfEEBtePuEAgzROri+iCKp59CqlEMBrCsd3Um0MCdbuOfvkXGBHBz+bqX7VJY1ujlSdMefmbJtHAkDANnsaaVb+eli9Dk6139041sptsLytD+EfJzaitX6crBwKZ2WDx2P6LHo8B+iSOzOJxjf/08zlXqFw1vsk62IN6lisuZ89QyZw23RvOx3obLAGYs1GxAlMl9qQdpXcmuE1+lPR3g8gZ0BfnTeYwflC2wbR1tuwGG98lyUGCvGLyqNKAQTN87XV4IFQWR81mi1c5CcasoWhKf9D9nAik9aK7A915fEE5IvpeuUdZseDxDVVN5dBIs5q2PIHFAS0rDsDBc=");
|
||||
public final static SkinData LOVESTRUCK = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMTAyNDMyNjUsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzczMTY5YWQwZTUyYjM1N2NiZGYxZDU0NGVkNGNmOWJmOTI4YmI0ZWNlMDhlY2YyY2M0YmYyYTlmMjJhODI4MmQifX19", "LL4RiSKQoTZamRQ4QG6izpvhgFu5gAqW4eZxcWAihk7GkhyxifpJpBTOzKrj5hH9fCUfYkkijVWUYTEcVSVRWhocp2HXW59TbKfxOeMvHU5vTMwgpwm6PnUfwuTsRPSLC7WMnEreI3cjOxPVmXbTniOSd+o8j4oOIgwFS+VLPiYLh5Jl16i5I/9ekafl3/x41NISKWl62geqO2jPWehlk+r3soiRJsxaKw20T61GSNLu19iA96Rz2T2tUHB4opm8hbLgoiNL2g1affTjq3cZPLHH4JWF3vPhqLB5uw6xb55vFLM/PP0YiEMIi7YZOfRGeaPp7uXbXgHeew+7PG9UDVMfqbwANQY4ndECijZoei54+xX3MDXkMhQsc5S+FLnGH6e4d008v81eEOyzJUPkKbGxLCBgTUb1s4IHwomCr30twPlo1IuFBOY1qeVvZUfAfPJsREuj5q/oCAoYFgupmb3ClWECnwwaH/T4wdHjfSBHoZQdLzcgDOAl0b5EXxWmYBECqk/WA4TrYIDVGdwkqjI0RkPLUoxTj6135KO+F7P7PwhU9WBGeW8hHq918DBL0fjQVHjrzvolTqwmw6nySSePnPOxFX/iwtHWzpBa9V6kUNNN+V7OGTgRr0H/yUxB+oq1F8UBqyqT4YpqxXCSD36derF/Xt5IdpTbEbGBpm0=");
|
||||
public final static SkinData SANTA = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk3OTM3NTgsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2MyNTM5ZGFkZDUxYmE5ZTg0YzFhOTE1OTY3NWUxZTJiYWM1NmFlNmFlNTMxNTQyZDI1YTlkM2Q1YzQ2ODZmNiJ9fX0=","gvLc0Vo6+1vl17vrFCbK1eNqa4/ix4xiwcWae7WOCvqiVIX4sdIPagOGUrKsDdEhuWCKkTWILGP1K3wYfC9v/0mXZvbu0sRln+APTOsswMkQmbKcA1zTFTMpwEI+nIMzYJSbIx5wjz28K5hDf/umtHH2GADTENdJGGUtU4CyEdeHTzcqIAEV3bcMLkfTKvwKUWqI5gZbbercqmDeGkmXVS9297a9paRX1NfEL9pFT0pjdH3tCjgvvKfAwGC6tYtvTFbfcJocqgI+PI2f5OFf62A4XjWwWFi4wxCHVYNpqs/XTbfF64K7KVE0d9gsLjJoB8DMZPxlNpMFA0R5OIW6Q7Qjyz9IKxUqEYRCQbuUKpHyNDcmVKcTJRwBpCHeqAbTbweZHd5tzrT/terWhLEMsK1+lH2KBfIRIRB9kd3epyShNjSEKoly6uRXVxU+IJtfcq0aFVZlwgG3c1Ds9jbsNJV158e1n6WCmvT00RLdvpcIekwUKODhi3zFeFkrVvV50tGYqXLRZenitLJvDzx4c0IGK4krALrUS0oybinBS7/GmW3Ktz3xbGKZSzzaDw0EKB7Y6XHdb4yqR1xS7lAWgv4cNDEIUSzUDJ7HpmDCIF2A5kPS4XVYFCclyR6qPGD5e+9apVhBMz4lfYlT1IfRAUQlucO4UpAlkXs7ho3pQXU=");
|
||||
public final static SkinData SECRET_PACKAGE = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMTAzNzE3OTIsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2QyNWI5YTRjOWRhOThkZTliZmIwZDNjOWI1M2MzMjJhMjgxN2IyMTMxOTQzY2E1YWM2NTBjZThmMzEzZjdhIn19fQ==", "Wb5T0Zhp1RVt78V/i8dYrwZCNT0xZIRe3LvL0bngH498f8Jrl43KHgTi4f299zE9giVynkTogGhJ8inq/xqFCRctl7Nn9L3LVu78uQwt+fs+o+kw/Qc+lggFSjEIc+fc13AZndpec0Df46Kh/OGD7NXbtbLb6TE/0dU2RwQlvZrZ/QHYJb8OJ6aUcnHvAZim8NUtG/nlZtSClepHVSuKdNnfzoF9rFVFA/x4jTr6mZYPZ33YgQd2oTAPk+qE3iN+0InjZQNs2YLoKFmFrgzn+tGvNApC0siF0HEZGQCFIwJOtnBsasGoxujIrln/ZdOil+5ac4VWInXr8lKgY0Q3Ocy8/0cJl+E/XqB+ztG29zhB8B1zdHBfJr+MgeSIqBCPx4SCtY6r7gnMlQYG+uVx5NP3S5aJW/cEfDyXmpCykIcBPzeErnKC0SiAqXkCVNjWJpX6qRWvWMXqS69w6ht6qHvEY2GxlZUb5AP+JgFlsl3hJDms6EPvM4zNL0Ko4oWIBzwYRQXiemrP9TGgyo0aL1RcQ0JgBFO2hSo37PK0YL3tUPgteJXzm21wu0TiZLkLCWSgMUfYfvVnhTa+xzod0xvfujpN6Y1DUTdcf8WS8TRYw2JigSkWrRW0fXPBCtTtQN5jiwM5/HrTpNLzg03J6SpfZ+rr8Rhq0S/8beQOMas=");
|
||||
|
||||
public final static SkinData CHISS = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTk1NDI5NjgyNDEsInByb2ZpbGVJZCI6IjFkMmJmZTYxN2ViZDQ0NWRiYTdkODM1NGEwZmZkMWVhIiwicHJvZmlsZU5hbWUiOiJDaGlzcyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTg3MmNkMzRjY2IzMTIxYjRjNmEzOGFjM2JmOGVkM2UwMzk3YmQ2YTg4NDI4YjdhZmM2ZTUyNTI4NTVhMzQzIiwibWV0YWRhdGEiOnsibW9kZWwiOiJzbGltIn19fX0=", "hNTLRA2acZYx2dM90lnJN8FMK/ceD3+AxKNdD5FrXzxGtYL4C1Jr/vbTE0UosmwFP3wScNEW/fuDOjeZRjZHMJdvgDZMlMK/5KDhOY6sj/RS9RckztsgummSyjH/hdDn7TWWfhZLMbiia/K0VReI9eq2yD6zGQpvMlz5hB/5SX5YHWXvCah3TL4UzYSlSVDlwY/Q3sVuIZUr8m/LIXJwniJKLGo6tUgtiJd9eseOsbBpVjzCUtLD8A9WBe2/eODgmLfqEvXESIoDRG8vL2nPSXWma/YolYHIl32/i+ZxVD7dRRaXQFYSiLI24EtzX1pPhMjyaTLazP9abH43J6J31w02pKM7N/xTa62020L/YfRRKGT5lygEDb1NMoSpAjszPxah+Ra2/L+yUWEI8cMES6I4mIJ00tclPjWK01xhIn3tqg+y2gqsGHwPhu/7vmF5NirNfKFw0qciKNBfbCAF7ae+mkUKjmAPuvBUBqQb7BOcpNVWsCo/XvzmiZZYsf5P4Uwz8LqUK4uH6V/5dg7lY2Xg3+IUylsrDqLGFDI8iy/NdjIQMbuRadh4IDO6DcmxBri2Ax4JNBPBTnRezge8uq37MZcft/IXQgFWKB9RtidVEACaTOkRj27k+Ojnkki+j44k0wZB47hiXFUHMCHl3a0SVdQe15ZbVsQj/HAvAS0=");
|
||||
public final static SkinData DEFEK7 = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTk1NDI3ODkwNTksInByb2ZpbGVJZCI6Ijg5ZDQ2M2Y3MjNlYzQ3MGE4MjQ0NDU3ZjBjOGQ4NjFjIiwicHJvZmlsZU5hbWUiOiJkZWZlazciLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2JmYWNjOWM4ZjhlY2E1OWU0NTE4MTUxZmE4OGFiMDZjOTFmNjM3OTE2NzJmMTRlNGYzODY3YTI2OTVlN2NmYmYifSwiQ0FQRSI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzIyYjljNWVhNzYzYzg2ZmM1Y2FlYTMzZDgyYjBmYTY1YTdjMjI4ZmQzMjFiYTU0NzY2ZWE5NWEzZDBiOTc5MyJ9fX0=", "jBoRvkhQXz+nap8yJJIZ+4HClMItWODumeSOYjXytP3WWKHK0UMq0xC/keXsnmvo89lMRdRbknPt2ZX5Flgyjgr4Rt0KtDvpL/hG4BUsTWryUZZMKxdd6DkZXYRtTogLUfHeDYIz+cZQ0aXGMtvX/ZYTXJfMi6FYbIHY/qEEDnWhDX5y+SPpaJaZByPsvzi+qbfcFGnJ6nqi9ccyZYnYpnI2IVBM/yO/VRXWHxfqvJ0VVvv5KsGmVbko2Jxo0SDCxUL2UTH2+eol53FxhkkC+m2geC14k1zsZQLHDF3BgAG9+kFJ4UEoYRKF2Gy1FxeDCJtjYNdrYR8fdaUKRMcpBgEs+ZGe2U9EVVS/ZcBCjB7S+1Ne2bPzPFzTQPuBoMgggo1xbxBmQ5NyhYo4gwgj/xjSLIhb+5h7ioN1URfSRcfYdVv6RRO9l/u9l09jEom8y/jGRviefpEr+/e9iAl5Dd/6nzQgosBQja3NSfqYZmyuet2eI9zu61CObDTpR6yaCbNgBe/lWofRfULdpJpgjb4UNTBom3q82FcCiOe02OekGPw4+YlilhICBhajF5JzN8FKAdqI1osDcX3KuJgikYIW3voNaOP5YN3GXgilJNdou20KFC8ICq68HglgX7/0rLrWKIEoswnINIM6HcJbQuXncVPwQhV6K34Hlt/Na60=");
|
||||
public final static SkinData SNOWMAN = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTAwMTk4Nzk5NDIsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzEzMTgxYWViODQzODk3NzM1ZDQwMmIyNDk2OTQxNmZkYjBjZTM0YTZiOTM3ODE2MjQzNzU2ZTlkYWU1OGUzIn19fQ==","NZvsNu+HQ5uvGWq6O8VNDGq9A145bmk2IkHiz916uRVPMRqqCI/zwhKWNLlFACE/feuLkhYAois29ec6sVVOtHIoNA+S5q1Mb/Vjc3TJQxzqmx2FZOhJiIttFwYuo9WomQKBqrPMSJ9tpQig4wzoqldeeTjWC3dLz7JeX+gkzinryVjG7NNN9L5hXK5/BBxRcrtwmXJfUlSANyrd8RZW7mEUgU8yxlzdqTu0w7bZLjQNd4vciwoF3NelXDorMIIqiHTkuQesG91Njtu25VCUDK3nXbqEnZw2ZtxB5fT5G2Omm/vkNSRXc0P7iqchVowdYQcMlQUsp65xpkBbFS4LwjzDkYIfLmF++hePb8z72Gz77FxhO5sRLGreSH227McyL/0CtWNKm9ZZIfQtZZjEZTj9+eiJMCloCMg3yWa1VBOiLHzz0wY6gGklccIImPyXEg7E0dIK8qYseJMhmmBNZ8pDOkbUDp3mRlrQ2iyClgQkbuR63j79IBUaCxmsa3NnrAtaJklzd9mzkHXfMBh2XT7Gl8AhJS6JK5kCvip1rBBI8yjrsjE/E+lyJFIbC4rXxyMDGZWkcdrd7U4ZFYKiLHbzdFRqX+11qs9xO2BvomGXkATCzYmOf2kQ86R6rNN0+JfE4QpKzj2WWt3C8ky2qpuXZz29p0816E3/qseYtgg=");
|
||||
public final static SkinData TEDDY_BEAR = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTUxMDkzOTE4MjYsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzQ0OTU4ZDdjNjlhZTQ4NGM2NWYzMTM0N2NkY2M5MmM2OWY1NDA2ODA1YjUzNjUyYTc1YThlZDc5OWRmNyJ9fX0=", "sNTRV9jTjLszUmyaqyEG7N8d5RM1jbwMSXi34S2EkVmIjWsowfSMnHRQqqgZfxcyqBM5I7MljtB84IeQWu4rqhyFrM9blWvtowjijFIOgKCs97q2sswv9iauU6ohvgTpgN5B0Q16MJmMIgZU8d8TATtEaIzq2eg6Ve1AJlNnW4huGNsoNfm8WdVU1tZmsYAwtVP/ryvhyj7mHyVF27m0Sm4fZRf/lHH5gEJYB4JHSAoEhjPIQOdkgRMJRrWGOfhhiGs3kEWmsRGfIPFo2ZJfcu+TFV2rd4Q+A1LmY8kimnzdKX3InXeKbk8qzcgqGNro4XFnSiHo1d6/B+N0JeYOTITYRQ6u24rNSUh5ezbG01iikVFCfrgb7UR6utoLK15F4/fmhpex+BJpmyZoXAqk08tZws/5wsIWQ1okrGcbBKWEHhw2ekUc82US21/W53vd657UBg7FuqM4FhkAqmsYPvYLMpNYxxmDJaI8uJyU7cnGFYyBaFlqUxfJUfcFTwWo10JO3yp5FjqeCQa7rFvfpsqw3w2mBpJmlZ5HRjfS5pmhk0QiY0TRfwZfFemkuZYnNbO82qLUm+6zTm0fbC90Swt8nNr/42ajzEoUjnL6VsERIXS5/fPwjftbQAC60ujy8yo66Sp3sSAALNg5zjM+Uizkq2f9Axc+kind22hp10M=");
|
||||
public final static SkinData UNCLE_SAM = new SkinData("eyJ0aW1lc3RhbXAiOjE0NjYxODA0NjY4NTcsInByb2ZpbGVJZCI6IjlmY2FlZDhiMTRiNTRmN2ZhNjRjYjYwNDBlNzA1MjcyIiwicHJvZmlsZU5hbWUiOiJMQ2FzdHIxIiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9jYzM1YWRmZTQ3ODBjNmU2NTk4YTJlYzk2ZjdhZGQ5ZDc4NjljMjBlZjRmYjEyNjk2NmJhOGFlMDRlOWRhIn19fQ==", "NmJ+hXmvwQlYFYY7YVQWRr11yBbAfJP+jk11SQ91gUUtJJjb4v8RFbNu5UXNCKxYj3BPtldqshG1maNB0NWJRud7ZyAdHc0JMmR1vtHEge9Hhet4fLyyaZ9rZn4BvD9Guqgv9H/mZzUzrft9TIho0Qbu/U++lVsbZXC2GrJDDMyLnYr9C7f+FUnr0z4WvkNcg23SHBOYkOYT95NSdykIka3c3v+/HvSvuwOnMsfVxqLyCZLpo20vamBJ1uK1dmx2+TVGnUPlofFHRdOXOpJc+YmicJvrsQR6a9zlvnTbU4MYClMOKvjLe6aX5Af+n8Gw3oKcm0PuR8CPLyf9kjcmUF6XMiEXAWWJtCgvhCiFV5/mQQH3cQ1kqk4BDLUxMVhG5tzjKLoQQy39cFM32ee+QFjXlzy59meC8jgvPmOVU3GpJ32XWOtaXMCyeJrhz2QVKRLEr2KZgz8Pd8VrHARXVZsNYEasj8z0cHjgSJqTU9kD90CC+4YpvdyRBRqbNQig5KuGCqUHKgflsEsM7YrFRKP5As1LgqYQfqRAMmLSo47eW0onOwchC9wCqqisPlYSuDRt4Mun/KFGqYh1Sghn8/gzu49La8BpwlekjVEoPEcDaIIgnFzOvgmmgMANkoJ3PzhHoHMoXtObe3eSTi+eYp4qAQVzkTxfF3WXY2fui1M=");
|
||||
|
||||
// Comments this out for now, so it doesn't load the player profile
|
||||
// A better way to do this would check for the properties when getting the skull or the skin
|
||||
// Might change on the next version
|
||||
//public final static SkinData MOOSHROOM = new SkinData("eyJ0aW1lc3RhbXAiOjE0NDk4NzI0OTU0MTcsInByb2ZpbGVJZCI6ImE5ZDBjMDcyYmYxOTQwYTFhMTkzNjhkMDlkNTAwMjZlIiwicHJvZmlsZU5hbWUiOiJTcGlyaXR1c1NhbmN0dXMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzIxOWJlYTU0Y2FkN2Q1OGFiNWRhNDA2YjBhOTJhYjNhODI0MjI1MjY2Nzc3ZTUzNGI3ZGI2YzM3MmRkZmY3ZiJ9fX0=","UoSif81+UyvkcaanU8KAMYBpw9mefAmWehE2liDUFvk+y0X/9NovsxTYVpIDCltTSpLW3sNgamvbj4Ybs+s6DbudPiEkvh0ER7Bv2v29UJw7RzIdr6/1g548X12zcnh5iPGz/P75uNRnSfTFQx0ed8P/GNkPIjWpDuJFxEj6KcPzrCAGMx+BVw1VwryBIYf9cCDHky8z0bxR89rjiIvPTBFI6MRhqI3vgpEBTySHDS+Ki0Hwl5oa3PwS6+jgYx/4RSfFsb+BawcvDk2Xpkt5UimvqZ5BceYLIfCt4KbShYipgLXLfYUZrntjPemd3SxthjxUuA07i44UxRdiC8uqy1twLT/HUS28gpk68lA/id9tKFwu1CUzshgcmvQPt3ghtNViNziR/2t7D/+5D31Vzmhf6n7Pnpdirt/5frMi2BKMMs7pLa0EF8CrrDU7QCwPav+EZVGFvVZbxSkCDq+n3IQ3PUWSCzy6KPxpdOlUjD0pAfLoiNj0P8u4+puQtID76r/St8ExchYl2dodUImu1ZETWeFUClF3ZGat62evx8uRQEI2W4dsVwj40VUfjaAuvyDzuouaKTrCzJXLQZZjR1B8URvuK61fGX0nhW607mEi6DE+nxP2ZoBrROEX4e37Ap6+TQn9Q8tKDPdcxtwSOpPO4Qkncjn/mGtP9lZU/DQ=");
|
||||
|
||||
//public final static SkinData CHISS = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTk1NDI5NjgyNDEsInByb2ZpbGVJZCI6IjFkMmJmZTYxN2ViZDQ0NWRiYTdkODM1NGEwZmZkMWVhIiwicHJvZmlsZU5hbWUiOiJDaGlzcyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTg3MmNkMzRjY2IzMTIxYjRjNmEzOGFjM2JmOGVkM2UwMzk3YmQ2YTg4NDI4YjdhZmM2ZTUyNTI4NTVhMzQzIiwibWV0YWRhdGEiOnsibW9kZWwiOiJzbGltIn19fX0=", "hNTLRA2acZYx2dM90lnJN8FMK/ceD3+AxKNdD5FrXzxGtYL4C1Jr/vbTE0UosmwFP3wScNEW/fuDOjeZRjZHMJdvgDZMlMK/5KDhOY6sj/RS9RckztsgummSyjH/hdDn7TWWfhZLMbiia/K0VReI9eq2yD6zGQpvMlz5hB/5SX5YHWXvCah3TL4UzYSlSVDlwY/Q3sVuIZUr8m/LIXJwniJKLGo6tUgtiJd9eseOsbBpVjzCUtLD8A9WBe2/eODgmLfqEvXESIoDRG8vL2nPSXWma/YolYHIl32/i+ZxVD7dRRaXQFYSiLI24EtzX1pPhMjyaTLazP9abH43J6J31w02pKM7N/xTa62020L/YfRRKGT5lygEDb1NMoSpAjszPxah+Ra2/L+yUWEI8cMES6I4mIJ00tclPjWK01xhIn3tqg+y2gqsGHwPhu/7vmF5NirNfKFw0qciKNBfbCAF7ae+mkUKjmAPuvBUBqQb7BOcpNVWsCo/XvzmiZZYsf5P4Uwz8LqUK4uH6V/5dg7lY2Xg3+IUylsrDqLGFDI8iy/NdjIQMbuRadh4IDO6DcmxBri2Ax4JNBPBTnRezge8uq37MZcft/IXQgFWKB9RtidVEACaTOkRj27k+Ojnkki+j44k0wZB47hiXFUHMCHl3a0SVdQe15ZbVsQj/HAvAS0=");
|
||||
//public final static SkinData DEFEK7 = new SkinData("eyJ0aW1lc3RhbXAiOjE0NTk1NDI3ODkwNTksInByb2ZpbGVJZCI6Ijg5ZDQ2M2Y3MjNlYzQ3MGE4MjQ0NDU3ZjBjOGQ4NjFjIiwicHJvZmlsZU5hbWUiOiJkZWZlazciLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2JmYWNjOWM4ZjhlY2E1OWU0NTE4MTUxZmE4OGFiMDZjOTFmNjM3OTE2NzJmMTRlNGYzODY3YTI2OTVlN2NmYmYifSwiQ0FQRSI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzIyYjljNWVhNzYzYzg2ZmM1Y2FlYTMzZDgyYjBmYTY1YTdjMjI4ZmQzMjFiYTU0NzY2ZWE5NWEzZDBiOTc5MyJ9fX0=", "jBoRvkhQXz+nap8yJJIZ+4HClMItWODumeSOYjXytP3WWKHK0UMq0xC/keXsnmvo89lMRdRbknPt2ZX5Flgyjgr4Rt0KtDvpL/hG4BUsTWryUZZMKxdd6DkZXYRtTogLUfHeDYIz+cZQ0aXGMtvX/ZYTXJfMi6FYbIHY/qEEDnWhDX5y+SPpaJaZByPsvzi+qbfcFGnJ6nqi9ccyZYnYpnI2IVBM/yO/VRXWHxfqvJ0VVvv5KsGmVbko2Jxo0SDCxUL2UTH2+eol53FxhkkC+m2geC14k1zsZQLHDF3BgAG9+kFJ4UEoYRKF2Gy1FxeDCJtjYNdrYR8fdaUKRMcpBgEs+ZGe2U9EVVS/ZcBCjB7S+1Ne2bPzPFzTQPuBoMgggo1xbxBmQ5NyhYo4gwgj/xjSLIhb+5h7ioN1URfSRcfYdVv6RRO9l/u9l09jEom8y/jGRviefpEr+/e9iAl5Dd/6nzQgosBQja3NSfqYZmyuet2eI9zu61CObDTpR6yaCbNgBe/lWofRfULdpJpgjb4UNTBom3q82FcCiOe02OekGPw4+YlilhICBhajF5JzN8FKAdqI1osDcX3KuJgikYIW3voNaOP5YN3GXgilJNdou20KFC8ICq68HglgX7/0rLrWKIEoswnINIM6HcJbQuXncVPwQhV6K34Hlt/Na60=");
|
||||
|
||||
private Property _skinProperty;
|
||||
|
||||
|
@ -0,0 +1,126 @@
|
||||
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.BiConsumer;
|
||||
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;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize a {@link CompletionStage} by executing code on the
|
||||
* main thread after its normal or exceptional completion.
|
||||
*
|
||||
* @param action the {@link BiConsumer} that will execute
|
||||
* @return a {@link BiConsumer} to be passed as an argument to
|
||||
* {@link CompletionStage#whenComplete(BiConsumer)}
|
||||
* @see CompletableFuture#whenComplete(BiConsumer)
|
||||
*/
|
||||
public static <T> BiConsumer<? super T,? super Throwable> complete(BiConsumer<? super T,? super Throwable> action)
|
||||
{
|
||||
return (val, throwable) -> runBlocking(() -> action.accept(val, throwable));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package mineplex.core.common.util;
|
||||
|
||||
import mineplex.core.common.CurrencyType;
|
||||
import mineplex.core.common.Rank;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@ -200,6 +201,11 @@ public class F
|
||||
return out;
|
||||
}
|
||||
|
||||
public static String currency(CurrencyType type, int amount)
|
||||
{
|
||||
return type.getString(amount) + ChatColor.RESET + C.mBody;
|
||||
}
|
||||
|
||||
public static String vowelAN(String word)
|
||||
{
|
||||
return word.toLowerCase().startsWith("a")
|
||||
|
@ -256,33 +256,36 @@ public class MapUtil
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
public static boolean ClearWorldReferences(String worldName)
|
||||
{
|
||||
HashMap regionfiles = (HashMap) RegionFileCache.a;
|
||||
|
||||
try
|
||||
synchronized (RegionFileCache.class)
|
||||
{
|
||||
for (Iterator<Object> iterator = regionfiles.entrySet().iterator(); iterator.hasNext();)
|
||||
{
|
||||
Map.Entry e = (Map.Entry) iterator.next();
|
||||
RegionFile file = (RegionFile) e.getValue();
|
||||
HashMap regionfiles = (HashMap) RegionFileCache.a;
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
for (Iterator<Object> iterator = regionfiles.entrySet().iterator(); iterator.hasNext(); )
|
||||
{
|
||||
file.c();
|
||||
iterator.remove();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
Map.Entry e = (Map.Entry) iterator.next();
|
||||
RegionFile file = (RegionFile) e.getValue();
|
||||
|
||||
try
|
||||
{
|
||||
file.c();
|
||||
iterator.remove();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception while removing world reference for '" + worldName + "'!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.out.println("Exception while removing world reference for '" + worldName + "'!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static BlockPosition getBlockPos(int x, int y, int z)
|
||||
|
@ -44,9 +44,9 @@ public class ProfileLoader
|
||||
return profile;
|
||||
}
|
||||
|
||||
private void addProperties(GameProfile profile)
|
||||
public static boolean addProperties(GameProfile profile)
|
||||
{
|
||||
String uuid = getUUID(skinOwner);
|
||||
String uuid = profile.getId().toString().replaceAll("-", "");
|
||||
try
|
||||
{
|
||||
// Get the name from SwordPVP
|
||||
@ -85,11 +85,15 @@ public class ProfileLoader
|
||||
Bukkit.getLogger().log(Level.WARNING, "Failed to apply auth property", e);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -3,7 +3,6 @@ package mineplex.core.common.util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@ -28,9 +27,9 @@ import org.bukkit.inventory.meta.BannerMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.bukkit.material.Bed;
|
||||
|
||||
import mineplex.core.common.block.MultiBlockUpdaterAgent;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.Blocks;
|
||||
import net.minecraft.server.v1_8_R3.EnumDirection;
|
||||
import net.minecraft.server.v1_8_R3.IBlockData;
|
||||
import net.minecraft.server.v1_8_R3.Item;
|
||||
import net.minecraft.server.v1_8_R3.MathHelper;
|
||||
@ -92,6 +91,8 @@ public class UtilBlock
|
||||
*/
|
||||
public static HashSet<BlockFace> horizontals = new HashSet<>();
|
||||
|
||||
private static MultiBlockUpdaterAgent _quickChangeRecorder;
|
||||
|
||||
static
|
||||
{
|
||||
|
||||
@ -604,14 +605,52 @@ public class UtilBlock
|
||||
return getInBoundingBox(a, b, true);
|
||||
}
|
||||
|
||||
public static ArrayList<Block> getInBoundingBox(Location a, Location b, boolean ignoreAir)
|
||||
public static ArrayList<Block> getInBoundingBox(Location a, Location b, boolean ignoreAir) {
|
||||
return getInBoundingBox(a, b, ignoreAir, false, true, true);
|
||||
}
|
||||
|
||||
public static ArrayList<Block> getInBoundingBox(Location a, Location b, boolean ignoreAir, boolean hollow, boolean walls, boolean ceilfloor)
|
||||
{
|
||||
ArrayList<Block> blocks = new ArrayList<Block>();
|
||||
|
||||
for (int x = Math.min(a.getBlockX(), b.getBlockX()); x <= Math.max(a.getBlockX(), b.getBlockX()); x++)
|
||||
for (int y = Math.min(a.getBlockY(), b.getBlockY()); y <= Math.max(a.getBlockY(), b.getBlockY()); y++)
|
||||
for (int z = Math.min(a.getBlockZ(), b.getBlockZ()); z <= Math.max(a.getBlockZ(), b.getBlockZ()); z++)
|
||||
int xmin = Math.min(a.getBlockX(), b.getBlockX());
|
||||
int xmax = Math.max(a.getBlockX(), b.getBlockX());
|
||||
|
||||
int ymin = Math.min(a.getBlockY(), b.getBlockY());
|
||||
int ymax = Math.max(a.getBlockY(), b.getBlockY());
|
||||
|
||||
int zmin = Math.min(a.getBlockZ(), b.getBlockZ());
|
||||
int zmax = Math.max(a.getBlockZ(), b.getBlockZ());
|
||||
|
||||
for (int x = xmin; x <= xmax; x++)
|
||||
for (int y = ymin; y <= ymax; y++)
|
||||
for (int z = zmin; z <= zmax; z++)
|
||||
{
|
||||
|
||||
if(hollow)
|
||||
{
|
||||
if(!(x == xmin || x == xmax || y == ymin || y == ymax || z == zmin || z == zmax)) continue;
|
||||
}
|
||||
|
||||
if(!walls)
|
||||
{
|
||||
if(
|
||||
(x == xmin || x == xmax) ||
|
||||
(z == zmin || z == zmax)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ceilfloor)
|
||||
{
|
||||
if(y == ymin || y == ymax)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Block block = a.getWorld().getBlockAt(x, y, z);
|
||||
|
||||
if (ignoreAir)
|
||||
@ -619,7 +658,9 @@ public class UtilBlock
|
||||
if (block.getType() != Material.AIR) blocks.add(block);
|
||||
}
|
||||
else
|
||||
{
|
||||
blocks.add(block);
|
||||
}
|
||||
}
|
||||
|
||||
return blocks;
|
||||
@ -1466,6 +1507,39 @@ public class UtilBlock
|
||||
return state.update(false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #setQuick(World, int, int, int, int, byte)}
|
||||
*/
|
||||
public static void startQuickRecording()
|
||||
{
|
||||
if(_quickChangeRecorder != null)
|
||||
{
|
||||
_quickChangeRecorder.send();
|
||||
_quickChangeRecorder.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
_quickChangeRecorder = new MultiBlockUpdaterAgent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #setQuick(World, int, int, int, int, byte)}
|
||||
*/
|
||||
public static void stopQuickRecording()
|
||||
{
|
||||
if(_quickChangeRecorder == null) return;
|
||||
_quickChangeRecorder.send();
|
||||
_quickChangeRecorder.reset();
|
||||
_quickChangeRecorder = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This doesn't send the block changes to the client. If you want to change lots of blocks and then send it to the player
|
||||
* then do <code>startQuickRecording()</code> first. Change all the blocks you want. Then to send it do
|
||||
* <code>stopQuickRecording()</code>. This will automatically send all the block changes to all relevant players.
|
||||
*/
|
||||
public static void setQuick(World world, int x, int y, int z, int type, byte data)
|
||||
{
|
||||
int cx = x >> 4;
|
||||
@ -1475,10 +1549,18 @@ public class UtilBlock
|
||||
world.loadChunk(cx, cz, true);
|
||||
}
|
||||
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = ((CraftWorld) world).getHandle().getChunkAt(x >> 4, z >> 4);
|
||||
WorldServer nmsWorld = ((CraftWorld) world).getHandle();
|
||||
|
||||
net.minecraft.server.v1_8_R3.Chunk chunk = nmsWorld.getChunkAt(x >> 4, z >> 4);
|
||||
BlockPosition pos = new BlockPosition(x, y, z);
|
||||
IBlockData ibd = net.minecraft.server.v1_8_R3.Block.getById(type).fromLegacyData(data);
|
||||
chunk.a(pos, ibd);
|
||||
nmsWorld.notify(pos);
|
||||
|
||||
// if(_quickChangeRecorder != null)
|
||||
// {
|
||||
// _quickChangeRecorder.addBlock(world.getBlockAt(x, y, z));
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1504,4 +1586,35 @@ public class UtilBlock
|
||||
{
|
||||
return boundless(origin.getLocation(), radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the max distance this blocks bounding box extends in the given block face. E.g. stone have a max:min of 1:0 in all direction.
|
||||
* Slabs have 0:1 in horizontal directions, but 0:0.5 or 0.5:1 depending on if it is top or bottom.
|
||||
* @param block The block to test
|
||||
* @param blockFace The direction to test in
|
||||
* @return
|
||||
*/
|
||||
public static double getSize(Block block, BlockFace blockFace)
|
||||
{
|
||||
BlockPosition bpos = new BlockPosition(block.getX(), block.getY(), block.getZ());
|
||||
net.minecraft.server.v1_8_R3.Block b = ((CraftWorld)block.getWorld()).getHandle().c(bpos);
|
||||
|
||||
switch (blockFace)
|
||||
{
|
||||
default:
|
||||
case WEST:
|
||||
return b.B(); //min-x
|
||||
case EAST:
|
||||
return b.C(); //max-x
|
||||
case DOWN:
|
||||
return b.D(); //min-y
|
||||
case UP:
|
||||
return b.E(); //max-y
|
||||
case NORTH:
|
||||
return b.F(); //min-z
|
||||
case SOUTH:
|
||||
return b.G(); //max-z
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,13 @@
|
||||
package mineplex.core.common.util;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Created by Shaun on 11/12/2014.
|
||||
@ -13,6 +20,8 @@ public class UtilColor
|
||||
public static final RGBData RgbLightRed = hexToRgb(0xeb1c1c);
|
||||
public static final RGBData RgbPurple = hexToRgb(0x9c17a3);
|
||||
|
||||
public static final Color DEFAULT_LEATHER_COLOR = Color.fromRGB(160, 101, 64);
|
||||
|
||||
public static byte chatColorToClayData(ChatColor chatColor)
|
||||
{
|
||||
//TODO
|
||||
@ -71,6 +80,52 @@ public class UtilColor
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static ChatColor woolDataToChatColor(byte data)
|
||||
{
|
||||
switch (data)
|
||||
{
|
||||
case 0:
|
||||
return ChatColor.WHITE;
|
||||
case 1:
|
||||
return ChatColor.GOLD;
|
||||
case 2:
|
||||
return ChatColor.DARK_PURPLE;
|
||||
case 3:
|
||||
return ChatColor.BLUE;
|
||||
case 4:
|
||||
return ChatColor.YELLOW;
|
||||
case 5:
|
||||
return ChatColor.GREEN;
|
||||
case 6:
|
||||
return ChatColor.LIGHT_PURPLE;
|
||||
case 7:
|
||||
return ChatColor.DARK_GRAY;
|
||||
case 8:
|
||||
return ChatColor.GRAY;
|
||||
case 9:
|
||||
return ChatColor.DARK_AQUA;
|
||||
case 10:
|
||||
return ChatColor.DARK_PURPLE;
|
||||
case 11:
|
||||
return ChatColor.DARK_BLUE;
|
||||
case 12:
|
||||
return ChatColor.DARK_RED;
|
||||
case 13:
|
||||
return ChatColor.DARK_GREEN;
|
||||
case 14:
|
||||
return ChatColor.RED;
|
||||
case 15:
|
||||
return ChatColor.BLACK;
|
||||
default:
|
||||
return ChatColor.WHITE;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector colorToVector(Color color)
|
||||
{
|
||||
return new Vector(Math.max(color.getRed()/255.0, 0.00001f), color.getGreen()/255.0, color.getBlue()/255.0);
|
||||
}
|
||||
|
||||
public static RGBData hexToRgb(int hex)
|
||||
{
|
||||
@ -91,4 +146,73 @@ public class UtilColor
|
||||
{
|
||||
return new RGBData(r, g, b);
|
||||
}
|
||||
|
||||
public static Color getNextColor(Color original, Color finalColor, int increment)
|
||||
{
|
||||
int red = original.getRed(), green = original.getGreen(), blue = original.getBlue();
|
||||
|
||||
if (red > finalColor.getRed())
|
||||
red -= increment;
|
||||
else if (red < finalColor.getRed())
|
||||
red += increment;
|
||||
else if (green > finalColor.getGreen())
|
||||
green -= increment;
|
||||
else if (green < finalColor.getGreen())
|
||||
green += increment;
|
||||
else if (blue > finalColor.getBlue())
|
||||
blue -= increment;
|
||||
else if (blue < finalColor.getBlue())
|
||||
blue += increment;
|
||||
|
||||
red = UtilMath.clamp(red, 0, 255);
|
||||
green = UtilMath.clamp(green, 0, 255);
|
||||
blue = UtilMath.clamp(blue, 0, 255);
|
||||
|
||||
return Color.fromRGB(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies Color to a Leather armor
|
||||
* @param itemStack
|
||||
* @param color
|
||||
* @return ItemStack with color applied
|
||||
*/
|
||||
public static ItemStack applyColor(@Nonnull ItemStack itemStack, Color color)
|
||||
{
|
||||
switch (itemStack.getType())
|
||||
{
|
||||
case LEATHER_HELMET:
|
||||
case LEATHER_CHESTPLATE:
|
||||
case LEATHER_LEGGINGS:
|
||||
case LEATHER_BOOTS:
|
||||
LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) itemStack.getItemMeta();
|
||||
|
||||
leatherArmorMeta.setColor(color);
|
||||
itemStack.setItemMeta(leatherArmorMeta);
|
||||
return itemStack;
|
||||
default:
|
||||
return itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets color from Leather armor
|
||||
* @param itemStack
|
||||
* @return Color of the item
|
||||
*/
|
||||
public static Color getItemColor(@Nonnull ItemStack itemStack)
|
||||
{
|
||||
switch (itemStack.getType())
|
||||
{
|
||||
case LEATHER_HELMET:
|
||||
case LEATHER_CHESTPLATE:
|
||||
case LEATHER_LEGGINGS:
|
||||
case LEATHER_BOOTS:
|
||||
LeatherArmorMeta leatherArmorMeta = (LeatherArmorMeta) itemStack.getItemMeta();
|
||||
|
||||
return leatherArmorMeta.getColor();
|
||||
default:
|
||||
return DEFAULT_LEATHER_COLOR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -258,6 +258,21 @@ public class UtilEnt
|
||||
}
|
||||
}
|
||||
|
||||
public static void addGoalSelector(Entity entity, int priority, PathfinderGoal goal)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(((CraftEntity)entity).getHandle() instanceof EntityInsentient)
|
||||
{
|
||||
((EntityInsentient)((CraftEntity)entity).getHandle()).goalSelector.a(priority, goal);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static void Rotate(LivingEntity entity, float yaw, float pitch)
|
||||
{
|
||||
EntityLiving handle = ((CraftLivingEntity) entity).getHandle();
|
||||
@ -856,6 +871,11 @@ public class UtilEnt
|
||||
{
|
||||
return ent.getLocation().getBlock().getTypeId() == 8 || ent.getLocation().getBlock().getTypeId() == 9;
|
||||
}
|
||||
|
||||
public static void setBoundingBox(Entity ent, double width, double height)
|
||||
{
|
||||
((CraftEntity)ent).getHandle().setSize((float) width, (float)height);
|
||||
}
|
||||
|
||||
public static void SetMetadata(Entity entity, String key, Object value)
|
||||
{
|
||||
@ -879,4 +899,40 @@ public class UtilEnt
|
||||
equipment.setItemInHand(item);
|
||||
}
|
||||
|
||||
public static byte getEntityEggData(EntityType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case CREEPER: return (byte) 50;
|
||||
case SKELETON: return (byte) 51;
|
||||
case SPIDER: return (byte) 52;
|
||||
case ZOMBIE: return (byte) 54;
|
||||
case SLIME: return (byte) 55;
|
||||
case GHAST: return (byte) 56;
|
||||
case PIG_ZOMBIE: return (byte) 57;
|
||||
case ENDERMAN: return (byte) 58;
|
||||
case CAVE_SPIDER: return (byte) 59;
|
||||
case SILVERFISH: return (byte) 60;
|
||||
case BLAZE: return (byte) 61;
|
||||
case MAGMA_CUBE: return (byte) 62;
|
||||
case BAT: return (byte) 65;
|
||||
case WITCH: return (byte) 66;
|
||||
case ENDERMITE: return (byte) 67;
|
||||
case GUARDIAN: return (byte) 68;
|
||||
//case SHULKER: return (byte) 69;
|
||||
case PIG: return (byte) 90;
|
||||
case SHEEP: return (byte) 91;
|
||||
case COW: return (byte) 92;
|
||||
case CHICKEN: return (byte) 93;
|
||||
case SQUID: return (byte) 94;
|
||||
case WOLF: return (byte) 95;
|
||||
case MUSHROOM_COW: return (byte) 96;
|
||||
case OCELOT: return (byte) 98;
|
||||
case HORSE: return (byte) 100;
|
||||
case RABBIT: return (byte) 101;
|
||||
case VILLAGER: return (byte) 120;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -108,4 +108,10 @@ public class UtilFirework
|
||||
UtilMath.random.nextBoolean()
|
||||
);
|
||||
}
|
||||
|
||||
public static void playFreedomFirework(Location location)
|
||||
{
|
||||
playFirework(location, FireworkEffect.builder().withColor(Color.RED).withColor(Color.BLUE)
|
||||
.withColor(Color.WHITE).withFade(Color.RED).withFade(Color.BLUE).withFade(Color.WHITE).build());
|
||||
}
|
||||
}
|
||||
|
@ -192,6 +192,13 @@ public class UtilGear
|
||||
|
||||
return item.getType() == mat;
|
||||
}
|
||||
|
||||
public static boolean isMatAndData(ItemStack item, Material mat, byte data)
|
||||
{
|
||||
if (item == null) return false;
|
||||
|
||||
return item.getType() == mat && item.getData().getData() == data;
|
||||
}
|
||||
|
||||
public static boolean isRepairable(ItemStack item)
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ import org.bukkit.inventory.PlayerInventory;
|
||||
public class UtilInv
|
||||
{
|
||||
private static Field _enchantmentNew;
|
||||
private static DullEnchantment _enchantment;
|
||||
private static DullEnchantment DULL_ENCHANTMENT;
|
||||
|
||||
static
|
||||
{
|
||||
@ -29,8 +29,8 @@ public class UtilInv
|
||||
_enchantmentNew.setAccessible(true);
|
||||
_enchantmentNew.set(null, true);
|
||||
|
||||
_enchantment = new DullEnchantment();
|
||||
EnchantmentWrapper.registerEnchantment(_enchantment);
|
||||
DULL_ENCHANTMENT = new DullEnchantment();
|
||||
EnchantmentWrapper.registerEnchantment(DULL_ENCHANTMENT);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@ -40,17 +40,17 @@ public class UtilInv
|
||||
|
||||
public static void addDullEnchantment(ItemStack itemStack)
|
||||
{
|
||||
itemStack.addEnchantment(_enchantment, 1);
|
||||
itemStack.addEnchantment(DULL_ENCHANTMENT, 1);
|
||||
}
|
||||
|
||||
public static void removeDullEnchantment(ItemStack itemStack)
|
||||
{
|
||||
itemStack.removeEnchantment(_enchantment);
|
||||
itemStack.removeEnchantment(DULL_ENCHANTMENT);
|
||||
}
|
||||
|
||||
public static DullEnchantment getDullEnchantment()
|
||||
{
|
||||
return _enchantment;
|
||||
return DULL_ENCHANTMENT;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -9,13 +9,21 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import mineplex.core.common.structs.ItemContainer;
|
||||
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
||||
import net.minecraft.server.v1_8_R3.NBTTagLong;
|
||||
|
||||
public class UtilItem
|
||||
{
|
||||
@ -1147,6 +1155,66 @@ public class UtilItem
|
||||
i.setItemMeta(im);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param item The item stack to use as source for this Item entity
|
||||
* @param loc Location of where to spawn the Item entity
|
||||
* @param dropNaturaly If false then no velocity is applied. If true then it drops with random velocity like from when blocks break.
|
||||
* @param allowPickup If false then it will disable pickup of this item.
|
||||
* @param ticksToLive Ticks before this item should be removed from the ground. (default 6000 ticks = 5min, -1 to never remove it)
|
||||
* @param allowMerge If false then the item will not merge with any other items.
|
||||
* @return
|
||||
*/
|
||||
|
||||
public static Item dropItem(ItemStack item, Location loc, boolean dropNaturaly, boolean allowPickup, int ticksToLive, boolean allowMerge)
|
||||
{
|
||||
Item ent;
|
||||
if(dropNaturaly)
|
||||
{
|
||||
ent = loc.getWorld().dropItemNaturally(loc, item);
|
||||
} else {
|
||||
ent = loc.getWorld().dropItem(loc, item);
|
||||
}
|
||||
if(!allowPickup)
|
||||
{
|
||||
ent.setPickupDelay(32767);
|
||||
}
|
||||
|
||||
ent.setTicksLived(32768);
|
||||
|
||||
UtilEnt.SetMetadata(ent, "UtilItemSpawning", true);
|
||||
|
||||
if(ticksToLive != -1)
|
||||
{
|
||||
Plugin plugin = Bukkit.getPluginManager().getPlugin("Hub");
|
||||
if(plugin == null) plugin = Bukkit.getPluginManager().getPlugin("Arcade");
|
||||
if(plugin == null) plugin = Bukkit.getPluginManager().getPlugins()[0];
|
||||
|
||||
new BukkitRunnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
ent.remove();
|
||||
}
|
||||
}.runTaskLater(plugin, ticksToLive);
|
||||
}
|
||||
|
||||
if(!allowMerge)
|
||||
{
|
||||
net.minecraft.server.v1_8_R3.ItemStack stack = CraftItemStack.asNMSCopy(ent.getItemStack());
|
||||
NBTTagCompound tag = stack.getTag();
|
||||
if(!stack.hasTag())
|
||||
{
|
||||
stack.setTag(new NBTTagCompound());
|
||||
tag = stack.getTag();
|
||||
}
|
||||
tag.set("Pickup_" + UtilMath.r(Integer.MAX_VALUE), new NBTTagLong(UtilMath.random.nextLong()));
|
||||
ent.setItemStack(CraftItemStack.asBukkitCopy(stack));
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
|
||||
public static double getAttackDamage(Material type)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
package mineplex.core.common.util;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -12,7 +13,26 @@ public class UtilParticle
|
||||
{
|
||||
public enum ViewDist
|
||||
{
|
||||
SHORT(8), NORMAL(24), LONG(48), LONGER(96), MAX(256);
|
||||
/**
|
||||
* 8 blocks
|
||||
*/
|
||||
SHORT(8),
|
||||
/**
|
||||
* 24 blocks
|
||||
*/
|
||||
NORMAL(24),
|
||||
/**
|
||||
* 48 blocks
|
||||
*/
|
||||
LONG(48),
|
||||
/**
|
||||
* 96 blocks
|
||||
*/
|
||||
LONGER(96),
|
||||
/**
|
||||
* 256 blocks
|
||||
*/
|
||||
MAX(256);
|
||||
|
||||
private int _dist;
|
||||
|
||||
@ -321,6 +341,21 @@ public class UtilParticle
|
||||
{
|
||||
PlayParticle(particle, location, offsetX, offsetY, offsetZ, speed, count, dist, UtilServer.getPlayers());
|
||||
}
|
||||
|
||||
|
||||
public static void playColoredParticle(Color color, ParticleType particleType, Location location, int count, ViewDist dist, Player... players)
|
||||
{
|
||||
if (particleType != ParticleType.RED_DUST
|
||||
&& particleType != ParticleType.MOB_SPELL_AMBIENT)
|
||||
return;
|
||||
PlayParticle(particleType, location, color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 1f, count, dist, players);
|
||||
}
|
||||
|
||||
public static void playColoredParticleToAll(Color color, ParticleType particleType, Location location, int count, ViewDist dist)
|
||||
{
|
||||
if (particleType != ParticleType.RED_DUST
|
||||
&& particleType != ParticleType.MOB_SPELL_AMBIENT)
|
||||
return;
|
||||
PlayParticleToAll(particleType, location, color.getRed() / 255F, color.getGreen() / 255F, color.getBlue() / 255F, 1f, count, dist);
|
||||
}
|
||||
|
||||
}
|
@ -1,15 +1,8 @@
|
||||
package mineplex.core.common.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
import net.minecraft.server.v1_8_R3.*;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
@ -29,17 +22,20 @@ import org.bukkit.util.Vector;
|
||||
|
||||
import mineplex.core.common.MinecraftVersion;
|
||||
import mineplex.core.common.events.PlayerMessageEvent;
|
||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
||||
|
||||
public class UtilPlayer
|
||||
{
|
||||
private static Random RANDOM = new Random();
|
||||
|
||||
// A mapping of player names (Keys) to the system time when they last changed active Hotbar Slot
|
||||
private static Map<String, Long> _hotbarUpdates = new HashMap<String, Long>();
|
||||
|
||||
private static Map<String, Long> _hotbarUpdates = new HashMap<>();
|
||||
|
||||
// A mapping of player UUIDs (Keys) to the world border they are using (if they are using)
|
||||
private static final Map<UUID, WorldBorder> WORLD_BORDERS = new HashMap<>();
|
||||
|
||||
// A mapping of player UUIDs (Keys) to the list of command they're allowed
|
||||
private static final Map<UUID, List<String>> ALLOWED_COMMANDS = new HashMap<>();
|
||||
|
||||
// The amount of time (in milliseconds) after changin hotbars that you can block
|
||||
public static final long BLOCKING_HOTBAR_DELAY = 100;
|
||||
|
||||
@ -68,6 +64,38 @@ public class UtilPlayer
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void hideFrom(Player player, Collection<Player> players) {
|
||||
players.stream().forEach(p->p.hidePlayer(player));
|
||||
}
|
||||
|
||||
public static void showFor(Player player, Collection<Player> players) {
|
||||
players.stream().forEach(p->p.hidePlayer(player));
|
||||
}
|
||||
|
||||
public static void hideFromAll(Player player, Collection<Player> except) {
|
||||
UtilServer.getPlayersCollection().stream().filter(p->!except.contains(p)).forEach(p->p.hidePlayer(player));
|
||||
}
|
||||
|
||||
public static void showForAll(Player player, Collection<Player> except) {
|
||||
UtilServer.getPlayersCollection().stream().filter(p->!except.contains(p)).forEach(p->p.showPlayer(player));
|
||||
}
|
||||
|
||||
public static void hideFrom(Player player, Player...players) {
|
||||
hideFrom(player, Arrays.asList(players));
|
||||
}
|
||||
|
||||
public static void showFor(Player player, Player...players) {
|
||||
showFor(player, Arrays.asList(players));
|
||||
}
|
||||
|
||||
public static void hideFromAll(Player player, Player...players) {
|
||||
hideFromAll(player, Arrays.asList(players));
|
||||
}
|
||||
|
||||
public static void showForAll(Player player, Player...players) {
|
||||
showForAll(player, Arrays.asList(players));
|
||||
}
|
||||
|
||||
public static boolean is1_9(Player player)
|
||||
{
|
||||
@ -823,6 +851,45 @@ public class UtilPlayer
|
||||
((CraftPlayer) player).getHandle().setWingsDeployAt(distance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the world border red screen for a player
|
||||
* @param player
|
||||
* @param warningDistance
|
||||
*/
|
||||
public static void sendRedScreen(Player player, int warningDistance)
|
||||
{
|
||||
WorldBorder worldBorder = WORLD_BORDERS.computeIfAbsent(player.getUniqueId(), uuid -> new WorldBorder());
|
||||
worldBorder.setCenter(player.getLocation().getX(), player.getLocation().getZ());
|
||||
worldBorder.setSize(10000);
|
||||
worldBorder.setWarningDistance(warningDistance);
|
||||
PacketPlayOutWorldBorder packet = new PacketPlayOutWorldBorder(worldBorder, PacketPlayOutWorldBorder.EnumWorldBorderAction.INITIALIZE);
|
||||
sendPacket(player, packet);
|
||||
WORLD_BORDERS.put(player.getUniqueId(), worldBorder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if player has a WorldBorder object stored
|
||||
* @param player
|
||||
* @return true if WorldBorder object is stored for that player
|
||||
*/
|
||||
public static boolean hasWorldBorder(Player player)
|
||||
{
|
||||
return WORLD_BORDERS.containsKey(player.getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes player from world border map
|
||||
* @param player
|
||||
*/
|
||||
public static void removeWorldBorder(Player player)
|
||||
{
|
||||
if (hasWorldBorder(player))
|
||||
{
|
||||
sendRedScreen(player, 0);
|
||||
WORLD_BORDERS.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
public static MinecraftVersion getVersion(Player player)
|
||||
{
|
||||
if (is1_9(player))
|
||||
@ -830,4 +897,50 @@ public class UtilPlayer
|
||||
|
||||
return MinecraftVersion.Version1_8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows player to run specific command
|
||||
* @param player The player to be allowed
|
||||
* @param command The command that will be allowed
|
||||
*/
|
||||
public static void allowCommand(Player player, String command)
|
||||
{
|
||||
List<String> commandList = new ArrayList<>();
|
||||
if (ALLOWED_COMMANDS.containsKey(player.getUniqueId()))
|
||||
commandList = ALLOWED_COMMANDS.get(player.getUniqueId());
|
||||
if (!commandList.contains(command))
|
||||
commandList.add(command);
|
||||
ALLOWED_COMMANDS.put(player.getUniqueId(), commandList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disallows player to run specific command
|
||||
* @param player The player to be disallowed
|
||||
* @param command The command that will be disallowed
|
||||
* @return True if player had command allowed
|
||||
*/
|
||||
public static boolean disallowCommand(Player player, String command)
|
||||
{
|
||||
if (!isCommandAllowed(player, command))
|
||||
return false;
|
||||
List<String> commandList = ALLOWED_COMMANDS.get(player.getUniqueId());
|
||||
commandList.remove(command);
|
||||
ALLOWED_COMMANDS.put(player.getUniqueId(), commandList);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isCommandAllowed(Player player, String command)
|
||||
{
|
||||
if (!ALLOWED_COMMANDS.containsKey(player.getUniqueId()))
|
||||
return false;
|
||||
if (!ALLOWED_COMMANDS.get(player.getUniqueId()).contains(command))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void removeAllowedCommands(Player player)
|
||||
{
|
||||
if (ALLOWED_COMMANDS.containsKey(player.getUniqueId()))
|
||||
ALLOWED_COMMANDS.remove(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
@ -112,7 +113,7 @@ public class UtilServer
|
||||
|
||||
public static Plugin getPlugin()
|
||||
{
|
||||
return getPluginManager().getPlugins()[0];
|
||||
return JavaPlugin.getProvidingPlugin(UtilServer.class);
|
||||
}
|
||||
|
||||
public static PluginManager getPluginManager()
|
||||
@ -196,4 +197,14 @@ public class UtilServer
|
||||
{
|
||||
return Lists.newArrayList(getPlayers());
|
||||
}
|
||||
|
||||
public static boolean isTestServer()
|
||||
{
|
||||
return getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Testing");
|
||||
}
|
||||
|
||||
public static boolean isHubServer()
|
||||
{
|
||||
return getPlugin().getConfig().getString("serverstatus.group").equalsIgnoreCase("Lobby");
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ public class UtilSkull
|
||||
if (displayHead)
|
||||
meta.setOwner(playerName);
|
||||
meta.setDisplayName(itemName);
|
||||
meta.setLore(itemLore);
|
||||
if (itemLore != null)
|
||||
meta.setLore(itemLore);
|
||||
skull.setItemMeta(meta);
|
||||
return skull;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
@ -17,8 +16,10 @@ import mineplex.core.common.CurrencyType;
|
||||
|
||||
public class UtilText
|
||||
{
|
||||
private static HashMap<Character, Integer> _characters = new HashMap<Character, Integer>();
|
||||
private static HashMap<Character, BufferedImage> _characterImages = new HashMap<Character, BufferedImage>();
|
||||
private static HashMap<Character, Integer> _characters = new HashMap<>();
|
||||
private static HashMap<Character, BufferedImage> _characterImages = new HashMap<>();
|
||||
|
||||
private final static char[] VOWELS = new char[]{'a', 'e', 'i', 'o', 'u'};
|
||||
|
||||
static
|
||||
{
|
||||
@ -286,12 +287,7 @@ public class UtilText
|
||||
|
||||
public static String[] splitLineToArray(String string, LineFormat lineFormat)
|
||||
{
|
||||
ArrayList<String> lineList = splitLine(string, lineFormat);
|
||||
|
||||
String[] lineArray = new String[lineList.size()];
|
||||
lineArray = lineList.toArray(lineArray);
|
||||
|
||||
return lineArray;
|
||||
return splitLinesToArray(string.split("\n"), lineFormat);
|
||||
}
|
||||
|
||||
public static ArrayList<String> splitLine(String string, LineFormat lineFormat)
|
||||
@ -308,7 +304,7 @@ public class UtilText
|
||||
// Empty
|
||||
if (string.equals("") || string.equals(" "))
|
||||
{
|
||||
strings.add(string);
|
||||
strings.add(" ");
|
||||
return strings;
|
||||
}
|
||||
|
||||
@ -624,7 +620,20 @@ public class UtilText
|
||||
|
||||
public static boolean plural(int x)
|
||||
{
|
||||
return x <= 0 ? true : x > 1;
|
||||
return x != 1;
|
||||
}
|
||||
|
||||
public static String plural(String word, int amount)
|
||||
{
|
||||
if(!plural(amount)) return word;
|
||||
String sufix = "s";
|
||||
if(word.endsWith("s") || word.endsWith("x") || word.endsWith("z") || word.endsWith("ch")) sufix = "es";
|
||||
else if(word.endsWith("y"))
|
||||
{
|
||||
word.substring(0, word.length()-2);
|
||||
sufix = "ies";
|
||||
}
|
||||
return word + sufix;
|
||||
}
|
||||
|
||||
public static String trim(int maxLength, String s)
|
||||
@ -661,20 +670,25 @@ public class UtilText
|
||||
{
|
||||
return getProgress(prefix, amount, suffix, progressDirectionSwap, 24);
|
||||
}
|
||||
|
||||
|
||||
public static String getProgress(String prefix, double amount, String suffix, boolean progressDirectionSwap, int bars)
|
||||
{
|
||||
return getProgress(prefix, amount, suffix, progressDirectionSwap, bars, C.cRed, C.cGreen);
|
||||
}
|
||||
|
||||
public static String getProgress(String prefix, double amount, String suffix, boolean progressDirectionSwap, int bars, String emptyColor, String fillColor)
|
||||
{
|
||||
if (progressDirectionSwap)
|
||||
amount = 1 - amount;
|
||||
|
||||
//Generate Bar
|
||||
String progressBar = C.cGreen + "";
|
||||
String progressBar = fillColor + "";
|
||||
boolean colorChange = false;
|
||||
for (int i=0 ; i<bars ; i++)
|
||||
{
|
||||
if (!colorChange && (float)i/(float)bars >= amount)
|
||||
{
|
||||
progressBar += C.cRed;
|
||||
progressBar += emptyColor;
|
||||
colorChange = true;
|
||||
}
|
||||
|
||||
@ -698,4 +712,59 @@ public class UtilText
|
||||
|
||||
return possesiveNoun.endsWith("s") ? possesiveNoun + "' " + noun : possesiveNoun + "'s " + noun;
|
||||
}
|
||||
|
||||
public static boolean startsWithVowel(String word)
|
||||
{
|
||||
if(word == null || word.isEmpty()) return false;
|
||||
|
||||
char v = word.toLowerCase().charAt(0);
|
||||
|
||||
for(char c : VOWELS)
|
||||
{
|
||||
if(c == v) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String getPronoun(String word)
|
||||
{
|
||||
return startsWithVowel(word) ? "an" : "a";
|
||||
}
|
||||
|
||||
public static String prefixPronoun(String word)
|
||||
{
|
||||
return getPronoun(word) + " " + word;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a replaceAll on all strings in the array. It will replace the strings inside
|
||||
* the given array. The returned array is the same instance as the one provided.
|
||||
*/
|
||||
public static String[] replaceAll(String[] array, String regex, String replacement)
|
||||
{
|
||||
if(array == null) return null;
|
||||
|
||||
for(int i = 0; i < array.length; i++)
|
||||
{
|
||||
if(array[i] == null) continue;
|
||||
array[i] = array[i].replaceAll(regex, replacement);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static String colorWords(String str, ChatColor... colors)
|
||||
{
|
||||
int c = 0, maxC = colors.length - 1;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (String word : str.split(" "))
|
||||
{
|
||||
stringBuilder.append(colors[c]);
|
||||
stringBuilder.append(word + " ");
|
||||
if (c < maxC)
|
||||
c++;
|
||||
else
|
||||
c = 0;
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
@ -79,6 +79,11 @@ public class UtilTime
|
||||
{
|
||||
return _ms;
|
||||
}
|
||||
|
||||
public static TimeUnit[] decreasingOrder()
|
||||
{
|
||||
return new TimeUnit[]{ DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -121,6 +126,41 @@ public class UtilTime
|
||||
{
|
||||
return convertString(Math.max(0, time), trim, TimeUnit.FIT);
|
||||
}
|
||||
|
||||
public static String convertColonString(long time)
|
||||
{
|
||||
return convertColonString(time, TimeUnit.HOURS, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a time into a colon separated string, displaying max to min units.
|
||||
*
|
||||
* @param time Time in milliseconds
|
||||
* @param max The max {@link TimeUnit} to display, inclusive
|
||||
* @param min The min {@link TimeUnit} to display, inclusive
|
||||
* @return A colon separated string to represent the time
|
||||
*/
|
||||
public static String convertColonString(long time, TimeUnit max, TimeUnit min)
|
||||
{
|
||||
if (time == -1) return "Permanent";
|
||||
else if (time == 0) return "0";
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
long curr = time;
|
||||
for (TimeUnit unit : TimeUnit.decreasingOrder())
|
||||
{
|
||||
if (unit.getMilliseconds() >= min.getMilliseconds() && unit.getMilliseconds() <= max.getMilliseconds())
|
||||
{
|
||||
long amt = curr / unit.getMilliseconds();
|
||||
if (amt < 10 && unit.getMilliseconds() != max.getMilliseconds()) sb.append('0'); // prefix single digit numbers with a 0
|
||||
sb.append(amt);
|
||||
if (unit.getMilliseconds() > min.getMilliseconds()) sb.append(':');
|
||||
curr -= amt * unit.getMilliseconds();
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String convertString(long time, int trim, TimeUnit type)
|
||||
{
|
||||
@ -140,7 +180,7 @@ public class UtilTime
|
||||
{
|
||||
if (type == TimeUnit.DAYS) text = (num = UtilMath.trim(trim, time / 86400000d)) + " Day";
|
||||
else if (type == TimeUnit.HOURS) text = (num = UtilMath.trim(trim, time / 3600000d)) + " Hour";
|
||||
else if (type == TimeUnit.MINUTES) text = (num = UtilMath.trim(trim, time / 60000d)) + " Minute";
|
||||
else if (type == TimeUnit.MINUTES) text = (int) (num = (int) UtilMath.trim(trim, time / 60000d)) + " Minute";
|
||||
else if (type == TimeUnit.SECONDS) text = (int) (num = (int) UtilMath.trim(trim, time / 1000d)) + " Second";
|
||||
else text = (int) (num = (int) UtilMath.trim(trim, time)) + " Millisecond";
|
||||
}
|
||||
|
@ -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,17 @@ 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(Location location)
|
||||
{
|
||||
return chunkToStr(location.getWorld().getName(), location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
}
|
||||
|
||||
public static String chunkToStr(String world, int x, int z)
|
||||
{
|
||||
return world + "," + x + "," + z;
|
||||
}
|
||||
|
||||
public static String chunkToStrClean(Chunk chunk)
|
||||
@ -289,4 +301,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);
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ public class WorldUtil
|
||||
{
|
||||
generator = server.getGenerator(name);
|
||||
}
|
||||
|
||||
|
||||
Convertable converter = new WorldLoaderServer(server.getWorldContainer());
|
||||
if (converter.isConvertable(name))
|
||||
|
@ -0,0 +1,70 @@
|
||||
package mineplex.core.common.util.banner;
|
||||
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.block.banner.PatternType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public enum CountryFlag
|
||||
{
|
||||
|
||||
Brazil(DyeColor.GREEN, new Pattern(DyeColor.YELLOW, PatternType.RHOMBUS_MIDDLE), new Pattern(DyeColor.BLUE, PatternType.CIRCLE_MIDDLE)),
|
||||
Usa(DyeColor.RED, new Pattern(DyeColor.WHITE, PatternType.STRIPE_SMALL), new Pattern(DyeColor.BLUE, PatternType.SQUARE_TOP_RIGHT)),
|
||||
Canada(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRIPE_TOP), new Pattern(DyeColor.RED, PatternType.STRIPE_BOTTOM),
|
||||
new Pattern(DyeColor.RED, PatternType.CIRCLE_MIDDLE)),
|
||||
Uk(DyeColor.BLUE, new Pattern(DyeColor.WHITE, PatternType.STRIPE_DOWNLEFT), new Pattern(DyeColor.WHITE, PatternType.STRIPE_DOWNRIGHT),
|
||||
new Pattern(DyeColor.RED, PatternType.STRAIGHT_CROSS), new Pattern(DyeColor.RED, PatternType.CROSS)),
|
||||
Ireland(DyeColor.WHITE, new Pattern(DyeColor.LIME, PatternType.STRIPE_TOP), new Pattern(DyeColor.ORANGE, PatternType.STRIPE_BOTTOM)),
|
||||
Spain(DyeColor.YELLOW, new Pattern(DyeColor.RED, PatternType.STRIPE_LEFT), new Pattern(DyeColor.RED, PatternType.STRIPE_RIGHT)),
|
||||
Japan(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.CIRCLE_MIDDLE)),
|
||||
South_Sudan(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRIPE_LEFT), new Pattern(DyeColor.BLACK, PatternType.STRIPE_RIGHT),
|
||||
new Pattern(DyeColor.GREEN, PatternType.TRIANGLE_BOTTOM)),
|
||||
Jamaica(DyeColor.GREEN, new Pattern(DyeColor.BLACK, PatternType.TRIANGLE_TOP), new Pattern(DyeColor.BLACK, PatternType.TRIANGLES_BOTTOM),
|
||||
new Pattern(DyeColor.YELLOW, PatternType.CROSS)),
|
||||
Italy(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRIPE_TOP), new Pattern(DyeColor.GREEN, PatternType.STRIPE_BOTTOM)),
|
||||
Senegal(DyeColor.YELLOW, new Pattern(DyeColor.RED, PatternType.STRIPE_TOP), new Pattern(DyeColor.GREEN, PatternType.STRIPE_BOTTOM),
|
||||
new Pattern(DyeColor.GREEN, PatternType.CIRCLE_MIDDLE)),
|
||||
France(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRIPE_TOP), new Pattern(DyeColor.BLUE, PatternType.STRIPE_BOTTOM)),
|
||||
India(DyeColor.WHITE, new Pattern(DyeColor.ORANGE, PatternType.STRIPE_LEFT), new Pattern(DyeColor.GREEN, PatternType.STRIPE_RIGHT),
|
||||
new Pattern(DyeColor.BLUE, PatternType.CIRCLE_MIDDLE)),
|
||||
Belgium(DyeColor.YELLOW, new Pattern(DyeColor.BLACK, PatternType.STRIPE_BOTTOM), new Pattern(DyeColor.RED, PatternType.STRIPE_TOP)),
|
||||
England(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRAIGHT_CROSS)),
|
||||
Austria(DyeColor.RED, new Pattern(DyeColor.WHITE, PatternType.STRIPE_CENTER)),
|
||||
Armenia(DyeColor.RED, new Pattern(DyeColor.BLUE, PatternType.STRIPE_CENTER), new Pattern(DyeColor.ORANGE, PatternType.STRIPE_RIGHT)),
|
||||
Argentina(DyeColor.LIGHT_BLUE, new Pattern(DyeColor.WHITE, PatternType.STRIPE_CENTER), new Pattern(DyeColor.YELLOW, PatternType.CIRCLE_MIDDLE)),
|
||||
Greece(DyeColor.LIGHT_BLUE, new Pattern(DyeColor.WHITE, PatternType.STRIPE_SMALL), new Pattern(DyeColor.LIGHT_BLUE, PatternType.SQUARE_BOTTOM_LEFT)),
|
||||
Czech_Republic(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.HALF_VERTICAL_MIRROR), new Pattern(DyeColor.BLUE, PatternType.TRIANGLE_BOTTOM)),
|
||||
Romania(DyeColor.YELLOW, new Pattern(DyeColor.BLUE, PatternType.STRIPE_BOTTOM), new Pattern(DyeColor.RED, PatternType.STRIPE_TOP)),
|
||||
Honduras(DyeColor.WHITE, new Pattern(DyeColor.BLUE, PatternType.STRIPE_LEFT), new Pattern(DyeColor.BLUE, PatternType.STRIPE_RIGHT)),
|
||||
Algeria(DyeColor.WHITE, new Pattern(DyeColor.LIME, PatternType.HALF_HORIZONTAL_MIRROR), new Pattern(DyeColor.RED, PatternType.CIRCLE_MIDDLE)),
|
||||
Portugal(DyeColor.RED, new Pattern(DyeColor.GREEN, PatternType.STRIPE_TOP), new Pattern(DyeColor.YELLOW, PatternType.CIRCLE_MIDDLE)),
|
||||
Bahrain(DyeColor.RED, new Pattern(DyeColor.WHITE, PatternType.TRIANGLES_BOTTOM)),
|
||||
Germany(DyeColor.RED, new Pattern(DyeColor.BLACK, PatternType.STRIPE_LEFT), new Pattern(DyeColor.YELLOW, PatternType.STRIPE_RIGHT)),
|
||||
Gabon(DyeColor.YELLOW, new Pattern(DyeColor.BLUE, PatternType.STRIPE_RIGHT), new Pattern(DyeColor.LIME, PatternType.STRIPE_LEFT)),
|
||||
Scotland(DyeColor.BLUE, new Pattern(DyeColor.WHITE, PatternType.CROSS)),
|
||||
Peru(DyeColor.WHITE, new Pattern(DyeColor.RED, PatternType.STRIPE_TOP), new Pattern(DyeColor.RED, PatternType.STRIPE_BOTTOM)),
|
||||
Tanzania(DyeColor.LIME, new Pattern(DyeColor.LIGHT_BLUE, PatternType.DIAGONAL_RIGHT), new Pattern(DyeColor.BLACK, PatternType.STRIPE_DOWNLEFT)),
|
||||
Morocco(DyeColor.RED, new Pattern(DyeColor.GREEN, PatternType.CIRCLE_MIDDLE)),
|
||||
Solomon_Islands(DyeColor.GREEN, new Pattern(DyeColor.BLUE, PatternType.DIAGONAL_LEFT_MIRROR), new Pattern(DyeColor.YELLOW, PatternType.STRIPE_DOWNRIGHT)),
|
||||
Switzerland(DyeColor.RED, new Pattern(DyeColor.WHITE, PatternType.STRAIGHT_CROSS), new Pattern(DyeColor.RED, PatternType.STRIPE_BOTTOM),
|
||||
new Pattern(DyeColor.RED, PatternType.STRIPE_TOP)),
|
||||
Finland(DyeColor.BLUE, new Pattern(DyeColor.WHITE, PatternType.SQUARE_BOTTOM_LEFT), new Pattern(DyeColor.WHITE, PatternType.SQUARE_BOTTOM_RIGHT),
|
||||
new Pattern(DyeColor.WHITE, PatternType.HALF_HORIZONTAL), new Pattern(DyeColor.BLUE, PatternType.STRIPE_CENTER)),
|
||||
South_Africa(DyeColor.WHITE, new Pattern(DyeColor.BLUE, PatternType.HALF_VERTICAL_MIRROR), new Pattern(DyeColor.RED, PatternType.HALF_VERTICAL),
|
||||
new Pattern(DyeColor.GREEN, PatternType.STRIPE_CENTER), new Pattern(DyeColor.BLACK, PatternType.TRIANGLE_BOTTOM)),
|
||||
Poland(DyeColor.RED, new Pattern(DyeColor.WHITE, PatternType.HALF_VERTICAL_MIRROR));
|
||||
|
||||
private DyeColor _baseColor;
|
||||
private Pattern[] _patterns;
|
||||
|
||||
CountryFlag(DyeColor baseColor, Pattern... patterns){
|
||||
_baseColor = baseColor;
|
||||
_patterns = patterns;
|
||||
}
|
||||
|
||||
public ItemStack getBanner()
|
||||
{
|
||||
return UtilBanner.createBanner(_baseColor, _patterns);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package mineplex.core.common.util.banner;
|
||||
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.BannerMeta;
|
||||
|
||||
public class UtilBanner
|
||||
{
|
||||
|
||||
public static ItemStack createBanner(DyeColor baseColor, Pattern... patterns)
|
||||
{
|
||||
ItemStack banner = new ItemStack(Material.BANNER);
|
||||
BannerMeta bannerMeta = (BannerMeta) banner.getItemMeta();
|
||||
bannerMeta.setBaseColor(baseColor);
|
||||
for (Pattern pattern : patterns)
|
||||
{
|
||||
bannerMeta.addPattern(pattern);
|
||||
}
|
||||
banner.setItemMeta(bannerMeta);
|
||||
return banner;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
|
||||
import mineplex.core.common.util.UtilParticle;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ColoredParticle extends ParticleData
|
||||
{
|
||||
|
||||
private ParticleColor _color;
|
||||
|
||||
public ColoredParticle(UtilParticle.ParticleType particleType, ParticleColor color, Location location)
|
||||
{
|
||||
super(particleType, location);
|
||||
if ((particleType == UtilParticle.ParticleType.RED_DUST || particleType == UtilParticle.ParticleType.MOB_SPELL_AMBIENT)
|
||||
&& !(color instanceof DustSpellColor))
|
||||
throw new IllegalArgumentException("RED_DUST and MOB_SPELL_AMBIENT particle types require a DustSpellColor!");
|
||||
else if(particleType == UtilParticle.ParticleType.NOTE && !(color instanceof NoteColor))
|
||||
throw new IllegalArgumentException("NOTE particle type requires a NoteColor!");
|
||||
else if(particleType != UtilParticle.ParticleType.RED_DUST && particleType != UtilParticle.ParticleType.MOB_SPELL_AMBIENT
|
||||
&& particleType != UtilParticle.ParticleType.NOTE)
|
||||
throw new IllegalArgumentException("Particle Type must be RED_DUST, MOB_SPELL_AMBIENT!");
|
||||
_particleType = particleType;
|
||||
_color = color;
|
||||
_location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(UtilParticle.ViewDist viewDist, Player... players)
|
||||
{
|
||||
float x = _color.getX();
|
||||
if (_particleType == UtilParticle.ParticleType.RED_DUST && x == 0)
|
||||
x = Float.MIN_NORMAL;
|
||||
UtilParticle.PlayParticle(_particleType, _location, x, _color.getY(), _color.getZ(), 1, 0, viewDist, players);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(UtilParticle.ViewDist viewDist)
|
||||
{
|
||||
display(viewDist, UtilServer.getPlayers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display()
|
||||
{
|
||||
display(UtilParticle.ViewDist.NORMAL);
|
||||
}
|
||||
|
||||
public void setColor(ParticleColor color)
|
||||
{
|
||||
_color = color;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class DustSpellColor extends ParticleColor
|
||||
{
|
||||
|
||||
private int _red, _green, _blue;
|
||||
|
||||
public DustSpellColor(Color color)
|
||||
{
|
||||
_red = color.getRed();
|
||||
_green = color.getGreen();
|
||||
_blue = color.getBlue();
|
||||
}
|
||||
|
||||
public DustSpellColor(int r, int g, int b)
|
||||
{
|
||||
_red = r;
|
||||
_green = g;
|
||||
_blue = b;
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return (float) _red / 255f;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return (float) _green / 255f;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return (float) _blue / 255f;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
import mineplex.core.common.util.UtilParticle;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class NormalParticle extends ParticleData
|
||||
{
|
||||
|
||||
public NormalParticle(UtilParticle.ParticleType particleType, Location location)
|
||||
{
|
||||
super(particleType, location);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public class NoteColor extends ParticleColor
|
||||
{
|
||||
|
||||
private int _red, _green, _blue;
|
||||
|
||||
public NoteColor(Color color)
|
||||
{
|
||||
_red = color.getRed();
|
||||
_green = color.getGreen();
|
||||
_blue = color.getBlue();
|
||||
}
|
||||
|
||||
public NoteColor(int r, int g, int b)
|
||||
{
|
||||
_red = r;
|
||||
_green = g;
|
||||
_blue = b;
|
||||
}
|
||||
|
||||
public float getX()
|
||||
{
|
||||
return (float) _red / 24f;
|
||||
}
|
||||
|
||||
public float getY()
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public float getZ()
|
||||
{
|
||||
return 0f;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public abstract class ParticleColor
|
||||
{
|
||||
|
||||
public abstract float getX();
|
||||
|
||||
public abstract float getY();
|
||||
|
||||
public abstract float getZ();
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package mineplex.core.common.util.particles;
|
||||
|
||||
import mineplex.core.common.util.UtilParticle;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class ParticleData
|
||||
{
|
||||
|
||||
protected UtilParticle.ParticleType _particleType;
|
||||
protected Location _location;
|
||||
|
||||
public ParticleData(UtilParticle.ParticleType particleType, Location location)
|
||||
{
|
||||
_particleType = particleType;
|
||||
_location = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the particles for selected players
|
||||
* @param viewDist The distance of the particle view
|
||||
* @param players The players that will receive the particle
|
||||
*/
|
||||
public void display(UtilParticle.ViewDist viewDist, Player... players)
|
||||
{
|
||||
UtilParticle.PlayParticle(_particleType, _location, 0f, 0f, 0f, 0f, 1, viewDist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the particles for all the players
|
||||
* @param viewDist The distance of the particle view
|
||||
*/
|
||||
public void display(UtilParticle.ViewDist viewDist)
|
||||
{
|
||||
display(viewDist, UtilServer.getPlayers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the particles for all the players, with a NORMAL view distance
|
||||
*/
|
||||
public void display()
|
||||
{
|
||||
display(UtilParticle.ViewDist.NORMAL);
|
||||
}
|
||||
|
||||
public void setLocation(Location location)
|
||||
{
|
||||
_location = location;
|
||||
}
|
||||
|
||||
public Location getLocation()
|
||||
{
|
||||
return _location;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package mineplex.core.common.util.worldgen;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
/**
|
||||
* A simple clean room void chunk generator
|
||||
*/
|
||||
|
||||
public class WorldGenCleanRoom extends ChunkGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* Creates a clean void chunk with no blocks
|
||||
*/
|
||||
@Override
|
||||
public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome)
|
||||
{
|
||||
return createChunkData(world);
|
||||
}
|
||||
|
||||
}
|
@ -1,57 +1,59 @@
|
||||
package mineplex.core.common.weight;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class WeightSet<T>
|
||||
{
|
||||
|
||||
private static Random random = new Random();
|
||||
|
||||
private Set<Weight<T>> _weights;
|
||||
|
||||
private Set<Weight<T>> _weights = new HashSet<Weight<T>>();
|
||||
|
||||
private volatile transient Set<T> _keyset;
|
||||
|
||||
public WeightSet()
|
||||
{
|
||||
_weights = new HashSet<Weight<T>>();
|
||||
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public WeightSet(Weight<T>... weights)
|
||||
{
|
||||
this();
|
||||
|
||||
for (Weight<T> weight : weights)
|
||||
{
|
||||
_weights.add(weight);
|
||||
}
|
||||
computeKeyset();
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
public WeightSet(T... elements)
|
||||
{
|
||||
this();
|
||||
|
||||
for (T element : elements)
|
||||
{
|
||||
_weights.add(new Weight<T>(1, element)); // Constant weight of 1 means all elements are equally likely
|
||||
}
|
||||
computeKeyset();
|
||||
}
|
||||
|
||||
public WeightSet(Collection<T> elements)
|
||||
{
|
||||
this();
|
||||
|
||||
for (T element : elements)
|
||||
{
|
||||
_weights.add(new Weight<T>(1, element)); // Constant weight of 1 means all elements are equally likely
|
||||
}
|
||||
computeKeyset();
|
||||
}
|
||||
|
||||
public void add(int weight, T element)
|
||||
{
|
||||
_weights.add(new Weight<T>(weight, element));
|
||||
computeKeyset();
|
||||
}
|
||||
|
||||
private int getTotalWeight()
|
||||
@ -87,13 +89,11 @@ public class WeightSet<T>
|
||||
|
||||
public Set<T> elements()
|
||||
{
|
||||
Set<T> elements = new HashSet<T>();
|
||||
|
||||
for (Weight<T> weight : _weights)
|
||||
{
|
||||
elements.add(weight.getValue());
|
||||
}
|
||||
|
||||
return elements;
|
||||
return this._keyset;
|
||||
}
|
||||
|
||||
private void computeKeyset()
|
||||
{
|
||||
_keyset = Collections.unmodifiableSet(_weights.stream().map(Weight::getValue).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import net.minecraft.server.v1_8_R3.Entity;
|
||||
import net.minecraft.server.v1_8_R3.EntityArmorStand;
|
||||
import net.minecraft.server.v1_8_R3.Packet;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayInUseEntity.EnumEntityUseAction;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutAttachEntity;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityMetadata;
|
||||
@ -59,7 +58,7 @@ public class CustomTagFix extends MiniPlugin implements IPacketHandler, NCPHook
|
||||
private NautHashMap<String, NautHashMap<Integer, Integer>> _entityRiding = new NautHashMap<String, NautHashMap<Integer, Integer>>();
|
||||
|
||||
private HashSet<String> _loggedIn = new HashSet<String>();
|
||||
private HashSet<Integer> _ignoreSkulls = new HashSet<Integer>();
|
||||
private HashSet<Integer> _ignoreIds = new HashSet<Integer>();
|
||||
|
||||
private NautHashMap<UUID, Long> _exemptTimeMap = new NautHashMap<UUID, Long>();
|
||||
private NautHashMap<UUID, NautHashMap<CheckType, Long>> _doubleStrike = new NautHashMap<UUID, NautHashMap<CheckType, Long>>();
|
||||
@ -220,12 +219,11 @@ public class CustomTagFix extends MiniPlugin implements IPacketHandler, NCPHook
|
||||
PacketPlayOutSpawnEntityLiving spawnPacket = (PacketPlayOutSpawnEntityLiving) packet;
|
||||
|
||||
// Ignore Armor stand packets
|
||||
if (spawnPacket.b == EntityType.ARMOR_STAND.getTypeId() || spawnPacket.l == null || spawnPacket.l.c() == null
|
||||
|| spawnPacket.a == 777777)
|
||||
if (spawnPacket.b == EntityType.ARMOR_STAND.getTypeId() || spawnPacket.l == null || spawnPacket.l.c() == null)
|
||||
{
|
||||
if (spawnPacket.b == EntityType.ARMOR_STAND.getTypeId())
|
||||
{
|
||||
_ignoreSkulls.add(spawnPacket.a);
|
||||
_ignoreIds.add(spawnPacket.a);
|
||||
}
|
||||
|
||||
return;
|
||||
@ -322,7 +320,7 @@ public class CustomTagFix extends MiniPlugin implements IPacketHandler, NCPHook
|
||||
{
|
||||
PacketPlayOutEntityMetadata metaPacket = (PacketPlayOutEntityMetadata) packet;
|
||||
|
||||
if (metaPacket.a != 777777 && !_ignoreSkulls.contains(metaPacket.a) && metaPacket.a != owner.getEntityId())
|
||||
if (metaPacket.a != 777777 && !_ignoreIds.contains(metaPacket.a) && metaPacket.a != owner.getEntityId())
|
||||
{
|
||||
boolean isDisplaying = _entityMap.get(owner.getName()).containsKey(metaPacket.a);
|
||||
String currentName = _entityNameMap.get(owner.getName()).get(metaPacket.a);
|
||||
@ -423,9 +421,9 @@ public class CustomTagFix extends MiniPlugin implements IPacketHandler, NCPHook
|
||||
else if (packet instanceof PacketPlayOutSpawnEntity)
|
||||
{
|
||||
PacketPlayOutSpawnEntity spawnPacket = (PacketPlayOutSpawnEntity) packet;
|
||||
if (spawnPacket.j == 66 && spawnPacket.a != 777777)
|
||||
if (spawnPacket.j == 78) // Armor Stand Object ID
|
||||
{
|
||||
_ignoreSkulls.add(spawnPacket.a);
|
||||
_ignoreIds.add(spawnPacket.a);
|
||||
}
|
||||
}
|
||||
else if (packet instanceof PacketPlayInUseEntity)
|
||||
|
@ -1,8 +1,5 @@
|
||||
package mineplex.core;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -99,12 +96,12 @@ public abstract class MiniPlugin implements Listener
|
||||
|
||||
public final void addCommand(ICommand command)
|
||||
{
|
||||
CommandCenter.Instance.AddCommand(command);
|
||||
CommandCenter.Instance.addCommand(command);
|
||||
}
|
||||
|
||||
public final void removeCommand(ICommand command)
|
||||
{
|
||||
CommandCenter.Instance.RemoveCommand(command);
|
||||
CommandCenter.Instance.removeCommand(command);
|
||||
}
|
||||
|
||||
public void log(String message)
|
||||
|
@ -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
|
||||
|
@ -38,7 +38,7 @@ public class TestRank extends CommandBase<CoreClientManager>
|
||||
|
||||
if (args == null)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + AliasUsed + " MODERATOR"));
|
||||
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + _aliasUsed + " MODERATOR"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -30,7 +30,7 @@ public class UpdateRank extends CommandBase<CoreClientManager>
|
||||
{
|
||||
if (args == null)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + AliasUsed + " joeschmo MODERATOR"));
|
||||
UtilPlayer.message(caller, F.main(Plugin.getName(), "/" + _aliasUsed + " joeschmo MODERATOR"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,33 +1,26 @@
|
||||
package mineplex.core.achievement;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
|
||||
import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.achievement.command.StatsCommand;
|
||||
import mineplex.core.achievement.ui.AchievementShop;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.NautHashMap;
|
||||
import mineplex.core.common.util.UtilGear;
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.elo.EloManager;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.incognito.IncognitoManager;
|
||||
import mineplex.core.stats.StatsManager;
|
||||
import mineplex.core.stats.event.StatChangeEvent;
|
||||
|
||||
public class AchievementManager extends MiniPlugin
|
||||
{
|
||||
private IncognitoManager _incognitoManager;
|
||||
private StatsManager _statsManager;
|
||||
private EloManager _eloManager;
|
||||
|
||||
@ -39,10 +32,11 @@ public class AchievementManager extends MiniPlugin
|
||||
|
||||
private boolean _shopEnabled = true;
|
||||
|
||||
public AchievementManager(StatsManager statsManager, CoreClientManager clientManager, DonationManager donationManager, EloManager eloManager)
|
||||
public AchievementManager(StatsManager statsManager, CoreClientManager clientManager, DonationManager donationManager, IncognitoManager incognitoManager, EloManager eloManager)
|
||||
{
|
||||
super("Achievement Manager", statsManager.getPlugin());
|
||||
|
||||
_incognitoManager = incognitoManager;
|
||||
_statsManager = statsManager;
|
||||
_eloManager = eloManager;
|
||||
_shop = new AchievementShop(this, _statsManager, clientManager, donationManager, "Achievement");
|
||||
@ -221,4 +215,9 @@ public class AchievementManager extends MiniPlugin
|
||||
{
|
||||
_shopEnabled = var;
|
||||
}
|
||||
|
||||
public IncognitoManager getIncognito()
|
||||
{
|
||||
return _incognitoManager;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import org.bukkit.entity.Player;
|
||||
import mineplex.core.achievement.AchievementManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
|
||||
public class StatsCommand extends CommandBase<AchievementManager>
|
||||
@ -29,6 +31,14 @@ public class StatsCommand extends CommandBase<AchievementManager>
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (/* StaffServer special case */Plugin.getIncognito() != null && Plugin.getIncognito().Get(target).Hidden)
|
||||
{
|
||||
UtilPlayer.message(caller,
|
||||
F.main("Online Player Search", "" + C.mCount + "0" + C.mBody + " matches for [" + C.mElem
|
||||
+ args[0] + C.mBody + "]."));
|
||||
return;
|
||||
}
|
||||
|
||||
Plugin.openShop(caller, target);
|
||||
}
|
||||
|
@ -54,22 +54,28 @@ public class Blood extends MiniPlugin
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void display(BloodEvent event)
|
||||
{
|
||||
for (int i = 0 ; i < event.getParticles() ; i++)
|
||||
if(event.isCancelled()) return;
|
||||
|
||||
if(event.getMaterial() != null && event.getMaterial() != Material.AIR)
|
||||
{
|
||||
Item item = event.getLocation().getWorld().dropItem(event.getLocation(),
|
||||
new ItemBuilder(event.getMaterial(), 1, event.getMaterialData()).setTitle("" + System.nanoTime()).build());
|
||||
|
||||
item.setVelocity(new Vector((Math.random() - 0.5)*event.getVelocityMult(),Math.random()*event.getVelocityMult(),(Math.random() - 0.5)*event.getVelocityMult()));
|
||||
|
||||
item.setPickupDelay(999999);
|
||||
|
||||
_blood.put(item, event.getTicks());
|
||||
for (int i = 0 ; i < event.getParticles() ; i++)
|
||||
{
|
||||
Item item = event.getLocation().getWorld().dropItem(event.getLocation(),
|
||||
new ItemBuilder(event.getMaterial(), 1, event.getMaterialData()).setTitle("" + System.nanoTime()).build());
|
||||
|
||||
item.setVelocity(new Vector((Math.random() - 0.5)*event.getVelocityMult(),Math.random()*event.getVelocityMult(),(Math.random() - 0.5)*event.getVelocityMult()));
|
||||
|
||||
item.setPickupDelay(999999);
|
||||
|
||||
_blood.put(item, event.getTicks());
|
||||
}
|
||||
}
|
||||
|
||||
if (event.getBloodStep())
|
||||
event.getLocation().getWorld().playEffect(event.getLocation(), Effect.STEP_SOUND, 55);
|
||||
|
||||
event.getLocation().getWorld().playSound(event.getLocation(), event.getSound(), event.getSoundVolume(), event.getSoundPitch());
|
||||
if(event.getSound() != null)
|
||||
event.getLocation().getWorld().playSound(event.getLocation(), event.getSound(), event.getSoundVolume(), event.getSoundPitch());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -14,6 +14,7 @@ import mineplex.core.bonuses.gui.BonusGui;
|
||||
import mineplex.core.bonuses.gui.SpinGui;
|
||||
import mineplex.core.bonuses.redis.VoteHandler;
|
||||
import mineplex.core.bonuses.redis.VotifierCommand;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.*;
|
||||
import mineplex.core.common.util.UtilParticle.ParticleType;
|
||||
@ -21,6 +22,7 @@ import mineplex.core.common.util.UtilParticle.ViewDist;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.donation.GiveDonorData;
|
||||
import mineplex.core.facebook.FacebookManager;
|
||||
import mineplex.core.gadget.GadgetManager;
|
||||
import mineplex.core.hologram.Hologram;
|
||||
import mineplex.core.hologram.HologramManager;
|
||||
import mineplex.core.inventory.ClientItem;
|
||||
@ -36,6 +38,7 @@ import mineplex.core.status.ServerStatusManager;
|
||||
import mineplex.core.treasure.TreasureType;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.core.youtube.YoutubeManager;
|
||||
import mineplex.database.Tables;
|
||||
import mineplex.database.tables.records.BonusRecord;
|
||||
import mineplex.serverdata.commands.ServerCommandManager;
|
||||
@ -119,6 +122,8 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
private RewardManager _rewardManager;
|
||||
private StatsManager _statsManager;
|
||||
private FacebookManager _facebookManager;
|
||||
private YoutubeManager _youtubeManager;
|
||||
private BoosterManager _boosterManager;
|
||||
public boolean _enabled;
|
||||
private Npc _carlNpc;
|
||||
private AnimationCarl _animation;
|
||||
@ -157,7 +162,7 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
updateOffSet();
|
||||
}
|
||||
|
||||
public BonusManager(JavaPlugin plugin, CoreClientManager clientManager, ServerStatusManager statusManager, DonationManager donationManager, PollManager pollManager, NpcManager npcManager, HologramManager hologramManager, StatsManager statsManager, InventoryManager inventoryManager, PetManager petManager, FacebookManager facebookManager)
|
||||
public BonusManager(JavaPlugin plugin, CoreClientManager clientManager, ServerStatusManager statusManager, DonationManager donationManager, PollManager pollManager, NpcManager npcManager, HologramManager hologramManager, StatsManager statsManager, InventoryManager inventoryManager, PetManager petManager, FacebookManager facebookManager, YoutubeManager youtubeManager, GadgetManager gadgetManager, BoosterManager boosterManager)
|
||||
{
|
||||
super("Bonus", plugin);
|
||||
_repository = new BonusRepository(plugin, this, donationManager);
|
||||
@ -166,17 +171,14 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
_npcManager = npcManager;
|
||||
_hologramManager = hologramManager;
|
||||
_inventoryManager = inventoryManager;
|
||||
_boosterManager = boosterManager;
|
||||
|
||||
_rewardManager = new RewardManager(clientManager, statusManager, donationManager, inventoryManager, petManager, statsManager,
|
||||
100, 250,
|
||||
500, 1000,
|
||||
4000, 6000,
|
||||
12000, 32000,
|
||||
true, true);
|
||||
_rewardManager = new RewardManager(_clientManager, _donationManager, _inventoryManager, petManager, statsManager, gadgetManager);
|
||||
|
||||
_pollManager = pollManager;
|
||||
_statsManager = statsManager;
|
||||
_facebookManager = facebookManager;
|
||||
_youtubeManager = youtubeManager;
|
||||
|
||||
_voteList = new ArrayList<String>();
|
||||
_voteList.add("http://vote1.mineplex.com");
|
||||
@ -415,6 +417,7 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
public static final long DAILY_STREAK_RESET_TIME = 1000 * 60 * 60 * 12;
|
||||
public static final long VOTE_STREAK_RESET_TIME = 1000 * 60 * 60 * 24;
|
||||
|
||||
|
||||
public void attemptDailyBonus(final Player player, final BonusAmount amount, final Callback<Boolean> result)
|
||||
{
|
||||
if (timeTillDailyBonus(player) > 0)
|
||||
@ -824,7 +827,7 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
if (entity.equals(_carlNpc.getEntity()))
|
||||
{
|
||||
updateDailyStreak(event.getPlayer());
|
||||
new BonusGui(_plugin, event.getPlayer(), this, _rewardManager, _facebookManager).openInventory();
|
||||
new BonusGui(_plugin, event.getPlayer(), this, _rewardManager, _facebookManager, _youtubeManager, _boosterManager).openInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@ -840,7 +843,7 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
if (event.getEntity().equals(_carlNpc.getEntity()))
|
||||
{
|
||||
updateDailyStreak(player);
|
||||
new BonusGui(_plugin, player, this, _rewardManager, _facebookManager).openInventory();
|
||||
new BonusGui(_plugin, player, this, _rewardManager, _facebookManager, _youtubeManager, _boosterManager).openInventory();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -902,17 +905,23 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
int availableRewards = 0;
|
||||
|
||||
if (canVote(player)) availableRewards++;
|
||||
if (_youtubeManager.canYoutube(player)) availableRewards++;
|
||||
if (canRank(player) && _clientManager.hasRank(player, Rank.ULTRA) && isPastAugust()) availableRewards++;
|
||||
if (canDaily(player)) availableRewards++;
|
||||
if (getPollManager().getNextPoll(_pollManager.Get(player), _clientManager.Get(player).GetRank()) != null) availableRewards++;
|
||||
if (!_facebookManager.hasRedeemed(player)) availableRewards++;
|
||||
if (_boosterManager.getTipManager().Get(player).getTips() > 0) availableRewards++;
|
||||
|
||||
Hologram hologram;
|
||||
|
||||
|
||||
if (client.getHologram() == null)
|
||||
{
|
||||
double yAdd = 2.45;
|
||||
double yAdd = 2.3;
|
||||
if(!UtilPlayer.is1_9(player))
|
||||
{
|
||||
yAdd = 2.45;
|
||||
}
|
||||
hologram = new Hologram(_hologramManager, _carlNpc.getLocation().clone().add(0, yAdd, 0), "");
|
||||
hologram.setHologramTarget(Hologram.HologramTarget.WHITELIST);
|
||||
hologram.addPlayer(player);
|
||||
@ -1048,6 +1057,11 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
return _facebookManager;
|
||||
}
|
||||
|
||||
public YoutubeManager getYoutubeManager()
|
||||
{
|
||||
return _youtubeManager;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void Join(final PlayerJoinEvent event)
|
||||
{
|
||||
@ -1065,6 +1079,8 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
public void Quit(PlayerQuitEvent event)
|
||||
{
|
||||
_showCarl.remove(event.getPlayer().getName());
|
||||
// Removes from allow command map
|
||||
UtilPlayer.removeAllowedCommands(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@ -1179,4 +1195,9 @@ public class BonusManager extends MiniClientPlugin<BonusClientData> implements I
|
||||
{
|
||||
return "SELECT * FROM bonus WHERE accountId = '" + accountId + "';";
|
||||
}
|
||||
|
||||
public BoosterManager getBoosterManager()
|
||||
{
|
||||
return _boosterManager;
|
||||
}
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
package mineplex.core.bonuses.commands;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import mineplex.core.bonuses.BonusManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.command.CommandCenter;
|
||||
import mineplex.core.command.ICommand;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.NautHashMap;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Allows players to run rank-specific commands
|
||||
* Found no better place to create it
|
||||
*/
|
||||
public class AllowCommand extends CommandBase<BonusManager>
|
||||
{
|
||||
|
||||
private BonusManager _plugin;
|
||||
|
||||
public AllowCommand(BonusManager plugin)
|
||||
{
|
||||
super(plugin, Rank.MODERATOR, "allowCommand", "allowCmd");
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
if (args.length < 2 || args.length > 3)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "Usage: /allowCmd <player> <command> [disallow]"));
|
||||
return;
|
||||
}
|
||||
NautHashMap<String, ICommand> commands = CommandCenter.getCommands();
|
||||
if (!commands.containsKey(args[1].toLowerCase()))
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "Command not found!"));
|
||||
return;
|
||||
}
|
||||
ICommand iCommand = commands.get(args[1]);
|
||||
Rank playerRank = _plugin.getClientManager().Get(caller).GetRank();
|
||||
if (playerRank.compareTo(iCommand.GetRequiredRank()) > 0
|
||||
&& Arrays.asList(iCommand.GetSpecificRanks()).contains(playerRank))
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "You're not allowed to use that command!"));
|
||||
return;
|
||||
}
|
||||
boolean disallow = false;
|
||||
if (args.length == 3)
|
||||
disallow = Boolean.parseBoolean(args[2]);
|
||||
Player receiver = UtilPlayer.searchExact(args[0]);
|
||||
if (receiver == null)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "Could not find player " + F.name(args[0]) + "!"));
|
||||
return;
|
||||
}
|
||||
if (receiver.getUniqueId().equals(caller.getUniqueId()))
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "You can't use that for yourself!"));
|
||||
return;
|
||||
}
|
||||
if (disallow)
|
||||
{
|
||||
boolean canDisallow = UtilPlayer.disallowCommand(receiver, args[1].toLowerCase());
|
||||
if (!canDisallow)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "That command was not allowed for the player " + F.name(receiver.getName()) + "!"));
|
||||
return;
|
||||
}
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "You disallowed the player " + F.name(receiver.getName()) + " to use the command " + F.elem(args[1]) + "!"));
|
||||
UtilPlayer.message(receiver, F.main("Allow Command", "The player " + F.name(caller.getName()) + " disallowed you to use the command " + F.elem(args[1]) + "!"));
|
||||
return;
|
||||
}
|
||||
UtilPlayer.allowCommand(receiver, args[1].toLowerCase());
|
||||
UtilPlayer.message(caller, F.main("Allow Command", "You allowed the player " + F.name(receiver.getName()) + " to use the command " + F.elem(args[1]) + "!"));
|
||||
UtilPlayer.message(receiver, F.main("Allow Command", "The player " + F.name(caller.getName()) + " allowed you to use the command " + F.elem(args[1]) + "!"));
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package mineplex.core.bonuses.commands;
|
||||
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import mineplex.core.command.CommandBase;
|
||||
@ -7,8 +8,8 @@ import mineplex.core.common.Rank;
|
||||
import mineplex.core.bonuses.BonusManager;
|
||||
import mineplex.core.bonuses.gui.BonusGui;
|
||||
|
||||
public class GuiCommand extends CommandBase<BonusManager>{
|
||||
|
||||
public class GuiCommand extends CommandBase<BonusManager>
|
||||
{
|
||||
public GuiCommand(BonusManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "bonus");
|
||||
@ -17,7 +18,7 @@ public class GuiCommand extends CommandBase<BonusManager>{
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
new BonusGui(Plugin.getPlugin(), caller, Plugin, Plugin.getRewardManager(), Plugin.getFacebookManager()).openInventory();
|
||||
new BonusGui(Plugin.getPlugin(), caller, Plugin, Plugin.getRewardManager(), Plugin.getFacebookManager(), Plugin.getYoutubeManager(), Plugin.getBoosterManager()).openInventory();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
package mineplex.core.bonuses.gui;
|
||||
|
||||
import mineplex.core.bonuses.gui.buttons.FacebookButton;
|
||||
import mineplex.core.bonuses.BonusManager;
|
||||
import mineplex.core.bonuses.gui.buttons.*;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.facebook.FacebookManager;
|
||||
import mineplex.core.gui.SimpleGui;
|
||||
import mineplex.core.reward.RewardManager;
|
||||
import mineplex.core.bonuses.BonusManager;
|
||||
import mineplex.core.bonuses.gui.buttons.CarlSpinButton;
|
||||
import mineplex.core.bonuses.gui.buttons.DailyBonusButton;
|
||||
import mineplex.core.bonuses.gui.buttons.PollButton;
|
||||
import mineplex.core.bonuses.gui.buttons.RankBonusButton;
|
||||
import mineplex.core.bonuses.gui.buttons.VoteButton;
|
||||
|
||||
import mineplex.core.youtube.YoutubeManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
@ -19,22 +15,28 @@ public class BonusGui extends SimpleGui
|
||||
|
||||
private BonusManager manager;
|
||||
|
||||
public BonusGui(Plugin plugin, Player player, BonusManager manager, RewardManager rewardManager, FacebookManager facebookManager)
|
||||
public BonusGui(Plugin plugin, Player player, BonusManager manager, RewardManager rewardManager, FacebookManager facebookManager, YoutubeManager youtubeManager, BoosterManager boosterManager)
|
||||
{
|
||||
super(plugin, player, player.getName() + "'s Bonuses", 5 * 9);
|
||||
|
||||
this.manager = manager;
|
||||
|
||||
setItem(9, new VoteButton(plugin, player, this, manager));
|
||||
setItem(10, new VoteButton(plugin, player, this, manager));
|
||||
|
||||
setItem(11, new RankBonusButton(getPlugin(), player, this, manager));
|
||||
setItem(12, new RankBonusButton(getPlugin(), player, this, manager));
|
||||
|
||||
setItem(13, new DailyBonusButton(getPlugin(), player, this, manager));
|
||||
setItem(14, new DailyBonusButton(getPlugin(), player, this, manager));
|
||||
|
||||
setItem(15, new PollButton(getPlugin(), player, manager.getPollManager(), manager.getClientManager(), this, manager));
|
||||
setItem(16, new PollButton(getPlugin(), player, manager.getPollManager(), manager.getClientManager(), this, manager));
|
||||
|
||||
setItem(19, new FacebookButton(player, facebookManager));
|
||||
|
||||
setItem(21, new YoutubeButton(player, youtubeManager));
|
||||
|
||||
setItem(23, new TwitterButton(player));
|
||||
|
||||
setItem(25, new ClaimTipsButton(getPlugin(), player, this, manager, boosterManager));
|
||||
|
||||
setItem(17, new FacebookButton(player, facebookManager));
|
||||
|
||||
setItem(31, new CarlSpinButton(getPlugin(), player, manager, rewardManager));
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.reward.Reward;
|
||||
import mineplex.core.reward.RewardData;
|
||||
import mineplex.core.reward.RewardManager;
|
||||
import mineplex.core.reward.RewardPool.Type;
|
||||
import mineplex.core.reward.RewardRarity;
|
||||
import mineplex.core.reward.RewardType;
|
||||
import mineplex.core.shop.item.ShopItem;
|
||||
@ -101,11 +102,11 @@ public class SpinGui extends SimpleGui
|
||||
{
|
||||
if (i != _stopSpinnerAt + 4)
|
||||
{
|
||||
_rewards[i] = rewardManager.nextReward(player, null, false, RewardType.SpinnerFiller, true);
|
||||
_rewards[i] = rewardManager.nextReward(player, Type.CARL_SPINNER, null, false, RewardType.SpinnerFiller, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rewards[i] = rewardManager.nextReward(player, null, false, RewardType.SpinnerReal, true);
|
||||
_rewards[i] = rewardManager.nextReward(player, Type.CARL_SPINNER, null, false, RewardType.SpinnerReal, true);
|
||||
_reward = _rewards[i];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
package mineplex.core.bonuses.gui;
|
||||
|
||||
import mineplex.core.common.jsonchat.ClickEvent;
|
||||
import mineplex.core.common.jsonchat.JsonMessage;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.gui.GuiItem;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class TwitterButton implements GuiItem
|
||||
{
|
||||
private static final ItemStack ICON = new ItemBuilder(Material.EGG)
|
||||
.setTitle(C.cGreen + C.Bold + "Visit us on Twitter")
|
||||
.addLore(
|
||||
C.cWhite + "Check out and follow Mineplex on",
|
||||
C.cWhite + "Twitter for Giveaways, Announcements,",
|
||||
C.cWhite + "Teasers, and Tips!",
|
||||
" ",
|
||||
C.cGreen + "Click to visit us on Twitter!"
|
||||
)
|
||||
.build();
|
||||
private final Player _player;
|
||||
|
||||
public TwitterButton(Player player)
|
||||
{
|
||||
this._player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
@Override
|
||||
public void click(ClickType clickType)
|
||||
{
|
||||
_player.closeInventory();
|
||||
|
||||
new JsonMessage(C.cAquaB + "Click here to visit our Twitter page!").click(ClickEvent.OPEN_URL, "https://www.twitter.com/Mineplex").sendToPlayer(_player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getObject()
|
||||
{
|
||||
return ICON;
|
||||
}
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
package mineplex.core.bonuses.gui.buttons;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.common.CurrencyType;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.common.util.UtilTime.TimeUnit;
|
||||
import mineplex.core.gui.GuiItem;
|
||||
import mineplex.core.gui.ItemRefresher;
|
||||
import mineplex.core.gui.pages.LoadingWindow;
|
||||
import mineplex.core.gui.pages.TimedMessageWindow;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.shop.item.ShopItem;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.core.bonuses.BonusAmount;
|
||||
import mineplex.core.bonuses.BonusClientData;
|
||||
import mineplex.core.bonuses.BonusManager;
|
||||
import mineplex.core.bonuses.StreakRecord;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class ClaimTipsButton implements GuiItem, Listener
|
||||
{
|
||||
private ItemStack _item;
|
||||
|
||||
private Player _player;
|
||||
private Plugin _plugin;
|
||||
private ItemRefresher _gui;
|
||||
|
||||
private BonusManager _bonusManager;
|
||||
private BoosterManager _boosterManager;
|
||||
|
||||
public ClaimTipsButton(Plugin plugin, Player player, ItemRefresher gui, BonusManager bonusManager, BoosterManager boosterManager)
|
||||
{
|
||||
_bonusManager = bonusManager;
|
||||
_boosterManager = boosterManager;
|
||||
_player = player;
|
||||
_plugin = plugin;
|
||||
_gui = gui;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup()
|
||||
{
|
||||
Bukkit.getPluginManager().registerEvents(this, getPlugin());
|
||||
setItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
HandlerList.unregisterAll(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(ClickType clickType)
|
||||
{
|
||||
if (isAvailable()) {
|
||||
_item = ItemStackFactory.Instance.CreateStack(Material.LAPIS_BLOCK, (byte)0, 1, ChatColor.BLUE + "Processing...");
|
||||
refreshItem();
|
||||
new LoadingWindow(getPlugin(), getPlayer(), 6*9);
|
||||
_boosterManager.getTipManager().claimTips(getPlayer(), claimed -> {
|
||||
if (claimed > 0)
|
||||
{
|
||||
// Woo, success!
|
||||
setItem();
|
||||
|
||||
if (getPlayer().getOpenInventory() != null)
|
||||
{
|
||||
new TimedMessageWindow(getPlugin(), getPlayer(), ItemStackFactory.Instance.CreateStack(Material.STAINED_GLASS_PANE, DyeColor.LIME.getData(), 1, ChatColor.GREEN + "Amplifier Thanks Collected"), "Thanks Collected", 6*9, 20*3, getGui()).openInventory();
|
||||
}
|
||||
|
||||
UtilPlayer.message(getPlayer(), F.main("Carl", "You collected " + F.currency(CurrencyType.TREASURE_SHARD, claimed) + " from Amplifiers!"));
|
||||
// Pending explosions are strange.. Not sure why we are using strings. Either way, lets display a rank reward effect
|
||||
_bonusManager.addPendingExplosion(getPlayer(), "RANK");
|
||||
getPlayer().playSound(getPlayer().getLocation(), Sound.NOTE_PLING, 1, 1.6f);
|
||||
}
|
||||
else if (claimed == 0)
|
||||
{
|
||||
// No tips to claim
|
||||
if (getPlayer().getOpenInventory() != null)
|
||||
{
|
||||
new TimedMessageWindow(getPlugin(), getPlayer(), ItemStackFactory.Instance.CreateStack(Material.STAINED_GLASS_PANE, DyeColor.RED.getData(), 1, ChatColor.RED + "No Thanks to Claim!"), "You have no thanks to claim!", 6*9, 20*3, getGui()).openInventory();
|
||||
}
|
||||
|
||||
UtilPlayer.message(getPlayer(), F.main("Carl", "You have no rewards to claim!"));
|
||||
getPlayer().playSound(getPlayer().getLocation(), Sound.ENDERDRAGON_GROWL, 1, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed to claim
|
||||
if (getPlayer().getOpenInventory() != null)
|
||||
{
|
||||
new TimedMessageWindow(getPlugin(), getPlayer(), ItemStackFactory.Instance.CreateStack(Material.STAINED_GLASS_PANE, DyeColor.RED.getData(), 1, ChatColor.RED + "Error collecting rewards. Try again later."), "Error", 6*9, 20*3, getGui()).openInventory();
|
||||
}
|
||||
|
||||
UtilPlayer.message(getPlayer(), F.main("Carl", "Error collecting rewards. Try again later."));
|
||||
getPlayer().playSound(getPlayer().getLocation(), Sound.ENDERDRAGON_GROWL, 1, 10);
|
||||
}
|
||||
|
||||
getPlayer().closeInventory();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
getPlayer().playSound(getPlayer().getLocation(), Sound.ITEM_BREAK, 1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
private void setItem()
|
||||
{
|
||||
ArrayList<String> lore = new ArrayList<String>();
|
||||
Material material;
|
||||
String itemName;
|
||||
|
||||
if (isAvailable())
|
||||
{
|
||||
material = Material.EMERALD;
|
||||
itemName = C.cGreen + C.Bold + "Game Amplifiers";
|
||||
lore.add(" ");
|
||||
lore.add(C.cYellow + "Your Rewards");
|
||||
lore.add(" " + C.cWhite + getTips() + " Treasure Shards");
|
||||
lore.add(" ");
|
||||
lore.add(ChatColor.RESET + "Click to Claim!");
|
||||
}
|
||||
else
|
||||
{
|
||||
material = Material.REDSTONE_BLOCK;
|
||||
itemName = C.cRed + C.Bold + "Game Amplifiers";
|
||||
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Use Amplifiers to earn rewards");
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Get Amplifiers at " + C.cGreen + "mineplex.com/shop");
|
||||
}
|
||||
|
||||
_item = new ShopItem(material, itemName, lore.toArray(new String[0]), 1, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getObject()
|
||||
{
|
||||
return _item;
|
||||
}
|
||||
|
||||
public void refreshItem()
|
||||
{
|
||||
getGui().refreshItem(this);
|
||||
}
|
||||
|
||||
private int getTips()
|
||||
{
|
||||
return _boosterManager.getTipManager().Get(getPlayer()).getTips();
|
||||
}
|
||||
|
||||
private boolean isAvailable()
|
||||
{
|
||||
return getTips() > 0;
|
||||
}
|
||||
|
||||
public Plugin getPlugin()
|
||||
{
|
||||
return _plugin;
|
||||
}
|
||||
|
||||
public Player getPlayer()
|
||||
{
|
||||
return _player;
|
||||
}
|
||||
|
||||
public ItemRefresher getGui()
|
||||
{
|
||||
return _gui;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package mineplex.core.bonuses.gui.buttons;
|
||||
|
||||
import mineplex.core.common.jsonchat.ClickEvent;
|
||||
import mineplex.core.common.jsonchat.JsonMessage;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.gui.GuiItem;
|
||||
import mineplex.core.itemstack.ItemBuilder;
|
||||
import mineplex.core.youtube.YoutubeManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class YoutubeButton implements GuiItem
|
||||
{
|
||||
private static final ItemStack DISABLED_ICON = new ItemBuilder(Material.APPLE)
|
||||
.setTitle(C.cGreen + C.Bold + "Visit us on YouTube")
|
||||
.addLore(
|
||||
C.cWhite + "Come back tomorrow for your",
|
||||
C.cWhite + "Daily 250 Shard Reward!",
|
||||
" ",
|
||||
C.cWhite + "Check out the latest Video",
|
||||
C.cWhite + "on the MineplexGames Channel!",
|
||||
" ",
|
||||
C.cWhite + "Be sure and Subscribe so you",
|
||||
C.cWhite + "don't miss a video!",
|
||||
" ",
|
||||
C.cGreen + "Click to visit us on YouTube!"
|
||||
)
|
||||
.build();
|
||||
private static final ItemStack ENABLED_ICON = new ItemBuilder(Material.APPLE)
|
||||
.setTitle(C.cGreen + C.Bold + "Visit us on YouTube")
|
||||
.addLore(
|
||||
C.cYellow + "Claim your Daily 250 Shard Reward",
|
||||
C.cWhite + "by checking out the latest Video",
|
||||
C.cWhite + "on the MineplexGames Channel!",
|
||||
C.cWhite + " ",
|
||||
C.cWhite + "Be sure and Subscribe so you",
|
||||
C.cWhite + "don't miss a video!",
|
||||
" ",
|
||||
C.cGreen + "Click to visit us on YouTube!"
|
||||
)
|
||||
.build();
|
||||
private final Player _player;
|
||||
private final YoutubeManager _youtubeManager;
|
||||
|
||||
public YoutubeButton(Player player, YoutubeManager youtubeManager)
|
||||
{
|
||||
this._player = player;
|
||||
this._youtubeManager = youtubeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
|
||||
@Override
|
||||
public void click(ClickType clickType)
|
||||
{
|
||||
_player.closeInventory();
|
||||
|
||||
final String message;
|
||||
if (_youtubeManager.canYoutube(_player))
|
||||
{
|
||||
message = "Click here to claim YouTube Prize!";
|
||||
_youtubeManager.attemptYoutube(_player);
|
||||
} else
|
||||
{
|
||||
message = "Click here to visit our YouTube page!";
|
||||
}
|
||||
|
||||
new JsonMessage(C.cAquaB + message).click(ClickEvent.OPEN_URL, "https://www.youtube.com/mineplexgamesofficial").sendToPlayer(_player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getObject()
|
||||
{
|
||||
return _youtubeManager.canYoutube(_player) ? ENABLED_ICON : DISABLED_ICON;
|
||||
}
|
||||
}
|
146
Plugins/Mineplex.Core/src/mineplex/core/boosters/Booster.java
Normal file
146
Plugins/Mineplex.Core/src/mineplex/core/boosters/Booster.java
Normal file
@ -0,0 +1,146 @@
|
||||
package mineplex.core.boosters;
|
||||
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class Booster
|
||||
{
|
||||
private int _id;
|
||||
private String _playerName;
|
||||
private UUID _uuid;
|
||||
private int _accountId;
|
||||
private int _duration;
|
||||
private double _multiplier;
|
||||
private Date _startTime;
|
||||
private Date _endTime;
|
||||
private Date _activationTime;
|
||||
// private PropertyMap _propertyMap;
|
||||
|
||||
public Booster()
|
||||
{
|
||||
}
|
||||
|
||||
public int getId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public String getPlayerName()
|
||||
{
|
||||
return _playerName;
|
||||
}
|
||||
|
||||
public UUID getUuid()
|
||||
{
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
public int getAccountId()
|
||||
{
|
||||
return _accountId;
|
||||
}
|
||||
|
||||
public int getDuration()
|
||||
{
|
||||
return _duration;
|
||||
}
|
||||
|
||||
public Date getStartTime()
|
||||
{
|
||||
return _startTime;
|
||||
}
|
||||
|
||||
public Date getEndTime()
|
||||
{
|
||||
return _endTime;
|
||||
}
|
||||
|
||||
public Date getActivationTime()
|
||||
{
|
||||
return _activationTime;
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
Date now = new Date();
|
||||
return getStartTime().before(now) && getEndTime().after(now);
|
||||
}
|
||||
|
||||
public long getTimeRemaining()
|
||||
{
|
||||
if (isActive())
|
||||
{
|
||||
return Math.max(0, getEndTime().getTime() - System.currentTimeMillis());
|
||||
}
|
||||
else if (getEndTime().after(new Date()))
|
||||
{
|
||||
return _duration * 1000L;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String getTimeRemainingString()
|
||||
{
|
||||
return UtilTime.convertColonString(getTimeRemaining(), UtilTime.TimeUnit.MINUTES, UtilTime.TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public double getMultiplier()
|
||||
{
|
||||
return _multiplier;
|
||||
}
|
||||
|
||||
// public PropertyMap getPropertyMap()
|
||||
// {
|
||||
// return _propertyMap;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Booster booster = (Booster) o;
|
||||
|
||||
if (_id != booster._id) return false;
|
||||
return _accountId == booster._accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result = _id;
|
||||
result = 31 * result + _accountId;
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getIncreasePercent()
|
||||
{
|
||||
return (int) (getMultiplier() - 1) * 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Booster{" +
|
||||
"_id=" + _id +
|
||||
", _playerName='" + _playerName + '\'' +
|
||||
", _uuid=" + _uuid +
|
||||
", _accountId=" + _accountId +
|
||||
", _duration=" + _duration +
|
||||
", _multiplier=" + _multiplier +
|
||||
", _startTime=" + _startTime +
|
||||
", _endTime=" + _endTime +
|
||||
", _activationTime=" + _activationTime +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package mineplex.core.boosters;
|
||||
|
||||
import mineplex.core.common.api.ApiResponse;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterApiResponse extends ApiResponse
|
||||
{
|
||||
private Date startTime;
|
||||
|
||||
public Date getStartTime()
|
||||
{
|
||||
return startTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "BoosterApiResponse{" +
|
||||
"startTime='" + startTime + '\'' +
|
||||
"} " + super.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,394 @@
|
||||
package mineplex.core.boosters;
|
||||
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.boosters.command.BoosterCommand;
|
||||
import mineplex.core.boosters.event.BoosterActivateEvent;
|
||||
import mineplex.core.boosters.event.BoosterExpireEvent;
|
||||
import mineplex.core.boosters.event.BoosterUpdateEvent;
|
||||
import mineplex.core.boosters.gui.BoosterShop;
|
||||
import mineplex.core.boosters.redis.BoosterUpdateRepository;
|
||||
import mineplex.core.boosters.tips.BoosterTipManager;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.UtilGear;
|
||||
import mineplex.core.common.util.UtilInv;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.inventory.InventoryManager;
|
||||
import mineplex.core.itemstack.ItemStackFactory;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* BoosterManager handles the majority of logic for creating and getting Boosters. Every BoosterManager stores a cache
|
||||
* for all boosters across all servers. We pull all boosters from the API when the server boots up. To keep them in sync,
|
||||
* instead of consistently polling the API I have decided to go with a redis pub/sub solution to ensuring all boosters
|
||||
* across all servers are up to date. Whenever the Booster API receives a call to add or modify boosters, it will publish
|
||||
* an updated version of all boosters over redis.
|
||||
*
|
||||
* Boosters are enabled on live servers using "Booster Groups". A {@link mineplex.serverdata.data.ServerGroup} can specify
|
||||
* which BoosterGroup applies to it. If there is no BoosterGroup, then it means the server does not use boosters. To add
|
||||
* a BoosterGroup, you must add to the "boostergroups" set on redis (the same way the servergroups set works), otherwise
|
||||
* the API will return an error saying that BoosterGroup does not exist. Currently BoosterGroups are no more than a String
|
||||
* key for Boosters. In the future we may want to look into implementing BoosterGroup specific data such as default
|
||||
* booster length and multiplier.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterManager extends MiniPlugin
|
||||
{
|
||||
// The InventoryManager item name for boosters. This is required to activate a booster on servers
|
||||
public static final String BOOSTER_ITEM = "Game Booster";
|
||||
// Item in arcade lobbies that opens the booster gui
|
||||
public static final ItemStack INTERFACE_ITEM = ItemStackFactory.Instance.CreateStack(Material.EMERALD, (byte)0, 1, ChatColor.RESET + C.cGreen + "Game Amplifiers");
|
||||
// Slot for the booster gui item
|
||||
public static final int INTERFACE_SLOT = 7;
|
||||
|
||||
private BoosterRepository _repository;
|
||||
private CoreClientManager _clientManager;
|
||||
private DonationManager _donationManager;
|
||||
private InventoryManager _inventoryManager;
|
||||
|
||||
private BoosterTipManager _tipManager;
|
||||
private BoosterShop _shop;
|
||||
private String _boosterGroup;
|
||||
|
||||
private boolean _giveInterfaceItem;
|
||||
|
||||
private long _cacheLastUpdated;
|
||||
private Map<String, List<Booster>> _boosterCache = new HashMap<>();
|
||||
|
||||
public BoosterManager(JavaPlugin plugin, String boosterGroup, CoreClientManager clientManager, DonationManager donationManager, InventoryManager inventoryManager)
|
||||
{
|
||||
super("Booster Manager", plugin);
|
||||
|
||||
_repository = new BoosterRepository();
|
||||
_boosterGroup = boosterGroup;
|
||||
_clientManager = clientManager;
|
||||
_donationManager = donationManager;
|
||||
_inventoryManager = inventoryManager;
|
||||
|
||||
_tipManager = new BoosterTipManager(plugin, clientManager, donationManager);
|
||||
_shop = new BoosterShop(this, clientManager, donationManager);
|
||||
|
||||
try
|
||||
{
|
||||
Map<String, List<Booster>> boosters = _repository.getBoosters();
|
||||
if (boosters != null) _boosterCache = boosters;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Failed to load boosters on server start.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
_giveInterfaceItem = canActivateBoosters();
|
||||
|
||||
new BoosterUpdateRepository(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands()
|
||||
{
|
||||
addCommand(new BoosterCommand(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call to grab all Boosters
|
||||
*/
|
||||
@Deprecated
|
||||
public void getBoostersAsync(Callback<Map<String, List<Booster>>> callback)
|
||||
{
|
||||
runAsync(() -> {
|
||||
try
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
Map<String, List<Booster>> boosters = _repository.getBoosters();
|
||||
long timeTaken = System.currentTimeMillis() - time;
|
||||
runSync(() -> {
|
||||
handleBoosterUpdate(boosters);
|
||||
if (callback != null) callback.run(boosters);
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Failed to grab boosters;");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an API call to grab all boosters for a specific booster group
|
||||
* @param boosterGroup
|
||||
* @param callback
|
||||
*/
|
||||
@Deprecated
|
||||
public void getBoostersAsync(String boosterGroup, Callback<List<Booster>> callback)
|
||||
{
|
||||
runAsync(() -> {
|
||||
try
|
||||
{
|
||||
List<Booster> boosters = _repository.getBoosters(boosterGroup);
|
||||
if (callback != null) runSync(() -> callback.run(boosters));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.err.println("Failed to grab boosters for boostergroup: " + boosterGroup);
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the new boosterMap whenever a BoosterUpdateEvent is sent. This will compare itself to the current
|
||||
* cached BoosterMap and call events when it finds a booster was activated or deactivated
|
||||
* @param boosterMap The new booster map
|
||||
*/
|
||||
private void handleBoosterUpdate(Map<String, List<Booster>> boosterMap)
|
||||
{
|
||||
_boosterCache.entrySet().stream()
|
||||
.filter(entry -> entry.getValue().size() > 0)
|
||||
.filter(entry -> boosterMap.get(entry.getKey()) == null)
|
||||
.forEach(entry -> callNextTick(new BoosterExpireEvent(entry.getKey(), entry.getValue().get(0))));
|
||||
|
||||
for (Map.Entry<String, List<Booster>> entry : boosterMap.entrySet())
|
||||
{
|
||||
List<Booster> current = _boosterCache.get(entry.getKey());
|
||||
if (entry.getValue() != null && !entry.getValue().isEmpty())
|
||||
{
|
||||
if (current == null || current.isEmpty())
|
||||
{
|
||||
// New booster was added
|
||||
callNextTick(new BoosterActivateEvent(entry.getKey(), entry.getValue().get(0)));
|
||||
} else if (!current.get(0).equals(entry.getValue().get(0)))
|
||||
{
|
||||
// First booster was deactivated, new booster replaced it
|
||||
callNextTick(new BoosterExpireEvent(entry.getKey(), current.get(0)));
|
||||
callNextTick(new BoosterActivateEvent(entry.getKey(), entry.getValue().get(0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cacheLastUpdated = System.currentTimeMillis();
|
||||
_boosterCache = boosterMap;
|
||||
}
|
||||
|
||||
private void tickBoosterCache()
|
||||
{
|
||||
List<Event> events = new ArrayList<>(3);
|
||||
for (Map.Entry<String, List<Booster>> entry : _boosterCache.entrySet())
|
||||
{
|
||||
Iterator<Booster> iterator = entry.getValue().iterator();
|
||||
boolean removedOne = false;
|
||||
while (iterator.hasNext())
|
||||
{
|
||||
Booster booster = iterator.next();
|
||||
if (!booster.isActive())
|
||||
{
|
||||
iterator.remove();
|
||||
removedOne = true;
|
||||
events.add(new BoosterExpireEvent(entry.getKey(), booster));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (removedOne) events.add(new BoosterActivateEvent(entry.getKey(), booster));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
events.forEach(Bukkit.getPluginManager()::callEvent);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void tickBoosters(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() == UpdateType.MIN_10)
|
||||
{
|
||||
// sync with API every 10 minutes, incase pubsub fails
|
||||
getBoostersAsync(null);
|
||||
}
|
||||
else if (event.getType() == UpdateType.SEC)
|
||||
{
|
||||
tickBoosterCache();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all boosters for the active booster group
|
||||
* @return list of boosters, or null if there is no active booster group
|
||||
*/
|
||||
public List<Booster> getBoosters()
|
||||
{
|
||||
if (_boosterGroup == null || _boosterGroup.length() == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<Booster> boosters = _boosterCache.get(_boosterGroup);
|
||||
return boosters == null ? Collections.emptyList() : boosters;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBoosterGroup()
|
||||
{
|
||||
return _boosterGroup;
|
||||
}
|
||||
|
||||
public long getBoostTime()
|
||||
{
|
||||
return getBoostTime(_boosterGroup);
|
||||
}
|
||||
|
||||
public long getBoostTime(String boosterGroup)
|
||||
{
|
||||
long time = 0;
|
||||
List<Booster> boosters = _boosterCache.get(boosterGroup);
|
||||
if (boosters != null && boosters.size() > 0)
|
||||
{
|
||||
for (Booster booster : boosters)
|
||||
{
|
||||
time += booster.getTimeRemaining();
|
||||
}
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
public Booster getActiveBooster()
|
||||
{
|
||||
return getActiveBooster(_boosterGroup);
|
||||
}
|
||||
|
||||
public Booster getActiveBooster(String boosterGroup)
|
||||
{
|
||||
List<Booster> boosters = _boosterCache.get(boosterGroup);
|
||||
if (boosters != null)
|
||||
{
|
||||
for (Booster booster : boosters)
|
||||
{
|
||||
if (booster.getEndTime().after(new Date()))
|
||||
return booster;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void activateBooster(Player player, Callback<BoosterApiResponse> callback)
|
||||
{
|
||||
activateBooster(_boosterGroup, player, callback);
|
||||
}
|
||||
|
||||
public void activateBooster(String serverGroup, Player player, Callback<BoosterApiResponse> callback)
|
||||
{
|
||||
String playerName = player.getName();
|
||||
UUID uuid = player.getUniqueId();
|
||||
int accountId = _clientManager.getAccountId(player);
|
||||
// PropertyMap propertyMap = ((CraftPlayer) player).getHandle().getProfile().getProperties();
|
||||
|
||||
runAsync(() -> {
|
||||
BoosterApiResponse response = _repository.addBooster(serverGroup, playerName, uuid, accountId, 3600);
|
||||
callback.run(response);
|
||||
});
|
||||
}
|
||||
|
||||
public void chargeBooster(Player player, Callback<Boolean> callback)
|
||||
{
|
||||
_inventoryManager.addItemToInventory(callback, player, BOOSTER_ITEM, -1);
|
||||
}
|
||||
|
||||
public void refundBooster(Player player, Callback<Boolean> callback)
|
||||
{
|
||||
_inventoryManager.addItemToInventory(callback, player, BOOSTER_ITEM, 1);
|
||||
}
|
||||
|
||||
public void openShop(Player player)
|
||||
{
|
||||
_shop.attemptShopOpen(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Booster updates are sent from {@link mineplex.core.boosters.redis.BoosterUpdateListener}
|
||||
*/
|
||||
@EventHandler
|
||||
public void onBoosterUpdate(BoosterUpdateEvent event)
|
||||
{
|
||||
handleBoosterUpdate(event.getBoosterMap());
|
||||
}
|
||||
|
||||
public BoosterTipManager getTipManager()
|
||||
{
|
||||
return _tipManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of unactivated game boosters a player owns
|
||||
* @param player
|
||||
* @return The amount of unactivated game boosters the player owns
|
||||
*/
|
||||
public int getAvailableBoosterCount(Player player)
|
||||
{
|
||||
return _inventoryManager.Get(player).getItemCount(BOOSTER_ITEM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can players activate boosters on this server?
|
||||
* @return true if players are able to activate a booster on this server
|
||||
*/
|
||||
public boolean canActivateBoosters()
|
||||
{
|
||||
return _boosterGroup != null && _boosterGroup.length() > 0;
|
||||
}
|
||||
|
||||
public void giveInterfaceItem(Player player)
|
||||
{
|
||||
if (_giveInterfaceItem && !UtilGear.isMat(player.getInventory().getItem(INTERFACE_SLOT), Material.EMERALD))
|
||||
{
|
||||
player.getInventory().setItem(INTERFACE_SLOT, INTERFACE_ITEM);
|
||||
|
||||
UtilInv.Update(player);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent event)
|
||||
{
|
||||
giveInterfaceItem(event.getPlayer());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteract(PlayerInteractEvent event)
|
||||
{
|
||||
if (INTERFACE_ITEM.equals(event.getPlayer().getItemInHand()))
|
||||
{
|
||||
openShop(event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, List<Booster>> getBoosterCache()
|
||||
{
|
||||
return _boosterCache;
|
||||
}
|
||||
|
||||
private void callNextTick(Event event)
|
||||
{
|
||||
runSync(() -> getPluginManager().callEvent(event));
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package mineplex.core.boosters;
|
||||
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.shop.confirmation.ConfirmationCallback;
|
||||
import mineplex.core.shop.confirmation.ConfirmationProcessor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterProcessor implements ConfirmationProcessor
|
||||
{
|
||||
private BoosterManager _boosterManager;
|
||||
private Player _player;
|
||||
|
||||
public BoosterProcessor(BoosterManager boosterManager, Player player)
|
||||
{
|
||||
_boosterManager = boosterManager;
|
||||
_player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(ConfirmationCallback callback)
|
||||
{
|
||||
_boosterManager.chargeBooster(_player, data -> {
|
||||
if (data)
|
||||
{
|
||||
_boosterManager.activateBooster(_player, response -> {
|
||||
if (response.isSuccess())
|
||||
{
|
||||
long timeToStart = response.getStartTime().getTime() - System.currentTimeMillis();
|
||||
if (timeToStart <= 0) _player.sendMessage(F.main("Amplifier", "Game Amplifier Activated!"));
|
||||
else _player.sendMessage(F.main("Amplifier", "Game Amplifier Added. It will start in " + F.elem(UtilTime.convertString(timeToStart, 2, UtilTime.TimeUnit.FIT))));
|
||||
callback.resolve("Success!");
|
||||
}
|
||||
else
|
||||
{
|
||||
_player.sendMessage(C.cRed + "There was an error trying to enable your Game Amplifier");
|
||||
if (response.getStatusCode() == 503 && response.getError() != null && response.getError().length() > 0)
|
||||
{
|
||||
// Service Unavailable HTTP Code
|
||||
_player.sendMessage(C.cRed + "Error: " + response.getError());
|
||||
}
|
||||
|
||||
_boosterManager.refundBooster(_player, null);
|
||||
callback.reject("Failed. Try again later.");
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
callback.reject("Failed charging account.");
|
||||
_player.sendMessage(F.main("Amplifier", "There was an error charging your account. Try again later!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package mineplex.core.boosters;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import mineplex.core.common.api.ApiEndpoint;
|
||||
import mineplex.core.common.api.ApiFieldNamingStrategy;
|
||||
import mineplex.core.common.api.ApiResponse;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Boosters interaction is handled through a web API. All data is represented as JSON and then parsed using gson.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterRepository extends ApiEndpoint
|
||||
{
|
||||
public BoosterRepository()
|
||||
{
|
||||
super("/booster", new GsonBuilder().setFieldNamingStrategy(new ApiFieldNamingStrategy())
|
||||
// .registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer())
|
||||
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX").create());
|
||||
}
|
||||
|
||||
public Map<String, List<Booster>> getBoosters()
|
||||
{
|
||||
return getWebCall().get("/", new TypeToken<Map<String, List<Booster>>>(){}.getType());
|
||||
}
|
||||
|
||||
public List<Booster> getBoosters(String serverGroup)
|
||||
{
|
||||
return Arrays.asList(getWebCall().get("/" + serverGroup, Booster[].class));
|
||||
}
|
||||
|
||||
public BoosterApiResponse addBooster(String serverGroup, String playerName, UUID uuid, int accountId, int duration)
|
||||
{
|
||||
JsonObject body = new JsonObject();
|
||||
body.addProperty("playerName", playerName);
|
||||
body.addProperty("uuid", uuid.toString());
|
||||
body.addProperty("accountId", accountId);
|
||||
body.addProperty("duration", duration);
|
||||
// body.add("propertyMap", getGson().toJsonTree(propertyMap));
|
||||
|
||||
return getWebCall().post("/" + serverGroup, BoosterApiResponse.class, body);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package mineplex.core.boosters.command;
|
||||
|
||||
import mineplex.core.boosters.BoosterApiResponse;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class AddCommand extends CommandBase<BoosterManager>
|
||||
{
|
||||
public AddCommand(BoosterManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "add");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
if (args != null && args.length > 0)
|
||||
{
|
||||
String serverGroup = args[0];
|
||||
Plugin.activateBooster(serverGroup, caller, new Callback<BoosterApiResponse>()
|
||||
{
|
||||
@Override
|
||||
public void run(BoosterApiResponse response)
|
||||
{
|
||||
if (response.isSuccess())
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Amplifier", "Successfully added amplifier to " + F.elem(serverGroup)));
|
||||
}
|
||||
else
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Amplifier", "Failed to add amplifier. Error: " + F.elem(response.getError())));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
help(caller);
|
||||
}
|
||||
}
|
||||
|
||||
private void help(Player caller)
|
||||
{
|
||||
UtilPlayer.message(caller, F.help("amplifier add <servergroup>", "Add an amplifier to that server group", Rank.DEVELOPER));
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package mineplex.core.boosters.command;
|
||||
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
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 org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterCommand extends MultiCommandBase<BoosterManager>
|
||||
{
|
||||
public BoosterCommand(BoosterManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "amplifier", "booster");
|
||||
|
||||
AddCommand(new AddCommand(plugin));
|
||||
AddCommand(new GuiCommand(plugin));
|
||||
AddCommand(new ReloadCommand(plugin));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void Help(Player caller, String[] args)
|
||||
{
|
||||
UtilPlayer.message(caller, F.help("amplifier add <group>", "Add an amplifier to that group", Rank.DEVELOPER));
|
||||
UtilPlayer.message(caller, F.help("amplifier gui", "Open Amplifier GUI", Rank.DEVELOPER));
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package mineplex.core.boosters.command;
|
||||
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class GuiCommand extends CommandBase<BoosterManager>
|
||||
{
|
||||
public GuiCommand(BoosterManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "gui");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
Plugin.openShop(caller);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package mineplex.core.boosters.command;
|
||||
|
||||
import mineplex.core.boosters.Booster;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ReloadCommand extends CommandBase<BoosterManager>
|
||||
{
|
||||
public ReloadCommand(BoosterManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "reload");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
Plugin.getBoostersAsync(data -> {
|
||||
if (data != null)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Amplifier", "Amplifiers reloaded!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package mineplex.core.boosters.event;
|
||||
|
||||
import mineplex.core.boosters.Booster;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Called when a Booster is activated. This will be called regardless of which "BoosterGroup" the current server is set
|
||||
* to, so if you only want Boosters on the current BoosterGroup, you will need to verify it.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterActivateEvent extends Event
|
||||
{
|
||||
private String _boosterGroup;
|
||||
private Booster _booster;
|
||||
|
||||
public BoosterActivateEvent(String boosterGroup, Booster booster)
|
||||
{
|
||||
_boosterGroup = boosterGroup;
|
||||
_booster = booster;
|
||||
}
|
||||
|
||||
public String getBoosterGroup()
|
||||
{
|
||||
return _boosterGroup;
|
||||
}
|
||||
|
||||
public Booster getBooster()
|
||||
{
|
||||
return _booster;
|
||||
}
|
||||
|
||||
private static final HandlerList _handlers = new HandlerList();
|
||||
private static HandlerList getHandlerList()
|
||||
{
|
||||
return _handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package mineplex.core.boosters.event;
|
||||
|
||||
import mineplex.core.boosters.Booster;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
/**
|
||||
* Called when a Booster is finished.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterExpireEvent extends Event
|
||||
{
|
||||
private String _boosterGroup;
|
||||
private Booster _booster;
|
||||
|
||||
public BoosterExpireEvent(String boosterGroup, Booster booster)
|
||||
{
|
||||
_boosterGroup = boosterGroup;
|
||||
_booster = booster;
|
||||
}
|
||||
|
||||
public String getBoosterGroup()
|
||||
{
|
||||
return _boosterGroup;
|
||||
}
|
||||
|
||||
public Booster getBooster()
|
||||
{
|
||||
return _booster;
|
||||
}
|
||||
|
||||
private static final HandlerList _handlers = new HandlerList();
|
||||
private static HandlerList getHandlerList()
|
||||
{
|
||||
return _handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package mineplex.core.boosters.event;
|
||||
|
||||
import mineplex.core.boosters.Booster;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Called when {@link mineplex.core.boosters.redis.BoosterUpdateListener} receives updated Boosters over redis pubsub.
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterUpdateEvent extends Event
|
||||
{
|
||||
private Map<String, List<Booster>> _boosterMap;
|
||||
|
||||
public BoosterUpdateEvent(Map<String, List<Booster>> boosterMap)
|
||||
{
|
||||
_boosterMap = boosterMap;
|
||||
}
|
||||
|
||||
public Map<String, List<Booster>> getBoosterMap()
|
||||
{
|
||||
return _boosterMap;
|
||||
}
|
||||
|
||||
private static final HandlerList _handlers = new HandlerList();
|
||||
private static HandlerList getHandlerList()
|
||||
{
|
||||
return _handlers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HandlerList getHandlers()
|
||||
{
|
||||
return getHandlerList();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package mineplex.core.boosters.gui;
|
||||
|
||||
import mineplex.core.boosters.BoosterApiResponse;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.shop.item.IButton;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
@Deprecated
|
||||
public class ActivateBoosterButton implements IButton
|
||||
{
|
||||
private BoosterShop _boosterShop;
|
||||
private BoosterManager _boosterManager;
|
||||
|
||||
public ActivateBoosterButton(BoosterShop boosterShop, BoosterManager boosterManager)
|
||||
{
|
||||
_boosterShop = boosterShop;
|
||||
_boosterManager = boosterManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(Player player, ClickType clickType)
|
||||
{
|
||||
player.closeInventory();
|
||||
|
||||
_boosterManager.chargeBooster(player, data -> {
|
||||
if (data)
|
||||
{
|
||||
_boosterManager.activateBooster(player, response -> {
|
||||
if (response.isSuccess())
|
||||
{
|
||||
long timeToStart = response.getStartTime().getTime() - System.currentTimeMillis();
|
||||
if (timeToStart <= 0) player.sendMessage(F.main("Amplifier", "Amplifier Activated!"));
|
||||
else player.sendMessage(F.main("Amplifier", "Game Amplifier Added. It will start in " + F.elem(UtilTime.convertString(timeToStart, 2, UtilTime.TimeUnit.FIT))));
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(C.cRed + "There was an error trying to enable your Amplifier :(");
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
player.sendMessage(F.main("Amplifier", "There was an error charging your account. Try again later!"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,230 @@
|
||||
package mineplex.core.boosters.gui;
|
||||
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.boosters.Booster;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.boosters.BoosterProcessor;
|
||||
import mineplex.core.common.Pair;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.UtilTime;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.shop.confirmation.ConfirmationPage;
|
||||
import mineplex.core.shop.item.ShopItem;
|
||||
import mineplex.core.shop.page.ShopPageBase;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterPage extends ShopPageBase<BoosterManager, BoosterShop>
|
||||
{
|
||||
public BoosterPage(BoosterManager plugin, BoosterShop shop, CoreClientManager clientManager, DonationManager donationManager, Player player)
|
||||
{
|
||||
super(plugin, shop, clientManager, donationManager, "Game Amplifiers", player, 45);
|
||||
|
||||
buildPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPage()
|
||||
{
|
||||
ArrayList<String> lore = new ArrayList<>();
|
||||
|
||||
int amplifierCount = getPlugin().getAvailableBoosterCount(getPlayer());
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "You own " + C.cGreen + amplifierCount + C.cWhite + " Game Amplifiers");
|
||||
if (getPlugin().canActivateBoosters() && amplifierCount > 0)
|
||||
{
|
||||
List<Booster> boosters = getPlugin().getBoosters();
|
||||
|
||||
long waitTime = getPlugin().getBoostTime();
|
||||
if (waitTime == 0)
|
||||
{
|
||||
lore.add(C.cWhite + "Amplifier would activate " + C.cGreen + "now");
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Once this Amplifier is activated");
|
||||
lore.add(C.cGray + "or queued you are not able to");
|
||||
lore.add(C.cGray + "cancel or refund it. You will still");
|
||||
lore.add(C.cGray + "earn rewards if you are offline.");
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Click to Activate Amplifier");
|
||||
}
|
||||
else
|
||||
{
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Amplifier would activate in " + C.cGreen + UtilTime.convertColonString(waitTime, UtilTime.TimeUnit.HOURS, UtilTime.TimeUnit.SECONDS));
|
||||
if (boosters.size() - 1 == 1)
|
||||
{
|
||||
lore.add(C.cWhite + "There is " + C.cGreen + 1 + C.cWhite + " Amplifier queued");
|
||||
}
|
||||
else if (boosters.size() - 1 > 0)
|
||||
{
|
||||
lore.add(C.cWhite + "There are " + C.cGreen + (boosters.size() - 1) + C.cWhite + " Amplifiers queued");
|
||||
}
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Once this Amplifier is activated");
|
||||
lore.add(C.cGray + "or queued you are not able to");
|
||||
lore.add(C.cGray + "cancel or refund it. You will still");
|
||||
lore.add(C.cGray + "earn rewards if you are offline.");
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Click to Queue Amplifier");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Game Amplifiers allow you to");
|
||||
lore.add(C.cGray + "increase the gems and shards");
|
||||
lore.add(C.cGray + "earned in that game for 1 hour.");
|
||||
lore.add(C.cGray + "You will also earn bonus rewards");
|
||||
lore.add(C.cGray + "from players thanking you while");
|
||||
lore.add(C.cGray + "your amplifier is active.");
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Get Amplifiers at " + C.cGreen + "mineplex.com/shop");
|
||||
}
|
||||
|
||||
ShopItem booster = new ShopItem(Material.SUGAR, "Game Amplifier", lore.toArray(new String[0]), 0, false, false);
|
||||
if (getPlugin().canActivateBoosters() && amplifierCount > 0)
|
||||
{
|
||||
addButton(13, booster, this::openConfirmation);
|
||||
}
|
||||
else
|
||||
{
|
||||
setItem(13, booster);
|
||||
}
|
||||
|
||||
addBoosterQueue();
|
||||
// addOtherBoosters();
|
||||
}
|
||||
|
||||
private void openConfirmation(Player player, ClickType type)
|
||||
{
|
||||
ArrayList<String> lore = new ArrayList<>();
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Once this Amplifier is activated");
|
||||
lore.add(C.cGray + "or queued you are not able to");
|
||||
lore.add(C.cGray + "cancel or refund it. You will still");
|
||||
lore.add(C.cGray + "earn rewards if you are offline.");
|
||||
ShopItem booster = new ShopItem(Material.SUGAR, "Game Amplifier", lore.toArray(new String[0]), 0, false, false);
|
||||
|
||||
BoosterProcessor processor = new BoosterProcessor(getPlugin(), getPlayer());
|
||||
ConfirmationPage<BoosterManager, BoosterShop> page = new ConfirmationPage<>(getPlugin(), getShop(),
|
||||
getClientManager(), getDonationManager(), getPlayer(), this, processor, booster);
|
||||
getShop().openPageForPlayer(getPlayer(), page);
|
||||
}
|
||||
|
||||
private void addBoosterQueue()
|
||||
{
|
||||
if (getPlugin().getBoosters() == null)
|
||||
return;
|
||||
|
||||
List<Booster> boosters = getPlugin().getBoosters();
|
||||
int startIndex = Math.max(0, (9 - boosters.size()) / 2);
|
||||
for (int i = 0; i < boosters.size() && i < 18; i++)
|
||||
{
|
||||
int slot = startIndex + 27 + i;
|
||||
Booster booster = boosters.get(i);
|
||||
boolean active = booster.isActive();
|
||||
int queueIndex = Math.max(1, i);
|
||||
boolean owns = getPlayer().getUniqueId().equals(booster.getUuid());
|
||||
|
||||
long timeActivatedDif = System.currentTimeMillis() - booster.getActivationTime().getTime();
|
||||
String activationTime = UtilTime.convertString(timeActivatedDif, 0, UtilTime.TimeUnit.FIT);
|
||||
|
||||
List<String> lore = new ArrayList<>();
|
||||
if (active)
|
||||
{
|
||||
lore.add(C.cWhite + "Active");
|
||||
lore.add(" ");
|
||||
String expireTime = UtilTime.convertColonString(booster.getTimeRemaining(), UtilTime.TimeUnit.MINUTES, UtilTime.TimeUnit.SECONDS);
|
||||
lore.add(C.cWhite + "Added by " + C.cGreen + booster.getPlayerName());
|
||||
lore.add(C.cWhite + "Expires in " + C.cGreen + expireTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
long timeToActive = booster.getStartTime().getTime() - System.currentTimeMillis();
|
||||
String activeString = UtilTime.convertColonString(timeToActive, UtilTime.TimeUnit.HOURS, UtilTime.TimeUnit.SECONDS);
|
||||
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Added by " + C.cGreen + booster.getPlayerName());
|
||||
lore.add(C.cWhite + "Starts in " + C.cGreen + activeString);
|
||||
// lore.add(C.cWhite + "Position " + C.cGreen + queueIndex + C.cWhite + " in queue");
|
||||
}
|
||||
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Added " + activationTime + " ago");
|
||||
|
||||
ShopItem shopItem = new ShopItem(booster.isActive() ? Material.EMERALD_BLOCK : Material.REDSTONE_BLOCK,
|
||||
"Game Amplifier", lore.toArray(new String[0]), queueIndex, !active, false);
|
||||
setItem(slot, shopItem);
|
||||
|
||||
// Add glow if the booster belongs to you
|
||||
if (owns)
|
||||
{
|
||||
addGlow(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addOtherBoosters()
|
||||
{
|
||||
Map<String, List<Booster>> boosterMap = getPlugin().getBoosterCache();
|
||||
List<Triple<Integer, String, Booster>> tripleList = new ArrayList<>();
|
||||
for (Map.Entry<String, List<Booster>> entry : boosterMap.entrySet())
|
||||
{
|
||||
String boosterGroup = entry.getKey();
|
||||
// dont display boosters for the current booster group
|
||||
if (boosterGroup.equals(getPlugin().getBoosterGroup()))
|
||||
continue;
|
||||
|
||||
List<Booster> boosters = entry.getValue();
|
||||
for (int i = 0; i < boosters.size(); i++)
|
||||
{
|
||||
Booster booster = boosters.get(i);
|
||||
if (booster.getUuid().equals(getPlayer().getUniqueId()))
|
||||
{
|
||||
tripleList.add(Triple.of(i, boosterGroup, booster));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int startIndex = Math.max(0, (9 - tripleList.size()) / 2);
|
||||
for (int i = 0; i < 9 && i < tripleList.size(); i++)
|
||||
{
|
||||
Triple<Integer, String, Booster> triple = tripleList.get(i);
|
||||
int deliveryAmount = Math.max(1, triple.getLeft());
|
||||
String boosterGroup = triple.getMiddle();
|
||||
Booster booster = triple.getRight();
|
||||
long timeActivatedDif = System.currentTimeMillis() - booster.getActivationTime().getTime();
|
||||
String activationTime = UtilTime.convertString(timeActivatedDif, 2, UtilTime.TimeUnit.FIT);
|
||||
|
||||
List<String> lore = new ArrayList<String>();
|
||||
lore.add(" ");
|
||||
lore.add(C.cWhite + "Server: " + C.cGreen + boosterGroup);
|
||||
if (booster.isActive())
|
||||
{
|
||||
lore.add(C.cWhite + "Expires in " + C.cGreen + UtilTime.convertColonString(booster.getTimeRemaining(), UtilTime.TimeUnit.MINUTES, UtilTime.TimeUnit.SECONDS));
|
||||
}
|
||||
else
|
||||
{
|
||||
long timeToActive = booster.getStartTime().getTime() - System.currentTimeMillis();
|
||||
lore.add(C.cWhite + "Starts in " + C.cGreen + UtilTime.convertColonString(timeToActive, UtilTime.TimeUnit.HOURS, UtilTime.TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
lore.add(" ");
|
||||
lore.add(C.cGray + "Added " + activationTime + " ago");
|
||||
|
||||
ShopItem shopItem = new ShopItem(Material.GOLD_BLOCK,
|
||||
"Game Amplifier", lore.toArray(new String[0]), 1, false, false);
|
||||
setItem(startIndex + i + 27, shopItem);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package mineplex.core.boosters.gui;
|
||||
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.boosters.BoosterManager;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.shop.ShopBase;
|
||||
import mineplex.core.shop.page.ShopPageBase;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterShop extends ShopBase<BoosterManager>
|
||||
{
|
||||
public BoosterShop(BoosterManager plugin, CoreClientManager clientManager, DonationManager donationManager)
|
||||
{
|
||||
super(plugin, clientManager, donationManager, "Game Amplifiers");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShopPageBase<BoosterManager, ? extends ShopBase<BoosterManager>> buildPagesFor(Player player)
|
||||
{
|
||||
return new BoosterPage(getPlugin(), this, getClientManager(), getDonationManager(), player);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void update(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() != UpdateType.SEC)
|
||||
return;
|
||||
|
||||
getPlayerPageMap().values().stream().filter(value -> value instanceof BoosterPage).forEach(ShopPageBase::refresh);
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package mineplex.core.boosters.redis;
|
||||
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import mineplex.core.boosters.Booster;
|
||||
import mineplex.core.boosters.event.BoosterUpdateEvent;
|
||||
import mineplex.core.common.api.ApiFieldNamingStrategy;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import redis.clients.jedis.JedisPubSub;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterUpdateListener extends JedisPubSub
|
||||
{
|
||||
private Gson _gson = new GsonBuilder().setFieldNamingStrategy(new ApiFieldNamingStrategy())
|
||||
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX").create();
|
||||
private JavaPlugin _plugin;
|
||||
|
||||
public BoosterUpdateListener(JavaPlugin plugin)
|
||||
{
|
||||
_plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String channel, String message)
|
||||
{
|
||||
try
|
||||
{
|
||||
Map<String, List<Booster>> boosterMap = _gson.fromJson(message, new TypeToken<Map<String, List<Booster>>>() {}.getType());
|
||||
_plugin.getServer().getScheduler().runTask(_plugin, () -> Bukkit.getPluginManager().callEvent(new BoosterUpdateEvent(boosterMap)));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
System.out.println("Failed to load booster update");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package mineplex.core.boosters.redis;
|
||||
|
||||
import mineplex.serverdata.Region;
|
||||
import mineplex.serverdata.redis.RedisRepository;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterUpdateRepository extends RedisRepository
|
||||
{
|
||||
private JavaPlugin _plugin;
|
||||
|
||||
public BoosterUpdateRepository(JavaPlugin plugin)
|
||||
{
|
||||
super(Region.ALL);
|
||||
|
||||
_plugin = plugin;
|
||||
init();
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
Thread thread = new Thread("Booster Subscriber")
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try (Jedis jedis = getResource(false))
|
||||
{
|
||||
jedis.subscribe(new BoosterUpdateListener(_plugin), "minecraft.boosters");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
thread.start();
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package mineplex.core.boosters.tips;
|
||||
|
||||
import mineplex.core.MiniDbClientPlugin;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.boosters.Booster;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.recharge.Recharge;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterTipManager extends MiniDbClientPlugin<PlayerTipData>
|
||||
{
|
||||
public static final int TIP_FOR_SPONSOR = 5;
|
||||
public static final int TIP_FOR_TIPPER = 5;
|
||||
|
||||
private BoosterTipRepository _repository;
|
||||
private DonationManager _donationManager;
|
||||
|
||||
public BoosterTipManager(JavaPlugin plugin, CoreClientManager clientManager, DonationManager donationManager)
|
||||
{
|
||||
super("Amplifier Thanks", plugin, clientManager);
|
||||
|
||||
_donationManager = donationManager;
|
||||
_repository = new BoosterTipRepository(plugin);
|
||||
}
|
||||
|
||||
public void addTip(Player player, Booster booster, Callback<TipAddResult> callback)
|
||||
{
|
||||
if (!Recharge.Instance.use(player, "Amplifier Thanks", 1000 * 60 * 10, true, false))
|
||||
{
|
||||
callback.run(TipAddResult.ON_COOLDOWN);
|
||||
return;
|
||||
}
|
||||
|
||||
int accountId = ClientManager.getAccountId(player);
|
||||
|
||||
// Break out if client manager has a bad account id
|
||||
if (accountId == -1)
|
||||
{
|
||||
callback.run(TipAddResult.INVALID_ACCOUNT_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
// You can't tip yourself, silly!
|
||||
if (accountId == booster.getAccountId())
|
||||
{
|
||||
callback.run(TipAddResult.CANNOT_TIP_SELF);
|
||||
return;
|
||||
}
|
||||
|
||||
runAsync(() -> {
|
||||
TipAddResult result;
|
||||
if (_repository.addTip(accountId, booster.getAccountId(), booster.getId(), TIP_FOR_SPONSOR))
|
||||
{
|
||||
_donationManager.rewardCoinsUntilSuccess(null, "Tips", player.getName(), accountId, TIP_FOR_TIPPER);
|
||||
result = TipAddResult.SUCCESS;
|
||||
}
|
||||
else
|
||||
result = TipAddResult.ALREADY_TIPPED_BOOSTER;
|
||||
|
||||
runSync(() -> callback.run(result));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim all tips for a player and add those tips to their account (Treasure Shards)
|
||||
* This will call a database routine that handles the tip process.
|
||||
*
|
||||
* The callback will return -1 on a failed attempt or 0 if there was no tips to claim
|
||||
* @param player The player with tips to claim
|
||||
* @param callback Callback returning the amount of tips claimed
|
||||
*/
|
||||
public void claimTips(Player player, Callback<Integer> callback)
|
||||
{
|
||||
String playerName = player.getName();
|
||||
int accountId = ClientManager.getAccountId(player);
|
||||
|
||||
if (accountId == -1)
|
||||
{
|
||||
// uh oh, invalid account id!
|
||||
if (callback != null) callback.run(-1);
|
||||
}
|
||||
|
||||
runAsync(() -> {
|
||||
int tips = _repository.claimTips(accountId);
|
||||
runSync(() -> {
|
||||
if (tips > 0)
|
||||
{
|
||||
_donationManager.rewardCoinsUntilSuccess(null, "Tips", playerName, accountId, tips);
|
||||
}
|
||||
|
||||
// Reset tips back to 0
|
||||
if (Get(player) != null) Get(player).setTips(0);
|
||||
if (callback != null) callback.run(tips);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQuery(int accountId, String uuid, String name)
|
||||
{
|
||||
return "SELECT tips FROM Account.accountTip WHERE accountTip.accountId = " + accountId + ";";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PlayerTipData AddPlayer(String player)
|
||||
{
|
||||
return new PlayerTipData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processLoginResultSet(String playerName, int accountId, ResultSet resultSet) throws SQLException
|
||||
{
|
||||
PlayerTipData data = new PlayerTipData();
|
||||
|
||||
while (resultSet.next())
|
||||
{
|
||||
data.setTips(resultSet.getInt(1));
|
||||
}
|
||||
|
||||
Set(playerName, data);
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package mineplex.core.boosters.tips;
|
||||
|
||||
import mineplex.core.database.MinecraftRepository;
|
||||
import mineplex.database.routines.AddTip;
|
||||
import mineplex.database.routines.ClaimTips;
|
||||
import mineplex.serverdata.database.DBPool;
|
||||
import mineplex.serverdata.database.RepositoryBase;
|
||||
import mineplex.serverdata.database.column.ColumnInt;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BoosterTipRepository extends MinecraftRepository
|
||||
{
|
||||
public static String LOG_TIP = "INSERT INTO Account.accountTipLogs (accountId, boosterId) VALUES (?, ?)";
|
||||
public static String ADD_TIP = "INSERT INTO Account.accountTip (accountId, tips) VALUES (?, ?) ON DUPLICATE KEY UPDATE tips = tips + ?";
|
||||
|
||||
public BoosterTipRepository(JavaPlugin plugin)
|
||||
{
|
||||
super(plugin, DBPool.getAccount());
|
||||
}
|
||||
|
||||
public boolean addTip(int tipperId, int receiverId, int boosterId, int tipAmount)
|
||||
{
|
||||
AddTip addTip = new AddTip();
|
||||
addTip.setTipperAccountId(tipperId);
|
||||
addTip.setBoosterAccountId(receiverId);
|
||||
addTip.setBoosterId(boosterId);
|
||||
addTip.setTipAmount(tipAmount);
|
||||
addTip.execute(jooq().configuration());
|
||||
return addTip.getSuccess() == 1;
|
||||
}
|
||||
|
||||
public int claimTips(int accountId)
|
||||
{
|
||||
ClaimTips claimTips = new ClaimTips();
|
||||
claimTips.setAccountId_in(accountId);
|
||||
claimTips.execute(jooq().configuration());
|
||||
return claimTips.getTipsClaimed();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package mineplex.core.boosters.tips;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class PlayerTipData
|
||||
{
|
||||
private int _tips;
|
||||
|
||||
public PlayerTipData()
|
||||
{
|
||||
_tips = 0;
|
||||
}
|
||||
|
||||
public int getTips()
|
||||
{
|
||||
return _tips;
|
||||
}
|
||||
|
||||
public void setTips(int tips)
|
||||
{
|
||||
_tips = tips;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package mineplex.core.boosters.tips;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public enum TipAddResult
|
||||
{
|
||||
ALREADY_TIPPED_BOOSTER("You have already thanked this Amplifier!"),
|
||||
INVALID_ACCOUNT_ID("Uh oh, something went wrong. Try relogging"),
|
||||
CANNOT_TIP_SELF("You can't thank yourself, silly!"),
|
||||
ON_COOLDOWN(null),
|
||||
SUCCESS(null);
|
||||
|
||||
private String _friendlyMessage;
|
||||
|
||||
TipAddResult(String friendlyMessage)
|
||||
{
|
||||
_friendlyMessage = friendlyMessage;
|
||||
}
|
||||
|
||||
public String getFriendlyMessage()
|
||||
{
|
||||
return _friendlyMessage;
|
||||
}
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package mineplex.core.brawl.fountain;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
/**
|
||||
* This class handled filling a vertical area with a specific block based off a percent
|
||||
*
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class BlockProgressBar
|
||||
{
|
||||
// Starting block for the block fill
|
||||
private final Block _startBlock;
|
||||
// Direction the blockfill takes place in
|
||||
private final BlockFace _direction;
|
||||
// Blocks in order from lowest to highes
|
||||
private final Block[] _blocks;
|
||||
// Material used to fill the blocks
|
||||
private final Material _material;
|
||||
|
||||
public BlockProgressBar(Block startBlock, Material material, BlockFace direction)
|
||||
{
|
||||
_startBlock = startBlock;
|
||||
_material = material;
|
||||
_direction = direction;
|
||||
|
||||
// Add blocks to array
|
||||
int i;
|
||||
Block curr;
|
||||
Block[] blocks = new Block[100]; // max of 100 to prevent blocking
|
||||
for (i = 0, curr = startBlock; (curr.getType() == Material.AIR || curr.getType() == material) && i < blocks.length; i++)
|
||||
{
|
||||
blocks[i] = curr;
|
||||
curr = curr.getRelative(direction);
|
||||
}
|
||||
|
||||
_blocks = new Block[i];
|
||||
System.arraycopy(blocks, 0, _blocks, 0, i);
|
||||
}
|
||||
|
||||
// Update the blockfill based on fill percent
|
||||
public void update(double percent)
|
||||
{
|
||||
double percentPerBlock = 1D / _blocks.length;
|
||||
double check = 0;
|
||||
|
||||
for (int i = 0; i < _blocks.length; i++)
|
||||
{
|
||||
_blocks[i].setType(percent > check ? _material : Material.AIR);
|
||||
|
||||
check += percentPerBlock;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package mineplex.core.brawl.fountain;
|
||||
|
||||
import mineplex.core.shop.ShopBase;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public interface BrawlShopProvider
|
||||
{
|
||||
public ShopBase getBrawlShop();
|
||||
}
|
@ -0,0 +1,250 @@
|
||||
package mineplex.core.brawl.fountain;
|
||||
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.brawl.fountain.gui.FountainShop;
|
||||
import mineplex.core.common.SortedSchematicLoader;
|
||||
import mineplex.core.common.block.schematic.UtilSchematic;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilText;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.hologram.Hologram;
|
||||
import mineplex.core.hologram.HologramManager;
|
||||
import mineplex.core.stats.StatsManager;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.serverdata.redis.counter.GoalCounter;
|
||||
import mineplex.serverdata.redis.counter.GoalCounterListener;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* Represents a fountain that players can add gems to, with a reward for reaching specific goals
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class Fountain implements GoalCounterListener
|
||||
{
|
||||
// Manager Injections
|
||||
private final HologramManager _hologramManager;
|
||||
private final StatsManager _statsManager;
|
||||
|
||||
private boolean _brawlActive;
|
||||
private final String _name;
|
||||
private final String _dataKey;
|
||||
private final Location _location;
|
||||
private final Hologram _hologram;
|
||||
private final GoalCounter _counter;
|
||||
// private final BlockProgressBar _blockProgressBar;
|
||||
private final SortedSchematicLoader<Double> _schematicLoader;
|
||||
|
||||
private final FountainShop _shop;
|
||||
|
||||
public Fountain(Location location, Location pasteLocation, String name, String dataKey, long goal, FountainManager fountainManager,
|
||||
CoreClientManager clientManager, DonationManager donationManager, HologramManager hologramManager,
|
||||
StatsManager statsManager)
|
||||
{
|
||||
_hologramManager = hologramManager;
|
||||
_statsManager = statsManager;
|
||||
|
||||
_name = name;
|
||||
_dataKey = dataKey;
|
||||
_location = location;
|
||||
_hologram = new Hologram(hologramManager, location.clone().add(4, 3, -3), name).start();
|
||||
_counter = new GoalCounter(dataKey, 5000, goal);
|
||||
_counter.addListener(this);
|
||||
_brawlActive = false;
|
||||
// _blockProgressBar = new BlockProgressBar(_lavaLocation.getBlock(), Material.LAVA, BlockFace.UP);
|
||||
_schematicLoader = new SortedSchematicLoader<>(pasteLocation);
|
||||
loadSchematics();
|
||||
|
||||
_shop = new FountainShop(this, fountainManager, clientManager, donationManager);
|
||||
|
||||
updateVisuals();
|
||||
}
|
||||
|
||||
private void loadSchematics()
|
||||
{
|
||||
try
|
||||
{
|
||||
_schematicLoader.addSchematic(0.0, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain0.schematic")));
|
||||
_schematicLoader.addSchematic(0.2, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain20.schematic")));
|
||||
_schematicLoader.addSchematic(0.4, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain40.schematic")));
|
||||
_schematicLoader.addSchematic(0.6, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain60.schematic")));
|
||||
_schematicLoader.addSchematic(0.8, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain80.schematic")));
|
||||
_schematicLoader.addSchematic(1.0, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain100.schematic")));
|
||||
_schematicLoader.addSchematic(2.0, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain200.schematic")));
|
||||
_schematicLoader.addSchematic(3.0, UtilSchematic.loadSchematic(new File("../../update/schematic/fountain300.schematic")));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.err.println("Failed to load Gem Fountain Schematics");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateVisuals()
|
||||
{
|
||||
double fillPercent = getFillPercent();
|
||||
|
||||
if (isBrawlActive())
|
||||
{
|
||||
ArrayList<String> text = new ArrayList<>();
|
||||
if (fillPercent >= 1)
|
||||
{
|
||||
text.add(C.cRed + C.Bold + "Weekend Brawl is Active!");
|
||||
if (fillPercent >= 2)
|
||||
{
|
||||
text.add("Bonus Reward Unlocked:");
|
||||
if (fillPercent >= 3)
|
||||
{
|
||||
text.add(C.cGreen + "3X Experience in Brawl");
|
||||
}
|
||||
else
|
||||
{
|
||||
text.add(C.cGreen + "2X Experience in Brawl");
|
||||
}
|
||||
}
|
||||
text.add(" ");
|
||||
text.add("Speak to the Fountain Keeper to Join!");
|
||||
}
|
||||
else
|
||||
{
|
||||
text.add(C.cRed + "Brawl goal was not met");
|
||||
text.add("Come back next week");
|
||||
}
|
||||
|
||||
_hologram.setText(text.toArray(new String[text.size()]));
|
||||
_schematicLoader.update(fillPercent);
|
||||
}
|
||||
else
|
||||
{
|
||||
double flatPercent = fillPercent - (int) fillPercent;
|
||||
|
||||
String fillColor;
|
||||
String emptyColor;
|
||||
String goalMessage;
|
||||
|
||||
if (fillPercent < 1)
|
||||
{
|
||||
fillColor = C.cGreen;
|
||||
emptyColor = C.cRed;
|
||||
goalMessage = "100% to Unlock Weekend Brawl";
|
||||
} else if (fillPercent < 2)
|
||||
{
|
||||
fillColor = C.cYellow;
|
||||
emptyColor = C.cGreen;
|
||||
goalMessage = "200% to Unlock 2x XP for Weekend Brawl";
|
||||
} else if (fillPercent < 3)
|
||||
{
|
||||
fillColor = C.cAqua;
|
||||
emptyColor = C.cYellow;
|
||||
goalMessage = "300% to Unlock 3x XP for Weekend Brawl";
|
||||
} else
|
||||
{
|
||||
fillColor = C.cAqua;
|
||||
emptyColor = C.cYellow;
|
||||
goalMessage = "All Rewards Unlocked!";
|
||||
flatPercent = 1;
|
||||
}
|
||||
|
||||
int intPercent = (int) (fillPercent * 100);
|
||||
String progressBar = UtilText.getProgress(null, flatPercent, null, false, 30, emptyColor, fillColor);
|
||||
_hologram.setText(_name + C.Reset + " " + intPercent + "%", goalMessage, progressBar);
|
||||
_schematicLoader.update(fillPercent);
|
||||
}
|
||||
}
|
||||
|
||||
public void increment(Player player, long amount)
|
||||
{
|
||||
_statsManager.incrementStat(player, getStatName(), amount);
|
||||
_counter.addAndGet(amount);
|
||||
updateVisuals();
|
||||
}
|
||||
|
||||
public long getAmountAdded(Player player)
|
||||
{
|
||||
return _statsManager.Get(player).getStat(getStatName());
|
||||
}
|
||||
|
||||
private final String getStatName()
|
||||
{
|
||||
return "Global.Fountain." + getDataKey();
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
public String getDataKey()
|
||||
{
|
||||
return _dataKey;
|
||||
}
|
||||
|
||||
public void openShop(Player player)
|
||||
{
|
||||
_shop.attemptShopOpen(player);
|
||||
}
|
||||
|
||||
public double getFillPercent()
|
||||
{
|
||||
return Math.min(3, _counter.getFillPercent());
|
||||
}
|
||||
|
||||
public long getCount()
|
||||
{
|
||||
return _counter.getCount();
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_counter.reset();
|
||||
updateVisuals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMilestone(GoalCounter counter, int milestone)
|
||||
{
|
||||
switch (milestone)
|
||||
{
|
||||
case 1:
|
||||
Bukkit.broadcastMessage(F.main("Fountain", "The Gem Fountain has reached 100%! Brawl Game unlocked this week"));
|
||||
break;
|
||||
case 2:
|
||||
Bukkit.broadcastMessage(F.main("Fountain", "The Gem Fountain has reached 200%! 2x XP enabled for Brawl!"));
|
||||
break;
|
||||
case 3:
|
||||
Bukkit.broadcastMessage(F.main("Fountain", "The Gem Fountain has reached 300%! 3x XP enabled for Brawl!"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateBrawlActive()
|
||||
{
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("PST"));
|
||||
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
if (dayOfWeek == Calendar.FRIDAY || dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY)
|
||||
{
|
||||
_brawlActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_brawlActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBrawlActive()
|
||||
{
|
||||
return _brawlActive;
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package mineplex.core.brawl.fountain;
|
||||
|
||||
import mineplex.core.MiniPlugin;
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.brawl.fountain.command.FountainCommand;
|
||||
import mineplex.core.brawl.fountain.gui.FountainShop;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.common.util.UtilServer;
|
||||
import mineplex.core.common.util.UtilWorld;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.hologram.HologramManager;
|
||||
import mineplex.core.stats.StatsManager;
|
||||
import mineplex.core.updater.UpdateType;
|
||||
import mineplex.core.updater.event.UpdateEvent;
|
||||
import mineplex.serverdata.Region;
|
||||
import mineplex.serverdata.redis.counter.Counter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class FountainManager extends MiniPlugin
|
||||
{
|
||||
private HologramManager _hologramManager;
|
||||
private StatsManager _statsManager;
|
||||
private DonationManager _donationManager;
|
||||
// used so we can inject the brawl shop (only on hub) into fountain code
|
||||
private BrawlShopProvider _brawlShopProvider;
|
||||
|
||||
private Fountain _gemFountain;
|
||||
|
||||
public FountainManager(JavaPlugin plugin, CoreClientManager clientManager, DonationManager donationManager, HologramManager hologramManager, StatsManager statsManager, BrawlShopProvider shopProvider)
|
||||
{
|
||||
super("Counter", plugin);
|
||||
|
||||
_hologramManager = hologramManager;
|
||||
_statsManager = statsManager;
|
||||
_donationManager = donationManager;
|
||||
_brawlShopProvider = shopProvider;
|
||||
|
||||
World world = Bukkit.getWorlds().get(0);//-43.5, 66, -38.5
|
||||
|
||||
int goal = !new File("eu.dat").exists() ? 300000000 : 5000000;
|
||||
_gemFountain = new Fountain(new Location(world, -32.5, 72, -23.5), new Location(world, -43.5, 67, -38.5),
|
||||
C.cGreen + "Gem Fountain", "GemFountain_01", goal, this, clientManager, donationManager, _hologramManager, _statsManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCommands()
|
||||
{
|
||||
addCommand(new FountainCommand(this));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void updateFountainCount(UpdateEvent event)
|
||||
{
|
||||
if (event.getType() != UpdateType.SEC)
|
||||
return;
|
||||
|
||||
_gemFountain.updateBrawlActive();
|
||||
_gemFountain.updateVisuals();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onInteractAtEntity(PlayerInteractAtEntityEvent event)
|
||||
{
|
||||
Entity entity = event.getRightClicked();
|
||||
if (entity.getCustomName() != null && entity.isCustomNameVisible())
|
||||
{
|
||||
if (entity.getCustomName().contains("Weekend Brawl") && getBrawlShopProvider() != null)
|
||||
{
|
||||
getBrawlShopProvider().getBrawlShop().attemptShopOpen(event.getPlayer());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onDamage(EntityDamageByEntityEvent event)
|
||||
{
|
||||
if (!(event.getDamager() instanceof Player))
|
||||
return;
|
||||
|
||||
Entity entity = event.getEntity();
|
||||
if (entity.getCustomName() != null && entity.isCustomNameVisible())
|
||||
{
|
||||
if (entity.getCustomName().contains("Weekend Brawl") && getBrawlShopProvider() != null)
|
||||
{
|
||||
getBrawlShopProvider().getBrawlShop().attemptShopOpen(((Player) event.getDamager()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Fountain getGemFountain()
|
||||
{
|
||||
return _gemFountain;
|
||||
}
|
||||
|
||||
public DonationManager getDonationManager()
|
||||
{
|
||||
return _donationManager;
|
||||
}
|
||||
|
||||
public BrawlShopProvider getBrawlShopProvider()
|
||||
{
|
||||
return _brawlShopProvider;
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package mineplex.core.brawl.fountain;
|
||||
|
||||
import mineplex.core.common.CurrencyType;
|
||||
import mineplex.core.shop.item.SalesPackageBase;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class GemFountainSalesPackage extends SalesPackageBase
|
||||
{
|
||||
public GemFountainSalesPackage(int gems)
|
||||
{
|
||||
super("Add " + gems + " Gems", Material.EMERALD, (byte) 0, new String[] {}, gems, 1);
|
||||
|
||||
CurrencyCostMap.put(CurrencyType.GEM, gems);
|
||||
KnownPackage = false;
|
||||
OneTimePurchaseOnly = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sold(Player player, CurrencyType currencyType)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package mineplex.core.brawl.fountain.command;
|
||||
|
||||
import mineplex.core.brawl.fountain.FountainManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.CurrencyType;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.Callback;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import mineplex.core.server.util.TransactionResponse;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Command to add gems to the fountain
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class AddCommand extends CommandBase<FountainManager>
|
||||
{
|
||||
public AddCommand(FountainManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "add");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
if (args == null || args.length != 1)
|
||||
{
|
||||
help(caller);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
int amount = Integer.parseInt(args[0]);
|
||||
|
||||
Plugin.getDonationManager().purchaseUnknownSalesPackage(new Callback<TransactionResponse>()
|
||||
{
|
||||
@Override
|
||||
public void run(TransactionResponse result)
|
||||
{
|
||||
if (result == TransactionResponse.Success)
|
||||
{
|
||||
Plugin.getGemFountain().increment(caller, amount);
|
||||
UtilPlayer.message(caller, F.main("Fountain", "Added " + F.elem(amount) + " to the fountain!"));
|
||||
}
|
||||
else if (result == TransactionResponse.InsufficientFunds)
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Fountain", "You do not have enough gems!"));
|
||||
}
|
||||
else
|
||||
{
|
||||
UtilPlayer.message(caller, F.main("Fountain", "There was an error processing your request!"));
|
||||
}
|
||||
}
|
||||
}, caller, "GemFountain.Add", CurrencyType.GEM, amount, false);
|
||||
}
|
||||
catch (NumberFormatException ex)
|
||||
{
|
||||
help(caller);
|
||||
}
|
||||
}
|
||||
|
||||
private void help(Player player)
|
||||
{
|
||||
UtilPlayer.message(player, F.help("/fountain add", "<amount>", Rank.DEVELOPER));
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package mineplex.core.brawl.fountain.command;
|
||||
|
||||
import mineplex.core.brawl.fountain.FountainManager;
|
||||
import mineplex.core.command.MultiCommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class FountainCommand extends MultiCommandBase<FountainManager>
|
||||
{
|
||||
public FountainCommand(FountainManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "fountain");
|
||||
|
||||
AddCommand(new AddCommand(plugin));
|
||||
AddCommand(new GuiCommand(plugin));
|
||||
AddCommand(new ResetCommand(plugin));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void Help(Player caller, String[] args)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package mineplex.core.brawl.fountain.command;
|
||||
|
||||
import mineplex.core.brawl.fountain.FountainManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Command to open the fountain gui without speaking to the fountain keeper
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class GuiCommand extends CommandBase<FountainManager>
|
||||
{
|
||||
public GuiCommand(FountainManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "gui");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
Plugin.getGemFountain().openShop(caller);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package mineplex.core.brawl.fountain.command;
|
||||
|
||||
import mineplex.core.brawl.fountain.FountainManager;
|
||||
import mineplex.core.command.CommandBase;
|
||||
import mineplex.core.common.Rank;
|
||||
import mineplex.core.common.util.F;
|
||||
import mineplex.core.common.util.UtilPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Command to reset the fountain
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class ResetCommand extends CommandBase<FountainManager>
|
||||
{
|
||||
public ResetCommand(FountainManager plugin)
|
||||
{
|
||||
super(plugin, Rank.DEVELOPER, "reset");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void Execute(Player caller, String[] args)
|
||||
{
|
||||
Plugin.getGemFountain().reset();
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package mineplex.core.brawl.fountain.gui;
|
||||
|
||||
import mineplex.core.account.CoreClientManager;
|
||||
import mineplex.core.brawl.fountain.Fountain;
|
||||
import mineplex.core.brawl.fountain.FountainManager;
|
||||
import mineplex.core.brawl.fountain.gui.button.FountainAddButton;
|
||||
import mineplex.core.common.CurrencyType;
|
||||
import mineplex.core.common.MaterialData;
|
||||
import mineplex.core.common.util.C;
|
||||
import mineplex.core.donation.DonationManager;
|
||||
import mineplex.core.shop.item.ShopItem;
|
||||
import mineplex.core.shop.page.ShopPageBase;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* @author Shaun Bennett
|
||||
*/
|
||||
public class FountainPage extends ShopPageBase<FountainManager, FountainShop>
|
||||
{
|
||||
private final MaterialData EMPTY_XP = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 7);
|
||||
private final MaterialData XP = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 5);
|
||||
private final MaterialData EMPTY_XP100 = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 5);
|
||||
private final MaterialData XP100 = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 4);
|
||||
private final MaterialData EMPTY_XP200 = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 4);
|
||||
private final MaterialData XP200 = MaterialData.of(Material.STAINED_GLASS_PANE, (byte) 3);
|
||||
private final int[] XP_SLOTS = { 2, 3, 4, 5, 6 };
|
||||
|
||||
private Fountain _fountain;
|
||||
|
||||
public FountainPage(FountainManager plugin, FountainShop shop, CoreClientManager clientManager, DonationManager donationManager, Fountain fountain, Player player)
|
||||
{
|
||||
super(plugin, shop, clientManager, donationManager, "Fountain Keeper", player, 27);
|
||||
|
||||
_fountain = fountain;
|
||||
|
||||
buildPage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildPage()
|
||||
{
|
||||
// Experience Bar
|
||||
long added = _fountain.getAmountAdded(getPlayer());
|
||||
final double fillPercent = _fountain.getFillPercent();
|
||||
String title = ((int)(fillPercent * 100)) + "% Complete";
|
||||
boolean canAdd = fillPercent < 3;
|
||||
|
||||
String unlockMessage;
|
||||
if (fillPercent < 1) unlockMessage = "Reach 100% to unlock Weekend Brawl Game";
|
||||
else if (fillPercent < 2) unlockMessage = "Reach 200% to unlock 2x XP in Brawl";
|
||||
else if (fillPercent < 3) unlockMessage = "Reach 300% to unlock 3x XP in Brawl";
|
||||
else unlockMessage = "All rewards unlocked!";
|
||||
|
||||
String[] lore = new String[] {
|
||||
" ",
|
||||
C.cWhite + unlockMessage,
|
||||
" ",
|
||||
C.cWhite + "You have added " + C.cGreen + added + " Gems"};
|
||||
|
||||
final double percentForEach = 1D / XP_SLOTS.length;
|
||||
double check = percentForEach;
|
||||
|
||||
double flatPercent = fillPercent == 3 ? 1 : fillPercent - ((int) fillPercent);
|
||||
for (int i = 0; i < XP_SLOTS.length; i++)
|
||||
{
|
||||
MaterialData data;
|
||||
if (fillPercent < 1) data = flatPercent >= check ? XP : EMPTY_XP;
|
||||
else if (fillPercent < 2) data = flatPercent >= check ? XP100 : EMPTY_XP100;
|
||||
else data = flatPercent >= check ? XP200 : EMPTY_XP200;
|
||||
ShopItem shopItem = new ShopItem(data.getMaterial(), data.getData(), title,
|
||||
lore, 1, false, false);
|
||||
|
||||
setItem(XP_SLOTS[i], shopItem);
|
||||
check += percentForEach;
|
||||
}
|
||||
|
||||
if (canAdd)
|
||||
{
|
||||
int playerGems = getDonationManager().Get(getPlayer()).GetGems();
|
||||
ShopItem add1 = new ShopItem(Material.EMERALD, "Add 100 Gems", new String[]{}, 1, playerGems < 100, false);
|
||||
ShopItem add2 = new ShopItem(Material.EMERALD, "Add 1,000 Gems", new String[]{}, 64, playerGems < 1000, false);
|
||||
ShopItem add3 = new ShopItem(Material.EMERALD_BLOCK, "Add 10,000 Gems", new String[]{}, 1, playerGems < 10000, false);
|
||||
ShopItem add4 = new ShopItem(Material.EMERALD_BLOCK, "Add 100,000 Gems", new String[]{}, 64, playerGems < 100000, false);
|
||||
// Buttons
|
||||
addButton(19, add1, new FountainAddButton(this, 100));
|
||||
addButton(21, add2, new FountainAddButton(this, 1000));
|
||||
addButton(23, add3, new FountainAddButton(this, 10000));
|
||||
addButton(25, add4, new FountainAddButton(this, 100000));
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user