Implement Message Json and sendRaw methods

This commit is contained in:
ulumulu1510 2015-04-08 06:38:01 +02:00 committed by Olof Larsson
parent 9587b756c9
commit 7f45486600
15 changed files with 1780 additions and 218 deletions

View File

@ -0,0 +1,98 @@
package com.massivecraft.massivecore.adapter;
import java.lang.reflect.Type;
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
import com.massivecraft.massivecore.xlib.gson.JsonElement;
import com.massivecraft.massivecore.xlib.gson.JsonNull;
import com.massivecraft.massivecore.xlib.gson.JsonParseException;
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
public class LowercaseEnumAdapter<T extends Enum<T>> implements JsonDeserializer<T>, JsonSerializer<T>
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
protected final Class<T> clazz;
public Class<T> getClazz() { return this.clazz; }
// -------------------------------------------- //
// INSTANCE & CONSTRUCT
// -------------------------------------------- //
public static <T extends Enum<T>> LowercaseEnumAdapter<T> get(Class<T> clazz)
{
return new LowercaseEnumAdapter<T>(clazz);
}
public LowercaseEnumAdapter(Class<T> clazz)
{
if (clazz == null) throw new IllegalArgumentException("passed clazz param is null");
if ( ! clazz.isEnum()) throw new IllegalArgumentException("passed clazz param must be an enum");
this.clazz = clazz;
}
// -------------------------------------------- //
// OVERRIDE
// -------------------------------------------- //
@Override
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context)
{
if (src == null) return JsonNull.INSTANCE;
return new JsonPrimitive(src.name().toLowerCase());
}
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
{
if (json == null) return null;
T value = getEnumValueFrom(json);
return value;
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public static <T> T[] getEnumValues(Class<T> clazz)
{
if (clazz == null) throw new IllegalArgumentException("passed clazz param is null");
if ( ! clazz.isEnum()) throw new IllegalArgumentException("passed clazz param must be an enum");
T[] ret = clazz.getEnumConstants();
if (ret == null) throw new RuntimeException("failed to retrieve enum constants at runtime");
return ret;
}
public static String getComparable(Enum<?> value)
{
if (value == null) return null;
return getComparable(value.name());
}
public static String getComparable(String string)
{
if (string == null) return null;
return string.toLowerCase();
}
public T getEnumValueFrom(JsonElement json)
{
String jsonString = json.getAsString();
jsonString = getComparable(jsonString);
for (T value : getEnumValues(clazz))
{
if (getComparable(value).equals(jsonString)) return value;
}
return null;
}
}

View File

@ -24,6 +24,7 @@ import com.massivecraft.massivecore.cmd.req.Req;
import com.massivecraft.massivecore.cmd.req.ReqHasPerm; import com.massivecraft.massivecore.cmd.req.ReqHasPerm;
import com.massivecraft.massivecore.collections.MassiveList; import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.PermUtil; import com.massivecraft.massivecore.util.PermUtil;
import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.util.Txt;
@ -1093,6 +1094,45 @@ public class MassiveCommand
return Mixin.msgOne(this.sender, msgs); return Mixin.msgOne(this.sender, msgs);
} }
// CONVENIENCE RAW
public boolean sendRaw(Mson mson)
{
return Mixin.messageRawOne(this.sender, mson);
}
public boolean sendRaw(Mson... mson)
{
return Mixin.messageRawOne(this.sender, mson);
}
public boolean sendRaw(Collection<Mson> mson)
{
return Mixin.messageRawOne(this.sender, mson);
}
// CONVENIENCE MSON
public Mson mson()
{
return Mson.mson();
}
public Mson mson(Object... parts)
{
return Mson.mson(parts);
}
public List<Mson> msons(Object... parts)
{
return Mson.msons(parts);
}
public List<Mson> msons(Collection<?> parts)
{
return Mson.msons(parts);
}
// -------------------------------------------- // // -------------------------------------------- //
// ARGUMENT READERS // ARGUMENT READERS
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -35,7 +35,7 @@ public class MassiveCoreBukkitCommand extends Command implements PluginIdentifia
name, name,
massiveCommand.getDesc(), massiveCommand.getDesc(),
massiveCommand.getUseageTemplate(), massiveCommand.getUseageTemplate(),
new ArrayList<String>() // We don't use aliases Collections.<String>emptyList() // We don't use aliases
); );
this.massiveCommand = massiveCommand; this.massiveCommand = massiveCommand;
} }

View File

@ -5,11 +5,12 @@ import java.util.Collection;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.Predictate; import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.mson.Mson;
public interface MessageMixin public interface MessageMixin
{ {
// -------------------------------------------- // // -------------------------------------------- //
// RAW MESSAGE // MESSAGE
// -------------------------------------------- // // -------------------------------------------- //
// All // All
@ -28,7 +29,7 @@ public interface MessageMixin
public boolean messageOne(Object sendeeObject, Collection<String> messages); public boolean messageOne(Object sendeeObject, Collection<String> messages);
// -------------------------------------------- // // -------------------------------------------- //
// PARSE MESSAGE // PARSE MSG
// -------------------------------------------- // // -------------------------------------------- //
// All // All
@ -46,4 +47,23 @@ public interface MessageMixin
public boolean msgOne(Object sendeeObject, String msg, Object... args); public boolean msgOne(Object sendeeObject, String msg, Object... args);
public boolean msgOne(Object sendeeObject, Collection<String> msgs); public boolean msgOne(Object sendeeObject, Collection<String> msgs);
// -------------------------------------------- //
// RAW MESSAGE
// -------------------------------------------- //
// All
public boolean messageRawAll(Mson mson);
public boolean messageRawAll(Mson... msons);
public boolean messageRawAll(Collection<Mson> msons);
// Predictate
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson mson);
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson... msons);
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Collection<Mson> msons);
// One
public boolean messageRawOne(Object sendeeObject, Mson mson);
public boolean messageRawOne(Object sendeeObject, Mson... msons);
public boolean messageRawOne(Object sendeeObject, Collection<Mson> msons);
} }

View File

@ -2,24 +2,25 @@ package com.massivecraft.massivecore.mixin;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.Predictate; import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.util.MUtil; import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.Txt; import com.massivecraft.massivecore.util.Txt;
public abstract class MessageMixinAbstract implements MessageMixin public abstract class MessageMixinAbstract implements MessageMixin
{ {
// -------------------------------------------- // // -------------------------------------------- //
// RAW MESSAGE // MESSAGE
// -------------------------------------------- // // -------------------------------------------- //
// All // All
@Override @Override
public boolean messageAll(String message) public boolean messageAll(String message)
{ {
return this.messageAll(Arrays.asList(message)); return this.messageAll(Collections.singleton(message));
} }
@Override @Override
@ -32,7 +33,7 @@ public abstract class MessageMixinAbstract implements MessageMixin
@Override @Override
public boolean messagePredictate(Predictate<CommandSender> predictate, String message) public boolean messagePredictate(Predictate<CommandSender> predictate, String message)
{ {
return this.messagePredictate(predictate, MUtil.list(message)); return this.messagePredictate(predictate, Collections.singleton(message));
} }
@Override @Override
@ -45,7 +46,7 @@ public abstract class MessageMixinAbstract implements MessageMixin
@Override @Override
public boolean messageOne(Object sendeeObject, String message) public boolean messageOne(Object sendeeObject, String message)
{ {
return this.messageOne(sendeeObject, MUtil.list(message)); return this.messageOne(sendeeObject, Collections.singleton(message));
} }
@Override @Override
@ -55,7 +56,7 @@ public abstract class MessageMixinAbstract implements MessageMixin
} }
// -------------------------------------------- // // -------------------------------------------- //
// PARSE MESSAGE // PARSE MSG
// -------------------------------------------- // // -------------------------------------------- //
// They are all in abstract! // They are all in abstract!
@ -116,4 +117,47 @@ public abstract class MessageMixinAbstract implements MessageMixin
return this.messageOne(sendeeObject, Txt.parse(msgs)); return this.messageOne(sendeeObject, Txt.parse(msgs));
} }
// -------------------------------------------- //
// RAW MESSAGE
// -------------------------------------------- //
// All
@Override
public boolean messageRawAll(Mson mson)
{
return this.messageRawAll(Arrays.asList(mson));
}
@Override
public boolean messageRawAll(Mson... msons)
{
return this.messageRawAll(Arrays.asList(msons));
}
// Predictate
@Override
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson mson)
{
return this.messageRawPredictate(predictate, Arrays.asList(mson));
}
@Override
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson... msons)
{
return this.messageRawPredictate(predictate, Arrays.asList(msons));
}
// One
@Override
public boolean messageRawOne(Object sendeeObject, Mson mson)
{
return this.messageRawOne(sendeeObject, Arrays.asList(mson));
}
@Override
public boolean messageRawOne(Object sendeeObject, Mson... msons)
{
return this.messageRawOne(sendeeObject, Arrays.asList(msons));
}
} }

View File

@ -3,9 +3,12 @@ package com.massivecraft.massivecore.mixin;
import java.util.Collection; import java.util.Collection;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.massivecraft.massivecore.Predictate; import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.PacketUtil;
public class MessageMixinDefault extends MessageMixinAbstract public class MessageMixinDefault extends MessageMixinAbstract
{ {
@ -54,4 +57,56 @@ public class MessageMixinDefault extends MessageMixinAbstract
return true; return true;
} }
// Raw message aka. JsonString
@Override
public boolean messageRawAll(Collection<Mson> msons)
{
if (msons == null) return false;
for (CommandSender sender : IdUtil.getOnlineSenders())
{
this.messageRawOne(sender, msons);
}
return true;
}
@Override
public boolean messageRawPredictate(Predictate<CommandSender> predictate, Collection<Mson> msons)
{
if (predictate == null) return false;
if (msons == null) return false;
for (CommandSender sender : IdUtil.getOnlineSenders())
{
if ( ! predictate.apply(sender)) continue;
this.messageRawOne(sender, msons);
}
return true;
}
@Override
public boolean messageRawOne(Object sendeeObject, Collection<Mson> msons)
{
if (msons == null) return false;
CommandSender sender = IdUtil.getSender(sendeeObject);
if (sender == null) return false;
if (sender instanceof Player && PacketUtil.isRawAvailable())
{
Player player = (Player) sender;
for (Mson mson : msons)
{
PacketUtil.sendRaw(player, mson.toRaw());
}
}
else
{
for (Mson mson : msons)
{
sender.sendMessage(mson.toPlain());
}
}
return true;
}
} }

View File

@ -14,6 +14,7 @@ import org.bukkit.permissions.Permissible;
import com.massivecraft.massivecore.Predictate; import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave; import com.massivecraft.massivecore.event.EventMassiveCorePlayerLeave;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.ps.PS; import com.massivecraft.massivecore.ps.PS;
import com.massivecraft.massivecore.teleport.Destination; import com.massivecraft.massivecore.teleport.Destination;
@ -312,6 +313,48 @@ public class Mixin
return getMessageMixin().msgOne(senderObject, msgs); return getMessageMixin().msgOne(senderObject, msgs);
} }
// RAW All
public static boolean messageRawAll(Mson mson)
{
return getMessageMixin().messageRawAll(mson);
}
public static boolean messageRawAll(Mson... msons)
{
return getMessageMixin().messageRawAll(msons);
}
public static boolean messageRawAll(Collection<Mson> msons)
{
return getMessageMixin().messageRawAll(msons);
}
// RAW Predictate
public static boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson mson)
{
return getMessageMixin().messageRawPredictate(predictate, mson);
}
public static boolean messageRawPredictate(Predictate<CommandSender> predictate, Mson... msons)
{
return getMessageMixin().messageRawPredictate(predictate, msons);
}
public static boolean messageRawPredictate(Predictate<CommandSender> predictate, Collection<Mson> msons)
{
return getMessageMixin().messageRawPredictate(predictate, msons);
}
// RAW One
public static boolean messageRawOne(Object senderObject, Mson mson)
{
return getMessageMixin().messageRawOne(senderObject, mson);
}
public static boolean messageRawOne(Object senderObject, Mson... msons)
{
return getMessageMixin().messageRawOne(senderObject, msons);
}
public static boolean messageRawOne(Object senderObject, Collection<Mson> msons)
{
return getMessageMixin().messageRawOne(senderObject, msons);
}
// -------------------------------------------- // // -------------------------------------------- //
// STATIC EXPOSE: TITLE // STATIC EXPOSE: TITLE
// -------------------------------------------- // // -------------------------------------------- //

View File

@ -3,7 +3,7 @@ package com.massivecraft.massivecore.mixin;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.IdUtil;
import com.massivecraft.massivecore.util.TitleUtil; import com.massivecraft.massivecore.util.PacketUtil;
public class TitleMixinDefault extends TitleMixinAbstract public class TitleMixinDefault extends TitleMixinAbstract
{ {
@ -29,13 +29,13 @@ public class TitleMixinDefault extends TitleMixinAbstract
if (titleSub == null) titleSub = ""; if (titleSub == null) titleSub = "";
if (titleMain == null) titleMain = ""; if (titleMain == null) titleMain = "";
return TitleUtil.sendTitle(player, ticksIn, ticksStay, ticksOut, titleMain, titleSub); return PacketUtil.sendTitle(player, ticksIn, ticksStay, ticksOut, titleMain, titleSub);
} }
@Override @Override
public boolean isTitlesAvailable() public boolean isTitlesAvailable()
{ {
return TitleUtil.isAvailable(); return PacketUtil.isTitleAvailable();
} }
} }

View File

@ -0,0 +1,108 @@
package com.massivecraft.massivecore.mson;
import static com.massivecraft.massivecore.mson.Mson.mson;
import java.util.List;
import org.bukkit.ChatColor;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.util.Txt;
public class ATest
{
public static void main(String[] args)
{
try
{
// Test getMsonFrom
Mson ofMson = mson(new Mson().text("hello"));
System.out.println("ofMson:" + ofMson); // Success
Mson ofString = mson("hello");
System.out.println("ofString:" + ofString); // Success
Mson ofCollection = mson(new MassiveList<String>("hello ", "you!"));
System.out.println("ofCollection:" + ofCollection); // Success
// Test children
Mson child = mson("test").color(ChatColor.BLUE)
.addChild(" test2").link("www.massivecraft.com")
.addChild(" test3 ")
.addChildren("this ", "is only ", "one way to do it!")
.root()
.tooltip("Holy moly!");
System.out.println("child:" + child.root()); // Success
// Test siblings
Mson sibling = mson(
"test",
" test2",
" test3",
new Mson().text(" Test4, children: ").addChild("Child1 ")
.addSiblings("Sibling 1 ", "Sibling 2 ", "Sibling 3 ")
.addSibling("Sibling 4").root()
).tooltip("Holy moly!");
System.out.println("sibling:" + sibling.root()); // Success
// Test fromParsedMessage
Mson parsed = Mson.fromParsedMessage(Txt.parse("white <i>in<em>fo <b><em><bold>bad <lime>green"));
System.out.println("parsed:" + parsed); // Success
Mson parsed2 = Mson.parse("white <i>in<em>fo <b><bold>bad <lime>green");
System.out.println("parsed2:" + parsed2.toRaw()); // Success
Mson parseFormat = Mson.parse("<i>insert here %s whatever <g> you <b>%s <g>could wish for!", "!1337!", "herpi derp");
System.out.println("parseFormat:" + parseFormat); // Success
// Test format
Mson format = Mson.format("Just a %s simple string! :)", "very");
System.out.println("format:" + format); // Success
// Test split
List<Mson> split = format.split(Txt.REGEX_WHITESPACE.toString());
System.out.println("split:" + mson(split)); // Success
/*
* Test replace
*/
Mson charr = mson("1 2 3 4 5 6 1 7 tests").addChild(" 01010101").root().replace('1', '0');
System.out.println("char:" + charr); // Success
Mson sequence = mson("1 2 3 4 5 6 1 7 tests").addChild(" 01010101").root().replace("1", "0");
System.out.println("sequence:" + sequence); // Success
Mson regex = mson("1 2 3 4 5 6 1 7 tests").addChild(" 01010101").root().replaceAll("1", "0");
System.out.println("regex:" + regex); // Success
//Mson replaceFirst = Mson.of("1 2 3 4 5 6 1 7 tests").addChild(" 01010101").getRoot().replaceFirst("1", "0");
//System.out.println("replaceFirst:" + replaceFirst.toRaw()); // Success
/*
* Test special replaceAll
*/
// replace string mson
Mson replaceAll1 = mson("1 2 3 4 5 6 1 7 tests").color(ChatColor.BLUE).addChild(" 1+1+1").addChild("herpiderp").root().replaceAll("1", mson("0"));
System.out.println("replaceAll1:" + replaceAll1.root()); // Success
Mson overload = mson("hello").addChild("hello").addChild("hello").root().replaceAll("hello", mson("lol"));
System.out.println("overload:" + overload.root()); // Success
Mson toReplace = new Mson().text("hallo");
// replace mson mson
Mson replaceAll2 = mson("1 2 3 4 5 6 7 tests").addChild(toReplace).addSibling(" miep").root().replaceAll(toReplace, mson("tests"));
System.out.println("replaceAll2:" + replaceAll2.root()); // Success
Mson overload2 = mson("1 2 3 4 5 6 7 tests").addChild("hallo").addChild("hallo").addChild("hallo").addSibling(" miep").root().replaceAll(mson("hallo"), mson("tests"));
System.out.println("overload2:" + overload2.root()); // Success
}
catch(Throwable t)
{
t.printStackTrace();
}
}
}

View File

@ -0,0 +1,897 @@
package com.massivecraft.massivecore.mson;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.regex.Pattern;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import com.massivecraft.massivecore.Predictate;
import com.massivecraft.massivecore.adapter.LowercaseEnumAdapter;
import com.massivecraft.massivecore.collections.MassiveList;
import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.Txt;
import com.massivecraft.massivecore.xlib.gson.Gson;
import com.massivecraft.massivecore.xlib.gson.GsonBuilder;
import com.massivecraft.massivecore.xlib.gson.JsonElement;
public class Mson implements Serializable
{
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
public static final Pattern PARSE_PREFIX = Pattern.compile("\u00A7");
// -------------------------------------------- //
// GSON
// -------------------------------------------- //
public static final Gson GSON = new GsonBuilder()
.disableHtmlEscaping()
.registerTypeAdapter(ChatColor.class, LowercaseEnumAdapter.get(ChatColor.class))
.registerTypeAdapter(MsonEventAction.class, LowercaseEnumAdapter.get(MsonEventAction.class))
.create();
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
// FIELD: The Msons text
// A parents text can't be null, then Mojang throws an exception.
// It does not make sense for something which doesn't have extras
// to not have text, because then it doesn't show up at all.
protected String text = "";
public String text() { return this.text; }
public Mson text(String text) { this.text = Objects.requireNonNull(text); return this; }
public boolean textHas() { return ! this.text().isEmpty(); }
// FIELD: Color of the mson
protected ChatColor color = null;
public ChatColor color() { return this.color; }
public ChatColor colorEffective() { return color() != null ? color() : colorInherited(); }
public ChatColor colorInherited() { return parentHas() ? parent().colorEffective() : null; }
public Mson color(ChatColor color)
{
if (color != null && ! color.isColor()) throw new IllegalArgumentException("color must be a color");
this.color = color;
return this;
}
// FIELD: bold
protected Boolean bold = null;
public Boolean bold() { return bold; }
public Mson bold(Boolean bold) { this.bold = bold; return this; }
public boolean boldEffective() { return bold() != null ? bold() : boldInherited(); }
public boolean boldInherited() { return parentHas() && parent().boldEffective(); }
// FIELD: italic
protected Boolean italic = null;
public Boolean italic() { return this.italic; }
public Mson italic(Boolean italic) { this.italic = italic; return this; }
public boolean italicEffective() { return italic() != null ? italic() : italicInherited(); }
protected boolean italicInherited() { return parentHas() && parent().italicEffective(); }
// FIELD: underlined
protected Boolean underlined = null;
public Boolean underlined() { return this.underlined; }
public Mson underlined(Boolean underlined) { this.underlined = underlined; return this; }
public boolean underlinedEffective() { return italic() != null ? italic() : italicInherited(); }
protected boolean underlinedInherited() { return parentHas() && parent().underlinedEffective(); }
// FIELD: strikethrough
protected Boolean strikethrough = null;
public Boolean strikethrough() { return this.strikethrough; }
public Mson striketrhough(Boolean strikethrough) { this.strikethrough = strikethrough; return this; }
public boolean strikethroughEffective() { return strikethrough() != null ? strikethrough() : strikethroughInherited(); }
protected boolean strikethroughInherited() { return parentHas() && parent().strikethroughEffective(); }
// FIELD: obfuscated
protected Boolean obfuscated = null;
public Boolean obfuscated() { return this.obfuscated; }
public Mson obfuscated(Boolean obfuscated) { this.obfuscated = obfuscated; return this; }
public boolean obfuscatedEffective() { return obfuscated() != null ? obfuscated() : obfuscatedInherited(); }
protected boolean obfuscatedInherited() { return parentHas() && parent().obfuscatedEffective(); }
// FIELD: The Events which happen when you click, hover over or shift-click the message
protected MsonEvent clickEvent = null;
public MsonEvent clickEvent() { return this.clickEvent; }
public MsonEvent clickEventEffective() { return clickEvent() != null ? clickEvent() : clickEventInherited(); }
protected MsonEvent clickEventInherited() { return this.parentHas() ? this.parent().clickEventEffective() : null; }
public Mson clickEvent(MsonEvent clickEvent)
{
if (clickEvent != null && ! clickEvent.isClickEvent()) throw new IllegalArgumentException("clickEvent may not be hoverEvent");
this.clickEvent = clickEvent;
return this;
}
protected MsonEvent hoverEvent = null;
public MsonEvent hoverEvent() { return this.hoverEvent; }
public MsonEvent hoverEventEffective() { return hoverEvent() != null ? hoverEvent() : hoverEventInherited(); }
protected MsonEvent hoverEventInherited() { return this.parentHas() ? this.parent().hoverEventEffective() : null; }
public Mson hoverEvent(MsonEvent hoverEvent)
{
if (hoverEvent != null && ! hoverEvent.isHoverEvent()) throw new IllegalArgumentException("hoverEvent may not be clickEvent");
this.hoverEvent = hoverEvent;
return this;
}
protected String insertionString = null;
public String insertionString() { return this.insertionString; }
public String insertionStringEffective() { return insertionString() != null ? insertionString() : insertionStringInherited(); }
public Mson insertionString(String insertionString) { this.insertionString = insertionString; return this; }
protected String insertionStringInherited() { return this.parentHas() ? this.parent().insertionStringEffective() : null; }
// The other parts of the message
protected List<Mson> extra = null;
public List<Mson> extra() { return this.extra; }
public Mson extra(List<Mson> extra) { this.extra = extra; return this; }
public boolean extraHas() { return this.extra() != null; }
public List<Mson> extraCreative()
{
if ( ! this.extraHas()) this.extra(new MassiveList<Mson>());
return this.extra();
}
// Parent & Root
protected transient Mson parent = null;
public Mson parent() { return this.parent; }
public Mson parent(Mson parent) { this.parent = parent; return this; }
public boolean parentHas() { return this.parent() != null; }
public Mson parentCreative()
{
if ( ! this.parentHas()) this.parent(new Mson());
return this.parent();
}
public boolean isRoot() { return this.parent() == null; }
public Mson root()
{
Mson root = this;
while (true)
{
Mson parent = root.parent();
if (parent == null) break;
root = parent;
}
return root;
}
// -------------------------------------------- //
// CONVENIENCE MSON EVENT
// -------------------------------------------- //
public Mson link(String link) { this.clickEvent(MsonEvent.openUrl(link)); return this; }
public Mson suggest(String replace) { this.clickEvent(MsonEvent.replace(replace)); return this; }
public Mson command(String command) { this.clickEvent(MsonEvent.performCmd(command)); return this; }
public Mson tooltip(String tooltip) { this.hoverEvent(MsonEvent.hoverText(text)); return this; }
public Mson tooltip(String... tooltip) { this.hoverEvent(MsonEvent.hoverText(text)); return this; }
public Mson tooltip(Collection<String> tooltip) { this.hoverEvent(MsonEvent.hoverText(text)); return this; }
public Mson tooltipParse(String tooltip) { this.hoverEvent(MsonEvent.hoverTextParse(text)); return this; }
public Mson tooltipParse(String... tooltip) { this.hoverEvent(MsonEvent.hoverTextParse(text)); return this; }
public Mson tooltipParse(Collection<String> tooltip) { this.hoverEvent(MsonEvent.hoverTextParse(text)); return this; }
// -------------------------------------------- //
// CONVENIENCE STYLE
// -------------------------------------------- //
public Mson style(ChatColor... styles)
{
for (ChatColor style : styles)
{
this.style(style);
}
return this;
}
public Mson style(ChatColor style)
{
if (style == ChatColor.RESET) return this.removeStyles();
if (style == ChatColor.BOLD) return this.bold(true);
if (style == ChatColor.ITALIC) return this.italic(true);
if (style == ChatColor.UNDERLINE) return this.underlined(true);
if (style == ChatColor.STRIKETHROUGH) return this.striketrhough(true);
if (style == ChatColor.MAGIC) return this.obfuscated(true);
if (style.isColor()) return this.color(color);
throw new UnsupportedOperationException(style.name());
}
public Mson removeStyles()
{
// NOTE: We can't use null.
// Since we want to override color and format in parents.
this.color = ChatColor.WHITE;
this.bold = false;
this.italic = false;
this.underlined = false;
this.strikethrough = false;
this.obfuscated = false;
return this;
}
// -------------------------------------------- //
// BUILD TREE
// -------------------------------------------- //
// Child, called on parent or root
public Mson addChild(Object child)
{
if (child == null) throw new NullPointerException("child");
Mson mson = Mson.mson(child);
List<Mson> extra = this.extraCreative();
mson.parent(this);
extra.add(mson);
return mson; // Return child
}
public Mson addChildren(Object... children)
{
if (children == null) throw new NullPointerException("children");
for (Object part : children)
{
this.addChild(part);
}
return this; // Return this
}
// Sibling, normally called on child
public Mson addSibling(Object sibling)
{
if (sibling == null) throw new NullPointerException("sibling");
Mson parent = this.parentCreative();
return parent.addChild(sibling); // Return sibling
}
public Mson addSiblings(Object... siblings)
{
if (siblings == null) throw new NullPointerException("siblings");
Mson parent = this.parentCreative();
if ( ! parent.equals(this.parent())) this.parent(parent);
parent.addChildren(siblings);
return this; // Return this
}
// -------------------------------------------- //
// SIMPLE CLEAN
// -------------------------------------------- //
// These methods, exist to clean up after mistakes.
// So they are very forgiving.
public boolean isEmpty()
{
// It has text, not empty.
if (this.textHas()) return false;
if (this.extraHas())
{
for (Mson extra : this.extra())
{
// It is null. So kinda empty.
if (extra == null) continue;
// It is empty
if (extra.isEmpty()) continue;
// It was not empty.
return false;
}
}
// We are empty.
return true;
}
// Detaches uneccessary extras.
public Mson simpleClean()
{
if ( ! this.extraHas()) return this;
if (this.extra().isEmpty())
{
this.extra(null);
return this;
}
for (ListIterator<Mson> it = this.extra().listIterator(); it.hasNext();)
{
Mson extra = it.next();
if (extra == null)
{
it.remove();
continue;
}
if (extra.isEmpty())
{
extra.parent(null);
it.remove();
continue;
}
extra.simpleClean();
}
return this;
}
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
public Mson()
{
}
public static Mson mson()
{
return new Mson();
}
public static Mson mson(Object... parts)
{
return Mson.getMson(parts);
}
private static Mson getMson(Object part)
{
if (part == null) throw new NullPointerException("part");
if (part instanceof Mson)
{
return (Mson) part;
}
else if (part instanceof String)
{
String text = (String) part;
return mson().text(text);
}
else if (part instanceof Collection<?>)
{
Collection<?> parts = (Collection<?>) part;
List<Mson> msons = Mson.msons(parts);
if (msons.isEmpty()) return mson();
if (msons.size() == 1) return msons.get(0);
return mson().extra(msons);
}
else if (part instanceof Object[])
{
Object[] parts = (Object[]) part;
return getMson(Arrays.asList(parts));
}
else
{
throw new IllegalArgumentException("We only accept Strings, Msons, Collections and Arrays");
}
}
public static List<Mson> msons(Object... parts)
{
return msons(Arrays.asList(parts));
}
public static List<Mson> msons(Collection<?> parts)
{
if (parts == null) throw new NullPointerException("parts");
List<Mson> msons = new MassiveList<Mson>();
for (Object part : parts)
{
msons.add(getMson(part));
}
return msons;
}
public static Mson fromParsedMessage(String message)
{
if (message == null) throw new NullPointerException("message");
// Everything must have a color.
// Because when we split, we assume that each part starts with a color code.
// Here we assure it starts with one.
message = ensureStartsWithColorCode(message);
// We split at color/format change.
String[] parts = PARSE_PREFIX.split(message);
// Since we start with a color, the first element will be empty.
// We don't want that empty element.
parts = Arrays.copyOfRange(parts, 1, parts.length);
List<Mson> msons = new ArrayList<Mson>();
ChatColor latestColor = null;
Boolean bold = null;
Boolean italic = null;
Boolean underlined = null;
Boolean strikethrough = null;
Boolean obfuscated = null;
for (String part : parts)
{
ChatColor color = ChatColor.getByChar(part.charAt(0));
String text = part.substring(1);
if ((color != null && color.isColor()) || color == ChatColor.RESET)
{
latestColor = color;
bold = null;
italic = null;
underlined = null;
strikethrough = null;
obfuscated = null;
}
if (color == ChatColor.RESET) latestColor = null;
else if (color == ChatColor.BOLD) bold = true;
else if (color == ChatColor.ITALIC) italic = true;
else if (color == ChatColor.UNDERLINE) underlined = true;
else if (color == ChatColor.STRIKETHROUGH) strikethrough = true;
else if (color == ChatColor.MAGIC) obfuscated = true;
// Don't add empty msons.
if (text.isEmpty()) continue;
Mson mson = new Mson()
.text(text)
.color(latestColor)
.bold(bold)
.italic(italic)
.underlined(underlined)
.striketrhough(strikethrough)
.obfuscated(obfuscated);
msons.add(mson);
}
return Mson.mson(msons);
}
private static String ensureStartsWithColorCode(String message)
{
if ( ! message.startsWith("\u00A7"))
{
message = ChatColor.RESET + message;
}
return message;
}
// Parse redirects, convert to Mson directly
public static Mson parse(String string) { return Mson.fromParsedMessage(Txt.parse(string)); }
public static Mson parse(String format, Object... args) { return Mson.fromParsedMessage(Txt.parse(format, args)); }
public static Mson format(String format, Object... args)
{
return Mson.mson(String.format(format, args));
}
public Mson copy()
{
Mson copy = new Mson()
.text(this.text)
.color(this.color)
.bold(this.bold)
.italic(this.italic)
.underlined(this.underlined)
.striketrhough(this.strikethrough)
.obfuscated(this.obfuscated)
.insertionString(this.insertionString)
.clickEvent(this.clickEvent)
.hoverEvent(this.hoverEvent);
if (this.extraHas())
{
List<Mson> extras = new MassiveList<Mson>(this.extra.size());
for (Mson extra : this.extra)
{
Mson extraCopy = extra.copy();
extraCopy.parent(copy);
extras.add(extraCopy);
}
copy.extra(extras);
}
return copy;
}
private Mson copyFormatAndBehaviour(Mson ancestor)
{
if (ancestor == null) throw new NullPointerException("ancestor");
this.color(ancestor.color());
this.bold(ancestor.bold());
this.italic(ancestor.italic());
this.underlined(ancestor.underlined());
this.striketrhough(ancestor.strikethrough());
this.obfuscated(ancestor.obfuscated());
this.hoverEvent(ancestor.hoverEvent());
this.clickEvent(ancestor.clickEvent());
this.insertionString(ancestor.insertionString());
return this;
}
// -------------------------------------------- //
// STRING LIKE METHODS
// -------------------------------------------- //
// Split
public List<Mson> split(String regex)
{
return this.split(regex, 0);
}
public List<Mson> split(String regex, int limit)
{
return split(Pattern.compile(regex), limit);
}
public List<Mson> split(Pattern pattern)
{
return this.split(pattern, 0);
}
public List<Mson> split(Pattern pattern, int limit)
{
if (pattern == null) throw new NullPointerException("pattern");
boolean limited = (limit == 0 ? false : true);
List<Mson> msons = new MassiveList<Mson>();
String[] splited = pattern.split(this.text(), limit);
if (splited.length == 1) return new MassiveList<Mson>(this);
for (String string : splited)
{
if (string.isEmpty()) continue;
Mson part = new Mson().text(string);
part.copyFormatAndBehaviour(this);
msons.add(part);
}
int size = msons.size();
for (Mson part : this.extraCreative())
{
if (limited)
{
limit -= size;
if (limit <= 0) break;
}
List<Mson> innerMsons = part.split(pattern, limit);
msons.addAll(innerMsons);
size = innerMsons.size();
}
return msons;
}
// Replace
public Mson replace(char oldChar, char newChar)
{
this.text(this.text().replace(oldChar, newChar));
if (this.extraHas())
{
for (Mson part : this.extra())
{
part.replace(oldChar, newChar);
}
}
return this;
}
public Mson replace(CharSequence replace, CharSequence replacement)
{
if (replace == null) throw new NullPointerException("replace");
if (replacement == null) throw new NullPointerException("replacement");
this.text(this.text().replace(replace, replacement));
if (this.extraHas())
{
for (Mson part : this.extra())
{
part.replace(replace, replacement);
}
}
return this;
}
public Mson replaceAll(String regex, String replacement)
{
if (regex == null) throw new NullPointerException("regex");
if (replacement == null) throw new NullPointerException("replacement");
this.text(this.text().replaceAll(regex, replacement));
if (this.extraHas())
{
for (Mson part : this.extra())
{
part.replaceAll(regex, replacement);
}
}
return this;
}
// Special replace all
public Mson replaceAll(String regex, Mson replacement)
{
return replaceAll(Pattern.compile(regex), replacement);
}
public Mson replaceAll(Pattern pattern, Mson replacement)
{
if (pattern == null) throw new NullPointerException("pattern");
if (replacement == null) throw new NullPointerException("replacement");
// We don't want the same object to eventually be part of itself
Mson repCopy = replacement.copy();
String text = (this.text() + " "); // Prepare text
// Split the string of this msons text and create an iterator
// and create the list of mson with the replacements in between ...
List<Mson> msons = new MassiveList<Mson>();
for (ListIterator<String> it = Arrays.asList(pattern.split(text)).listIterator(); it.hasNext();)
{
String string = it.next();
// string might be empty, we don't want these empty msons
if ( ! string.isEmpty())
{
Mson part = Mson.mson(string);
msons.add(part);
// Delete security spacing at the last string
if ( ! it.hasNext()) part.text(string.substring(0, string.length() - 1));
}
// In between every part, add in replacement
if (it.hasNext()) msons.add(repCopy);
}
// ... and forge back together, unless the whole text is "replaced", then set it to be the replacement itself.
Mson mson;
if ( ! msons.isEmpty())
{
mson = msons.get(0).copy();
msons.remove(0);
mson.copyFormatAndBehaviour(this);
if ( ! msons.isEmpty()) mson.extra(msons);
}
else
{
mson = repCopy;
}
mson.parent(this.parent());
// If there is no extra, return here...
List<Mson> extra = this.extra();
if (extra == null) return mson;
// ... otherwise iterate over the extra and modify it.
for (ListIterator<Mson> it = extra.listIterator(); it.hasNext();)
{
Mson part = it.next();
int index = extra.indexOf(part);
part = part.replaceAll(pattern, replacement);
part.parent(mson);
extra.set(index, part);
}
// If the current mson has any extra ...
List<Mson> extras = mson.extra();
if( extras != null)
{
// ... apply tree structure again ...
extras.get(extras.size() - 1).extra(extra);
}
else
{
// ... set the extra directly ...
mson.extra(extra);
}
mson.simpleClean();
// ... and return recreated mson
return mson;
}
public Mson replaceAll(Mson replace, Mson replacement)
{
if (replace == null) throw new NullPointerException("replace");
if (replacement == null) throw new NullPointerException("replacement");
// We don't want the same object to eventually be part of itself
Mson repCopy = replacement.copy();
Mson mson = this;
List<Mson> extra = this.extra();
if (mson.equals(replace))
{
mson = repCopy;
mson.parent(this.parent());
if (extra != null) mson.extraCreative().addAll(extra);
}
if (extra == null) return mson;
for (ListIterator<Mson> it = extra.listIterator(); it.hasNext();)
{
int index = it.nextIndex();
Mson part = it.next();
part = part.replaceAll(replace, replacement);
part.parent(mson);
extra.set(index, part);
}
mson.extra(extra);
return mson;
}
// -------------------------------------------- //
// SEND
// -------------------------------------------- //
// All
public boolean sendAll()
{
return Mixin.messageRawAll(this);
}
// Predictate
public boolean sendPredictate(Predictate<CommandSender> predictate)
{
return Mixin.messageRawPredictate(predictate, this);
}
// One
public boolean sendOne(Object senderObject)
{
return Mixin.messageRawOne(senderObject, this);
}
// -------------------------------------------- //
// TO JSON, RAW, PLAIN & STRING
// -------------------------------------------- //
public JsonElement rootToJson() { return this.root().toJson(); }
public JsonElement toJson()
{
return GSON.toJsonTree(this);
}
public String rootToRaw() { return this.root().toRaw(); }
public String toRaw()
{
return this.toJson().toString();
}
public String toPlain()
{
StringBuilder ret = new StringBuilder();
ret.append(toPlainSimple(this));
if (this.extraHas())
{
for (Mson part : this.extra())
{
ret.append(ChatColor.RESET);
ret.append(part.toPlain());
}
}
return ret.toString();
}
// Turns a single mson (without it's children) into plain text.
protected static String toPlainSimple(Mson mson)
{
if (mson.textHas())
{
// Color must be put in BEFORE formatting.
// http://minecraft.gamepedia.com/Formatting_codes#Formatting_codes
StringBuilder ret = new StringBuilder(mson.text().length());
if (mson.colorEffective() != null) ret.append(mson.colorEffective());
if (mson.boldEffective()) ret.append(ChatColor.BOLD);
if (mson.italicEffective()) ret.append(ChatColor.ITALIC);
if (mson.underlinedEffective()) ret.append(ChatColor.UNDERLINE);
if (mson.strikethroughEffective()) ret.append(ChatColor.STRIKETHROUGH);
if (mson.obfuscatedEffective()) ret.append(ChatColor.MAGIC);
ret.append(mson.text());
return ret.toString();
}
return "";
}
@Override
public String toString()
{
return this.toRaw();
}
// -------------------------------------------- //
// EQUALS AND HASHCODE
// -------------------------------------------- //
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(this.text);
result = prime * result + Objects.hashCode(this.color);
result = prime * result + Objects.hashCode(this.bold);
result = prime * result + Objects.hashCode(this.italic);
result = prime * result + Objects.hashCode(this.obfuscated);
result = prime * result + Objects.hashCode(this.strikethrough);
result = prime * result + Objects.hashCode(this.underlined);
result = prime * result + Objects.hashCode(this.clickEvent);
result = prime * result + Objects.hashCode(this.hoverEvent);
result = prime * result + Objects.hashCode(this.insertionString);
result = prime * result + Objects.hashCode(this.extra);
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if ( ! (obj instanceof Mson)) return false;
Mson that = (Mson) obj;
if ( ! MUtil.equals(this.text, that.text)) return false;
if ( ! MUtil.equals(this.color, that.color)) return false;
if ( ! MUtil.equals(this.bold, that.bold)) return false;
if ( ! MUtil.equals(this.italic, that.italic)) return false;
if ( ! MUtil.equals(this.obfuscated, that.obfuscated)) return false;
if ( ! MUtil.equals(this.strikethrough, that.strikethrough)) return false;
if ( ! MUtil.equals(this.underlined, that.underlined)) return false;
if ( ! MUtil.equals(this.clickEvent, that.clickEvent)) return false;
if ( ! MUtil.equals(this.hoverEvent, that.hoverEvent)) return false;
if ( ! MUtil.equals(this.insertionString, that.insertionString)) return false;
if ( ! MUtil.equals(this.extra, that.extra)) return false;
return true;
}
}

View File

@ -0,0 +1,129 @@
package com.massivecraft.massivecore.mson;
import java.io.Serializable;
import java.util.Collection;
import java.util.Objects;
import com.massivecraft.massivecore.util.MUtil;
import com.massivecraft.massivecore.util.Txt;
public class MsonEvent implements Serializable
{
// -------------------------------------------- //
// CONSTANTS
// -------------------------------------------- //
private static final long serialVersionUID = 1L;
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
protected final MsonEventAction action;
public MsonEventAction getEventActionType() { return this.action; }
protected final String value;
public String getActionText() { return this.value; }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
protected MsonEvent(MsonEventAction action, String value)
{
this.action = action;
this.value = value;
}
// -------------------------------------------- //
// FACTORY
// -------------------------------------------- //
public static MsonEvent valueOf(MsonEventAction type, String action)
{
return new MsonEvent(type, action);
}
// clickEvents
public static MsonEvent openUrl(String url)
{
return MsonEvent.valueOf(MsonEventAction.OPEN_URL, url);
}
public static MsonEvent replace(String replace)
{
return MsonEvent.valueOf(MsonEventAction.SUGGEST_COMMAND , replace);
}
public static MsonEvent performCmd(String cmd)
{
return MsonEvent.valueOf(MsonEventAction.RUN_COMMAND, cmd);
}
// hoverEvents
public static MsonEvent hoverText(String hoverText)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, hoverText);
}
public static MsonEvent hoverText(String... hoverTexts)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, Txt.implode(hoverTexts, "\n"));
}
public static MsonEvent hoverText(Collection<String> hoverTexts)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, Txt.implode(hoverTexts, "\n"));
}
// hoverEventsParsed
public static MsonEvent hoverTextParse(String hoverText)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, Txt.parse(hoverText));
}
public static MsonEvent hoverTextParse(String... hoverTexts)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, Txt.parse(Txt.implode(hoverTexts, "\n")));
}
public static MsonEvent hoverTextParse(Collection<String> hoverTexts)
{
return MsonEvent.valueOf(MsonEventAction.SHOW_TEXT, Txt.parse(Txt.implode(hoverTexts, "\n")));
}
// -------------------------------------------- //
// CONVENIENCE
// -------------------------------------------- //
public boolean isHoverEvent() { return this.getEventActionType().isHoverAction(); }
public boolean isClickEvent() { return this.getEventActionType().isClickAction(); }
// -------------------------------------------- //
// EQUALS AND HASHCODE
// -------------------------------------------- //
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + Objects.hashCode(action);
result = prime * result + Objects.hashCode(value);
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if ( ! (obj instanceof MsonEvent)) return false;
MsonEvent that = (MsonEvent) obj;
if ( ! MUtil.equals(this.action, that.action)) return false;
if ( ! MUtil.equals(this.value, that.value)) return false;
return true;
}
}

View File

@ -0,0 +1,44 @@
package com.massivecraft.massivecore.mson;
public enum MsonEventAction
{
// -------------------------------------------- //
// ENUM
// -------------------------------------------- //
SUGGEST_COMMAND(),
RUN_COMMAND(),
OPEN_URL(),
SHOW_TEXT(true)
// End of list
;
// -------------------------------------------- //
// FIELD
// -------------------------------------------- //
private boolean isHoverAction;
public boolean isHoverAction() { return this.isHoverAction; }
// NOTE: This behaviour might change.
// So to check if something is a click action this method should be called.
// Doing !action.isHoverAction();
// Shouldn't be done outside of this class.
public boolean isClickAction() { return ! this.isHoverAction(); }
// -------------------------------------------- //
// CONSTRUCT
// -------------------------------------------- //
private MsonEventAction(boolean isHoveraction)
{
this.isHoverAction = isHoveraction;
}
private MsonEventAction()
{
this(false);
}
}

View File

@ -9,6 +9,7 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import com.massivecraft.massivecore.mixin.Mixin; import com.massivecraft.massivecore.mixin.Mixin;
import com.massivecraft.massivecore.mson.Mson;
import com.massivecraft.massivecore.util.IdUtil; import com.massivecraft.massivecore.util.IdUtil;
public abstract class SenderEntity<E extends SenderEntity<E>> extends Entity<E> public abstract class SenderEntity<E extends SenderEntity<E>> extends Entity<E>
@ -159,6 +160,23 @@ public abstract class SenderEntity<E extends SenderEntity<E>> extends Entity<E>
return Mixin.msgOne(this.getId(), msgs); return Mixin.msgOne(this.getId(), msgs);
} }
// CONVENIENCE SEND RAW
public boolean sendRaw(Mson mson)
{
return Mixin.messageRawOne(this.getId(), mson);
}
public boolean sendRaw(Mson... msons)
{
return Mixin.messageRawOne(this.getId(), msons);
}
public boolean sendRaw(Collection<Mson> msons)
{
return Mixin.messageRawOne(this.getId(), msons);
}
// CONVENIENCE GAME-MODE // CONVENIENCE GAME-MODE
public GameMode getGameMode(GameMode def) public GameMode getGameMode(GameMode def)

View File

@ -0,0 +1,272 @@
package com.massivecraft.massivecore.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.logging.Level;
import org.bukkit.entity.Player;
import org.json.simple.JSONObject;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.particleeffect.ReflectionUtils;
import com.massivecraft.massivecore.particleeffect.ReflectionUtils.PackageType;
public final class PacketUtil
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
// Is using
private static boolean useTitles = false;
private static boolean useRaw = false;
// The enums used to tell which packet it is.
// They correspond to the commands with the same name.
private static Class<?> titleEnumClass;
private static Enum<?> titleMainEnum;
private static Enum<?> titleSubEnum;
private static Enum<?> titleTimesEnum;
// Method used to prepare text so it can be sent
private static Method chatSerializer;
// The object we send instead of a string
private static Class<?> iChatBaseComponent;
// Handling the players conenction
private static Method getHandle;
private static Field playerConnection;
private static Method sendPacket;
// The title packet and its constructor
private static Constructor<?> titlePacketConstructor;
private static Constructor<?> titlePacketConstructorTimes;
// The chat packet and its constructor
private static Constructor<?> chatPacketConstructor;
// -------------------------------------------- //
// SETUP
// -------------------------------------------- //
static
{
try
{
// The enum used for titles
titleEnumClass = getTitleEnumClass();
// Get the title enum values.
for (Object o : titleEnumClass.getEnumConstants())
{
Enum<?> e = (Enum<?>) o;
if (e.name().equalsIgnoreCase("TITLE")) titleMainEnum = e;
else if (e.name().equalsIgnoreCase("SUBTITLE")) titleSubEnum = e;
else if (e.name().equalsIgnoreCase("TIMES")) titleTimesEnum = e;
}
// Get chatserializer and chat component.
iChatBaseComponent = PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent");
chatSerializer = getChatSerializer();
// Get title packet and it's constructor
Class<?> titlePacketClass = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutTitle");
titlePacketConstructor = ReflectionUtils.getConstructor(titlePacketClass, titleEnumClass, iChatBaseComponent);
titlePacketConstructorTimes = ReflectionUtils.getConstructor(titlePacketClass, titleEnumClass, iChatBaseComponent, Integer.class, Integer.class, Integer.class);
// Get Chat packet and it's constructor
Class<?> chatPacketClass = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutChat");
chatPacketConstructor = ReflectionUtils.getConstructor(chatPacketClass, iChatBaseComponent);
// Player connection
getHandle = ReflectionUtils.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
playerConnection = ReflectionUtils.getField("EntityPlayer", PackageType.MINECRAFT_SERVER, false, "playerConnection");
sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", PackageType.MINECRAFT_SERVER.getClass("Packet"));
// Set accessible
setAllAccessible();
// This succeeded, we use titles and the chat.
useTitles = true;
useRaw = true;
}
catch (Exception ex)
{
MassiveCore.get().log(Level.INFO, "If you use 1.7.X or below, disregard this error");
MassiveCore.get().log(Level.INFO, "If you use 1.8.X or above, please report at https://github.com/MassiveCraft/MassiveCore/issues");
ex.printStackTrace();
MassiveCore.get().log(Level.INFO, "If you use 1.7.X or below, disregard this error");
MassiveCore.get().log(Level.INFO, "If you use 1.8.X or above, please report at https://github.com/MassiveCraft/MassiveCore/issues");
// It didn't succeed, we will not use titles.
useTitles = false;
useRaw = false;
}
}
public static Class<?> getTitleEnumClass() throws ClassNotFoundException
{
Class<?> ret;
try
{
ret = titleEnumClass = PackageType.MINECRAFT_SERVER.getClass("EnumTitleAction");
}
catch (ClassNotFoundException e)
{
// Since 1.8.3
ret = titleEnumClass = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutTitle$EnumTitleAction");
}
return ret;
}
public static Method getChatSerializer() throws Exception
{
Method ret;
try
{
ret = chatSerializer = PackageType.MINECRAFT_SERVER.getClass("ChatSerializer").getDeclaredMethod("a", String.class);
}
catch (ClassNotFoundException e)
{
// Since 1.8.3
ret = chatSerializer = PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent$ChatSerializer").getDeclaredMethod("a", String.class);
}
return ret;
}
public static void setAllAccessible()
{
chatSerializer.setAccessible(true);
titlePacketConstructor.setAccessible(true);
titlePacketConstructorTimes.setAccessible(true);
chatPacketConstructor.setAccessible(true);
getHandle.setAccessible(true);
playerConnection.setAccessible(true);
sendPacket.setAccessible(true);
}
// -------------------------------------------- //
// AVAILABLE
// -------------------------------------------- //
public static boolean isTitleAvailable()
{
return useTitles;
}
public static boolean isRawAvailable()
{
return useRaw;
}
// -------------------------------------------- //
// SEND TITLES
// -------------------------------------------- //
public static boolean sendTitle(Player player, int ticksIn, int ticksStay, int ticksOut, String titleMain, String titleSub)
{
if ( ! useTitles) return false;
try
{
// Fadein, stay, fadeout
Object timesPacket = titlePacketConstructorTimes.newInstance(titleTimesEnum, null, ticksIn, ticksStay, ticksOut);
sendPacket(player, timesPacket);
if (titleMain != null)
{
titleMain = toJson(titleMain);
// Title
Object titleMainChat = toChatBaseComponent(titleMain);
Object titleMainPacket = titlePacketConstructor.newInstance(titleMainEnum, titleMainChat);
sendPacket(player, titleMainPacket);
}
if (titleSub != null)
{
titleSub = toJson(titleSub);
// SubTitle
Object titleSubChat = toChatBaseComponent(titleSub);
Object titleSubPacket = titlePacketConstructor.newInstance(titleSubEnum, titleSubChat);
sendPacket(player, titleSubPacket);
}
}
catch (Exception ex)
{
MassiveCore.get().log("<b>Sending title failed!");
ex.printStackTrace();
// So we failed, didn't work.
return false;
}
//It worked.
return true;
}
// -------------------------------------------- //
// SEND RAW
// -------------------------------------------- //
public static boolean sendRaw(Player player, String string)
{
if ( ! useRaw) return false;
try
{
Object rawChat = toChatBaseComponent(string);
Object chatPacket = chatPacketConstructor.newInstance(rawChat);
sendPacket(player, chatPacket);
}
catch (Exception ex)
{
MassiveCore.get().log("<b>Sending raw chat failed!");
ex.printStackTrace();
// So we failed and it didn't work.
return false;
}
return true;
}
// -------------------------------------------- //
// UTIL
// -------------------------------------------- //
public static void sendPacket(Player player, Object packet) throws Exception
{
sendPacket.invoke(getPlayerConnection(player), packet);
}
public static Object getPlayerConnection(Player player) throws Exception
{
return playerConnection.get(getHandle.invoke(player));
}
public static Object toChatBaseComponent(String str) throws Exception
{
return chatSerializer.invoke(null, str);
}
// -------------------------------------------- //
// JSON
// -------------------------------------------- //
public static String toJson(String str)
{
str = JSONObject.escape(str);
str = "{\"text\": \"" + str + "\"}";
return str;
}
}

View File

@ -1,206 +0,0 @@
package com.massivecraft.massivecore.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.logging.Level;
import org.bukkit.entity.Player;
import org.json.simple.JSONObject;
import com.massivecraft.massivecore.MassiveCore;
import com.massivecraft.massivecore.particleeffect.ReflectionUtils;
import com.massivecraft.massivecore.particleeffect.ReflectionUtils.PackageType;
public final class TitleUtil
{
// -------------------------------------------- //
// FIELDS
// -------------------------------------------- //
private static boolean useTitles = false;
// The enums used to tell which packet it is.
// They correspond to the commands with the same name.
private static Class<?> titleEnumClass;
private static Enum<?> titleEnum;
private static Enum<?> subtitleEnum;
private static Enum<?> timesEnum;
// Method used to prepare text so it can be send
private static Method chatSerializer;
// The object we send instead of a string
private static Class<?> iChatBaseComponent;
// Handling the players conenction
private static Method getHandle;
private static Field playerConnection;
private static Method sendPacket;
// The packet and its constructor
private static Constructor<?> packetConstructor;
private static Constructor<?> packetConstructorTimes;
// -------------------------------------------- //
// SETUP
// -------------------------------------------- //
static
{
try
{
// The enum used
try
{
titleEnumClass = PackageType.MINECRAFT_SERVER.getClass("EnumTitleAction");
}
catch (ClassNotFoundException e)
{
// Since 1.8.3
titleEnumClass = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutTitle$EnumTitleAction");
}
// Get the enum values.
for (Object o : titleEnumClass.getEnumConstants())
{
Enum<?> e = (Enum<?>) o;
if (e.name().equalsIgnoreCase("TITLE")) titleEnum = e;
else if (e.name().equalsIgnoreCase("SUBTITLE")) subtitleEnum = e;
else if (e.name().equalsIgnoreCase("TIMES")) timesEnum = e;
}
// Get chatserializer and chat component.
iChatBaseComponent = PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent");
try
{
chatSerializer = PackageType.MINECRAFT_SERVER.getClass("ChatSerializer").getDeclaredMethod("a", String.class);
}
catch (ClassNotFoundException e)
{
// Since 1.8.3
chatSerializer = PackageType.MINECRAFT_SERVER.getClass("IChatBaseComponent$ChatSerializer").getDeclaredMethod("a", String.class);
}
// Get packet and it's constructor
Class<?> packetClass = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutTitle");
packetConstructor = ReflectionUtils.getConstructor(packetClass, titleEnumClass, iChatBaseComponent);
packetConstructorTimes = ReflectionUtils.getConstructor(packetClass, titleEnumClass, iChatBaseComponent, Integer.class, Integer.class, Integer.class);
// Player connection
getHandle = ReflectionUtils.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle");
playerConnection = ReflectionUtils.getField("EntityPlayer", PackageType.MINECRAFT_SERVER, false, "playerConnection");
sendPacket = ReflectionUtils.getMethod(playerConnection.getType(), "sendPacket", PackageType.MINECRAFT_SERVER.getClass("Packet"));
// Set accesible
chatSerializer.setAccessible(true);
packetConstructor.setAccessible(true);
packetConstructorTimes.setAccessible(true);
getHandle.setAccessible(true);
playerConnection.setAccessible(true);
sendPacket.setAccessible(true);
// This succeeded, we use titles.
useTitles = true;
}
catch (Exception e)
{
MassiveCore.get().log(Level.INFO, "If you use 1.7.X or below, disregard this error");
MassiveCore.get().log(Level.INFO, "If you use 1.8.X or above, please report at https://github.com/MassiveCraft/MassiveCore/issues");
e.printStackTrace();
MassiveCore.get().log(Level.INFO, "If you use 1.7.X or below, disregard this error");
MassiveCore.get().log(Level.INFO, "If you use 1.8.X or above, please report at https://github.com/MassiveCraft/MassiveCore/issues");
// It didn't suceed, we will not use titles.
useTitles = false;
}
}
// -------------------------------------------- //
// AVAILABLE
// -------------------------------------------- //
public static boolean isAvailable()
{
return useTitles;
}
// -------------------------------------------- //
// SEND TITLES
// -------------------------------------------- //
public static boolean sendTitle(Player player, int ticksIn, int ticksStay, int ticksOut, String titleMain, String titleSub)
{
if ( ! useTitles)
{
return false;
}
try
{
// Fadein, stay, fadeout
Object timesPacket = packetConstructorTimes.newInstance(timesEnum, null, ticksIn, ticksStay, ticksOut);
sendPacket.invoke(playerConnection.get( getHandle.invoke(player) ), timesPacket);
}
catch (Exception e)
{
e.printStackTrace();
// So we failed, didn't work.
return false;
}
if (titleMain != null)
{
titleMain = toJson(titleMain);
try
{
// Title
Object titleMainChat = chatSerializer.invoke(null, titleMain);
Object titleMainPacket = packetConstructor.newInstance(titleEnum, titleMainChat);
sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), titleMainPacket);
}
catch (Exception e)
{
e.printStackTrace();
// So we failed, didn't work.
return false;
}
}
if (titleSub != null)
{
titleSub = toJson(titleSub);
try
{
// SubTitle
Object titleSubChat = chatSerializer.invoke(null, titleSub);
Object titleSubPacket = packetConstructor.newInstance(subtitleEnum, titleSubChat);
sendPacket.invoke(playerConnection.get(getHandle.invoke(player)), titleSubPacket);
}
catch (Exception e)
{
e.printStackTrace();
// So we failed, didn't work.
return false;
}
}
//It worked.
return true;
}
// -------------------------------------------- //
// JSON
// -------------------------------------------- //
public static String toJson(String str)
{
str = JSONObject.escape(str);
str = "{\"text\": \"" + str + "\"}";
return str;
}
}