Initial commit (Forge 1291).
This commit is contained in:
10
patches/org/bukkit/Bukkit.java.patch
Normal file
10
patches/org/bukkit/Bukkit.java.patch
Normal file
@ -0,0 +1,10 @@
|
||||
--- ../src-base/minecraft/org/bukkit/Bukkit.java
|
||||
+++ ../src-work/minecraft/org/bukkit/Bukkit.java
|
||||
@@ -301,6 +301,7 @@
|
||||
*/
|
||||
public static void reload() {
|
||||
server.reload();
|
||||
+ org.spigotmc.CustomTimingsHandler.reload(); // Spigot
|
||||
}
|
||||
|
||||
/**
|
259
patches/org/bukkit/Effect.java.patch
Normal file
259
patches/org/bukkit/Effect.java.patch
Normal file
@ -0,0 +1,259 @@
|
||||
--- ../src-base/minecraft/org/bukkit/Effect.java
|
||||
+++ ../src-work/minecraft/org/bukkit/Effect.java
|
||||
@@ -5,6 +5,7 @@
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import org.bukkit.block.BlockFace;
|
||||
+import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.potion.Potion;
|
||||
|
||||
/**
|
||||
@@ -79,27 +80,183 @@
|
||||
/**
|
||||
* The flames seen on a mobspawner; a visual effect.
|
||||
*/
|
||||
- MOBSPAWNER_FLAMES(2004, Type.VISUAL);
|
||||
+ MOBSPAWNER_FLAMES(2004, Type.VISUAL),
|
||||
+ /**
|
||||
+ * The spark that comes off a fireworks
|
||||
+ */
|
||||
+ FIREWORKS_SPARK("fireworksSpark", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Critical hit particles
|
||||
+ */
|
||||
+ CRIT("crit", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Blue critical hit particles
|
||||
+ */
|
||||
+ MAGIC_CRIT("magicCrit", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Multicolored potion effect particles
|
||||
+ */
|
||||
+ POTION_SWIRL("mobSpell", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Multicolored potion effect particles that are slightly transparent
|
||||
+ */
|
||||
+ POTION_SWIRL_TRANSPARENT("mobSpellAmbient", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A puff of white potion swirls
|
||||
+ */
|
||||
+ SPELL("spell", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A puff of white stars
|
||||
+ */
|
||||
+ INSTANT_SPELL("instantSpell", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A puff of purple particles
|
||||
+ */
|
||||
+ WITCH_MAGIC("witchMagic", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The note that appears above note blocks
|
||||
+ */
|
||||
+ NOTE("note", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particles shown at nether portals
|
||||
+ */
|
||||
+ PORTAL("portal", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The symbols that fly towards the enchantment table
|
||||
+ */
|
||||
+ FLYING_GLYPH("enchantmenttable", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Fire particles
|
||||
+ */
|
||||
+ FLAME("flame", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particles that pop out of lava
|
||||
+ */
|
||||
+ LAVA_POP("lava", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A small gray square
|
||||
+ */
|
||||
+ FOOTSTEP("footstep", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Water particles
|
||||
+ */
|
||||
+ SPLASH("splash", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Smoke particles
|
||||
+ */
|
||||
+ PARTICLE_SMOKE("smoke", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The biggest explosion particle effect
|
||||
+ */
|
||||
+ EXPLOSION_HUGE("hugeexplosion", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A larger version of the explode particle
|
||||
+ */
|
||||
+ EXPLOSION_LARGE("largeexplode", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Explosion particles
|
||||
+ */
|
||||
+ EXPLOSION("explode", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Small gray particles
|
||||
+ */
|
||||
+ VOID_FOG("depthsuspend", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Small gray particles
|
||||
+ */
|
||||
+ SMALL_SMOKE("townaura", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * A puff of white smoke
|
||||
+ */
|
||||
+ CLOUD("cloud", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Multicolored dust particles
|
||||
+ */
|
||||
+ COLOURED_DUST("reddust", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * Snowball breaking
|
||||
+ */
|
||||
+ SNOWBALL_BREAK("snowballpoof", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The water drip particle that appears on blocks under water
|
||||
+ */
|
||||
+ WATERDRIP("dripWater", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The lava drip particle that appears on blocks under lava
|
||||
+ */
|
||||
+ LAVADRIP("dripLava", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * White particles
|
||||
+ */
|
||||
+ SNOW_SHOVEL("snowshovel", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particle shown when a slime jumps
|
||||
+ */
|
||||
+ SLIME("slime", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particle that appears when breading animals
|
||||
+ */
|
||||
+ HEART("heart", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particle that appears when hitting a villager
|
||||
+ */
|
||||
+ VILLAGER_THUNDERCLOUD("angryVillager", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particle that appears when trading with a villager
|
||||
+ */
|
||||
+ HAPPY_VILLAGER("happyVillager", Type.PARTICLE),
|
||||
+ /**
|
||||
+ * The particles generated when a tool breaks.
|
||||
+ * This particle requires a Material so that the client can select the correct texture.
|
||||
+ */
|
||||
+ ITEM_BREAK("iconcrack", Type.PARTICLE, Material.class),
|
||||
+ /**
|
||||
+ * The particles generated while breaking a block.
|
||||
+ * This particle requires a Material and data value so that the client can select the correct texture.
|
||||
+ */
|
||||
+ TILE_BREAK("blockcrack", Type.PARTICLE, MaterialData.class),
|
||||
+ /**
|
||||
+ * The particles generated while sprinting a block
|
||||
+ * This particle requires a Material and data value so that the client can select the correct texture.
|
||||
+ */
|
||||
+ TILE_DUST("blockdust", Type.PARTICLE, MaterialData.class);
|
||||
|
||||
private final int id;
|
||||
private final Type type;
|
||||
private final Class<?> data;
|
||||
private static final Map<Integer, Effect> BY_ID = Maps.newHashMap();
|
||||
+ private static final Map<String, Effect> BY_NAME = Maps.newHashMap();
|
||||
+ private final String particleName;
|
||||
|
||||
- Effect(int id, Type type) {
|
||||
+ private Effect(int id, Type type) {
|
||||
this(id,type,null);
|
||||
}
|
||||
|
||||
- Effect(int id, Type type, Class<?> data) {
|
||||
+ private Effect(int id, Type type, Class<?> data) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
+ particleName = null;
|
||||
}
|
||||
|
||||
+ private Effect(String particleName, Type type, Class<?> data) {
|
||||
+ this.particleName = particleName;
|
||||
+ this.type = type;
|
||||
+ id = 0;
|
||||
+ this.data = data;
|
||||
+ }
|
||||
+
|
||||
+ private Effect(String particleName, Type type) {
|
||||
+ this.particleName = particleName;
|
||||
+ this.type = type;
|
||||
+ id = 0;
|
||||
+ this.data = null;
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* Gets the ID for this effect.
|
||||
*
|
||||
- * @return ID of this effect
|
||||
+ * @return if this Effect isn't of type PARTICLE it returns ID of this effect
|
||||
* @deprecated Magic value
|
||||
*/
|
||||
@Deprecated
|
||||
@@ -108,6 +265,15 @@
|
||||
}
|
||||
|
||||
/**
|
||||
+ * Returns the effect's name. This returns null if the effect is not a particle
|
||||
+ *
|
||||
+ * @return The effect's name
|
||||
+ */
|
||||
+ public String getName() {
|
||||
+ return particleName;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
* @return The type of the effect.
|
||||
*/
|
||||
public Type getType() {
|
||||
@@ -115,8 +281,7 @@
|
||||
}
|
||||
|
||||
/**
|
||||
- * @return The class which represents data for this effect, or null if
|
||||
- * none
|
||||
+ * @return if this Effect isn't of type PARTICLE it returns the class which represents data for this effect, or null if none
|
||||
*/
|
||||
public Class<?> getData() {
|
||||
return this.data;
|
||||
@@ -136,12 +301,32 @@
|
||||
|
||||
static {
|
||||
for (Effect effect : values()) {
|
||||
- BY_ID.put(effect.id, effect);
|
||||
+ if (effect.type != Type.PARTICLE) {
|
||||
+ BY_ID.put(effect.id, effect);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
+ * Gets the Effect associated with the given name.
|
||||
+ *
|
||||
+ * @param name name of the Effect to return
|
||||
+ * @return Effect with the given name
|
||||
+ */
|
||||
+ public static Effect getByName(String name) {
|
||||
+ return BY_NAME.get(name);
|
||||
+ }
|
||||
+
|
||||
+ static {
|
||||
+ for (Effect effect : values()) {
|
||||
+ if (effect.type == Type.PARTICLE) {
|
||||
+ BY_NAME.put(effect.particleName, effect);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
* Represents the type of an effect.
|
||||
*/
|
||||
- public enum Type {SOUND, VISUAL}
|
||||
+ public enum Type {SOUND, VISUAL, PARTICLE}
|
||||
}
|
16
patches/org/bukkit/GameMode.java.patch
Normal file
16
patches/org/bukkit/GameMode.java.patch
Normal file
@ -0,0 +1,16 @@
|
||||
--- ../src-base/minecraft/org/bukkit/GameMode.java
|
||||
+++ ../src-work/minecraft/org/bukkit/GameMode.java
|
||||
@@ -11,7 +11,13 @@
|
||||
* have
|
||||
*/
|
||||
public enum GameMode {
|
||||
+ // Cauldron start - FakePlayers do not set their gametype and use the default
|
||||
/**
|
||||
+ * Default mode
|
||||
+ */
|
||||
+ NOT_SET(-1),
|
||||
+ // Cauldron end
|
||||
+ /**
|
||||
* Creative mode may fly, build instantly, become invulnerable and create
|
||||
* free items.
|
||||
*/
|
272
patches/org/bukkit/Material.java.patch
Normal file
272
patches/org/bukkit/Material.java.patch
Normal file
@ -0,0 +1,272 @@
|
||||
--- ../src-base/minecraft/org/bukkit/Material.java
|
||||
+++ ../src-work/minecraft/org/bukkit/Material.java
|
||||
@@ -3,6 +3,22 @@
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Map;
|
||||
|
||||
+// Cauldron start
|
||||
+import java.lang.reflect.Array;
|
||||
+import java.lang.reflect.Constructor;
|
||||
+import java.lang.reflect.Field;
|
||||
+import java.lang.reflect.Method;
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.Arrays;
|
||||
+import java.util.List;
|
||||
+
|
||||
+import org.bukkit.inventory.ItemStack;
|
||||
+
|
||||
+import net.minecraftforge.common.util.EnumHelper;
|
||||
+import net.minecraftforge.cauldron.api.inventory.BukkitOreDictionary;
|
||||
+import net.minecraftforge.cauldron.api.inventory.OreDictionaryEntry;
|
||||
+// Cauldron end
|
||||
+
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.material.Bed;
|
||||
@@ -418,14 +434,30 @@
|
||||
private final int id;
|
||||
private final Constructor<? extends MaterialData> ctor;
|
||||
private static Material[] byId = new Material[383];
|
||||
- private final static Map<String, Material> BY_NAME = Maps.newHashMap();
|
||||
+ private static Map<String, Material> BY_NAME = Maps.newHashMap(); // Cauldron - remove final
|
||||
private final int maxStack;
|
||||
private final short durability;
|
||||
+ // Cauldron start
|
||||
+ private static Object reflectionFactory;
|
||||
+ private static Method newConstructorAccessor;
|
||||
+ private static Method newInstance;
|
||||
+ private static Method newFieldAccessor;
|
||||
+ private static Method fieldAccessorSet;
|
||||
+ private static boolean isSetup;
|
||||
+ private boolean isForgeBlock = false;
|
||||
+ // Cauldron end
|
||||
|
||||
private Material(final int id) {
|
||||
this(id, 64);
|
||||
}
|
||||
|
||||
+ // Cauldron start - constructor used to set if the Material is a block or not
|
||||
+ private Material(final int id, boolean flag) {
|
||||
+ this(id, 64);
|
||||
+ this.isForgeBlock = flag;
|
||||
+ }
|
||||
+ // Cauldron end
|
||||
+
|
||||
private Material(final int id, final int stack) {
|
||||
this(id, stack, MaterialData.class);
|
||||
}
|
||||
@@ -526,7 +558,7 @@
|
||||
* @return true if this material is a block
|
||||
*/
|
||||
public boolean isBlock() {
|
||||
- return id < 256;
|
||||
+ return id < 256 || isForgeBlock; // Cauldron
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -615,16 +647,202 @@
|
||||
} catch (NumberFormatException ex) {}
|
||||
|
||||
if (result == null) {
|
||||
- String filtered = name.toUpperCase();
|
||||
-
|
||||
- filtered = filtered.replaceAll("\\s+", "_").replaceAll("\\W", "");
|
||||
+ // Cauldron start - extract to normalizeName()
|
||||
+ String filtered = normalizeName(name);
|
||||
result = BY_NAME.get(filtered);
|
||||
+ // Cauldron end
|
||||
}
|
||||
|
||||
+ // Cauldron start - Try the ore dictionary
|
||||
+ if (result == null) {
|
||||
+ BukkitOreDictionary dict = net.minecraftforge.cauldron.api.Cauldron.getOreDictionary();
|
||||
+ OreDictionaryEntry entry = dict.getOreEntry(name);
|
||||
+ if (entry != null) {
|
||||
+ List<ItemStack> items = dict.getDefinitions(entry);
|
||||
+ if (items.size() > 0) {
|
||||
+ // TODO check sanity on multiple item results
|
||||
+ ItemStack item = items.get(0);
|
||||
+ if (item.getDurability() == 0 || item.getDurability() == Short.MAX_VALUE) {
|
||||
+ result = item.getType();
|
||||
+ } else {
|
||||
+ // bad! we have an item with data!
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Cauldron end
|
||||
+
|
||||
return result;
|
||||
}
|
||||
|
||||
+ /* =============================== Cauldron START ============================= */
|
||||
+
|
||||
+ // use a normalize() function to ensure it is accessible after a round-trip
|
||||
+ public static String normalizeName(String name) {
|
||||
+ return name.toUpperCase().replaceAll("(:|\\s)", "_").replaceAll("\\W", "");
|
||||
+ }
|
||||
+
|
||||
+ public static Material addMaterial(int id, boolean isBlock)
|
||||
+ {
|
||||
+ return addMaterial(id, "X" + String.valueOf(id), isBlock);
|
||||
+ }
|
||||
+
|
||||
+ public static Material addMaterial(int id, String name, boolean isBlock) {
|
||||
+ if (byId[id] == null) {
|
||||
+ String materialName = normalizeName(name);
|
||||
+ Material material = (Material) EnumHelper.addEnum(Material.class, materialName, new Class[]{Integer.TYPE, Boolean.TYPE}, new Object[]{Integer.valueOf(id), isBlock});
|
||||
+ byId[id] = material;
|
||||
+ BY_NAME.put(materialName, material);
|
||||
+ BY_NAME.put("X" + String.valueOf(id), material);
|
||||
+ return material;
|
||||
+ }
|
||||
+ return null;
|
||||
+ }
|
||||
+
|
||||
+ public static void setMaterialName(int id, String name, boolean flag) {
|
||||
+ String materialName = normalizeName(name);
|
||||
+
|
||||
+ if (byId[id] == null)
|
||||
+ {
|
||||
+ addMaterial(id, materialName, flag);
|
||||
+ }
|
||||
+ else // replace existing enum
|
||||
+ {
|
||||
+ /* TODO: find out how to do this with Forge's EnumHelper (addEnum?) - used for enabling descriptive (vs numeric) Material names
|
||||
+ Material material = getMaterial(id);
|
||||
+ BY_NAME.remove(material);
|
||||
+ Material newMaterial = EnumHelper.replaceEnum(Material.class, material_name, material.ordinal(), new Class[] { Integer.TYPE }, new Object[] { Integer.valueOf(id) });
|
||||
+ if (newMaterial == null)
|
||||
+ System.out.println("Error replacing Material " + name + " with id " + id);
|
||||
+ else {
|
||||
+ byId[id] = newMaterial;
|
||||
+ BY_NAME.put(material_name, newMaterial);
|
||||
+ }
|
||||
+ */
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void setup()
|
||||
+ {
|
||||
+ if (isSetup)
|
||||
+ {
|
||||
+ return;
|
||||
+ }
|
||||
+ try {
|
||||
+ Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory", new Class[0]);
|
||||
+ reflectionFactory = getReflectionFactory.invoke(null, new Object[0]);
|
||||
+ newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", new Class[] { Constructor.class });
|
||||
+ newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", new Class[] { Object[].class });
|
||||
+ newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", new Class[] { Field.class, Boolean.TYPE });
|
||||
+ fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", new Class[] { Object.class, Object.class });
|
||||
+ } catch (Exception e) {
|
||||
+ e.printStackTrace();
|
||||
+ }
|
||||
+
|
||||
+ isSetup = true;
|
||||
+ }
|
||||
+
|
||||
+ private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception {
|
||||
+ Class[] parameterTypes = null;
|
||||
+
|
||||
+ parameterTypes = new Class[additionalParameterTypes.length + 2];
|
||||
+ parameterTypes[0] = String.class;
|
||||
+ parameterTypes[1] = Integer.TYPE;
|
||||
+ System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
|
||||
+
|
||||
+ return newConstructorAccessor.invoke(reflectionFactory, new Object[] { enumClass.getDeclaredConstructor(parameterTypes) });
|
||||
+ }
|
||||
+
|
||||
+ private static <T extends Enum<?>> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception {
|
||||
+ Object[] parms = null;
|
||||
+
|
||||
+ parms = new Object[additionalValues.length + 2];
|
||||
+ parms[0] = value;
|
||||
+ parms[1] = Integer.valueOf(ordinal);
|
||||
+ System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
|
||||
+
|
||||
+ return (T)enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] { parms }));
|
||||
+ }
|
||||
+
|
||||
+ private static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception {
|
||||
+ field.setAccessible(true);
|
||||
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
|
||||
+ modifiersField.setAccessible(true);
|
||||
+ modifiersField.setInt(field, field.getModifiers() & 0xFFFFFFEF);
|
||||
+ Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, new Object[] { field, Boolean.valueOf(false) });
|
||||
+ fieldAccessorSet.invoke(fieldAccessor, new Object[] { target, value });
|
||||
+ }
|
||||
+
|
||||
+ private static void blankField(Class<?> enumClass, String fieldName) throws Exception {
|
||||
+ for (Field field : Class.class.getDeclaredFields())
|
||||
+ if (field.getName().contains(fieldName)) {
|
||||
+ field.setAccessible(true);
|
||||
+ setFailsafeFieldValue(field, enumClass, null);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private static void cleanEnumCache(Class<?> enumClass) throws Exception
|
||||
+ {
|
||||
+ blankField(enumClass, "enumConstantDirectory");
|
||||
+ blankField(enumClass, "enumConstants");
|
||||
+ }
|
||||
+
|
||||
+ public static <T extends Enum<?>> T replaceEnum(Class<T> enumType, String enumName, int ordinal, Class<?>[] paramTypes, Object[] paramValues)
|
||||
+ {
|
||||
+ if (!isSetup) setup();
|
||||
+ Field valuesField = null;
|
||||
+ Field[] fields = enumType.getDeclaredFields();
|
||||
+ int flags = 4122;
|
||||
+ String valueType = String.format("[L%s;", new Object[] { enumType.getName() });
|
||||
+
|
||||
+ for (Field field : fields) {
|
||||
+ if (((field.getModifiers() & flags) != flags) || (!field.getType().getName().equals(valueType))) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ valuesField = field;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ valuesField.setAccessible(true);
|
||||
+ try
|
||||
+ {
|
||||
+ Enum[] previousValues = (Enum[])(Enum[])valuesField.get(enumType);
|
||||
+ Enum[] newValues = new Enum[previousValues.length];
|
||||
+ Enum newValue = null;
|
||||
+ for (Enum enumValue : previousValues)
|
||||
+ {
|
||||
+ if (enumValue.ordinal() == ordinal)
|
||||
+ {
|
||||
+ newValue = makeEnum(enumType, enumName, ordinal, paramTypes, paramValues);
|
||||
+ newValues[enumValue.ordinal()] = newValue;
|
||||
+ }
|
||||
+ else newValues[enumValue.ordinal()] = enumValue;
|
||||
+ }
|
||||
+ List values = new ArrayList(Arrays.asList(newValues));
|
||||
+
|
||||
+ setFailsafeFieldValue(valuesField, null, values.toArray((Enum[])(Enum[])Array.newInstance(enumType, 0)));
|
||||
+ cleanEnumCache(enumType);
|
||||
+ return (T) newValue;
|
||||
+ } catch (Exception e) {
|
||||
+ e.printStackTrace();
|
||||
+ throw new RuntimeException(e.getMessage(), e);
|
||||
+ }
|
||||
+ }
|
||||
+ /* =============================== Cauldron END============================= */
|
||||
+
|
||||
static {
|
||||
+ // Cauldron start
|
||||
+ byId = new Material[32000];
|
||||
+ BY_NAME = Maps.newHashMap();
|
||||
+
|
||||
+ reflectionFactory = null;
|
||||
+ newConstructorAccessor = null;
|
||||
+ newInstance = null;
|
||||
+ newFieldAccessor = null;
|
||||
+ fieldAccessorSet = null;
|
||||
+ isSetup = false;
|
||||
+ // Cauldron end
|
||||
for (Material material : values()) {
|
||||
if (byId.length > material.id) {
|
||||
byId[material.id] = material;
|
72
patches/org/bukkit/World.java.patch
Normal file
72
patches/org/bukkit/World.java.patch
Normal file
@ -0,0 +1,72 @@
|
||||
--- ../src-base/minecraft/org/bukkit/World.java
|
||||
+++ ../src-work/minecraft/org/bukkit/World.java
|
||||
@@ -1155,6 +1155,56 @@
|
||||
*/
|
||||
public boolean isGameRule(String rule);
|
||||
|
||||
+ // Spigot start
|
||||
+ public class Spigot
|
||||
+ {
|
||||
+
|
||||
+ /**
|
||||
+ * Plays an effect to all players within a default radius around a given
|
||||
+ * location.
|
||||
+ *
|
||||
+ * @param location the {@link Location} around which players must be to
|
||||
+ * see the effect
|
||||
+ * @param effect the {@link Effect}
|
||||
+ * @throws IllegalArgumentException if the location or effect is null.
|
||||
+ * It also throws when the effect requires a material or a material data
|
||||
+ */
|
||||
+ public void playEffect(Location location, Effect effect)
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Plays an effect to all players within a default radius around a given
|
||||
+ * location. The effect will use the provided material (and material
|
||||
+ * data if required). The particle's position on the client will be the
|
||||
+ * given location, adjusted on each axis by a normal distribution with
|
||||
+ * mean 0 and standard deviation given in the offset parameters, each
|
||||
+ * particle has independently calculated offsets. The effect will have
|
||||
+ * the given speed and particle count if the effect is a particle. Some
|
||||
+ * effect will create multiple particles.
|
||||
+ *
|
||||
+ * @param location the {@link Location} around which players must be to
|
||||
+ * see the effect
|
||||
+ * @param effect effect the {@link Effect}
|
||||
+ * @param id the item/block/data id for the effect
|
||||
+ * @param data the data value of the block/item for the effect
|
||||
+ * @param offsetX the amount to be randomly offset by in the X axis
|
||||
+ * @param offsetY the amount to be randomly offset by in the Y axis
|
||||
+ * @param offsetZ the amount to be randomly offset by in the Z axis
|
||||
+ * @param speed the speed of the particles
|
||||
+ * @param particleCount the number of particles
|
||||
+ * @param radius the radius around the location
|
||||
+ */
|
||||
+ public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius)
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Spigot spigot();
|
||||
+ // Spigot end
|
||||
+
|
||||
/**
|
||||
* Represents various map environment types that a world may be
|
||||
*/
|
||||
@@ -1203,6 +1253,12 @@
|
||||
return lookup.get(id);
|
||||
}
|
||||
|
||||
+ // Cauldron start - allow forge to register environments
|
||||
+ public static void registerEnvironment(Environment env) {
|
||||
+ lookup.put(env.getId(),env);
|
||||
+ }
|
||||
+ // Cauldron end
|
||||
+
|
||||
static {
|
||||
for (Environment env : values()) {
|
||||
lookup.put(env.getId(), env);
|
26
patches/org/bukkit/command/Command.java.patch
Normal file
26
patches/org/bukkit/command/Command.java.patch
Normal file
@ -0,0 +1,26 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/Command.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/Command.java
|
||||
@@ -31,6 +31,7 @@
|
||||
protected String usageMessage;
|
||||
private String permission;
|
||||
private String permissionMessage;
|
||||
+ public org.spigotmc.CustomTimingsHandler timings; // Spigot
|
||||
|
||||
protected Command(String name) {
|
||||
this(name, "", "/" + name, new ArrayList<String>());
|
||||
@@ -44,6 +45,7 @@
|
||||
this.usageMessage = usageMessage;
|
||||
this.aliases = aliases;
|
||||
this.activeAliases = new ArrayList<String>(aliases);
|
||||
+ this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,6 +202,7 @@
|
||||
public boolean setLabel(String name) {
|
||||
this.nextLabel = name;
|
||||
if (!isRegistered()) {
|
||||
+ this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
|
||||
this.label = name;
|
||||
return true;
|
||||
}
|
18
patches/org/bukkit/command/SimpleCommandMap.java.patch
Normal file
18
patches/org/bukkit/command/SimpleCommandMap.java.patch
Normal file
@ -0,0 +1,18 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/SimpleCommandMap.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/SimpleCommandMap.java
|
||||
@@ -176,11 +176,15 @@
|
||||
}
|
||||
|
||||
try {
|
||||
+ target.timings.startTiming(); // Spigot
|
||||
// Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false)
|
||||
target.execute(sender, sentCommandLabel, Arrays_copyOfRange(args, 1, args.length));
|
||||
+ target.timings.stopTiming(); // Spigot
|
||||
} catch (CommandException ex) {
|
||||
+ target.timings.stopTiming(); // Spigot
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
+ target.timings.stopTiming(); // Spigot
|
||||
throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex);
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/GameModeCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/GameModeCommand.java
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
GameMode mode = GameMode.getByValue(value);
|
||||
|
||||
- if (mode == null) {
|
||||
+ if (mode == null || mode == GameMode.NOT_SET) { // Cauldron
|
||||
if (modeArg.equalsIgnoreCase("creative") || modeArg.equalsIgnoreCase("c")) {
|
||||
mode = GameMode.CREATIVE;
|
||||
} else if (modeArg.equalsIgnoreCase("adventure") || modeArg.equalsIgnoreCase("a")) {
|
@ -0,0 +1,15 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/PluginsCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/PluginsCommand.java
|
||||
@@ -40,4 +40,12 @@
|
||||
|
||||
return "(" + plugins.length + "): " + pluginList.toString();
|
||||
}
|
||||
+
|
||||
+ // Spigot Start
|
||||
+ @Override
|
||||
+ public java.util.List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException
|
||||
+ {
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
28
patches/org/bukkit/command/defaults/ReloadCommand.java.patch
Normal file
28
patches/org/bukkit/command/defaults/ReloadCommand.java.patch
Normal file
@ -0,0 +1,28 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/ReloadCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/ReloadCommand.java
|
||||
@@ -18,11 +18,25 @@
|
||||
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||
+ // Cauldron start - disable reload as it causes many issues with mods
|
||||
+ /*
|
||||
if (!testPermission(sender)) return true;
|
||||
|
||||
+ org.spigotmc.CustomTimingsHandler.reload(); // Spigot: TODO: Why is this here?
|
||||
Bukkit.reload();
|
||||
Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Reload complete.");
|
||||
+ */
|
||||
+ sender.sendMessage(ChatColor.RED + "Reload not allowed on a Cauldron server.");
|
||||
+ // Cauldron end
|
||||
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ // Spigot Start
|
||||
+ @Override
|
||||
+ public java.util.List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException
|
||||
+ {
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
19
patches/org/bukkit/command/defaults/TellCommand.java.patch
Normal file
19
patches/org/bukkit/command/defaults/TellCommand.java.patch
Normal file
@ -0,0 +1,19 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/TellCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/TellCommand.java
|
||||
@@ -45,4 +45,16 @@
|
||||
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ // Spigot Start
|
||||
+ @Override
|
||||
+ public java.util.List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException
|
||||
+ {
|
||||
+ if ( args.length == 0 )
|
||||
+ {
|
||||
+ return super.tabComplete( sender, alias, args );
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/TestForCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/TestForCommand.java
|
||||
@@ -23,4 +23,16 @@
|
||||
sender.sendMessage(ChatColor.RED + "/testfor is only usable by commandblocks with analog output.");
|
||||
return true;
|
||||
}
|
||||
+
|
||||
+ // Spigot Start
|
||||
+ @Override
|
||||
+ public java.util.List<String> tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException
|
||||
+ {
|
||||
+ if ( args.length == 0 )
|
||||
+ {
|
||||
+ return super.tabComplete( sender, alias, args );
|
||||
+ }
|
||||
+ return java.util.Collections.emptyList();
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
160
patches/org/bukkit/command/defaults/TimingsCommand.java.patch
Normal file
160
patches/org/bukkit/command/defaults/TimingsCommand.java.patch
Normal file
@ -0,0 +1,160 @@
|
||||
--- ../src-base/minecraft/org/bukkit/command/defaults/TimingsCommand.java
|
||||
+++ ../src-work/minecraft/org/bukkit/command/defaults/TimingsCommand.java
|
||||
@@ -19,23 +19,97 @@
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
+// Spigot start
|
||||
+import java.io.ByteArrayOutputStream;
|
||||
+import java.io.OutputStream;
|
||||
+import java.net.HttpURLConnection;
|
||||
+import java.net.URL;
|
||||
+import java.net.URLEncoder;
|
||||
+import java.util.logging.Level;
|
||||
+
|
||||
+import org.bukkit.command.RemoteConsoleCommandSender;
|
||||
+import org.bukkit.plugin.SimplePluginManager;
|
||||
+import org.spigotmc.CustomTimingsHandler;
|
||||
+// Spigot end
|
||||
+
|
||||
public class TimingsCommand extends BukkitCommand {
|
||||
- private static final List<String> TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate");
|
||||
+ private static final List<String> TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot
|
||||
+ public static long timingStart = 0; // Spigot
|
||||
|
||||
public TimingsCommand(String name) {
|
||||
super(name);
|
||||
- this.description = "Records timings for all plugin events";
|
||||
- this.usageMessage = "/timings <reset|merged|separate>";
|
||||
+ this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot
|
||||
+ this.usageMessage = "/timings <reset|report|on|off|paste>"; // Spigot
|
||||
this.setPermission("bukkit.command.timings");
|
||||
}
|
||||
|
||||
+ // Spigot start - redesigned Timings Command
|
||||
+ public void executeSpigotTimings(CommandSender sender, String[] args) {
|
||||
+ if ( "on".equals( args[0] ) )
|
||||
+ {
|
||||
+ ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( true );
|
||||
+ CustomTimingsHandler.reload();
|
||||
+ sender.sendMessage( "Enabled Timings & Reset" );
|
||||
+ return;
|
||||
+ } else if ( "off".equals( args[0] ) )
|
||||
+ {
|
||||
+ ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( false );
|
||||
+ sender.sendMessage( "Disabled Timings" );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if ( !Bukkit.getPluginManager().useTimings() )
|
||||
+ {
|
||||
+ sender.sendMessage( "Please enable timings by typing /timings on" );
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ boolean paste = "paste".equals( args[0] );
|
||||
+ if ("reset".equals(args[0])) {
|
||||
+ CustomTimingsHandler.reload();
|
||||
+ sender.sendMessage("Timings reset");
|
||||
+ } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) {
|
||||
+ long sampleTime = System.nanoTime() - timingStart;
|
||||
+ int index = 0;
|
||||
+ File timingFolder = new File("timings");
|
||||
+ timingFolder.mkdirs();
|
||||
+ File timings = new File(timingFolder, "timings.txt");
|
||||
+ ByteArrayOutputStream bout = ( paste ) ? new ByteArrayOutputStream() : null;
|
||||
+ while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt");
|
||||
+ PrintStream fileTimings = null;
|
||||
+ try {
|
||||
+ fileTimings = ( paste ) ? new PrintStream( bout ) : new PrintStream( timings );
|
||||
+
|
||||
+ CustomTimingsHandler.printTimings(fileTimings);
|
||||
+ fileTimings.println( "Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)" );
|
||||
+
|
||||
+ if ( paste )
|
||||
+ {
|
||||
+ new PasteThread( sender, bout ).start();
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ sender.sendMessage("Timings written to " + timings.getPath());
|
||||
+ sender.sendMessage( "Paste contents of file into form at http://www.spigotmc.org/go/timings to read results." );
|
||||
+
|
||||
+ } catch (IOException e) {
|
||||
+ } finally {
|
||||
+ if (fileTimings != null) {
|
||||
+ fileTimings.close();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+
|
||||
@Override
|
||||
public boolean execute(CommandSender sender, String currentAlias, String[] args) {
|
||||
if (!testPermission(sender)) return true;
|
||||
- if (args.length != 1) {
|
||||
+ if (args.length < 1) { // Spigot
|
||||
sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
|
||||
return false;
|
||||
}
|
||||
+ if (true) { executeSpigotTimings(sender, args); return true; } // Spigot
|
||||
if (!sender.getServer().getPluginManager().useTimings()) {
|
||||
sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml");
|
||||
return true;
|
||||
@@ -118,4 +192,55 @@
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
+
|
||||
+ // Spigot start
|
||||
+ private static class PasteThread extends Thread
|
||||
+ {
|
||||
+
|
||||
+ private final CommandSender sender;
|
||||
+ private final ByteArrayOutputStream bout;
|
||||
+
|
||||
+ public PasteThread(CommandSender sender, ByteArrayOutputStream bout)
|
||||
+ {
|
||||
+ super( "Timings paste thread" );
|
||||
+ this.sender = sender;
|
||||
+ this.bout = bout;
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public synchronized void start() {
|
||||
+ if (sender instanceof RemoteConsoleCommandSender) {
|
||||
+ run();
|
||||
+ } else {
|
||||
+ super.start();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void run()
|
||||
+ {
|
||||
+ try
|
||||
+ {
|
||||
+ HttpURLConnection con = (HttpURLConnection) new URL( "http://paste.ubuntu.com/" ).openConnection();
|
||||
+ con.setDoOutput( true );
|
||||
+ con.setRequestMethod( "POST" );
|
||||
+ con.setInstanceFollowRedirects( false );
|
||||
+
|
||||
+ OutputStream out = con.getOutputStream();
|
||||
+ out.write( "poster=Spigot&syntax=text&content=".getBytes( "UTF-8" ) );
|
||||
+ out.write( URLEncoder.encode( bout.toString( "UTF-8" ), "UTF-8" ).getBytes( "UTF-8" ) );
|
||||
+ out.close();
|
||||
+ con.getInputStream().close();
|
||||
+
|
||||
+ String location = con.getHeaderField( "Location" );
|
||||
+ String pasteID = location.substring( "http://paste.ubuntu.com/".length(), location.length() - 1 );
|
||||
+ sender.sendMessage( ChatColor.GREEN + "View timings results can be viewed at http://www.spigotmc.org/go/timings?url=" + pasteID );
|
||||
+ } catch ( IOException ex )
|
||||
+ {
|
||||
+ sender.sendMessage( ChatColor.RED + "Error pasting timings, check your console for more information" );
|
||||
+ Bukkit.getServer().getLogger().log( Level.WARNING, "Could not paste timings", ex );
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Spigot end
|
||||
}
|
17
patches/org/bukkit/conversations/BooleanPrompt.java.patch
Normal file
17
patches/org/bukkit/conversations/BooleanPrompt.java.patch
Normal file
@ -0,0 +1,17 @@
|
||||
--- ../src-base/minecraft/org/bukkit/conversations/BooleanPrompt.java
|
||||
+++ ../src-work/minecraft/org/bukkit/conversations/BooleanPrompt.java
|
||||
@@ -15,12 +15,13 @@
|
||||
|
||||
@Override
|
||||
protected boolean isInputValid(ConversationContext context, String input) {
|
||||
- String[] accepted = {"true", "false", "on", "off", "yes", "no"};
|
||||
+ String[] accepted = {"true", "false", "on", "off", "yes", "no" /* Spigot: */, "y", "n", "1", "0", "right", "wrong", "correct", "incorrect", "valid", "invalid"}; // Spigot
|
||||
return ArrayUtils.contains(accepted, input.toLowerCase());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Prompt acceptValidatedInput(ConversationContext context, String input) {
|
||||
+ if (input.equalsIgnoreCase("y") || input.equals("1") || input.equalsIgnoreCase("right") || input.equalsIgnoreCase("correct") || input.equalsIgnoreCase("valid")) input = "true"; // Spigot
|
||||
return acceptValidatedInput(context, BooleanUtils.toBoolean(input));
|
||||
}
|
||||
|
23
patches/org/bukkit/conversations/Conversation.java.patch
Normal file
23
patches/org/bukkit/conversations/Conversation.java.patch
Normal file
@ -0,0 +1,23 @@
|
||||
--- ../src-base/minecraft/org/bukkit/conversations/Conversation.java
|
||||
+++ ../src-work/minecraft/org/bukkit/conversations/Conversation.java
|
||||
@@ -209,6 +209,7 @@
|
||||
* @param input The user's chat text.
|
||||
*/
|
||||
public void acceptInput(String input) {
|
||||
+ try { // Spigot
|
||||
if (currentPrompt != null) {
|
||||
|
||||
// Echo the user's input
|
||||
@@ -228,6 +229,12 @@
|
||||
currentPrompt = currentPrompt.acceptInput(context, input);
|
||||
outputNextPrompt();
|
||||
}
|
||||
+ // Spigot Start
|
||||
+ } catch ( Throwable t )
|
||||
+ {
|
||||
+ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.SEVERE, "Error handling conversation prompt", t );
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
||||
|
||||
/**
|
25
patches/org/bukkit/entity/Arrow.java.patch
Normal file
25
patches/org/bukkit/entity/Arrow.java.patch
Normal file
@ -0,0 +1,25 @@
|
||||
--- ../src-base/minecraft/org/bukkit/entity/Arrow.java
|
||||
+++ ../src-work/minecraft/org/bukkit/entity/Arrow.java
|
||||
@@ -39,4 +39,22 @@
|
||||
* @param critical whether or not it should be critical
|
||||
*/
|
||||
public void setCritical(boolean critical);
|
||||
+
|
||||
+ // Spigot start
|
||||
+ public class Spigot extends Entity.Spigot
|
||||
+ {
|
||||
+
|
||||
+ public double getDamage()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ public void setDamage(double damage)
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Spigot spigot();
|
||||
+ // Spigot end
|
||||
}
|
25
patches/org/bukkit/entity/Entity.java.patch
Normal file
25
patches/org/bukkit/entity/Entity.java.patch
Normal file
@ -0,0 +1,25 @@
|
||||
--- ../src-base/minecraft/org/bukkit/entity/Entity.java
|
||||
+++ ../src-work/minecraft/org/bukkit/entity/Entity.java
|
||||
@@ -291,4 +291,22 @@
|
||||
* @return The current vehicle.
|
||||
*/
|
||||
public Entity getVehicle();
|
||||
+
|
||||
+ // Spigot Start
|
||||
+ public class Spigot
|
||||
+ {
|
||||
+
|
||||
+ /**
|
||||
+ * Returns whether this entity is invulnerable.
|
||||
+ *
|
||||
+ * @return True if the entity is invulnerable.
|
||||
+ */
|
||||
+ public boolean isInvulnerable()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Spigot spigot();
|
||||
+ // Spigot End
|
||||
}
|
80
patches/org/bukkit/entity/Player.java.patch
Normal file
80
patches/org/bukkit/entity/Player.java.patch
Normal file
@ -0,0 +1,80 @@
|
||||
--- ../src-base/minecraft/org/bukkit/entity/Player.java
|
||||
+++ ../src-work/minecraft/org/bukkit/entity/Player.java
|
||||
@@ -1035,4 +1035,77 @@
|
||||
* @see Player#setHealthScaled(boolean)
|
||||
*/
|
||||
public double getHealthScale();
|
||||
+
|
||||
+ // Spigot start
|
||||
+ public class Spigot extends Entity.Spigot
|
||||
+ {
|
||||
+
|
||||
+ /**
|
||||
+ * Gets the connection address of this player, regardless of whether it
|
||||
+ * has been spoofed or not.
|
||||
+ *
|
||||
+ * @return the player's connection address
|
||||
+ */
|
||||
+ public InetSocketAddress getRawAddress()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius)
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets whether the player collides with entities
|
||||
+ *
|
||||
+ * @return the player's collision toggle state
|
||||
+ */
|
||||
+ public boolean getCollidesWithEntities()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether the player collides with entities
|
||||
+ *
|
||||
+ * @param collides whether the player should collide with entities or
|
||||
+ * not.
|
||||
+ */
|
||||
+ public void setCollidesWithEntities(boolean collides)
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Respawns the player if dead.
|
||||
+ */
|
||||
+ public void respawn()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets player locale language.
|
||||
+ *
|
||||
+ * @return the player's client language settings
|
||||
+ */
|
||||
+ public String getLocale()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Gets all players hidden with {@link hidePlayer(org.bukkit.entity.Player)}.
|
||||
+ *
|
||||
+ * @return a Set with all hidden players
|
||||
+ */
|
||||
+ public java.util.Set<Player> getHiddenPlayers()
|
||||
+ {
|
||||
+ throw new UnsupportedOperationException( "Not supported yet." );
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Spigot spigot();
|
||||
+ // Spigot end
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
--- ../src-base/minecraft/org/bukkit/event/entity/EntityDamageByBlockEvent.java
|
||||
+++ ../src-work/minecraft/org/bukkit/event/entity/EntityDamageByBlockEvent.java
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
+import com.google.common.base.Function;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
@@ -22,8 +23,8 @@
|
||||
this.damager = damager;
|
||||
}
|
||||
|
||||
- public EntityDamageByBlockEvent(final Block damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
|
||||
- super(damagee, cause, modifiers);
|
||||
+ public EntityDamageByBlockEvent(final Block damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
|
||||
+ super(damagee, cause, modifiers, modifierFunctions);
|
||||
this.damager = damager;
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
--- ../src-base/minecraft/org/bukkit/event/entity/EntityDamageByEntityEvent.java
|
||||
+++ ../src-work/minecraft/org/bukkit/event/entity/EntityDamageByEntityEvent.java
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
+import com.google.common.base.Function;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
/**
|
||||
@@ -21,8 +22,8 @@
|
||||
this.damager = damager;
|
||||
}
|
||||
|
||||
- public EntityDamageByEntityEvent(final Entity damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
|
||||
- super(damagee, cause, modifiers);
|
||||
+ public EntityDamageByEntityEvent(final Entity damager, final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
|
||||
+ super(damagee, cause, modifiers, modifierFunctions);
|
||||
this.damager = damager;
|
||||
}
|
||||
|
85
patches/org/bukkit/event/entity/EntityDamageEvent.java.patch
Normal file
85
patches/org/bukkit/event/entity/EntityDamageEvent.java.patch
Normal file
@ -0,0 +1,85 @@
|
||||
--- ../src-base/minecraft/org/bukkit/event/entity/EntityDamageEvent.java
|
||||
+++ ../src-work/minecraft/org/bukkit/event/entity/EntityDamageEvent.java
|
||||
@@ -10,6 +10,8 @@
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.util.NumberConversions;
|
||||
|
||||
+import com.google.common.base.Function;
|
||||
+import com.google.common.base.Functions;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
/**
|
||||
@@ -18,7 +20,9 @@
|
||||
public class EntityDamageEvent extends EntityEvent implements Cancellable {
|
||||
private static final HandlerList handlers = new HandlerList();
|
||||
private static final DamageModifier[] MODIFIERS = DamageModifier.values();
|
||||
+ private static final Function<? super Double, Double> ZERO = Functions.constant(-0.0);
|
||||
private final Map<DamageModifier, Double> modifiers;
|
||||
+ private final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions;
|
||||
private final Map<DamageModifier, Double> originals;
|
||||
private boolean cancelled;
|
||||
private final DamageCause cause;
|
||||
@@ -30,16 +34,20 @@
|
||||
|
||||
@Deprecated
|
||||
public EntityDamageEvent(final Entity damagee, final DamageCause cause, final double damage) {
|
||||
- this(damagee, cause, new EnumMap<DamageModifier, Double>(ImmutableMap.of(DamageModifier.BASE, damage)));
|
||||
+ this(damagee, cause, new EnumMap<DamageModifier, Double>(ImmutableMap.of(DamageModifier.BASE, damage)), new EnumMap<DamageModifier, Function<? super Double, Double>>(ImmutableMap.of(DamageModifier.BASE, ZERO)));
|
||||
}
|
||||
|
||||
- public EntityDamageEvent(final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers) {
|
||||
+ public EntityDamageEvent(final Entity damagee, final DamageCause cause, final Map<DamageModifier, Double> modifiers, final Map<DamageModifier, ? extends Function<? super Double, Double>> modifierFunctions) {
|
||||
super(damagee);
|
||||
Validate.isTrue(modifiers.containsKey(DamageModifier.BASE), "BASE DamageModifier missing");
|
||||
Validate.isTrue(!modifiers.containsKey(null), "Cannot have null DamageModifier");
|
||||
+ Validate.noNullElements(modifiers.values(), "Cannot have null modifier values");
|
||||
+ Validate.isTrue(modifiers.keySet().equals(modifierFunctions.keySet()), "Must have a modifier function for each DamageModifier");
|
||||
+ Validate.noNullElements(modifierFunctions.values(), "Cannot have null modifier function");
|
||||
this.originals = new EnumMap<DamageModifier, Double>(modifiers);
|
||||
this.cause = cause;
|
||||
this.modifiers = modifiers;
|
||||
+ this.modifierFunctions = modifierFunctions;
|
||||
}
|
||||
|
||||
public boolean isCancelled() {
|
||||
@@ -149,11 +157,39 @@
|
||||
}
|
||||
|
||||
/**
|
||||
- * Sets the raw amount of damage caused by the event
|
||||
+ * Sets the raw amount of damage caused by the event.
|
||||
+ * <p>
|
||||
+ * For compatibility this also recalculates the modifiers and scales
|
||||
+ * them by the difference between the modifier for the previous damage
|
||||
+ * value and the new one.
|
||||
*
|
||||
* @param damage The raw amount of damage caused by the event
|
||||
*/
|
||||
public void setDamage(double damage) {
|
||||
+ // These have to happen in the same order as the server calculates them, keep the enum sorted
|
||||
+ double remaining = damage;
|
||||
+ double oldRemaining = getDamage(DamageModifier.BASE);
|
||||
+ for (DamageModifier modifier : MODIFIERS) {
|
||||
+ if (!isApplicable(modifier)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ Function<? super Double, Double> modifierFunction = modifierFunctions.get(modifier);
|
||||
+ double newVanilla = modifierFunction.apply(remaining);
|
||||
+ double oldVanilla = modifierFunction.apply(oldRemaining);
|
||||
+ double difference = oldVanilla - newVanilla;
|
||||
+
|
||||
+ // Don't allow value to cross zero, assume zero values should be negative
|
||||
+ double old = getDamage(modifier);
|
||||
+ if (old > 0) {
|
||||
+ setDamage(modifier, Math.max(0, old - difference));
|
||||
+ } else {
|
||||
+ setDamage(modifier, Math.min(0, old - difference));
|
||||
+ }
|
||||
+ remaining += newVanilla;
|
||||
+ oldRemaining += oldVanilla;
|
||||
+ }
|
||||
+
|
||||
setDamage(DamageModifier.BASE, damage);
|
||||
}
|
||||
|
66
patches/org/bukkit/event/player/PlayerLoginEvent.java.patch
Normal file
66
patches/org/bukkit/event/player/PlayerLoginEvent.java.patch
Normal file
@ -0,0 +1,66 @@
|
||||
--- ../src-base/minecraft/org/bukkit/event/player/PlayerLoginEvent.java
|
||||
+++ ../src-work/minecraft/org/bukkit/event/player/PlayerLoginEvent.java
|
||||
@@ -14,6 +14,7 @@
|
||||
private final String hostname;
|
||||
private Result result = Result.ALLOWED;
|
||||
private String message = "";
|
||||
+ private final InetAddress realAddress; // Spigot
|
||||
|
||||
/**
|
||||
* @deprecated Address should be provided in other constructor
|
||||
@@ -40,19 +41,26 @@
|
||||
* @param address The address the player used to connect, provided for
|
||||
* timing issues
|
||||
*/
|
||||
- public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) {
|
||||
+ public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address, final InetAddress realAddress) { // Spigot
|
||||
super(player);
|
||||
this.hostname = hostname;
|
||||
this.address = address;
|
||||
+ // Spigot start
|
||||
+ this.realAddress = address;
|
||||
}
|
||||
|
||||
+ public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) {
|
||||
+ this(player, hostname, address, address);
|
||||
+ // Spigot end
|
||||
+ }
|
||||
+
|
||||
/**
|
||||
* @deprecated Address and hostname should be provided in other
|
||||
* constructor
|
||||
*/
|
||||
@Deprecated
|
||||
public PlayerLoginEvent(final Player player, final Result result, final String message) {
|
||||
- this(player, "", null, result, message);
|
||||
+ this(player, "", null, result, message, null); // Spigot
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,13 +73,24 @@
|
||||
* @param result The result status for this event
|
||||
* @param message The message to be displayed if result denies login
|
||||
*/
|
||||
- public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message) {
|
||||
- this(player, hostname, address);
|
||||
+ public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message, final InetAddress realAddress) { // Spigot
|
||||
+ this(player, hostname, address, realAddress); // Spigot
|
||||
this.result = result;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
+ // Spigot start
|
||||
/**
|
||||
+ * Gets the connection address of this player, regardless of whether it has been spoofed or not.
|
||||
+ *
|
||||
+ * @return the player's connection address
|
||||
+ */
|
||||
+ public InetAddress getRealAddress() {
|
||||
+ return realAddress;
|
||||
+ }
|
||||
+ // Spigot end
|
||||
+
|
||||
+ /**
|
||||
* Gets the current result of the login, as an enum
|
||||
*
|
||||
* @return Current Result of the login
|
@ -0,0 +1,17 @@
|
||||
--- ../src-base/minecraft/org/bukkit/event/player/PlayerTeleportEvent.java
|
||||
+++ ../src-work/minecraft/org/bukkit/event/player/PlayerTeleportEvent.java
|
||||
@@ -55,7 +55,14 @@
|
||||
* portal
|
||||
*/
|
||||
END_PORTAL,
|
||||
+ // Cauldron start - added cause for mods
|
||||
/**
|
||||
+ * Indicates the teleportation was caused by a player entering a
|
||||
+ * Mod portal
|
||||
+ */
|
||||
+ MOD,
|
||||
+ // Cauldron end
|
||||
+ /**
|
||||
* Indicates the teleportation was caused by an event not covered by
|
||||
* this enum
|
||||
*/
|
31
patches/org/bukkit/plugin/SimplePluginManager.java.patch
Normal file
31
patches/org/bukkit/plugin/SimplePluginManager.java.patch
Normal file
@ -0,0 +1,31 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/SimplePluginManager.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/SimplePluginManager.java
|
||||
@@ -132,7 +132,9 @@
|
||||
try {
|
||||
description = loader.getPluginDescription(file);
|
||||
String name = description.getName();
|
||||
- if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")) {
|
||||
+ if (name.equalsIgnoreCase("bukkit") || name.equalsIgnoreCase("minecraft") || name.equalsIgnoreCase("mojang")
|
||||
+ // Cauldron - Add more restricted names
|
||||
+ || name.equalsIgnoreCase("spigot") || name.equalsIgnoreCase("forge") || name.equalsIgnoreCase("cauldron") || name.equalsIgnoreCase("mcpc")) {
|
||||
server.getLogger().log(Level.SEVERE, "Could not load '" + file.getPath() + "' in folder '" + directory.getPath() + "': Restricted Name");
|
||||
continue;
|
||||
} else if (description.rawName.indexOf(' ') != -1) {
|
||||
@@ -188,6 +190,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // Cauldron - fill names for Cauldron-provided dependencies
|
||||
+ loadedPlugins.addAll(ImmutableSet.of("Cauldron", "Forge", "MCPC", "MCPC+"));
|
||||
+
|
||||
while (!plugins.isEmpty()) {
|
||||
boolean missingDependency = true;
|
||||
Iterator<String> pluginIterator = plugins.keySet().iterator();
|
||||
@@ -295,6 +300,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot
|
||||
return result.toArray(new Plugin[result.size()]);
|
||||
}
|
||||
|
12
patches/org/bukkit/plugin/SimpleServicesManager.java.patch
Normal file
12
patches/org/bukkit/plugin/SimpleServicesManager.java.patch
Normal file
@ -0,0 +1,12 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/SimpleServicesManager.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/SimpleServicesManager.java
|
||||
@@ -79,7 +79,8 @@
|
||||
while (it2.hasNext()) {
|
||||
RegisteredServiceProvider<?> registered = it2.next();
|
||||
|
||||
- if (registered.getPlugin().equals(plugin)) {
|
||||
+ Plugin oPlugin = registered.getPlugin();
|
||||
+ if (oPlugin != null ? oPlugin.equals(plugin) : plugin == null) {
|
||||
it2.remove();
|
||||
unregisteredEvents.add(new ServiceUnregisterEvent(registered));
|
||||
}
|
51
patches/org/bukkit/plugin/TimedRegisteredListener.java.patch
Normal file
51
patches/org/bukkit/plugin/TimedRegisteredListener.java.patch
Normal file
@ -0,0 +1,51 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/TimedRegisteredListener.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/TimedRegisteredListener.java
|
||||
@@ -11,6 +11,10 @@
|
||||
public class TimedRegisteredListener extends RegisteredListener {
|
||||
private int count;
|
||||
private long totalTime;
|
||||
+ // Spigot start
|
||||
+ public long curTickTotal = 0;
|
||||
+ public long violations = 0;
|
||||
+ // Spigot end
|
||||
private Class<? extends Event> eventClass;
|
||||
private boolean multiple = false;
|
||||
|
||||
@@ -20,6 +24,13 @@
|
||||
|
||||
@Override
|
||||
public void callEvent(Event event) throws EventException {
|
||||
+ // Spigot start
|
||||
+ if ( org.bukkit.Bukkit.getServer() != null && !org.bukkit.Bukkit.getServer().getPluginManager().useTimings() )
|
||||
+ {
|
||||
+ super.callEvent( event );
|
||||
+ return;
|
||||
+ }
|
||||
+ // Spigot end
|
||||
if (event.isAsynchronous()) {
|
||||
super.callEvent(event);
|
||||
return;
|
||||
@@ -34,7 +45,11 @@
|
||||
}
|
||||
long start = System.nanoTime();
|
||||
super.callEvent(event);
|
||||
- totalTime += System.nanoTime() - start;
|
||||
+ // Spigot start
|
||||
+ long diff = System.nanoTime() - start;
|
||||
+ curTickTotal += diff;
|
||||
+ totalTime += diff;
|
||||
+ // Spigot end
|
||||
}
|
||||
|
||||
private static Class<?> getCommonSuperclass(Class<?> class1, Class<?> class2) {
|
||||
@@ -50,6 +65,10 @@
|
||||
public void reset() {
|
||||
count = 0;
|
||||
totalTime = 0;
|
||||
+ // Spigot start
|
||||
+ curTickTotal = 0;
|
||||
+ violations = 0;
|
||||
+ // Spigot end
|
||||
}
|
||||
|
||||
/**
|
233
patches/org/bukkit/plugin/java/JavaPluginLoader.java.patch
Normal file
233
patches/org/bukkit/plugin/java/JavaPluginLoader.java.patch
Normal file
@ -0,0 +1,233 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/java/JavaPluginLoader.java
|
||||
@@ -1,5 +1,15 @@
|
||||
package org.bukkit.plugin.java;
|
||||
|
||||
+// Cauldron start
|
||||
+import java.io.BufferedReader;
|
||||
+import java.io.InputStreamReader;
|
||||
+import com.google.common.collect.BiMap;
|
||||
+import com.google.common.collect.HashBiMap;
|
||||
+import net.md_5.specialsource.InheritanceMap;
|
||||
+import net.md_5.specialsource.JarMapping;
|
||||
+import net.md_5.specialsource.transformer.MavenShade;
|
||||
+// Cauldron end
|
||||
+
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@@ -10,6 +20,7 @@
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
+import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarEntry;
|
||||
@@ -39,8 +50,11 @@
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import org.bukkit.plugin.TimedRegisteredListener;
|
||||
import org.bukkit.plugin.UnknownDependencyException;
|
||||
+import org.spigotmc.CustomTimingsHandler; // Spigot
|
||||
import org.yaml.snakeyaml.error.YAMLException;
|
||||
|
||||
+import com.google.common.collect.ImmutableList;
|
||||
+
|
||||
/**
|
||||
* Represents a Java plugin loader, allowing plugins in the form of .jar
|
||||
*/
|
||||
@@ -49,6 +63,7 @@
|
||||
private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), };
|
||||
private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
|
||||
private final Map<String, PluginClassLoader> loaders = new LinkedHashMap<String, PluginClassLoader>();
|
||||
+ public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot
|
||||
|
||||
/**
|
||||
* This class was not meant to be constructed explicitly
|
||||
@@ -59,43 +74,41 @@
|
||||
server = instance;
|
||||
}
|
||||
|
||||
- public Plugin loadPlugin(final File file) throws InvalidPluginException {
|
||||
+ public Plugin loadPlugin(File file) throws InvalidPluginException {
|
||||
Validate.notNull(file, "File cannot be null");
|
||||
|
||||
if (!file.exists()) {
|
||||
throw new InvalidPluginException(new FileNotFoundException(file.getPath() + " does not exist"));
|
||||
}
|
||||
|
||||
- final PluginDescriptionFile description;
|
||||
+ PluginDescriptionFile description;
|
||||
try {
|
||||
description = getPluginDescription(file);
|
||||
} catch (InvalidDescriptionException ex) {
|
||||
throw new InvalidPluginException(ex);
|
||||
}
|
||||
|
||||
- final File parentFile = file.getParentFile();
|
||||
- final File dataFolder = new File(parentFile, description.getName());
|
||||
- @SuppressWarnings("deprecation")
|
||||
- final File oldDataFolder = new File(parentFile, description.getRawName());
|
||||
+ File dataFolder = new File(file.getParentFile(), description.getName());
|
||||
+ File oldDataFolder = getDataFolder(file);
|
||||
|
||||
// Found old data folder
|
||||
if (dataFolder.equals(oldDataFolder)) {
|
||||
// They are equal -- nothing needs to be done!
|
||||
} else if (dataFolder.isDirectory() && oldDataFolder.isDirectory()) {
|
||||
- server.getLogger().warning(String.format(
|
||||
- "While loading %s (%s) found old-data folder: `%s' next to the new one `%s'",
|
||||
- description.getFullName(),
|
||||
+ server.getLogger().log(Level.INFO, String.format(
|
||||
+ "While loading %s (%s) found old-data folder: %s next to the new one: %s",
|
||||
+ description.getName(),
|
||||
file,
|
||||
oldDataFolder,
|
||||
dataFolder
|
||||
));
|
||||
} else if (oldDataFolder.isDirectory() && !dataFolder.exists()) {
|
||||
if (!oldDataFolder.renameTo(dataFolder)) {
|
||||
- throw new InvalidPluginException("Unable to rename old data folder: `" + oldDataFolder + "' to: `" + dataFolder + "'");
|
||||
+ throw new InvalidPluginException("Unable to rename old data folder: '" + oldDataFolder + "' to: '" + dataFolder + "'");
|
||||
}
|
||||
server.getLogger().log(Level.INFO, String.format(
|
||||
- "While loading %s (%s) renamed data folder: `%s' to `%s'",
|
||||
- description.getFullName(),
|
||||
+ "While loading %s (%s) renamed data folder: '%s' to '%s'",
|
||||
+ description.getName(),
|
||||
file,
|
||||
oldDataFolder,
|
||||
dataFolder
|
||||
@@ -104,14 +117,19 @@
|
||||
|
||||
if (dataFolder.exists() && !dataFolder.isDirectory()) {
|
||||
throw new InvalidPluginException(String.format(
|
||||
- "Projected datafolder: `%s' for %s (%s) exists and is not a directory",
|
||||
+ "Projected datafolder: '%s' for %s (%s) exists and is not a directory",
|
||||
dataFolder,
|
||||
- description.getFullName(),
|
||||
+ description.getName(),
|
||||
file
|
||||
));
|
||||
}
|
||||
|
||||
- for (final String pluginName : description.getDepend()) {
|
||||
+ List<String> depend = description.getDepend();
|
||||
+ if (depend == null) {
|
||||
+ depend = ImmutableList.<String>of();
|
||||
+ }
|
||||
+
|
||||
+ for (String pluginName : depend) {
|
||||
if (loaders == null) {
|
||||
throw new UnknownDependencyException(pluginName);
|
||||
}
|
||||
@@ -122,7 +140,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- final PluginClassLoader loader;
|
||||
+ PluginClassLoader loader;
|
||||
try {
|
||||
loader = new PluginClassLoader(this, getClass().getClassLoader(), description, dataFolder, file);
|
||||
} catch (InvalidPluginException ex) {
|
||||
@@ -136,6 +154,26 @@
|
||||
return loader.plugin;
|
||||
}
|
||||
|
||||
+ private File getDataFolder(File file) {
|
||||
+ File dataFolder = null;
|
||||
+
|
||||
+ String filename = file.getName();
|
||||
+ int index = file.getName().lastIndexOf(".");
|
||||
+
|
||||
+ if (index != -1) {
|
||||
+ String name = filename.substring(0, index);
|
||||
+
|
||||
+ dataFolder = new File(file.getParentFile(), name);
|
||||
+ } else {
|
||||
+ // This is if there is no extension, which should not happen
|
||||
+ // Using _ to prevent name collision
|
||||
+
|
||||
+ dataFolder = new File(file.getParentFile(), filename + "_");
|
||||
+ }
|
||||
+
|
||||
+ return dataFolder;
|
||||
+ }
|
||||
+
|
||||
public PluginDescriptionFile getPluginDescription(File file) throws InvalidDescriptionException {
|
||||
Validate.notNull(file, "File cannot be null");
|
||||
|
||||
@@ -283,13 +321,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName()+"("+eventClass.getSimpleName()+")", pluginParentTimer); // Spigot
|
||||
EventExecutor executor = new EventExecutor() {
|
||||
public void execute(Listener listener, Event event) throws EventException {
|
||||
try {
|
||||
if (!eventClass.isAssignableFrom(event.getClass())) {
|
||||
return;
|
||||
}
|
||||
+ // Spigot start
|
||||
+ boolean isAsync = event.isAsynchronous();
|
||||
+ if (!isAsync) timings.startTiming();
|
||||
method.invoke(listener, event);
|
||||
+ if (!isAsync) timings.stopTiming();
|
||||
+ // Spigot end
|
||||
} catch (InvocationTargetException ex) {
|
||||
throw new EventException(ex.getCause());
|
||||
} catch (Throwable t) {
|
||||
@@ -297,7 +341,7 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
- if (useTimings) {
|
||||
+ if (false) { // Spigot - RL handles useTimings check now
|
||||
eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
|
||||
} else {
|
||||
eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
|
||||
@@ -362,4 +406,44 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // Cauldron start
|
||||
+ private InheritanceMap globalInheritanceMap = null;
|
||||
+
|
||||
+ /**
|
||||
+ * Get the inheritance map for remapping all plugins
|
||||
+ */
|
||||
+ public InheritanceMap getGlobalInheritanceMap() {
|
||||
+ if (globalInheritanceMap == null) {
|
||||
+ Map<String, String> relocationsCurrent = new HashMap<String, String>();
|
||||
+ relocationsCurrent.put("net.minecraft.server", "net.minecraft.server."+PluginClassLoader.getNativeVersion());
|
||||
+ JarMapping currentMappings = new JarMapping();
|
||||
+
|
||||
+ try {
|
||||
+ currentMappings.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("mappings/"+PluginClassLoader.getNativeVersion()+"/cb2numpkg.srg"))),
|
||||
+ new MavenShade(relocationsCurrent),
|
||||
+ null, false);
|
||||
+ } catch (IOException ex) {
|
||||
+ ex.printStackTrace();
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+
|
||||
+ BiMap<String, String> inverseClassMap = HashBiMap.create(currentMappings.classes).inverse();
|
||||
+ globalInheritanceMap = new InheritanceMap();
|
||||
+
|
||||
+ BufferedReader reader = new BufferedReader(new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("mappings/"+PluginClassLoader.getNativeVersion()+"/nms.inheritmap")));
|
||||
+
|
||||
+ try {
|
||||
+ globalInheritanceMap.load(reader, inverseClassMap);
|
||||
+ } catch (IOException ex) {
|
||||
+ ex.printStackTrace();
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+ System.out.println("Loaded inheritance map of "+globalInheritanceMap.size()+" classes");
|
||||
+ }
|
||||
+
|
||||
+ return globalInheritanceMap;
|
||||
+ }
|
||||
+ // Cauldron end
|
||||
}
|
486
patches/org/bukkit/plugin/java/PluginClassLoader.java.patch
Normal file
486
patches/org/bukkit/plugin/java/PluginClassLoader.java.patch
Normal file
@ -0,0 +1,486 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/java/PluginClassLoader.java
|
||||
@@ -1,5 +1,23 @@
|
||||
package org.bukkit.plugin.java;
|
||||
|
||||
+// Cauldron start
|
||||
+import net.md_5.specialsource.provider.ClassLoaderProvider;
|
||||
+import net.md_5.specialsource.transformer.MavenShade;
|
||||
+//import org.bouncycastle.util.io.Streams;
|
||||
+import net.md_5.specialsource.*;
|
||||
+import net.md_5.specialsource.repo.*;
|
||||
+import net.minecraft.server.MinecraftServer;
|
||||
+import net.minecraftforge.cauldron.configuration.CauldronConfig;
|
||||
+import net.minecraftforge.cauldron.CauldronUtils;
|
||||
+
|
||||
+import org.bukkit.plugin.PluginDescriptionFile;
|
||||
+import java.io.*;
|
||||
+import java.net.JarURLConnection;
|
||||
+import java.security.CodeSigner;
|
||||
+import java.security.CodeSource;
|
||||
+import java.util.concurrent.*;
|
||||
+// Cauldron end
|
||||
+
|
||||
import java.io.File;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
@@ -15,16 +33,40 @@
|
||||
/**
|
||||
* A ClassLoader for plugins, to allow shared classes across multiple plugins
|
||||
*/
|
||||
-final class PluginClassLoader extends URLClassLoader {
|
||||
+public class PluginClassLoader extends URLClassLoader {
|
||||
private final JavaPluginLoader loader;
|
||||
- private final Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
|
||||
+ private final ConcurrentMap<String, Class<?>> classes = new ConcurrentHashMap<String, Class<?>>(); // Cauldron - Threadsafe classloading
|
||||
private final PluginDescriptionFile description;
|
||||
private final File dataFolder;
|
||||
private final File file;
|
||||
- final JavaPlugin plugin;
|
||||
+ JavaPlugin plugin; // Cauldron - remove final
|
||||
private JavaPlugin pluginInit;
|
||||
private IllegalStateException pluginState;
|
||||
+ // Cauldron start
|
||||
+ private JarRemapper remapper; // class remapper for this plugin, or null
|
||||
+ private RemapperProcessor remapperProcessor; // secondary; for inheritance & remapping reflection
|
||||
+ private boolean debug; // classloader debugging
|
||||
+ private int remapFlags = -1;
|
||||
|
||||
+ private static ConcurrentMap<Integer,JarMapping> jarMappings = new ConcurrentHashMap<Integer, JarMapping>();
|
||||
+ private static final int F_GLOBAL_INHERIT = 1 << 1;
|
||||
+ private static final int F_REMAP_OBCPRE = 1 << 2;
|
||||
+ private static final int F_REMAP_NMS152 = 1 << 3;
|
||||
+ private static final int F_REMAP_NMS164 = 1 << 4;
|
||||
+ private static final int F_REMAP_NMS172 = 1 << 5;
|
||||
+ private static final int F_REMAP_NMS179 = 1 << 6;
|
||||
+ private static final int F_REMAP_NMS1710 = 1 << 7;
|
||||
+ private static final int F_REMAP_OBC152 = 1 << 8;
|
||||
+ private static final int F_REMAP_OBC164 = 1 << 9;
|
||||
+ private static final int F_REMAP_OBC172 = 1 << 10;
|
||||
+ private static final int F_REMAP_OBC179 = 1 << 11;
|
||||
+ private static final int F_REMAP_OBC1710 = 1 << 12;
|
||||
+ private static final int F_REMAP_NMSPRE_MASK= 0xffff0000; // "unversioned" NMS plugin version
|
||||
+
|
||||
+ // This trick bypasses Maven Shade's package rewriting when using String literals [same trick in jline]
|
||||
+ private static final String org_bukkit_craftbukkit = new String(new char[] {'o','r','g','/','b','u','k','k','i','t','/','c','r','a','f','t','b','u','k','k','i','t'});
|
||||
+ // Cauldron end
|
||||
+
|
||||
PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException {
|
||||
super(new URL[] {file.toURI().toURL()}, parent);
|
||||
Validate.notNull(loader, "Loader cannot be null");
|
||||
@@ -34,6 +76,113 @@
|
||||
this.dataFolder = dataFolder;
|
||||
this.file = file;
|
||||
|
||||
+ // Cauldron start
|
||||
+
|
||||
+ String pluginName = this.description.getName();
|
||||
+
|
||||
+ // configure default remapper settings
|
||||
+ boolean useCustomClassLoader = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.custom-class-loader", true);
|
||||
+ debug = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.debug", false);
|
||||
+ boolean remapNMS1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R4", true);
|
||||
+ boolean remapNMS179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R3", true);
|
||||
+ boolean remapNMS172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_7_R1", true);
|
||||
+ boolean remapNMS164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_6_R3", true);
|
||||
+ boolean remapNMS152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-nms-v1_5_R3", true);
|
||||
+ String remapNMSPre = MinecraftServer.getServer().cauldronConfig.getString("plugin-settings.default.remap-nms-pre", "false");
|
||||
+ boolean remapOBC1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R4", true);
|
||||
+ boolean remapOBC179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R3", true);
|
||||
+ boolean remapOBC172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_7_R1", true);
|
||||
+ boolean remapOBC164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_6_R3", true);
|
||||
+ boolean remapOBC152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-v1_5_R3", true);
|
||||
+ boolean remapOBCPre = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-obc-pre", false);
|
||||
+ boolean globalInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.global-inheritance", true);
|
||||
+ boolean pluginInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.plugin-inheritance", true);
|
||||
+ boolean reflectFields = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-reflect-field", true);
|
||||
+ boolean reflectClass = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-reflect-class", true);
|
||||
+ boolean allowFuture = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings.default.remap-allow-future", false);
|
||||
+
|
||||
+ // plugin-specific overrides
|
||||
+ useCustomClassLoader = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".custom-class-loader", useCustomClassLoader, false);
|
||||
+ debug = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".debug", debug, false);
|
||||
+ remapNMS1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R4", remapNMS1710, false);
|
||||
+ remapNMS179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R3", remapNMS179, false);
|
||||
+ remapNMS172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_7_R1", remapNMS172, false);
|
||||
+ remapNMS164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_6_R3", remapNMS164, false);
|
||||
+ remapNMS152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-nms-v1_5_R3", remapNMS152, false);
|
||||
+ remapNMSPre = MinecraftServer.getServer().cauldronConfig.getString("plugin-settings."+pluginName+".remap-nms-pre", remapNMSPre, false);
|
||||
+ remapOBC1710 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R4", remapOBC1710, false);
|
||||
+ remapOBC179 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R3", remapOBC179, false);
|
||||
+ remapOBC172 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_7_R1", remapOBC172, false);
|
||||
+ remapOBC164 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_6_R3", remapOBC164, false);
|
||||
+ remapOBC152 = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-v1_5_R3", remapOBC152, false);
|
||||
+ remapOBCPre = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-obc-pre", remapOBCPre, false);
|
||||
+ globalInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".global-inheritance", globalInherit, false);
|
||||
+ pluginInherit = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".plugin-inheritance", pluginInherit, false);
|
||||
+ reflectFields = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-reflect-field", reflectFields, false);
|
||||
+ reflectClass = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-reflect-class", reflectClass, false);
|
||||
+ allowFuture = MinecraftServer.getServer().cauldronConfig.getBoolean("plugin-settings."+pluginName+".remap-allow-future", allowFuture, false);
|
||||
+
|
||||
+ if (debug) {
|
||||
+ System.out.println("PluginClassLoader debugging enabled for "+pluginName);
|
||||
+ }
|
||||
+
|
||||
+ if (!useCustomClassLoader) {
|
||||
+ remapper = null;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int flags = 0;
|
||||
+ if (remapNMS1710) flags |= F_REMAP_NMS1710;
|
||||
+ if (remapNMS179) flags |= F_REMAP_NMS179;
|
||||
+ if (remapNMS172) flags |= F_REMAP_NMS172;
|
||||
+ if (remapNMS164) flags |= F_REMAP_NMS164;
|
||||
+ if (remapNMS152) flags |= F_REMAP_NMS152;
|
||||
+ if (!remapNMSPre.equals("false")) {
|
||||
+ if (remapNMSPre.equals("1.7.10")) flags |= 0x17100000;
|
||||
+ else if (remapNMSPre.equals("1.7.9")) flags |= 0x01790000;
|
||||
+ else if (remapNMSPre.equals("1.7.2")) flags |= 0x01720000;
|
||||
+ else if (remapNMSPre.equals("1.6.4")) flags |= 0x01640000;
|
||||
+ else if (remapNMSPre.equals("1.5.2")) flags |= 0x01520000;
|
||||
+ else {
|
||||
+ System.out.println("Unsupported nms-remap-pre version '"+remapNMSPre+"', disabling");
|
||||
+ }
|
||||
+ }
|
||||
+ if (remapOBC1710) flags |= F_REMAP_OBC1710;
|
||||
+ if (remapOBC179) flags |= F_REMAP_OBC179;
|
||||
+ if (remapOBC172) flags |= F_REMAP_OBC172;
|
||||
+ if (remapOBC164) flags |= F_REMAP_OBC164;
|
||||
+ if (remapOBC152) flags |= F_REMAP_OBC152;
|
||||
+ if (remapOBCPre) flags |= F_REMAP_OBCPRE;
|
||||
+ if (globalInherit) flags |= F_GLOBAL_INHERIT;
|
||||
+
|
||||
+ remapFlags = flags; // used in findClass0
|
||||
+ JarMapping jarMapping = getJarMapping(flags);
|
||||
+
|
||||
+ // Load inheritance map
|
||||
+ if ((flags & F_GLOBAL_INHERIT) != 0) {
|
||||
+ if (debug) {
|
||||
+ System.out.println("Enabling global inheritance remapping");
|
||||
+ //ClassLoaderProvider.verbose = debug; // TODO: changed in https://github.com/md-5/SpecialSource/commit/132584eda4f0860c9d14f4c142e684a027a128b8#L3L48
|
||||
+ }
|
||||
+ jarMapping.setInheritanceMap(loader.getGlobalInheritanceMap());
|
||||
+ jarMapping.setFallbackInheritanceProvider(new ClassLoaderProvider(this));
|
||||
+ }
|
||||
+
|
||||
+ remapper = new JarRemapper(jarMapping);
|
||||
+
|
||||
+ if (pluginInherit || reflectFields || reflectClass) {
|
||||
+ remapperProcessor = new RemapperProcessor(
|
||||
+ pluginInherit ? loader.getGlobalInheritanceMap() : null,
|
||||
+ (reflectFields || reflectClass) ? jarMapping : null);
|
||||
+
|
||||
+ remapperProcessor.setRemapReflectField(reflectFields);
|
||||
+ remapperProcessor.setRemapReflectClass(reflectClass);
|
||||
+ remapperProcessor.debug = debug;
|
||||
+ } else {
|
||||
+ remapperProcessor = null;
|
||||
+ }
|
||||
+ // Cauldron end
|
||||
+
|
||||
try {
|
||||
Class<?> jarClass;
|
||||
try {
|
||||
@@ -58,34 +207,290 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
- protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
+ public Class<?> findClass(String name) throws ClassNotFoundException { // Cauldron - public access for plugins to support CB NMS -> MCP class remap
|
||||
return findClass(name, true);
|
||||
}
|
||||
|
||||
- Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException {
|
||||
- if (name.startsWith("org.bukkit.") || name.startsWith("net.minecraft.")) {
|
||||
- throw new ClassNotFoundException(name);
|
||||
+ // Cauldron start
|
||||
+ /**
|
||||
+ * Get the "native" obfuscation version, from our Maven shading version.
|
||||
+ */
|
||||
+ public static String getNativeVersion() {
|
||||
+ // see https://github.com/mbax/VanishNoPacket/blob/master/src/main/java/org/kitteh/vanish/compat/NMSManager.java
|
||||
+ if (CauldronUtils.deobfuscatedEnvironment()) return "v1_7_R4"; // support plugins in deobf environment
|
||||
+ final String packageName = org.bukkit.craftbukkit.CraftServer.class.getPackage().getName();
|
||||
+ return packageName.substring(packageName.lastIndexOf('.') + 1);
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Load NMS mappings from CraftBukkit mc-dev to repackaged srgnames for FML runtime deobf
|
||||
+ *
|
||||
+ * @param jarMapping An existing JarMappings instance to load into
|
||||
+ * @param obfVersion CraftBukkit version with internal obfuscation counter identifier
|
||||
+ * >=1.4.7 this is the major version + R#. v1_4_R1=1.4.7, v1_5_R1=1.5, v1_5_R2=1.5.1..
|
||||
+ * For older versions (including pre-safeguard) it is the full Minecraft version number
|
||||
+ * @throws IOException
|
||||
+ */
|
||||
+ private void loadNmsMappings(JarMapping jarMapping, String obfVersion) throws IOException {
|
||||
+ Map<String, String> relocations = new HashMap<String, String>();
|
||||
+ // mc-dev jar to CB, apply version shading (aka plugin safeguard)
|
||||
+ relocations.put("net.minecraft.server", "net.minecraft.server." + obfVersion);
|
||||
+
|
||||
+ // support for running 1.7.10 plugins in Cauldron dev
|
||||
+ if (CauldronUtils.deobfuscatedEnvironment() && obfVersion.equals("v1_7_R4"))
|
||||
+ {
|
||||
+ jarMapping.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/cb2pkgmcp.srg"))),
|
||||
+ new MavenShade(relocations),
|
||||
+ null, false);
|
||||
+
|
||||
+ jarMapping.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/obf2pkgmcp.srg"))),
|
||||
+ null, // no version relocation for obf
|
||||
+ null, false);
|
||||
+ // resolve naming conflict in FML/CB
|
||||
+ jarMapping.methods.put("net/minecraft/server/"+obfVersion+"/PlayerConnection/getPlayer ()Lorg/bukkit/craftbukkit/entity/CraftPlayer;", "getPlayerB");
|
||||
}
|
||||
- Class<?> result = classes.get(name);
|
||||
+ else
|
||||
+ {
|
||||
+ jarMapping.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/cb2numpkg.srg"))),
|
||||
+ new MavenShade(relocations),
|
||||
+ null, false);
|
||||
|
||||
- if (result == null) {
|
||||
- if (checkGlobal) {
|
||||
- result = loader.getClassByName(name);
|
||||
+ if (obfVersion.equals("v1_7_R4")) {
|
||||
+ jarMapping.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/"+obfVersion+"/obf2numpkg.srg"))),
|
||||
+ null, // no version relocation for obf
|
||||
+ null, false);
|
||||
}
|
||||
|
||||
+ // resolve naming conflict in FML/CB
|
||||
+ jarMapping.methods.put("net/minecraft/server/"+obfVersion+"/PlayerConnection/getPlayer ()Lorg/bukkit/craftbukkit/"+getNativeVersion()+"/entity/CraftPlayer;", "getPlayerB");
|
||||
+ }
|
||||
+ // remap bouncycastle to Forge's included copy, not the vanilla obfuscated copy (not in Cauldron), see #133
|
||||
+ //jarMapping.packages.put("net/minecraft/"+obfVersion+"/org/bouncycastle", "org/bouncycastle"); No longer needed
|
||||
+ }
|
||||
+
|
||||
+ private JarMapping getJarMapping(int flags) {
|
||||
+ JarMapping jarMapping = jarMappings.get(flags);
|
||||
+
|
||||
+ if (jarMapping != null) {
|
||||
+ if (debug) {
|
||||
+ System.out.println("Mapping reused for "+Integer.toHexString(flags));
|
||||
+ }
|
||||
+ return jarMapping;
|
||||
+ }
|
||||
+
|
||||
+ jarMapping = new JarMapping();
|
||||
+ try {
|
||||
+
|
||||
+ // Guava 10 is part of the Bukkit API, so plugins can use it, but FML includes Guava 15
|
||||
+ // To resolve this conflict, remap plugin usages to Guava 10 in a separate package
|
||||
+ // Most plugins should keep this enabled, unless they want a newer Guava
|
||||
+ jarMapping.packages.put("com/google/common", "guava10/com/google/common");
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit + "/libs/com/google/gson", "com/google/gson"); // Handle Gson being in a "normal" place
|
||||
+ // Bukkit moves these packages to nms while we keep them in root so we must relocate them for plugins that rely on them
|
||||
+ jarMapping.packages.put("net/minecraft/util/io", "io");
|
||||
+ jarMapping.packages.put("net/minecraft/util/com", "com");
|
||||
+ jarMapping.packages.put("net/minecraft/util/gnu", "gnu");
|
||||
+ jarMapping.packages.put("net/minecraft/util/org", "org");
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMS1710) != 0) {
|
||||
+ loadNmsMappings(jarMapping, "v1_7_R4");
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMS179) != 0) {
|
||||
+ loadNmsMappings(jarMapping, "v1_7_R3");
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMS172) != 0) {
|
||||
+ loadNmsMappings(jarMapping, "v1_7_R1");
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMS164) != 0) {
|
||||
+ loadNmsMappings(jarMapping, "v1_6_R3");
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMS152) != 0) {
|
||||
+ loadNmsMappings(jarMapping, "v1_5_R3");
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBC1710) != 0) {
|
||||
+ if (CauldronUtils.deobfuscatedEnvironment())
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R4", org_bukkit_craftbukkit);
|
||||
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R4", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBC179) != 0) {
|
||||
+ if (CauldronUtils.deobfuscatedEnvironment())
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R3", org_bukkit_craftbukkit);
|
||||
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R3", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBC172) != 0) {
|
||||
+ if (CauldronUtils.deobfuscatedEnvironment())
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R1", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ else jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_7_R1", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBC164) != 0) {
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_6_R3", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBC152) != 0) {
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/v1_5_R3", org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_OBCPRE) != 0) {
|
||||
+ // enabling unversioned obc not currently compatible with versioned obc plugins (overmapped) -
|
||||
+ // admins should enable remap-obc-pre on a per-plugin basis, as needed
|
||||
+ // then map unversioned to current version
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit+"/libs/org/objectweb/asm", "org/objectweb/asm"); // ?
|
||||
+ jarMapping.packages.put(org_bukkit_craftbukkit, org_bukkit_craftbukkit+"/"+getNativeVersion());
|
||||
+ }
|
||||
+
|
||||
+ if ((flags & F_REMAP_NMSPRE_MASK) != 0) {
|
||||
+ String obfVersion;
|
||||
+ switch (flags & F_REMAP_NMSPRE_MASK)
|
||||
+ {
|
||||
+ case 0x17100000: obfVersion = "v1_7_R4"; break;
|
||||
+ case 0x01790000: obfVersion = "v1_7_R3"; break;
|
||||
+ case 0x01720000: obfVersion = "v1_7_R1"; break;
|
||||
+ case 0x01640000: obfVersion = "v1_6_R3"; break;
|
||||
+ case 0x01510000: obfVersion = "v1_5_R2"; break;
|
||||
+ default: throw new IllegalArgumentException("Invalid unversioned mapping flags: "+Integer.toHexString(flags & F_REMAP_NMSPRE_MASK)+" in "+Integer.toHexString(flags));
|
||||
+ }
|
||||
+
|
||||
+ jarMapping.loadMappings(
|
||||
+ new BufferedReader(new InputStreamReader(loader.getClass().getClassLoader().getResourceAsStream("mappings/" + obfVersion + "/cb2numpkg.srg"))),
|
||||
+ null, // no version relocation!
|
||||
+ null, false);
|
||||
+ }
|
||||
+
|
||||
+ System.out.println("Mapping loaded "+jarMapping.packages.size()+" packages, "+jarMapping.classes.size()+" classes, "+jarMapping.fields.size()+" fields, "+jarMapping.methods.size()+" methods, flags "+Integer.toHexString(flags));
|
||||
+
|
||||
+ JarMapping currentJarMapping = jarMappings.putIfAbsent(flags, jarMapping);
|
||||
+ return currentJarMapping == null ? jarMapping : currentJarMapping;
|
||||
+ } catch (IOException ex) {
|
||||
+ ex.printStackTrace();
|
||||
+ throw new RuntimeException(ex);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ Class<?> findClass(String name, boolean checkGlobal) throws ClassNotFoundException {
|
||||
+ // Cauldron start - remap any calls for classes with packaged nms version
|
||||
+ if (name.startsWith("net.minecraft."))
|
||||
+ {
|
||||
+ JarMapping jarMapping = this.getJarMapping(remapFlags); // grab from SpecialSource
|
||||
+ String remappedClass = jarMapping.classes.get(name.replaceAll("\\.", "\\/")); // get remapped pkgmcp class name
|
||||
+ Class<?> clazz = ((net.minecraft.launchwrapper.LaunchClassLoader)MinecraftServer.getServer().getClass().getClassLoader()).findClass(remappedClass);
|
||||
+ return clazz;
|
||||
+ }
|
||||
+ if (name.startsWith("org.bukkit.")) {
|
||||
+ if (debug) {
|
||||
+ System.out.println("Unexpected plugin findClass on OBC/NMS: name="+name+", checkGlobal="+checkGlobal+"; returning not found");
|
||||
+ }
|
||||
+ throw new ClassNotFoundException(name);
|
||||
+ }
|
||||
+ // custom loader, if enabled, threadsafety
|
||||
+ synchronized (name.intern()) {
|
||||
+ Class<?> result = classes.get(name);
|
||||
+
|
||||
if (result == null) {
|
||||
- result = super.findClass(name);
|
||||
+ if (checkGlobal) {
|
||||
+ result = loader.getClassByName(name); // Don't warn on deprecation, but maintain overridability
|
||||
+ }
|
||||
|
||||
+ if (result == null) {
|
||||
+ if (remapper == null) {
|
||||
+ result = super.findClass(name);
|
||||
+ } else {
|
||||
+ result = remappedFindClass(name);
|
||||
+ }
|
||||
+
|
||||
+ if (result != null) {
|
||||
+ loader.setClass(name, result);
|
||||
+ }
|
||||
+ }
|
||||
if (result != null) {
|
||||
- loader.setClass(name, result);
|
||||
+ Class<?> old = classes.putIfAbsent(name, result);
|
||||
+ if (old != null && old != result) {
|
||||
+ System.err.println("Defined class " + name + " twice as different classes, " + result + " and " + old);
|
||||
+ result = old;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
- classes.put(name, result);
|
||||
+ return result;
|
||||
}
|
||||
+ // Cauldron end
|
||||
+ }
|
||||
+ private Class<?> remappedFindClass(String name) throws ClassNotFoundException {
|
||||
+ Class<?> result = null;
|
||||
|
||||
+ try {
|
||||
+ // Load the resource to the name
|
||||
+ String path = name.replace('.', '/').concat(".class");
|
||||
+ URL url = this.findResource(path);
|
||||
+ if (url != null) {
|
||||
+ InputStream stream = url.openStream();
|
||||
+ if (stream != null) {
|
||||
+ byte[] bytecode = null;
|
||||
+
|
||||
+ // Reflection remap and inheritance extract
|
||||
+ if (remapperProcessor != null) {
|
||||
+ // add to inheritance map
|
||||
+ bytecode = remapperProcessor.process(stream);
|
||||
+ if (bytecode == null) stream = url.openStream();
|
||||
+ }
|
||||
+
|
||||
+ /*if (bytecode == null) {
|
||||
+ bytecode = Streams.readAll(stream);
|
||||
+ }*/
|
||||
+
|
||||
+ // Remap the classes
|
||||
+ byte[] remappedBytecode = remapper.remapClassFile(bytecode, RuntimeRepo.getInstance());
|
||||
+
|
||||
+ if (debug) {
|
||||
+ File file = new File("remapped-plugin-classes/"+name+".class");
|
||||
+ file.getParentFile().mkdirs();
|
||||
+ try {
|
||||
+ FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
+ fileOutputStream.write(remappedBytecode);
|
||||
+ fileOutputStream.close();
|
||||
+ } catch (IOException ex) {
|
||||
+ ex.printStackTrace();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Define (create) the class using the modified byte code
|
||||
+ // The top-child class loader is used for this to prevent access violations
|
||||
+ // Set the codesource to the jar, not within the jar, for compatibility with
|
||||
+ // plugins that do new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI()))
|
||||
+ // instead of using getResourceAsStream - see https://github.com/MinecraftPortCentral/Cauldron-Plus/issues/75
|
||||
+ JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection(); // parses only
|
||||
+ URL jarURL = jarURLConnection.getJarFileURL();
|
||||
+ CodeSource codeSource = new CodeSource(jarURL, new CodeSigner[0]);
|
||||
+
|
||||
+ result = this.defineClass(name, remappedBytecode, 0, remappedBytecode.length, codeSource);
|
||||
+ if (result != null) {
|
||||
+ // Resolve it - sets the class loader of the class
|
||||
+ this.resolveClass(result);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } catch (Throwable t) {
|
||||
+ if (debug) {
|
||||
+ System.out.println("remappedFindClass("+name+") exception: "+t);
|
||||
+ t.printStackTrace();
|
||||
+ }
|
||||
+ throw new ClassNotFoundException("Failed to remap class "+name, t);
|
||||
+ }
|
||||
+
|
||||
return result;
|
||||
}
|
||||
+ // Cauldron end
|
||||
|
||||
Set<String> getClasses() {
|
||||
return classes.keySet();
|
11
patches/org/bukkit/plugin/messaging/Messenger.java.patch
Normal file
11
patches/org/bukkit/plugin/messaging/Messenger.java.patch
Normal file
@ -0,0 +1,11 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/messaging/Messenger.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/messaging/Messenger.java
|
||||
@@ -18,7 +18,7 @@
|
||||
/**
|
||||
* Represents the largest size that a Plugin Channel may be.
|
||||
*/
|
||||
- public static final int MAX_CHANNEL_SIZE = 16;
|
||||
+ public static final int MAX_CHANNEL_SIZE = 20; // Cauldron - Vanilla increased limit of C17PacketCustomPayload size from 16 -> 20 in 1.7
|
||||
|
||||
/**
|
||||
* Checks if the specified channel is a reserved name.
|
@ -0,0 +1,19 @@
|
||||
--- ../src-base/minecraft/org/bukkit/plugin/messaging/StandardMessenger.java
|
||||
+++ ../src-work/minecraft/org/bukkit/plugin/messaging/StandardMessenger.java
|
||||
@@ -421,7 +421,15 @@
|
||||
Set<PluginMessageListenerRegistration> registrations = getIncomingChannelRegistrations(channel);
|
||||
|
||||
for (PluginMessageListenerRegistration registration : registrations) {
|
||||
- registration.getListener().onPluginMessageReceived(channel, source, message);
|
||||
+ // Spigot Start
|
||||
+ try
|
||||
+ {
|
||||
+ registration.getListener().onPluginMessageReceived( channel, source, message );
|
||||
+ } catch ( Throwable t )
|
||||
+ {
|
||||
+ org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Could not pass incoming plugin message to " + registration.getPlugin(), t );
|
||||
+ }
|
||||
+ // Spigot End
|
||||
}
|
||||
}
|
||||
|
57
patches/org/bukkit/potion/PotionEffectType.java.patch
Normal file
57
patches/org/bukkit/potion/PotionEffectType.java.patch
Normal file
@ -0,0 +1,57 @@
|
||||
--- ../src-base/minecraft/org/bukkit/potion/PotionEffectType.java
|
||||
+++ ../src-work/minecraft/org/bukkit/potion/PotionEffectType.java
|
||||
@@ -202,7 +202,7 @@
|
||||
return "PotionEffectType[" + id + ", " + getName() + "]";
|
||||
}
|
||||
|
||||
- private static final PotionEffectType[] byId = new PotionEffectType[24];
|
||||
+ private static final Map<Integer, PotionEffectType> byId = new HashMap<Integer, PotionEffectType>(); // Cauldron change underlying storage to map
|
||||
private static final Map<String, PotionEffectType> byName = new HashMap<String, PotionEffectType>();
|
||||
// will break on updates.
|
||||
private static boolean acceptingNew = true;
|
||||
@@ -216,9 +216,9 @@
|
||||
*/
|
||||
@Deprecated
|
||||
public static PotionEffectType getById(int id) {
|
||||
- if (id >= byId.length || id < 0)
|
||||
+ if (id >= byId.size() || id < 0) // Cauldron
|
||||
return null;
|
||||
- return byId[id];
|
||||
+ return byId.get(id); // Cauldron
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,15 +240,18 @@
|
||||
* @param type PotionType to register
|
||||
*/
|
||||
public static void registerPotionEffectType(PotionEffectType type) {
|
||||
+ // Cauldron start - allow vanilla to replace potions
|
||||
+ /*
|
||||
if (byId[type.id] != null || byName.containsKey(type.getName().toLowerCase())) {
|
||||
throw new IllegalArgumentException("Cannot set already-set type");
|
||||
} else if (!acceptingNew) {
|
||||
throw new IllegalStateException(
|
||||
"No longer accepting new potion effect types (can only be done by the server implementation)");
|
||||
}
|
||||
-
|
||||
- byId[type.id] = type;
|
||||
+ */
|
||||
+ byId.put(type.id, type);
|
||||
byName.put(type.getName().toLowerCase(), type);
|
||||
+ // Cauldron end
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -264,6 +267,11 @@
|
||||
* @return Array of types.
|
||||
*/
|
||||
public static PotionEffectType[] values() {
|
||||
- return byId.clone();
|
||||
+ // Cauldron start
|
||||
+ int maxId = 0;
|
||||
+ for(int id : byId.keySet()) maxId = Math.max(maxId, id);
|
||||
+ PotionEffectType[] result = new PotionEffectType[maxId + 1];
|
||||
+ return byId.values().toArray(result); // Cauldron change underlying storage to map
|
||||
+ // Cauldron end
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user