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:
parent
babd54bb87
commit
aaa146c10d
14 changed files with 627 additions and 0 deletions
|
@ -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");
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
{
|
|
@ -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)
|
|
@ -3,12 +3,21 @@ package net.minecraftforge.common;
|
|||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
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.BlockLiquid;
|
||||
import net.minecraft.block.material.Material;
|
||||
|
@ -47,6 +56,8 @@ import net.minecraft.util.DamageSource;
|
|||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.JsonUtils;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.WeightedRandom;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -61,6 +72,10 @@ import net.minecraft.world.IBlockAccess;
|
|||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
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.event.AnvilUpdateEvent;
|
||||
import net.minecraftforge.event.ForgeEventFactory;
|
||||
|
@ -970,4 +985,132 @@ public class ForgeHooks
|
|||
{
|
||||
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
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import net.minecraft.util.DamageSource;
|
|||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
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.storage.IPlayerFileData;
|
||||
import net.minecraft.world.storage.SaveHandler;
|
||||
import net.minecraft.world.storage.loot.LootTable;
|
||||
import net.minecraftforge.client.event.ClientChatReceivedEvent;
|
||||
import net.minecraftforge.client.event.RenderBlockOverlayEvent;
|
||||
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));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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/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/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
|
||||
|
|
|
@ -289,3 +289,7 @@ private-f net.minecraft.server.management.PlayerManager$PlayerInstance field_187
|
|||
# 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_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
|
42
src/test/java/net/minecraftforge/debug/LootTablesDebug.java
Normal file
42
src/test/java/net/minecraftforge/debug/LootTablesDebug.java
Normal 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");
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue