Fix Mson event database bug.
This commit is contained in:
parent
982c8de90f
commit
cbf50c5741
@ -17,11 +17,11 @@ public class AdapterLowercaseEnum<T extends Enum<T>> implements JsonDeserializer
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
protected final Class<T> clazz;
|
||||
private final Class<T> clazz;
|
||||
public Class<T> getClazz() { return this.clazz; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// INSTANCE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static <T extends Enum<T>> AdapterLowercaseEnum<T> get(Class<T> clazz)
|
||||
@ -29,10 +29,14 @@ public class AdapterLowercaseEnum<T extends Enum<T>> implements JsonDeserializer
|
||||
return new AdapterLowercaseEnum<T>(clazz);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
public AdapterLowercaseEnum(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");
|
||||
if (clazz == null) throw new IllegalArgumentException("clazz is null");
|
||||
if ( ! clazz.isEnum()) throw new IllegalArgumentException("clazz is not enum");
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@ -43,65 +47,76 @@ public class AdapterLowercaseEnum<T extends Enum<T>> implements JsonDeserializer
|
||||
@Override
|
||||
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
// Null
|
||||
if (src == null) return JsonNull.INSTANCE;
|
||||
return new JsonPrimitive(src.name().toLowerCase());
|
||||
|
||||
String comparable = this.getComparable(src);
|
||||
return new JsonPrimitive(comparable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
// Null
|
||||
if (json == null) return null;
|
||||
T value = getEnumValueFrom(json);
|
||||
return value;
|
||||
if (json.equals(JsonNull.INSTANCE)) return null;
|
||||
|
||||
T ret = this.getEnumValueFrom(json);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// UTIL
|
||||
// GET ENUM VALUE FROM
|
||||
// -------------------------------------------- //
|
||||
|
||||
public T getEnumValueFrom(JsonElement json)
|
||||
{
|
||||
return getEnumValueFrom(json.toString());
|
||||
String string = this.getComparable(json);
|
||||
return this.getEnumValueFrom(string);
|
||||
}
|
||||
|
||||
public T getEnumValueFrom(String str)
|
||||
public T getEnumValueFrom(String string)
|
||||
{
|
||||
return getEnumValueFrom(str, clazz);
|
||||
string = this.getComparable(string);
|
||||
for (T value : this.getEnumValues())
|
||||
{
|
||||
String comparable = this.getComparable(value);
|
||||
if (comparable.equals(string)) return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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");
|
||||
// -------------------------------------------- //
|
||||
// GET ENUM VALUES
|
||||
// -------------------------------------------- //
|
||||
|
||||
public T[] getEnumValues()
|
||||
{
|
||||
Class<T> clazz = this.getClazz();
|
||||
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)
|
||||
// -------------------------------------------- //
|
||||
// GET COMPARABLE
|
||||
// -------------------------------------------- //
|
||||
|
||||
public String getComparable(Enum<?> value)
|
||||
{
|
||||
if (value == null) return null;
|
||||
return getComparable(value.name());
|
||||
return this.getComparable(value.name());
|
||||
}
|
||||
|
||||
public static String getComparable(String string)
|
||||
public String getComparable(JsonElement json)
|
||||
{
|
||||
if (json == null) return null;
|
||||
return this.getComparable(json.getAsString());
|
||||
}
|
||||
|
||||
public String getComparable(String string)
|
||||
{
|
||||
if (string == null) return null;
|
||||
return string.toLowerCase();
|
||||
}
|
||||
|
||||
public static<T extends Enum<T>> T getEnumValueFrom(String str, Class<T> clazz)
|
||||
{
|
||||
str = getComparable(str);
|
||||
|
||||
for (T value : getEnumValues(clazz))
|
||||
{
|
||||
if (getComparable(value).equals(str)) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import com.massivecraft.massivecore.mson.Mson;
|
||||
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.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
@ -27,8 +26,7 @@ public class AdapterMson implements JsonDeserializer<Mson>, JsonSerializer<Mson>
|
||||
@Override
|
||||
public JsonElement serialize(Mson src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
if (src == null) return JsonNull.INSTANCE;
|
||||
return src.toJson();
|
||||
return Mson.toJson(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,7 +2,6 @@ package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.massivecraft.massivecore.mson.Mson;
|
||||
import com.massivecraft.massivecore.mson.MsonEvent;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonDeserializer;
|
||||
@ -27,13 +26,13 @@ public class AdapterMsonEvent implements JsonDeserializer<MsonEvent>, JsonSerial
|
||||
@Override
|
||||
public JsonElement serialize(MsonEvent src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return Mson.GSON.toJsonTree(src);
|
||||
return MsonEvent.toJson(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MsonEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
return Mson.GSON.fromJson(json, MsonEvent.class);
|
||||
return MsonEvent.fromJson(json);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.massivecraft.massivecore.adapter;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
import com.massivecraft.massivecore.mson.Mson;
|
||||
import com.massivecraft.massivecore.mson.MsonEvent;
|
||||
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.JsonParseException;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializationContext;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonSerializer;
|
||||
|
||||
public class AdapterMsonEventFix implements JsonDeserializer<MsonEvent>, JsonSerializer<MsonEvent>
|
||||
{
|
||||
// -------------------------------------------- //
|
||||
// INSTANCE & CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static final AdapterMsonEventFix i = new AdapterMsonEventFix();
|
||||
public static AdapterMsonEventFix get() { return i; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// OVERRIDE
|
||||
// -------------------------------------------- //
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(MsonEvent src, Type typeOfSrc, JsonSerializationContext context)
|
||||
{
|
||||
return Mson.getGson(false).toJsonTree(src);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MsonEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
|
||||
{
|
||||
MsonEvent ret = Mson.getGson(false).fromJson(json, MsonEvent.class);
|
||||
ret.repair();
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.massivecraft.massivecore.adapter.AdapterLowercaseEnum;
|
||||
import com.massivecraft.massivecore.adapter.AdapterMsonEventFix;
|
||||
import com.massivecraft.massivecore.collections.MassiveList;
|
||||
import com.massivecraft.massivecore.command.MassiveCommand;
|
||||
import com.massivecraft.massivecore.mixin.MixinMessage;
|
||||
@ -26,6 +27,7 @@ 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;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonNull;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonPrimitive;
|
||||
|
||||
public class Mson implements Serializable
|
||||
@ -34,34 +36,60 @@ public class Mson implements Serializable
|
||||
// CONSTANTS: TECHY
|
||||
// -------------------------------------------- //
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final transient long serialVersionUID = 1L;
|
||||
|
||||
public static final Pattern PARSE_PREFIX = Pattern.compile("\u00A7");
|
||||
public static final transient Pattern PATTERN_PARSE_PREFIX = Pattern.compile("\u00A7");
|
||||
|
||||
public static final AdapterLowercaseEnum<ChatColor> ADAPTER_LOWERCASE_CHAT_COLOR = AdapterLowercaseEnum.get(ChatColor.class);
|
||||
public static final AdapterLowercaseEnum<MsonEventAction> ADAPTER_LOWERCASE_MSON_EVENT_ACTION = AdapterLowercaseEnum.get(MsonEventAction.class);
|
||||
public static final transient AdapterLowercaseEnum<ChatColor> ADAPTER_LOWERCASE_CHAT_COLOR = AdapterLowercaseEnum.get(ChatColor.class);
|
||||
public static final transient AdapterLowercaseEnum<MsonEventAction> ADAPTER_LOWERCASE_MSON_EVENT_ACTION = AdapterLowercaseEnum.get(MsonEventAction.class);
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTANTS: REUSABLE MSONS
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static final Mson SPACE = mson(" ");
|
||||
public static final Mson EMPTY = mson("");
|
||||
public static final Mson NEWLINE = mson("\n");
|
||||
public static final Mson DOT = mson(".");
|
||||
public static final transient Mson SPACE = mson(" ");
|
||||
public static final transient Mson EMPTY = mson("");
|
||||
public static final transient Mson NEWLINE = mson("\n");
|
||||
public static final transient Mson DOT = mson(".");
|
||||
|
||||
// -------------------------------------------- //
|
||||
// GSON
|
||||
// -------------------------------------------- //
|
||||
// We need two different Gson instances that chain into each other.
|
||||
// The external one contains repairs and preprocessors.
|
||||
// The internal one is free from repairs and preprocessors.
|
||||
// This way we can avoid stack overflows.
|
||||
|
||||
public static final Gson GSON;
|
||||
private static transient Gson GSON_EXTERNAL = null;
|
||||
private static transient Gson GSON_INTERNAL = null;
|
||||
|
||||
static
|
||||
public static Gson getGson(boolean external)
|
||||
{
|
||||
Gson ret = (external ? GSON_EXTERNAL : GSON_INTERNAL);
|
||||
if (ret == null)
|
||||
{
|
||||
ret = createGson(external);
|
||||
if (external)
|
||||
{
|
||||
GSON_EXTERNAL = ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
GSON_INTERNAL = ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static Gson createGson(boolean external)
|
||||
{
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.disableHtmlEscaping();
|
||||
|
||||
if (external) builder.registerTypeAdapter(MsonEvent.class, AdapterMsonEventFix.get());
|
||||
|
||||
builder.registerTypeAdapter(MsonEventAction.class, ADAPTER_LOWERCASE_MSON_EVENT_ACTION);
|
||||
|
||||
builder.registerTypeAdapter(ChatColor.class, ADAPTER_LOWERCASE_CHAT_COLOR);
|
||||
|
||||
// For some unknown reason, the different chat colors
|
||||
@ -77,7 +105,7 @@ public class Mson implements Serializable
|
||||
builder.registerTypeAdapter(color.getClass(), ADAPTER_LOWERCASE_CHAT_COLOR);
|
||||
}
|
||||
|
||||
GSON = builder.create();
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
@ -578,7 +606,7 @@ public class Mson implements Serializable
|
||||
message = ensureStartsWithColorCode(message);
|
||||
|
||||
// We split at color/format change.
|
||||
String[] parts = PARSE_PREFIX.split(message);
|
||||
String[] parts = PATTERN_PARSE_PREFIX.split(message);
|
||||
|
||||
// Since we start with a color, the first element will be empty.
|
||||
// We don't want that empty element.
|
||||
@ -1195,8 +1223,15 @@ public class Mson implements Serializable
|
||||
|
||||
public JsonElement toJson()
|
||||
{
|
||||
return GSON.toJsonTree(this);
|
||||
return toJson(this);
|
||||
}
|
||||
|
||||
public static JsonElement toJson(Mson mson)
|
||||
{
|
||||
if (mson == null) return JsonNull.INSTANCE;
|
||||
return getGson(true).toJsonTree(mson);
|
||||
}
|
||||
|
||||
public static Mson fromJson(JsonElement json)
|
||||
{
|
||||
// Escape the null.
|
||||
@ -1214,7 +1249,18 @@ public class Mson implements Serializable
|
||||
// Just a normal mson.
|
||||
if (json.isJsonObject())
|
||||
{
|
||||
return GSON.fromJson(json, Mson.class);
|
||||
Mson ret = getGson(true).fromJson(json, Mson.class);
|
||||
|
||||
// TODO: Temporary Repair
|
||||
MsonEvent event;
|
||||
|
||||
event = ret.getEvent(MsonEventType.CLICK);
|
||||
if (event != null) event.repair();
|
||||
|
||||
event = ret.getEvent(MsonEventType.HOVER);
|
||||
if (event != null) event.repair();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Something is horribly wrong.
|
||||
@ -1294,42 +1340,40 @@ public class Mson implements Serializable
|
||||
@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.insertion);
|
||||
result = prime * result + Objects.hashCode(this.extra);
|
||||
return result;
|
||||
return Objects.hash(
|
||||
this.text,
|
||||
this.color,
|
||||
this.bold,
|
||||
this.italic,
|
||||
this.underlined,
|
||||
this.strikethrough,
|
||||
this.obfuscated,
|
||||
this.clickEvent,
|
||||
this.hoverEvent,
|
||||
this.insertion,
|
||||
this.extra
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
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.insertion, that.insertion)) return false;
|
||||
if ( ! MUtil.equals(this.extra, that.extra)) return false;
|
||||
|
||||
return true;
|
||||
if (this == object) return true;
|
||||
if ( ! (object instanceof Mson)) return false;
|
||||
Mson that = (Mson)object;
|
||||
return MUtil.equals(
|
||||
this.text, that.text,
|
||||
this.color, that.color,
|
||||
this.bold, that.bold,
|
||||
this.italic, that.italic,
|
||||
this.underlined, that.underlined,
|
||||
this.strikethrough, that.strikethrough,
|
||||
this.obfuscated, that.obfuscated,
|
||||
this.clickEvent, that.clickEvent,
|
||||
this.hoverEvent, that.hoverEvent,
|
||||
this.insertion, that.insertion,
|
||||
this.extra, that.extra
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import com.massivecraft.massivecore.command.MassiveCommand;
|
||||
import com.massivecraft.massivecore.nms.NmsItemStackTooltip;
|
||||
import com.massivecraft.massivecore.util.MUtil;
|
||||
import com.massivecraft.massivecore.util.Txt;
|
||||
import com.massivecraft.massivecore.xlib.gson.JsonElement;
|
||||
|
||||
public final class MsonEvent implements Serializable
|
||||
{
|
||||
@ -23,12 +24,42 @@ public final class MsonEvent implements Serializable
|
||||
// FIELDS
|
||||
// -------------------------------------------- //
|
||||
|
||||
private final MsonEventAction action;
|
||||
// TODO: should be final. only temporairly mutable for repairs.
|
||||
private MsonEventAction action;
|
||||
public MsonEventAction getAction() { return this.action; }
|
||||
|
||||
// TODO: should be final. only temporairly mutable for repairs.
|
||||
@Deprecated
|
||||
public void setAction(MsonEventAction action) { this.action = action;}
|
||||
|
||||
private final String value;
|
||||
public String getValue() { return this.value; }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// REPAIR
|
||||
// -------------------------------------------- //
|
||||
// TODO: Remove this soon.
|
||||
|
||||
public void repair()
|
||||
{
|
||||
MsonEventAction action = this.getAction();
|
||||
if (action != null) return;
|
||||
|
||||
String value = this.getValue();
|
||||
if (value == null) return;
|
||||
|
||||
action = guessAction(value);
|
||||
this.setAction(action);
|
||||
}
|
||||
|
||||
private static MsonEventAction guessAction(String value)
|
||||
{
|
||||
if (value.startsWith("{id:")) return MsonEventAction.SHOW_ITEM;
|
||||
if (value.startsWith("/")) return MsonEventAction.SUGGEST_COMMAND;
|
||||
if (value.startsWith("http")) return MsonEventAction.OPEN_URL;
|
||||
return MsonEventAction.SHOW_TEXT;
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// CONSTRUCT
|
||||
// -------------------------------------------- //
|
||||
@ -39,6 +70,12 @@ public final class MsonEvent implements Serializable
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
// NoArg Constructor for GSON
|
||||
protected MsonEvent()
|
||||
{
|
||||
this(null, null);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// TOOLTIP
|
||||
// -------------------------------------------- //
|
||||
@ -137,6 +174,20 @@ public final class MsonEvent implements Serializable
|
||||
|
||||
public MsonEventType getType() { return this.getAction().getType(); }
|
||||
|
||||
// -------------------------------------------- //
|
||||
// JSON
|
||||
// -------------------------------------------- //
|
||||
|
||||
public static MsonEvent fromJson(JsonElement json)
|
||||
{
|
||||
return Mson.getGson(true).fromJson(json, MsonEvent.class);
|
||||
}
|
||||
|
||||
public static JsonElement toJson(MsonEvent event)
|
||||
{
|
||||
return Mson.getGson(true).toJsonTree(event);
|
||||
}
|
||||
|
||||
// -------------------------------------------- //
|
||||
// EQUALS AND HASHCODE
|
||||
// -------------------------------------------- //
|
||||
@ -144,24 +195,22 @@ public final class MsonEvent implements Serializable
|
||||
@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;
|
||||
return Objects.hash(
|
||||
this.action,
|
||||
this.value
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
public boolean equals(Object object)
|
||||
{
|
||||
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;
|
||||
if (this == object) return true;
|
||||
if ( ! (object instanceof MsonEvent)) return false;
|
||||
MsonEvent that = (MsonEvent) object;
|
||||
return MUtil.equals(
|
||||
this.action, that.action,
|
||||
this.value, that.value
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user