New LootTable interaction system and event.

Modders can now modify and reference internal elements of a loot table by name.
Editing can ONLY be done in the event and any external editing will cause a exception to be thrown.
See this gist for more information: https://gist.github.com/LexManos/77c983d67b9ad27010428478b66d50fd
This commit is contained in:
LexManos 2016-05-09 14:15:59 -07:00
parent babd54bb87
commit aaa146c10d
14 changed files with 627 additions and 0 deletions

View file

@ -0,0 +1,59 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootEntry.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootEntry.java
@@ -18,15 +18,17 @@
public abstract class LootEntry
{
+ protected final String entryName;
protected final int field_186364_c;
protected final int field_186365_d;
protected final LootCondition[] field_186366_e;
- protected LootEntry(int p_i46642_1_, int p_i46642_2_, LootCondition[] p_i46642_3_)
+ protected LootEntry(int p_i46642_1_, int p_i46642_2_, LootCondition[] p_i46642_3_, String entryName)
{
this.field_186364_c = p_i46642_1_;
this.field_186365_d = p_i46642_2_;
this.field_186366_e = p_i46642_3_;
+ this.entryName = entryName;
}
public int func_186361_a(float p_186361_1_)
@@ -34,6 +36,8 @@
return Math.max(MathHelper.func_76141_d((float)this.field_186364_c + (float)this.field_186365_d * p_186361_1_), 0);
}
+ public String getEntryName(){ return this.entryName; }
+
public abstract void func_186363_a(Collection<ItemStack> p_186363_1_, Random p_186363_2_, LootContext p_186363_3_);
protected abstract void func_186362_a(JsonObject p_186362_1_, JsonSerializationContext p_186362_2_);
@@ -57,6 +61,9 @@
alootcondition = new LootCondition[0];
}
+ LootEntry ret = net.minecraftforge.common.ForgeHooks.deserializeJsonLootEntry(s, jsonobject, i, j, alootcondition);
+ if (ret != null) return ret;
+
if (s.equals("item"))
{
return LootEntryItem.func_186367_a(jsonobject, p_deserialize_3_, i, j, alootcondition);
@@ -78,6 +85,8 @@
public JsonElement serialize(LootEntry p_serialize_1_, Type p_serialize_2_, JsonSerializationContext p_serialize_3_)
{
JsonObject jsonobject = new JsonObject();
+ if (p_serialize_1_.entryName != null && !p_serialize_1_.entryName.startsWith("custom#"))
+ jsonobject.addProperty("entryName", p_serialize_1_.entryName);
jsonobject.addProperty("weight", (Number)Integer.valueOf(p_serialize_1_.field_186364_c));
jsonobject.addProperty("quality", (Number)Integer.valueOf(p_serialize_1_.field_186365_d));
@@ -86,6 +95,9 @@
jsonobject.add("conditions", p_serialize_3_.serialize(p_serialize_1_.field_186366_e));
}
+ String type = net.minecraftforge.common.ForgeHooks.getLootEntryType(p_serialize_1_);
+ if (type != null) jsonobject.addProperty("type", type);
+ else
if (p_serialize_1_ instanceof LootEntryItem)
{
jsonobject.addProperty("type", "item");

View file

@ -0,0 +1,22 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootEntryEmpty.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootEntryEmpty.java
@@ -10,9 +10,9 @@
public class LootEntryEmpty extends LootEntry
{
- public LootEntryEmpty(int p_i46645_1_, int p_i46645_2_, LootCondition[] p_i46645_3_)
+ public LootEntryEmpty(int p_i46645_1_, int p_i46645_2_, LootCondition[] p_i46645_3_, String entryName)
{
- super(p_i46645_1_, p_i46645_2_, p_i46645_3_);
+ super(p_i46645_1_, p_i46645_2_, p_i46645_3_, entryName);
}
public void func_186363_a(Collection<ItemStack> p_186363_1_, Random p_186363_2_, LootContext p_186363_3_)
@@ -25,6 +25,6 @@
public static LootEntryEmpty func_186372_a(JsonObject p_186372_0_, JsonDeserializationContext p_186372_1_, int p_186372_2_, int p_186372_3_, LootCondition[] p_186372_4_)
{
- return new LootEntryEmpty(p_186372_2_, p_186372_3_, p_186372_4_);
+ return new LootEntryEmpty(p_186372_2_, p_186372_3_, p_186372_4_, net.minecraftforge.common.ForgeHooks.readLootEntryName(p_186372_0_, "empty"));
}
}

View file

@ -0,0 +1,39 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootEntryItem.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootEntryItem.java
@@ -18,9 +18,9 @@
protected final Item field_186368_a;
protected final LootFunction[] field_186369_b;
- public LootEntryItem(Item p_i46644_1_, int p_i46644_2_, int p_i46644_3_, LootFunction[] p_i46644_4_, LootCondition[] p_i46644_5_)
+ public LootEntryItem(Item p_i46644_1_, int p_i46644_2_, int p_i46644_3_, LootFunction[] p_i46644_4_, LootCondition[] p_i46644_5_, String entryName)
{
- super(p_i46644_2_, p_i46644_3_, p_i46644_5_);
+ super(p_i46644_2_, p_i46644_3_, p_i46644_5_, entryName);
this.field_186368_a = p_i46644_1_;
this.field_186369_b = p_i46644_4_;
}
@@ -42,7 +42,7 @@
if (itemstack.field_77994_a > 0)
{
- if (itemstack.field_77994_a < this.field_186368_a.func_77639_j())
+ if (itemstack.field_77994_a < this.field_186368_a.getItemStackLimit(itemstack))
{
p_186363_1_.add(itemstack);
}
@@ -82,6 +82,7 @@
public static LootEntryItem func_186367_a(JsonObject p_186367_0_, JsonDeserializationContext p_186367_1_, int p_186367_2_, int p_186367_3_, LootCondition[] p_186367_4_)
{
+ String name = net.minecraftforge.common.ForgeHooks.readLootEntryName(p_186367_0_, "item");
Item item = JsonUtils.func_188180_i(p_186367_0_, "name");
LootFunction[] alootfunction;
@@ -94,6 +95,6 @@
alootfunction = new LootFunction[0];
}
- return new LootEntryItem(item, p_186367_2_, p_186367_3_, alootfunction, p_186367_4_);
+ return new LootEntryItem(item, p_186367_2_, p_186367_3_, alootfunction, p_186367_4_, name);
}
}

View file

@ -0,0 +1,24 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootEntryTable.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootEntryTable.java
@@ -14,9 +14,9 @@
{
protected final ResourceLocation field_186371_a;
- public LootEntryTable(ResourceLocation p_i46639_1_, int p_i46639_2_, int p_i46639_3_, LootCondition[] p_i46639_4_)
+ public LootEntryTable(ResourceLocation p_i46639_1_, int p_i46639_2_, int p_i46639_3_, LootCondition[] p_i46639_4_, String entryName)
{
- super(p_i46639_2_, p_i46639_3_, p_i46639_4_);
+ super(p_i46639_2_, p_i46639_3_, p_i46639_4_, entryName);
this.field_186371_a = p_i46639_1_;
}
@@ -34,7 +34,8 @@
public static LootEntryTable func_186370_a(JsonObject p_186370_0_, JsonDeserializationContext p_186370_1_, int p_186370_2_, int p_186370_3_, LootCondition[] p_186370_4_)
{
+ String name = net.minecraftforge.common.ForgeHooks.readLootEntryName(p_186370_0_, "loot_table");
ResourceLocation resourcelocation = new ResourceLocation(JsonUtils.func_151200_h(p_186370_0_, "name"));
- return new LootEntryTable(resourcelocation, p_186370_2_, p_186370_3_, p_186370_4_);
+ return new LootEntryTable(resourcelocation, p_186370_2_, p_186370_3_, p_186370_4_, name);
}
}

View file

@ -0,0 +1,121 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootPool.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootPool.java
@@ -21,17 +21,19 @@
public class LootPool
{
- private final LootEntry[] field_186453_a;
- private final LootCondition[] field_186454_b;
+ private final List<LootEntry> field_186453_a;
+ private final List<LootCondition> field_186454_b;
private RandomValueRange field_186455_c;
private RandomValueRange field_186456_d;
+ private final String name;
- public LootPool(LootEntry[] p_i46643_1_, LootCondition[] p_i46643_2_, RandomValueRange p_i46643_3_, RandomValueRange p_i46643_4_)
+ private LootPool(LootEntry[] p_i46643_1_, LootCondition[] p_i46643_2_, RandomValueRange p_i46643_3_, RandomValueRange p_i46643_4_, String name)
{
- this.field_186453_a = p_i46643_1_;
- this.field_186454_b = p_i46643_2_;
+ this.field_186453_a = Lists.newArrayList(p_i46643_1_);
+ this.field_186454_b = Lists.newArrayList(p_i46643_2_);
this.field_186455_c = p_i46643_3_;
this.field_186456_d = p_i46643_4_;
+ this.name = name;
}
protected void func_186452_a(Collection<ItemStack> p_186452_1_, Random p_186452_2_, LootContext p_186452_3_)
@@ -72,7 +74,7 @@
public void func_186449_b(Collection<ItemStack> p_186449_1_, Random p_186449_2_, LootContext p_186449_3_)
{
- if (LootConditionManager.func_186638_a(this.field_186454_b, p_186449_2_, p_186449_3_))
+ if (LootConditionManager.testAllConditions(this.field_186454_b, p_186449_2_, p_186449_3_))
{
int i = this.field_186455_c.func_186511_a(p_186449_2_) + MathHelper.func_76141_d(this.field_186456_d.func_186507_b(p_186449_2_) * p_186449_3_.func_186491_f());
@@ -83,21 +85,74 @@
}
}
+ //======================== FORGE START =============================================
+ private boolean isFinalized = false;
+ public void finalize()
+ {
+ this.isFinalized = true;
+ }
+ public boolean isFinalized(){ return this.isFinalized; }
+ private void checkFinalized()
+ {
+ if (this.isFinalized())
+ throw new RuntimeException("Attempted to modify LootPool after being finalized!");
+ }
+
+ public String getName(){ return this.name; }
+ public RandomValueRange getRolls() { return this.field_186455_c; }
+ public RandomValueRange getBonusRolls() { return this.field_186456_d; }
+ public void setRolls (RandomValueRange v){ checkFinalized(); this.field_186455_c = v; }
+ public void setBonusRolls(RandomValueRange v){ checkFinalized(); this.field_186456_d = v; }
+
+ public LootEntry getEntry(String name)
+ {
+ for (LootEntry entry : this.field_186453_a)
+ if (name.equals(entry.getEntryName()))
+ return entry;
+ return null;
+ }
+ public LootEntry removeEntry(String name)
+ {
+ checkFinalized();
+ for (LootEntry entry : this.field_186453_a)
+ {
+ if (name.equals(entry.getEntryName()))
+ {
+ this.field_186453_a.remove(entry);
+ return entry;
+ }
+ }
+ return null;
+ }
+ public void addEntry(LootEntry entry)
+ {
+ checkFinalized();
+ for (LootEntry e : this.field_186453_a)
+ if (e == entry || e.getEntryName().equals(entry.getEntryName()))
+ throw new RuntimeException("Attempted to add a duplicate entry to pool: " + e.getEntryName());
+ this.field_186453_a.add(entry);
+ }
+ //TODO: Allow modifications of conditions? If so need a way to uniquely identify them.
+ //======================== FORGE END ===============================================
+
public static class Serializer implements JsonDeserializer<LootPool>, JsonSerializer<LootPool>
{
public LootPool deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_) throws JsonParseException
{
JsonObject jsonobject = JsonUtils.func_151210_l(p_deserialize_1_, "loot pool");
+ String name = net.minecraftforge.common.ForgeHooks.readPoolName(jsonobject);
LootEntry[] alootentry = (LootEntry[])JsonUtils.func_188174_a(jsonobject, "entries", p_deserialize_3_, LootEntry[].class);
LootCondition[] alootcondition = (LootCondition[])JsonUtils.func_188177_a(jsonobject, "conditions", new LootCondition[0], p_deserialize_3_, LootCondition[].class);
RandomValueRange randomvaluerange = (RandomValueRange)JsonUtils.func_188174_a(jsonobject, "rolls", p_deserialize_3_, RandomValueRange.class);
RandomValueRange randomvaluerange1 = (RandomValueRange)JsonUtils.func_188177_a(jsonobject, "bonus_rolls", new RandomValueRange(0.0F, 0.0F), p_deserialize_3_, RandomValueRange.class);
- return new LootPool(alootentry, alootcondition, randomvaluerange, randomvaluerange1);
+ return new LootPool(alootentry, alootcondition, randomvaluerange, randomvaluerange1, name);
}
public JsonElement serialize(LootPool p_serialize_1_, Type p_serialize_2_, JsonSerializationContext p_serialize_3_)
{
JsonObject jsonobject = new JsonObject();
+ if (p_serialize_1_.name != null && !p_serialize_1_.name.startsWith("custom#"))
+ jsonobject.add("name", p_serialize_3_.serialize(p_serialize_1_.name));
jsonobject.add("entries", p_serialize_3_.serialize(p_serialize_1_.field_186453_a));
jsonobject.add("rolls", p_serialize_3_.serialize(p_serialize_1_.field_186455_c));
@@ -106,7 +161,7 @@
jsonobject.add("bonus_rolls", p_serialize_3_.serialize(p_serialize_1_.field_186456_d));
}
- if (!ArrayUtils.isEmpty((Object[])p_serialize_1_.field_186454_b))
+ if (!p_serialize_1_.field_186454_b.isEmpty())
{
jsonobject.add("conditions", p_serialize_3_.serialize(p_serialize_1_.field_186454_b));
}

View file

@ -0,0 +1,75 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootTable.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootTable.java
@@ -24,11 +24,11 @@
{
private static final Logger field_186465_b = LogManager.getLogger();
public static final LootTable field_186464_a = new LootTable(new LootPool[0]);
- private final LootPool[] field_186466_c;
+ private final List<LootPool> field_186466_c;
public LootTable(LootPool[] p_i46641_1_)
{
- this.field_186466_c = p_i46641_1_;
+ this.field_186466_c = Lists.newArrayList(p_i46641_1_);
}
public List<ItemStack> func_186462_a(Random p_186462_1_, LootContext p_186462_2_)
@@ -146,6 +146,58 @@
return list;
}
+ //======================== FORGE START =============================================
+ private boolean isFinalized = false;
+ public void finalize()
+ {
+ this.isFinalized = true;
+ for (LootPool pool : this.field_186466_c)
+ pool.finalize();
+ }
+ public boolean isFinalized(){ return this.isFinalized; }
+ private void checkFinalized()
+ {
+ if (this.isFinalized())
+ throw new RuntimeException("Attempted to modify LootTable after being finalized!");
+ }
+
+ public LootPool getPool(String name)
+ {
+ for (LootPool pool : this.field_186466_c)
+ {
+ if (name.equals(pool.getName()))
+ return pool;
+ }
+ return null;
+ }
+
+ public LootPool removePool(String name)
+ {
+ checkFinalized();
+ for (LootPool pool : this.field_186466_c)
+ {
+ if (name.equals(pool.getName()))
+ {
+ this.field_186466_c.remove(pool);
+ return pool;
+ }
+ }
+
+ return null;
+ }
+
+ public void addPool(LootPool pool)
+ {
+ checkFinalized();
+ for (LootPool p : this.field_186466_c)
+ {
+ if (p == pool || p.getName().equals(pool.getName()))
+ throw new RuntimeException("Attempted to add a duplicate pool to loot table: " + pool.getName());
+ }
+ this.field_186466_c.add(pool);
+ }
+ //======================== FORGE END ===============================================
+
public static class Serializer implements JsonDeserializer<LootTable>, JsonSerializer<LootTable>
{
public LootTable deserialize(JsonElement p_deserialize_1_, Type p_deserialize_2_, JsonDeserializationContext p_deserialize_3_) throws JsonParseException

View file

@ -0,0 +1,20 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/LootTableManager.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/LootTableManager.java
@@ -102,7 +102,7 @@
try
{
- return (LootTable)LootTableManager.field_186526_b.fromJson(s, LootTable.class);
+ return net.minecraftforge.common.ForgeHooks.loadLootTable(LootTableManager.field_186526_b, p_186517_1_, s, true);
}
catch (JsonParseException jsonparseexception)
{
@@ -142,7 +142,7 @@
try
{
- return (LootTable)LootTableManager.field_186526_b.fromJson(s, LootTable.class);
+ return net.minecraftforge.common.ForgeHooks.loadLootTable(LootTableManager.field_186526_b, p_186518_1_, s, false);
}
catch (JsonParseException jsonparseexception)
{

View file

@ -0,0 +1,19 @@
--- ../src-base/minecraft/net/minecraft/world/storage/loot/conditions/LootConditionManager.java
+++ ../src-work/minecraft/net/minecraft/world/storage/loot/conditions/LootConditionManager.java
@@ -41,6 +41,16 @@
}
}
+
+ public static boolean testAllConditions(Iterable<LootCondition> conditions, Random rand, LootContext context)
+ {
+ if (conditions == null) return true;
+ for (LootCondition cond : conditions)
+ if (!cond.func_186618_a(rand, context))
+ return false;
+ return true;
+ }
+
public static boolean func_186638_a(LootCondition[] p_186638_0_, Random p_186638_1_, LootContext p_186638_2_)
{
if (p_186638_0_ == null)

View file

@ -3,12 +3,21 @@ package net.minecraftforge.common;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import com.google.common.base.Throwables;
import com.google.common.collect.Queues;
import com.google.common.collect.Sets;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid; import net.minecraft.block.BlockLiquid;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
@ -47,6 +56,8 @@ import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.JsonUtils;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.WeightedRandom; import net.minecraft.util.WeightedRandom;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -61,6 +72,10 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldSettings.GameType; import net.minecraft.world.WorldSettings.GameType;
import net.minecraft.world.storage.loot.LootEntry;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraft.world.storage.loot.LootTableManager;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.AnvilUpdateEvent; import net.minecraftforge.event.AnvilUpdateEvent;
import net.minecraftforge.event.ForgeEventFactory; import net.minecraftforge.event.ForgeEventFactory;
@ -970,4 +985,132 @@ public class ForgeHooks
{ {
MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.RightClickEmpty(player, hand)); MinecraftForge.EVENT_BUS.post(new PlayerInteractEvent.RightClickEmpty(player, hand));
} }
private static ThreadLocal<Deque<LootTableContext>> lootContext = new ThreadLocal<Deque<LootTableContext>>();
private static LootTableContext getLootTableContext()
{
LootTableContext ctx = lootContext.get().peek();
if (ctx == null)
throw new JsonParseException("Invalid call stack, could to grab json context!"); // Show I throw this? Do we care about custom deserializers outside the manager?
return ctx;
}
public static LootTable loadLootTable(Gson gson, ResourceLocation name, String data, boolean custom)
{
Deque<LootTableContext> que = lootContext.get();
if (que == null)
{
que = Queues.newArrayDeque();
lootContext.set(que);
}
LootTable ret = null;
try
{
que.push(new LootTableContext(name, custom));
ret = gson.fromJson(data, LootTable.class);
que.pop();
}
catch (JsonParseException e)
{
que.pop();
throw e;
}
if (!custom)
ret = ForgeEventFactory.loadLootTable(name, ret);
return ret;
}
private static class LootTableContext
{
public final ResourceLocation name;
private final boolean vanilla;
public final boolean custom;
public int poolCount = 0;
public int entryCount = 0;
private HashSet<String> entryNames = Sets.newHashSet();
private LootTableContext(ResourceLocation name, boolean custom)
{
this.name = name;
this.custom = custom;
this.vanilla = "minecraft".equals(this.name.getResourceDomain());
}
private void resetPoolCtx()
{
this.entryCount = 0;
this.entryNames.clear();
}
public String validateEntryName(String name)
{
if (!this.entryNames.contains(name))
{
this.entryNames.add(name);
return name;
}
if (!this.vanilla)
throw new JsonParseException("Loot Table \"" + this.name.toString() + "\" Duplicate entry name \"" + name + "\" for pool #" + (this.poolCount - 1) + " entry #" + (this.entryCount-1));
int x = 0;
while (this.entryNames.contains(name + "#" + x))
x++;
name = name + "#" + x;
this.entryNames.add(name);
return name;
}
}
public static String readPoolName(JsonObject json)
{
LootTableContext ctx = ForgeHooks.getLootTableContext();
ctx.resetPoolCtx();
if (json.has("name"))
return JsonUtils.getString(json, "name");
if (ctx.custom)
return "custom#" + json.hashCode(); //We don't care about custom ones modders shouldn't be editing them!
ctx.poolCount++;
if (!ctx.vanilla)
throw new JsonParseException("Loot Table \"" + ctx.name.toString() + "\" Missing `name` entry for pool #" + (ctx.poolCount - 1));
return ctx.poolCount == 1 ? "main" : "pool" + (ctx.poolCount - 1);
}
public static String readLootEntryName(JsonObject json, String type)
{
LootTableContext ctx = ForgeHooks.getLootTableContext();
ctx.entryCount++;
if (json.has("entryName"))
return ctx.validateEntryName(JsonUtils.getString(json, "EntryName"));
if (ctx.custom)
return "custom#" + json.hashCode(); //We don't care about custom ones modders shouldn't be editing them!
String name = null;
if ("item".equals(type))
name = JsonUtils.getString(json, "name");
else if ("loot_table".equals(type))
name = JsonUtils.getString(json, "name");
else if ("empty".equals(type))
name = "empty";
return ctx.validateEntryName(name);
}
//TODO: Some registry to support custom LootEntry types?
public static LootEntry deserializeJsonLootEntry(String type, JsonObject json, int weight, int quality, LootCondition[] conditions){ return null; }
public static String getLootEntryType(LootEntry entry){ return null; } //Companion to above function
} }

View file

@ -24,6 +24,7 @@ import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent; import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -39,6 +40,7 @@ import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.IChunkGenerator; import net.minecraft.world.chunk.IChunkGenerator;
import net.minecraft.world.storage.IPlayerFileData; import net.minecraft.world.storage.IPlayerFileData;
import net.minecraft.world.storage.SaveHandler; import net.minecraft.world.storage.SaveHandler;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraftforge.client.event.ClientChatReceivedEvent; import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.RenderBlockOverlayEvent; import net.minecraftforge.client.event.RenderBlockOverlayEvent;
import net.minecraftforge.client.event.RenderBlockOverlayEvent.OverlayType; import net.minecraftforge.client.event.RenderBlockOverlayEvent.OverlayType;
@ -541,4 +543,12 @@ public class ForgeEventFactory
MinecraftForge.EVENT_BUS.post(pre ? new PopulateChunkEvent.Pre(gen, world, rand, x, z, hasVillageGenerated) : new PopulateChunkEvent.Post(gen, world, rand, x, z, hasVillageGenerated)); MinecraftForge.EVENT_BUS.post(pre ? new PopulateChunkEvent.Pre(gen, world, rand, x, z, hasVillageGenerated) : new PopulateChunkEvent.Post(gen, world, rand, x, z, hasVillageGenerated));
} }
public static LootTable loadLootTable(ResourceLocation name, LootTable table)
{
LootTableLoadEvent event = new LootTableLoadEvent(name, table);
if (MinecraftForge.EVENT_BUS.post(event))
return LootTable.EMPTY_LOOT_TABLE;
return event.getTable();
}
} }

View file

@ -0,0 +1,43 @@
package net.minecraftforge.event;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.LootTable;
import net.minecraftforge.fml.common.eventhandler.Cancelable;
import net.minecraftforge.fml.common.eventhandler.Event;
/**
* Event fired when a LootTable json is loaded from json.
* This event is fired whenever resources are loaded, or when the server starts.
* This event will NOT be fired for LootTables loaded from the world folder, these are
* considered configurations files and should not be modified by mods.
*
* Canceling the event will make it load a empty loot table.
*
*/
@Cancelable
public class LootTableLoadEvent extends Event
{
private final ResourceLocation name;
private LootTable table;
public LootTableLoadEvent(ResourceLocation name, LootTable table)
{
this.name = name;
this.table = table;
}
public ResourceLocation getName()
{
return this.name;
}
public LootTable getTable()
{
return this.table;
}
public void setTable(LootTable table)
{
this.table = table;
}
}

View file

@ -47,3 +47,9 @@ net/minecraft/item/ItemStack.<init>(Lnet/minecraft/item/Item;IILnet/minecraft/nb
net/minecraft/block/BlockRedstoneWire.canConnectTo(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/EnumFacing;Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Z=p_176343_0_,p_176343_1_,world,pos net/minecraft/block/BlockRedstoneWire.canConnectTo(Lnet/minecraft/block/state/IBlockState;Lnet/minecraft/util/EnumFacing;Lnet/minecraft/world/IBlockAccess;Lnet/minecraft/util/math/BlockPos;)Z=p_176343_0_,p_176343_1_,world,pos
net/minecraft/client/renderer/block/model/BakedQuad.<init>([IILnet/minecraft/util/EnumFacing;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;ZLnet/minecraft/client/renderer/vertex/VertexFormat;)V=|p_i46574_1_,p_i46574_2_,p_i46574_3_,p_i46574_4_,applyDiffuseLighting,format net/minecraft/client/renderer/block/model/BakedQuad.<init>([IILnet/minecraft/util/EnumFacing;Lnet/minecraft/client/renderer/texture/TextureAtlasSprite;ZLnet/minecraft/client/renderer/vertex/VertexFormat;)V=|p_i46574_1_,p_i46574_2_,p_i46574_3_,p_i46574_4_,applyDiffuseLighting,format
net/minecraft/client/renderer/texture/TextureMap.<init>(Ljava/lang/String;Lnet/minecraft/client/renderer/texture/IIconCreator;Z)V=|p_i46100_1_,p_i46100_2_,skipFirst net/minecraft/client/renderer/texture/TextureMap.<init>(Ljava/lang/String;Lnet/minecraft/client/renderer/texture/IIconCreator;Z)V=|p_i46100_1_,p_i46100_2_,skipFirst
net/minecraft/world/storage/loot/LootPool.<init>([Lnet/minecraft/world/storage/loot/LootEntry;[Lnet/minecraft/world/storage/loot/conditions/LootCondition;Lnet/minecraft/world/storage/loot/RandomValueRange;Lnet/minecraft/world/storage/loot/RandomValueRange;Ljava/lang/String;)V=|p_i46643_1_,p_i46643_2_,p_i46643_3_,p_i46643_4_
net/minecraft/world/storage/loot/LootEntry.<init>(II[Lnet/minecraft/world/storage/loot/conditions/LootCondition;Ljava/lang/String;)V=|p_i46642_1_,p_i46642_2_,p_i46642_3_,entryName
net/minecraft/world/storage/loot/LootEntryItem.<init>(Lnet/minecraft/item/Item;II[Lnet/minecraft/world/storage/loot/functions/LootFunction;[Lnet/minecraft/world/storage/loot/conditions/LootCondition;Ljava/lang/String;)V=|p_i46644_1_,p_i46644_2_,p_i46644_3_,p_i46644_4_,p_i46644_5_,entryName
net/minecraft/world/storage/loot/LootEntryTable.<init>(Lnet/minecraft/util/ResourceLocation;II[Lnet/minecraft/world/storage/loot/conditions/LootCondition;Ljava/lang/String;)V=|p_i46639_1_,p_i46639_2_,p_i46639_3_,p_i46639_4_,entryName
net/minecraft/world/storage/loot/LootEntryEmpty.<init>(II[Lnet/minecraft/world/storage/loot/conditions/LootCondition;Ljava/lang/String;)V=|p_i46645_1_,p_i46645_2_,p_i46645_3_,entryName

View file

@ -289,3 +289,7 @@ private-f net.minecraft.server.management.PlayerManager$PlayerInstance field_187
# RenderLivingBase # RenderLivingBase
public net.minecraft.client.renderer.entity.RenderLivingBase func_177094_a(Lnet/minecraft/client/renderer/entity/layers/LayerRenderer;)Z # addLayer public net.minecraft.client.renderer.entity.RenderLivingBase func_177094_a(Lnet/minecraft/client/renderer/entity/layers/LayerRenderer;)Z # addLayer
public net.minecraft.client.renderer.entity.RenderLivingBase func_177089_b(Lnet/minecraft/client/renderer/entity/layers/LayerRenderer;)Z # removeLayer public net.minecraft.client.renderer.entity.RenderLivingBase func_177089_b(Lnet/minecraft/client/renderer/entity/layers/LayerRenderer;)Z # removeLayer
# LootTable Stuff
private-f net.minecraft.world.storage.loot.LootPool field_186455_c # rolls
private-f net.minecraft.world.storage.loot.LootPool field_186456_d # bonusRolls

View file

@ -0,0 +1,42 @@
package net.minecraftforge.debug;
import net.minecraft.init.Items;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.storage.loot.LootEntryItem;
import net.minecraft.world.storage.loot.LootPool;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraft.world.storage.loot.functions.LootFunction;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@Mod(modid=LootTablesDebug.MODID)
public class LootTablesDebug {
public static final String MODID = "loot_table_debug";
private static final ResourceLocation CUSTOM_LOOT = LootTableList.register(new ResourceLocation(MODID, "custom_loot"));
@Mod.EventHandler
public void init(FMLInitializationEvent event)
{
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void lootLoad(LootTableLoadEvent event)
{
if (!event.getName().equals(LootTableList.CHESTS_SPAWN_BONUS_CHEST))
return;
// Remove axes and replace with chestpeice, First vanilla entry is always called "main"
LootPool main = event.getTable().getPool("main"); //Note: This CAN NPE if another mod removes things
main.removeEntry("minecraft:wooden_axe");
main.removeEntry("minecraft:stone_axe");
main.addEntry(new LootEntryItem(Items.diamond_chestplate, 1, 0, new LootFunction[0], new LootCondition[0], MODID + ":diamond_chestplate"));
// Get rid of all building mats. Which is pool #3, index starts at 0, but 0 is named "main"
event.getTable().removePool("pool3");
}
}