fix vanilla loottables not applying

This commit is contained in:
Julian Krings 2024-12-28 00:43:01 +01:00
parent d192e2b6d1
commit 5c26ec2521
No known key found for this signature in database
GPG Key ID: 208C6E08C3B718D2
9 changed files with 79 additions and 44 deletions

View File

@ -104,6 +104,6 @@ public class IrisLootEvent extends Event {
if (!Bukkit.isPrimaryThread()) if (!Bukkit.isPrimaryThread())
J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join(); J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join();
else Bukkit.getPluginManager().callEvent(event); else Bukkit.getPluginManager().callEvent(event);
return !event.isCancelled(); return event.isCancelled();
} }
} }

View File

@ -0,0 +1,13 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.util.collection.KList;
import org.bukkit.block.data.BlockData;
public interface IObjectLoot {
KList<IrisBlockData> getFilter();
KList<BlockData> getFilter(IrisData manager);
boolean isExact();
String getName();
int getWeight();
}

View File

@ -34,7 +34,7 @@ import org.bukkit.block.data.BlockData;
@AllArgsConstructor @AllArgsConstructor
@Desc("Represents loot within this object or jigsaw piece") @Desc("Represents loot within this object or jigsaw piece")
@Data @Data
public class IrisObjectLoot { public class IrisObjectLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>(); private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class) @ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to") @Desc("The list of blocks this loot table should apply to")

View File

@ -41,6 +41,7 @@ import org.bukkit.TreeType;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
@Snippet("object-placer") @Snippet("object-placer")
@ -130,6 +131,7 @@ public class IrisObjectPlacement {
@ArrayType(min = 1, type = IrisObjectLoot.class) @ArrayType(min = 1, type = IrisObjectLoot.class)
@Desc("The loot tables to apply to these objects") @Desc("The loot tables to apply to these objects")
private KList<IrisObjectLoot> loot = new KList<>(); private KList<IrisObjectLoot> loot = new KList<>();
@ArrayType(min = 1, type = IrisObjectVanillaLoot.class)
@Desc("The vanilla loot tables to apply to these objects") @Desc("The vanilla loot tables to apply to these objects")
private KList<IrisObjectVanillaLoot> vanillaLoot = new KList<>(); private KList<IrisObjectVanillaLoot> vanillaLoot = new KList<>();
@Desc("Whether the given loot tables override any and all other loot tables available in the dimension, region or biome.") @Desc("Whether the given loot tables override any and all other loot tables available in the dimension, region or biome.")
@ -147,8 +149,7 @@ public class IrisObjectPlacement {
private KList<String> forbiddenCollisions = new KList<>(); private KList<String> forbiddenCollisions = new KList<>();
@Desc("Ignore any placement restrictions for this object") @Desc("Ignore any placement restrictions for this object")
private boolean forcePlace = false; private boolean forcePlace = false;
private transient AtomicCache<TableCache<IrisLootTable>> cache = new AtomicCache<>(); private transient AtomicCache<TableCache> cache = new AtomicCache<>();
private transient AtomicCache<TableCache<IrisVanillaLootTable>> vanillaCache = new AtomicCache<>();
public IrisObjectPlacement toPlacement(String... place) { public IrisObjectPlacement toPlacement(String... place) {
IrisObjectPlacement p = new IrisObjectPlacement(); IrisObjectPlacement p = new IrisObjectPlacement();
@ -219,21 +220,24 @@ public class IrisObjectPlacement {
return (int) Math.round(densityStyle.get(rng, x, z, data)); return (int) Math.round(densityStyle.get(rng, x, z, data));
} }
private TableCache<IrisLootTable> getCache(IrisData manager) { private TableCache getCache(IrisData manager) {
return cache.aquire(() -> getCache(manager, manager.getLootLoader()::load)); return cache.aquire(() -> {
TableCache cache = new TableCache();
cache.merge(getCache(manager, getVanillaLoot(), IrisObjectPlacement::getVanillaTable));
cache.merge(getCache(manager, getLoot(), manager.getLootLoader()::load));
return cache;
});
} }
private TableCache<IrisVanillaLootTable> getVanillaCache(IrisData manager) { private TableCache getCache(IrisData manager, KList<? extends IObjectLoot> list, Function<String, IrisLootTable> loader) {
return vanillaCache.aquire(() -> getCache(manager, IrisObjectPlacement::getVanillaTable)); TableCache tc = new TableCache();
}
private <T> TableCache<T> getCache(IrisData manager, Function<String, T> loader) { for (IObjectLoot loot : list) {
TableCache<T> tc = new TableCache<>();
for (IrisObjectLoot loot : getLoot()) {
if (loot == null) if (loot == null)
continue; continue;
T table = loader.apply(loot.getName()); IrisLootTable table = loader.apply(loot.getName());
if (table == null) { if (table == null) {
Iris.warn("Couldn't find loot table " + loot.getName()); Iris.warn("Couldn't find loot table " + loot.getName());
continue; continue;
@ -271,10 +275,10 @@ public class IrisObjectPlacement {
@Nullable @Nullable
private static IrisVanillaLootTable getVanillaTable(String name) { private static IrisVanillaLootTable getVanillaTable(String name) {
NamespacedKey key = NamespacedKey.fromString(name); return Optional.ofNullable(NamespacedKey.fromString(name))
if (key == null) .map(Bukkit::getLootTable)
return null; .map(IrisVanillaLootTable::new)
return new IrisVanillaLootTable(Bukkit.getLootTable(key)); .orElse(null);
} }
/** /**
@ -285,16 +289,9 @@ public class IrisObjectPlacement {
* @return The loot table it should use. * @return The loot table it should use.
*/ */
public IrisLootTable getTable(BlockData data, IrisData dataManager) { public IrisLootTable getTable(BlockData data, IrisData dataManager) {
IrisLootTable table = pickTable(data, getVanillaCache(dataManager)); TableCache cache = getCache(dataManager);
if (table == null) {
table = pickTable(data, getCache(dataManager));
}
return table;
}
private <T> T pickTable(BlockData data, TableCache<T> cache) {
if (B.isStorageChest(data)) { if (B.isStorageChest(data)) {
T picked = null; IrisLootTable picked = null;
if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) { if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) {
picked = cache.exact.get(data.getMaterial()).get(data).pullRandom(); picked = cache.exact.get(data.getMaterial()).get(data).pullRandom();
} else if (cache.basic.containsKey(data.getMaterial())) { } else if (cache.basic.containsKey(data.getMaterial())) {
@ -309,9 +306,15 @@ public class IrisObjectPlacement {
return null; return null;
} }
private static class TableCache<T> { private static class TableCache {
final transient WeightedRandom<T> global = new WeightedRandom<>(); final transient WeightedRandom<IrisLootTable> global = new WeightedRandom<>();
final transient KMap<Material, WeightedRandom<T>> basic = new KMap<>(); final transient KMap<Material, WeightedRandom<IrisLootTable>> basic = new KMap<>();
final transient KMap<Material, KMap<BlockData, WeightedRandom<T>>> exact = new KMap<>(); final transient KMap<Material, KMap<BlockData, WeightedRandom<IrisLootTable>>> exact = new KMap<>();
private void merge(TableCache other) {
global.merge(other.global);
basic.merge(other.basic, WeightedRandom::merge);
exact.merge(other.exact, (a, b) -> a.merge(b, WeightedRandom::merge));
}
} }
} }

View File

@ -17,7 +17,7 @@ import org.bukkit.block.data.BlockData;
@AllArgsConstructor @AllArgsConstructor
@Desc("Represents vanilla loot within this object or jigsaw piece") @Desc("Represents vanilla loot within this object or jigsaw piece")
@Data @Data
public class IrisObjectVanillaLoot { public class IrisObjectVanillaLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>(); private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class) @ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to") @Desc("The list of blocks this loot table should apply to")

View File

@ -20,32 +20,32 @@ public class IrisVanillaLootTable extends IrisLootTable {
@Override @Override
public String getName() { public String getName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return "Vanilla " + lootTable.getKey();
} }
@Override @Override
public int getRarity() { public int getRarity() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMaxPicked() { public int getMaxPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMinPicked() { public int getMinPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public int getMaxTries() { public int getMaxTries() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return 0;
} }
@Override @Override
public KList<IrisLoot> getLoot() { public KList<IrisLoot> getLoot() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return new KList<>();
} }
@Override @Override
@ -55,26 +55,26 @@ public class IrisVanillaLootTable extends IrisLootTable {
@Override @Override
public String getFolderName() { public String getFolderName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a folder name");
} }
@Override @Override
public String getTypeName() { public String getTypeName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a type name");
} }
@Override @Override
public File getLoadFile() { public File getLoadFile() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a load file");
} }
@Override @Override
public IrisData getLoader() { public IrisData getLoader() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); throw new UnsupportedOperationException("VanillaLootTables do not have a loader");
} }
@Override @Override
public KList<String> getPreprocessors() { public KList<String> getPreprocessors() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris"); return new KList<>();
} }
} }

View File

@ -28,6 +28,7 @@ import java.util.Comparator;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public class KMap<K, V> extends ConcurrentHashMap<K, V> { public class KMap<K, V> extends ConcurrentHashMap<K, V> {
@ -151,6 +152,17 @@ public class KMap<K, V> extends ConcurrentHashMap<K, V> {
return this; return this;
} }
/**
* Merge with another map
*
* @param m the map to merge
* @return this map (builder)
*/
public KMap<K, V> merge(KMap<K, V> m, BiFunction<V, V, V> merger) {
m.forEach((k, v) -> merge(k, v, merger));
return this;
}
/** /**
* Return a copy of this map * Return a copy of this map
* *

View File

@ -810,7 +810,7 @@ public class Cuboid implements Iterable<Block>, Cloneable, ConfigurationSerializ
} }
var b = w.getBlockAt((chunk.getX() << 4) + rX, y, (chunk.getZ() << 4) + rZ); var b = w.getBlockAt((chunk.getX() << 4) + rX, y, (chunk.getZ() << 4) + rZ);
if (++y >= maxY) { if (++y > maxY) {
y = minY; y = minY;
if (++rX > mX) { if (++rX > mX) {
if (++rZ > mZ) { if (++rZ > mZ) {

View File

@ -42,11 +42,18 @@ public class WeightedRandom<T> {
totalWeight += weight; totalWeight += weight;
} }
public WeightedRandom<T> merge(WeightedRandom<T> other) {
weightedObjects.addAll(other.weightedObjects);
totalWeight += other.totalWeight;
return this;
}
public T pullRandom() { public T pullRandom() {
int pull = random.nextInt(totalWeight); int pull = random.nextInt(totalWeight);
int index = 0; int index = 0;
while (pull > 0) { while (pull > 0) {
pull -= weightedObjects.get(index).getV(); pull -= weightedObjects.get(index).getV();
if (pull <= 0) break;
index++; index++;
} }
return weightedObjects.get(index).getK(); return weightedObjects.get(index).getK();