mirror of
https://github.com/AtlasMediaGroup/TotalFreedomMod.git
synced 2024-11-27 01:05:38 +00:00
add patch for negative infinity and infinity attributes causing disconnect
This commit is contained in:
parent
f0a9b6d747
commit
301c5b8da1
21
src/main/java/ca/momothereal/mojangson/MojangsonFinder.java
Normal file
21
src/main/java/ca/momothereal/mojangson/MojangsonFinder.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package ca.momothereal.mojangson;
|
||||||
|
|
||||||
|
import ca.momothereal.mojangson.ex.MojangsonParseException;
|
||||||
|
import ca.momothereal.mojangson.value.*;
|
||||||
|
|
||||||
|
import static ca.momothereal.mojangson.MojangsonToken.*;
|
||||||
|
|
||||||
|
public class MojangsonFinder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically detects the appropriate MojangsonValue from the given value.
|
||||||
|
* @param value The value to parse
|
||||||
|
* @return The resulting MojangsonValue. If the type couldn't be found, it falls back to MojangsonString
|
||||||
|
* @throws MojangsonParseException if the given value could not be parsed
|
||||||
|
*/
|
||||||
|
public static MojangsonValue readFromValue(String value) throws MojangsonParseException {
|
||||||
|
MojangsonValue val = new MojangsonString();
|
||||||
|
val.read(value);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
47
src/main/java/ca/momothereal/mojangson/MojangsonToken.java
Normal file
47
src/main/java/ca/momothereal/mojangson/MojangsonToken.java
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
package ca.momothereal.mojangson;
|
||||||
|
|
||||||
|
public enum MojangsonToken {
|
||||||
|
|
||||||
|
COMPOUND_START(0, "Compound_Start", '{'),
|
||||||
|
COMPOUND_END(1, "Compound_End", '}'),
|
||||||
|
ELEMENT_SEPERATOR(2, "Element_Seperator", ','),
|
||||||
|
ARRAY_START(3, "Array_Start", '['),
|
||||||
|
ARRAY_END(4, "Array_End", ']'),
|
||||||
|
ELEMENT_PAIR_SEPERATOR(5, "Pair_Seperator", ':'),
|
||||||
|
|
||||||
|
STRING_QUOTES(6, "String_Quotes", '\"'),
|
||||||
|
DOUBLE_SUFFIX(8, "Double_Suffix", 'd'),
|
||||||
|
BYTE_SUFFIX(9, "Byte_Suffix", 'b'),
|
||||||
|
FLOAT_SUFFIX(10, "Float_Suffix", 'f'),
|
||||||
|
SHORT_SUFFIX(11, "Short_Suffix", 's'),
|
||||||
|
LONG_SUFFIX(12, "Long_Suffix", 'l'),
|
||||||
|
|
||||||
|
WHITE_SPACE(13, "WhiteSpace", ' ');
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private String name;
|
||||||
|
private char symbol;
|
||||||
|
|
||||||
|
MojangsonToken(int id, String name, char symbol) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.symbol = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getSymbol() {
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.valueOf(symbol);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package ca.momothereal.mojangson.ex;
|
||||||
|
|
||||||
|
public class MojangsonParseException extends Exception {
|
||||||
|
|
||||||
|
private ParseExceptionReason reason;
|
||||||
|
|
||||||
|
public MojangsonParseException(String message, ParseExceptionReason reason) {
|
||||||
|
super(message);
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParseExceptionReason getReason() {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return reason.getMessage() + ": " + super.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ParseExceptionReason {
|
||||||
|
INVALID_FORMAT_NUM("Given value is not numerical"),
|
||||||
|
UNEXPECTED_SYMBOL("Unexpected symbol in Mojangson string");
|
||||||
|
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
ParseExceptionReason(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package ca.momothereal.mojangson.value;
|
||||||
|
|
||||||
|
import ca.momothereal.mojangson.MojangsonFinder;
|
||||||
|
import ca.momothereal.mojangson.ex.MojangsonParseException;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static ca.momothereal.mojangson.MojangsonToken.*;
|
||||||
|
|
||||||
|
public class MojangsonCompound extends HashMap<String, List<MojangsonValue>> implements MojangsonValue<Map<String, MojangsonValue>> {
|
||||||
|
|
||||||
|
private final int C_COMPOUND_START = 0; // Parsing context
|
||||||
|
private final int C_COMPOUND_PAIR_KEY = 1; // Parsing context
|
||||||
|
private final int C_COMPOUND_PAIR_VALUE = 2; // Parsing context
|
||||||
|
|
||||||
|
public MojangsonCompound() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MojangsonCompound(Map map) {
|
||||||
|
super(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(StringBuilder builder) {
|
||||||
|
builder.append(COMPOUND_START);
|
||||||
|
boolean start = true;
|
||||||
|
|
||||||
|
for (String key : keySet()) {
|
||||||
|
if (start) {
|
||||||
|
start = false;
|
||||||
|
} else {
|
||||||
|
builder.append(ELEMENT_SEPERATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.append(key).append(ELEMENT_PAIR_SEPERATOR);
|
||||||
|
List<MojangsonValue> value = get(key);
|
||||||
|
for(MojangsonValue val : value)
|
||||||
|
{
|
||||||
|
val.write(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.append(COMPOUND_END);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(String string) throws MojangsonParseException {
|
||||||
|
int context = C_COMPOUND_START;
|
||||||
|
String tmp_key = "", tmp_val = "";
|
||||||
|
int scope = 0;
|
||||||
|
boolean inString = false;
|
||||||
|
|
||||||
|
for (int index = 0; index < string.length(); index++) {
|
||||||
|
Character character = string.charAt(index);
|
||||||
|
|
||||||
|
if (character == STRING_QUOTES.getSymbol()) {
|
||||||
|
inString = !inString;
|
||||||
|
}
|
||||||
|
if (character == WHITE_SPACE.getSymbol()) {
|
||||||
|
if (!inString)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((character == COMPOUND_START.getSymbol() || character == ARRAY_START.getSymbol()) && !inString) {
|
||||||
|
scope++;
|
||||||
|
}
|
||||||
|
if ((character == COMPOUND_END.getSymbol() || character == ARRAY_END.getSymbol()) && !inString) {
|
||||||
|
scope--;
|
||||||
|
}
|
||||||
|
if (context == C_COMPOUND_START) {
|
||||||
|
if (character != COMPOUND_START.getSymbol()) {
|
||||||
|
parseException(index, character);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (context == C_COMPOUND_PAIR_KEY) {
|
||||||
|
if (character == ELEMENT_PAIR_SEPERATOR.getSymbol() && scope <= 1) {
|
||||||
|
context++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp_key += character;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (context == C_COMPOUND_PAIR_VALUE) {
|
||||||
|
if ((character == ELEMENT_SEPERATOR.getSymbol() || character == COMPOUND_END.getSymbol()) && scope <= 1 && !inString) {
|
||||||
|
context = C_COMPOUND_PAIR_KEY;
|
||||||
|
computeIfAbsent(tmp_key, k -> new ArrayList<>()).add(MojangsonFinder.readFromValue(tmp_val));
|
||||||
|
tmp_key = tmp_val = "";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tmp_val += character;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, MojangsonValue> getValue() {
|
||||||
|
HashMap<String, MojangsonValue> hack = new HashMap<>();
|
||||||
|
for(String string : keySet())
|
||||||
|
{
|
||||||
|
for(MojangsonValue value : get(string))
|
||||||
|
{
|
||||||
|
hack.put(string, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hack;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getValueClass() {
|
||||||
|
return Map.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseException(int index, char symbol) throws MojangsonParseException {
|
||||||
|
throw new MojangsonParseException("Index: " + index + ", symbol: \'" + symbol + "\'", MojangsonParseException.ParseExceptionReason.UNEXPECTED_SYMBOL);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package ca.momothereal.mojangson.value;
|
||||||
|
|
||||||
|
import ca.momothereal.mojangson.MojangsonToken;
|
||||||
|
import ca.momothereal.mojangson.ex.MojangsonParseException;
|
||||||
|
|
||||||
|
public class MojangsonString implements MojangsonValue<String> {
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public MojangsonString() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public MojangsonString(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(StringBuilder builder) {
|
||||||
|
builder.append(MojangsonToken.STRING_QUOTES).append(value).append(MojangsonToken.STRING_QUOTES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class getValueClass() {
|
||||||
|
return String.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(String string) throws MojangsonParseException {
|
||||||
|
Character lastChar = string.charAt(string.length() - 1);
|
||||||
|
Character firstChar = string.charAt(0);
|
||||||
|
|
||||||
|
if (firstChar == MojangsonToken.STRING_QUOTES.getSymbol() && lastChar == MojangsonToken.STRING_QUOTES.getSymbol()) {
|
||||||
|
value = string.substring(1, string.length() - 1);
|
||||||
|
} else {
|
||||||
|
value = string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package ca.momothereal.mojangson.value;
|
||||||
|
|
||||||
|
import ca.momothereal.mojangson.ex.MojangsonParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a value inside a compound or array.
|
||||||
|
* @param <T> The type of value this MojangsonValue holds
|
||||||
|
*/
|
||||||
|
public interface MojangsonValue<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the value to a StringBuilder buffer.
|
||||||
|
* @param builder The buffer to write to
|
||||||
|
*/
|
||||||
|
void write(StringBuilder builder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses and updates the current value to the given string representation
|
||||||
|
* @param string The string representation of the value
|
||||||
|
* @throws MojangsonParseException if the given value cannot be parsed
|
||||||
|
*/
|
||||||
|
void read(String string) throws MojangsonParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current literal value
|
||||||
|
* @return The current literal value of the MojangsonValue
|
||||||
|
*/
|
||||||
|
T getValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the literal value's class
|
||||||
|
* @return The literal value's class
|
||||||
|
*/
|
||||||
|
Class getValueClass();
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,24 @@
|
|||||||
package me.totalfreedom.totalfreedommod;
|
package me.totalfreedom.totalfreedommod;
|
||||||
|
|
||||||
|
import ca.momothereal.mojangson.ex.MojangsonParseException;
|
||||||
|
import ca.momothereal.mojangson.value.MojangsonCompound;
|
||||||
|
import ca.momothereal.mojangson.value.MojangsonValue;
|
||||||
|
import net.minecraft.server.v1_12_R1.NBTTagCompound;
|
||||||
|
import net.minecraft.server.v1_12_R1.NBTTagList;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.craftbukkit.v1_12_R1.inventory.CraftItemStack;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||||
import org.bukkit.event.player.PlayerLoginEvent;
|
import org.bukkit.event.player.PlayerLoginEvent;
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
import org.bukkit.event.player.PlayerMoveEvent;
|
||||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class MovementValidator extends FreedomService
|
public class MovementValidator extends FreedomService
|
||||||
{
|
{
|
||||||
@ -48,6 +61,43 @@ public class MovementValidator extends FreedomService
|
|||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
player.teleport(player.getWorld().getSpawnLocation());
|
player.teleport(player.getWorld().getSpawnLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getHelmet()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setHelmet(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your helmet slot.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getBoots()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setBoots(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your boots slot.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getLeggings()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setLeggings(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your leggings slot.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getChestplate()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setChestplate(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your chestplate slot.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getItemInMainHand()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setItemInMainHand(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your hand.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getItemInOffHand()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setItemInOffHand(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your offhand.");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH)
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
@ -62,4 +112,73 @@ public class MovementValidator extends FreedomService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerHoldItem(PlayerItemHeldEvent event)
|
||||||
|
{
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getItemInMainHand()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setItemInMainHand(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your hand.");
|
||||||
|
}
|
||||||
|
if (exploitItem(event.getPlayer().getInventory().getItemInOffHand()))
|
||||||
|
{
|
||||||
|
event.getPlayer().getInventory().setItemInOffHand(new ItemStack(Material.AIR));
|
||||||
|
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your offhand.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean exploitItem(ItemStack item)
|
||||||
|
{
|
||||||
|
net.minecraft.server.v1_12_R1.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
|
||||||
|
NBTTagList modifiers = getAttributeList(nmsStack);
|
||||||
|
MojangsonCompound compound = new MojangsonCompound();
|
||||||
|
boolean foundNegative = false;
|
||||||
|
boolean foundPositive = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String mod = modifiers.toString();
|
||||||
|
String fancy = ("{" + (mod.substring(1, mod.length() - 1).replace("{", "").replace("}", "")) + "}");
|
||||||
|
compound.read(fancy);
|
||||||
|
for (String key : compound.keySet())
|
||||||
|
{
|
||||||
|
if (Objects.equals(key, "Amount")) //null-safe .equals()
|
||||||
|
{
|
||||||
|
List<MojangsonValue> values = compound.get(key);
|
||||||
|
for (MojangsonValue val : values)
|
||||||
|
{
|
||||||
|
if (val.getValue().toString().equals("Infinityd"))
|
||||||
|
{
|
||||||
|
foundPositive = true;
|
||||||
|
}
|
||||||
|
if (val.getValue().toString().equals("-Infinityd"))
|
||||||
|
{
|
||||||
|
foundNegative = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MojangsonParseException e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return foundNegative && foundPositive;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private NBTTagList getAttributeList(net.minecraft.server.v1_12_R1.ItemStack stack)
|
||||||
|
{
|
||||||
|
if (stack.getTag() == null)
|
||||||
|
{
|
||||||
|
stack.setTag(new NBTTagCompound());
|
||||||
|
}
|
||||||
|
NBTTagList attr = stack.getTag().getList("AttributeModifiers", 10);
|
||||||
|
if (attr == null)
|
||||||
|
{
|
||||||
|
stack.getTag().set("AttributeModifiers", new NBTTagList());
|
||||||
|
}
|
||||||
|
return stack.getTag().getList("AttributeModifiers", 10);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user