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())
J.sfut(() -> Bukkit.getPluginManager().callEvent(event)).join();
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
@Desc("Represents loot within this object or jigsaw piece")
@Data
public class IrisObjectLoot {
public class IrisObjectLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class)
@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.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Function;
@Snippet("object-placer")
@ -130,6 +131,7 @@ public class IrisObjectPlacement {
@ArrayType(min = 1, type = IrisObjectLoot.class)
@Desc("The loot tables to apply to these objects")
private KList<IrisObjectLoot> loot = new KList<>();
@ArrayType(min = 1, type = IrisObjectVanillaLoot.class)
@Desc("The vanilla loot tables to apply to these objects")
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.")
@ -147,8 +149,7 @@ public class IrisObjectPlacement {
private KList<String> forbiddenCollisions = new KList<>();
@Desc("Ignore any placement restrictions for this object")
private boolean forcePlace = false;
private transient AtomicCache<TableCache<IrisLootTable>> cache = new AtomicCache<>();
private transient AtomicCache<TableCache<IrisVanillaLootTable>> vanillaCache = new AtomicCache<>();
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
public IrisObjectPlacement toPlacement(String... place) {
IrisObjectPlacement p = new IrisObjectPlacement();
@ -219,21 +220,24 @@ public class IrisObjectPlacement {
return (int) Math.round(densityStyle.get(rng, x, z, data));
}
private TableCache<IrisLootTable> getCache(IrisData manager) {
return cache.aquire(() -> getCache(manager, manager.getLootLoader()::load));
private TableCache getCache(IrisData manager) {
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) {
return vanillaCache.aquire(() -> getCache(manager, IrisObjectPlacement::getVanillaTable));
}
private TableCache getCache(IrisData manager, KList<? extends IObjectLoot> list, Function<String, IrisLootTable> loader) {
TableCache tc = new TableCache();
private <T> TableCache<T> getCache(IrisData manager, Function<String, T> loader) {
TableCache<T> tc = new TableCache<>();
for (IrisObjectLoot loot : getLoot()) {
for (IObjectLoot loot : list) {
if (loot == null)
continue;
T table = loader.apply(loot.getName());
IrisLootTable table = loader.apply(loot.getName());
if (table == null) {
Iris.warn("Couldn't find loot table " + loot.getName());
continue;
@ -271,10 +275,10 @@ public class IrisObjectPlacement {
@Nullable
private static IrisVanillaLootTable getVanillaTable(String name) {
NamespacedKey key = NamespacedKey.fromString(name);
if (key == null)
return null;
return new IrisVanillaLootTable(Bukkit.getLootTable(key));
return Optional.ofNullable(NamespacedKey.fromString(name))
.map(Bukkit::getLootTable)
.map(IrisVanillaLootTable::new)
.orElse(null);
}
/**
@ -285,16 +289,9 @@ public class IrisObjectPlacement {
* @return The loot table it should use.
*/
public IrisLootTable getTable(BlockData data, IrisData dataManager) {
IrisLootTable table = pickTable(data, getVanillaCache(dataManager));
if (table == null) {
table = pickTable(data, getCache(dataManager));
}
return table;
}
private <T> T pickTable(BlockData data, TableCache<T> cache) {
TableCache cache = getCache(dataManager);
if (B.isStorageChest(data)) {
T picked = null;
IrisLootTable picked = null;
if (cache.exact.containsKey(data.getMaterial()) && cache.exact.get(data.getMaterial()).containsKey(data)) {
picked = cache.exact.get(data.getMaterial()).get(data).pullRandom();
} else if (cache.basic.containsKey(data.getMaterial())) {
@ -309,9 +306,15 @@ public class IrisObjectPlacement {
return null;
}
private static class TableCache<T> {
final transient WeightedRandom<T> global = new WeightedRandom<>();
final transient KMap<Material, WeightedRandom<T>> basic = new KMap<>();
final transient KMap<Material, KMap<BlockData, WeightedRandom<T>>> exact = new KMap<>();
private static class TableCache {
final transient WeightedRandom<IrisLootTable> global = new WeightedRandom<>();
final transient KMap<Material, WeightedRandom<IrisLootTable>> basic = 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
@Desc("Represents vanilla loot within this object or jigsaw piece")
@Data
public class IrisObjectVanillaLoot {
public class IrisObjectVanillaLoot implements IObjectLoot {
private final transient AtomicCache<KList<BlockData>> filterCache = new AtomicCache<>();
@ArrayType(min = 1, type = IrisBlockData.class)
@Desc("The list of blocks this loot table should apply to")

View File

@ -20,32 +20,32 @@ public class IrisVanillaLootTable extends IrisLootTable {
@Override
public String getName() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return "Vanilla " + lootTable.getKey();
}
@Override
public int getRarity() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return 0;
}
@Override
public int getMaxPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return 0;
}
@Override
public int getMinPicked() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return 0;
}
@Override
public int getMaxTries() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return 0;
}
@Override
public KList<IrisLoot> getLoot() {
throw new IllegalStateException("Vanilla loot tables should not be used in Iris");
return new KList<>();
}
@Override
@ -55,26 +55,26 @@ public class IrisVanillaLootTable extends IrisLootTable {
@Override
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
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
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
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
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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
@SuppressWarnings("ALL")
public class KMap<K, V> extends ConcurrentHashMap<K, V> {
@ -151,6 +152,17 @@ public class KMap<K, V> extends ConcurrentHashMap<K, V> {
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
*

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);
if (++y >= maxY) {
if (++y > maxY) {
y = minY;
if (++rX > mX) {
if (++rZ > mZ) {

View File

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