diff --git a/src/main/java/org/dimdev/dimdoors/pockets/PocketGenerator.java b/src/main/java/org/dimdev/dimdoors/pockets/PocketGenerator.java index ead1896c..6fdc0a72 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/PocketGenerator.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/PocketGenerator.java @@ -8,6 +8,7 @@ import org.dimdev.dimdoors.DimensionalDoorsInitializer; import org.dimdev.dimdoors.ModConfig; import org.dimdev.dimdoors.rift.registry.LinkProperties; import org.dimdev.dimdoors.rift.targets.VirtualTarget; +import org.dimdev.dimdoors.util.PocketGenerationParameters; import org.dimdev.dimdoors.world.level.DimensionalRegistry; import org.dimdev.dimdoors.world.ModDimensions; import org.dimdev.dimdoors.world.pocket.Pocket; @@ -59,11 +60,12 @@ public final class PocketGenerator { } public static Pocket generateRandomPocketFromGroupV2(ServerWorld world, String group, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) { - return generatePocketV2(world, SchematicV2Handler.getInstance().getRandomPocketFromGroup(group), virtualLocation, linkTo, linkProperties); + PocketGenerationParameters parameters = new PocketGenerationParameters(world, group, virtualLocation, linkTo, linkProperties); + return generatePocketV2(SchematicV2Handler.getInstance().getRandomPocketFromGroup(group, parameters), parameters); } - public static Pocket generatePocketV2(ServerWorld world, VirtualPocket virtualPocket, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) { - return virtualPocket.prepareAndPlacePocket(world, virtualLocation, linkTo, linkProperties); + public static Pocket generatePocketV2(VirtualPocket virtualPocket, PocketGenerationParameters parameters) { + return virtualPocket.prepareAndPlacePocket(parameters); } /** diff --git a/src/main/java/org/dimdev/dimdoors/pockets/PocketTemplateV2.java b/src/main/java/org/dimdev/dimdoors/pockets/PocketTemplateV2.java index 484cebd2..7966769a 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/PocketTemplateV2.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/PocketTemplateV2.java @@ -32,7 +32,7 @@ public class PocketTemplateV2 { private final int size; private final String id; - public PocketTemplateV2(Schematic schematic, String group, int size, String id, float weight) { + public PocketTemplateV2(Schematic schematic, String group, int size, String id) { this.schematic = schematic; this.group = group; this.size = size; diff --git a/src/main/java/org/dimdev/dimdoors/pockets/SchematicV2Handler.java b/src/main/java/org/dimdev/dimdoors/pockets/SchematicV2Handler.java index 7ebfe73a..4e22f3bf 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/SchematicV2Handler.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/SchematicV2Handler.java @@ -16,7 +16,8 @@ import com.mojang.serialization.JsonOps; import net.minecraft.util.Identifier; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.dimdev.dimdoors.util.WeightedSet; +import org.dimdev.dimdoors.util.PocketGenerationParameters; +import org.dimdev.dimdoors.util.WeightedList; import org.dimdev.dimdoors.util.schematic.v2.Schematic; import net.minecraft.nbt.CompoundTag; @@ -27,7 +28,7 @@ public class SchematicV2Handler { private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create(); private static final SchematicV2Handler INSTANCE = new SchematicV2Handler(); private final Map templates = Maps.newHashMap(); - private final Map> templateMap = Maps.newHashMap(); //TODO: un-ugly-fy + private final Map> templateMap = Maps.newHashMap(); //TODO: un-ugly-fy private final List pocketTypes = Lists.newArrayList(); private static final Random RANDOM = new Random(new Random().nextLong()); private boolean loaded = false; @@ -70,17 +71,17 @@ public class SchematicV2Handler { */ private void loadResourceSchematics(PocketGroup type) throws URISyntaxException, IOException { String group = type.getGroup(); - WeightedSet weightedPockets = new WeightedSet<>(); + WeightedList weightedPockets = new WeightedList<>(); templateMap.put(group, weightedPockets); Path basePath = Paths.get(SchematicV2Handler.class.getResource(String.format("/data/dimdoors/pockets/schematic/v2/%s/", group)).toURI()); for (VirtualPocket virtualPocket : type.getEntries()) { - weightedPockets.add(virtualPocket, virtualPocket.getWeight()); + weightedPockets.add(virtualPocket); if (virtualPocket instanceof VirtualSchematicPocket) { VirtualSchematicPocket schemPocket = (VirtualSchematicPocket) virtualPocket; Path schemPath = basePath.resolve(schemPocket.getName() + ".schem"); CompoundTag schemTag = NbtIo.readCompressed(Files.newInputStream(schemPath)); Schematic schematic = Schematic.fromTag(schemTag); - PocketTemplateV2 template = new PocketTemplateV2(schematic, group, schemPocket.getSize(), schemPocket.getName(), schemPocket.getWeight()); + PocketTemplateV2 template = new PocketTemplateV2(schematic, group, schemPocket.getSize(), schemPocket.getName()); Identifier templateID = new Identifier("dimdoors", schemPocket.getName()); templates.put(templateID, template); schemPocket.setTemplateID(templateID); @@ -88,16 +89,16 @@ public class SchematicV2Handler { } } - public VirtualPocket getRandomPublicPocket() { - return getRandomPocketFromGroup("public"); + public VirtualPocket getRandomPublicPocket(PocketGenerationParameters parameters) { + return getRandomPocketFromGroup("public", parameters); } - public VirtualPocket getRandomPrivatePocket() { - return getRandomPocketFromGroup("private"); + public VirtualPocket getRandomPrivatePocket(PocketGenerationParameters parameters) { + return getRandomPocketFromGroup("private", parameters); } - public VirtualPocket getRandomPocketFromGroup(String group) { - return templateMap.get(group).getRandomWeighted(); + public VirtualPocket getRandomPocketFromGroup(String group, PocketGenerationParameters parameters) { + return templateMap.get(group).getRandomWeighted(parameters); } public static SchematicV2Handler getInstance() { diff --git a/src/main/java/org/dimdev/dimdoors/pockets/VirtualPocket.java b/src/main/java/org/dimdev/dimdoors/pockets/VirtualPocket.java index 33a13e9c..17e80172 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/VirtualPocket.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/VirtualPocket.java @@ -10,11 +10,17 @@ import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.SimpleRegistry; import org.dimdev.dimdoors.rift.registry.LinkProperties; import org.dimdev.dimdoors.rift.targets.VirtualTarget; +import org.dimdev.dimdoors.util.PocketGenerationParameters; +import org.dimdev.dimdoors.util.Weighted; import org.dimdev.dimdoors.world.pocket.Pocket; import org.dimdev.dimdoors.world.pocket.VirtualLocation; +/* + + */ + // maybe PocketEntry is a better name? Only realised after I named this that the previous PocketEntry would be redundant. -public abstract class VirtualPocket { +public abstract class VirtualPocket implements Weighted { public static final Registry> REGISTRY = FabricRegistryBuilder.from(new SimpleRegistry>(RegistryKey.ofRegistry(new Identifier("dimdoors", "virtual_pocket_type")), Lifecycle.stable())).buildAndRegister(); public static final Codec CODEC = new Codec() { @Override @@ -30,12 +36,10 @@ public abstract class VirtualPocket { }; - public abstract Pocket prepareAndPlacePocket(ServerWorld world, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties); + public abstract Pocket prepareAndPlacePocket(PocketGenerationParameters parameters); public abstract String toString(); // TODO: are equals() and hashCode() necessary? public abstract VirtualPocketType getType(); - public abstract int getWeight(); - public interface VirtualPocketType { VirtualPocketType SCHEMATIC = register("dimdoors:schematic", VirtualSchematicPocket.CODEC); diff --git a/src/main/java/org/dimdev/dimdoors/pockets/VirtualSchematicPocket.java b/src/main/java/org/dimdev/dimdoors/pockets/VirtualSchematicPocket.java index bcfd616c..c7ffbc74 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/VirtualSchematicPocket.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/VirtualSchematicPocket.java @@ -8,7 +8,8 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.dimdev.dimdoors.rift.registry.LinkProperties; import org.dimdev.dimdoors.rift.targets.VirtualTarget; -import org.dimdev.dimdoors.util.DimensionalRegistry; +import org.dimdev.dimdoors.util.PocketGenerationParameters; +import org.dimdev.dimdoors.world.level.DimensionalRegistry; import org.dimdev.dimdoors.world.pocket.Pocket; import org.dimdev.dimdoors.world.pocket.VirtualLocation; @@ -18,7 +19,7 @@ public class VirtualSchematicPocket extends VirtualPocket{ public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.INT.fieldOf("size").forGetter(VirtualSchematicPocket::getSize), Codec.STRING.fieldOf("id").forGetter(VirtualSchematicPocket::getName), - Codec.INT.optionalFieldOf("weight", 5).forGetter(VirtualSchematicPocket::getWeight) + Codec.INT.optionalFieldOf("weight", 5).forGetter(virtualSchematicPocket -> virtualSchematicPocket.getWeight(null)) ).apply(instance, VirtualSchematicPocket::new)); private final int size; @@ -49,15 +50,17 @@ public class VirtualSchematicPocket extends VirtualPocket{ } @Override - public int getWeight() { + public int getWeight(PocketGenerationParameters parameters){ return this.weight; } - - - @Override - public Pocket prepareAndPlacePocket(ServerWorld world, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) { + public Pocket prepareAndPlacePocket(PocketGenerationParameters parameters) { + ServerWorld world = parameters.getWorld(); + VirtualLocation virtualLocation = parameters.getVirtualLocation(); + VirtualTarget linkTo = parameters.getLinkTo(); + LinkProperties linkProperties = parameters.getLinkProperties(); + PocketTemplateV2 template = SchematicV2Handler.getInstance().getTemplates().get(templateID); if (template == null) throw new RuntimeException("Pocket template of id " + templateID + " not found!"); LOGGER.info("Generating pocket from template " + template.getId() + " at virtual location " + virtualLocation); diff --git a/src/main/java/org/dimdev/dimdoors/util/PocketGenerationParameters.java b/src/main/java/org/dimdev/dimdoors/util/PocketGenerationParameters.java new file mode 100644 index 00000000..e0ca5a83 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/util/PocketGenerationParameters.java @@ -0,0 +1,42 @@ +package org.dimdev.dimdoors.util; + +import net.minecraft.server.world.ServerWorld; +import org.dimdev.dimdoors.rift.registry.LinkProperties; +import org.dimdev.dimdoors.rift.targets.VirtualTarget; +import org.dimdev.dimdoors.world.pocket.VirtualLocation; + +public class PocketGenerationParameters { + private final ServerWorld world; + private final String group; + private final VirtualLocation virtualLocation; + private final VirtualTarget linkTo; + private final LinkProperties linkProperties; + + public PocketGenerationParameters(ServerWorld world, String group, VirtualLocation virtualLocation, VirtualTarget linkTo, LinkProperties linkProperties) { + this.world = world; + this.group = group; + this.virtualLocation = virtualLocation; + this.linkTo = linkTo; + this.linkProperties = linkProperties; + } + + public ServerWorld getWorld() { + return world; + } + + public String getGroup() { + return group; + } + + public VirtualLocation getVirtualLocation() { + return virtualLocation; + } + + public VirtualTarget getLinkTo() { + return linkTo; + } + + public LinkProperties getLinkProperties() { + return linkProperties; + } +} diff --git a/src/main/java/org/dimdev/dimdoors/util/Weighted.java b/src/main/java/org/dimdev/dimdoors/util/Weighted.java new file mode 100644 index 00000000..ac3a07dc --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/util/Weighted.java @@ -0,0 +1,9 @@ +package org.dimdev.dimdoors.util; + +public interface Weighted

{ + /* + Should always return the same number if the same parameters are provided. + returned number should always be >= 0 + */ + int getWeight(P parameters); +} diff --git a/src/main/java/org/dimdev/dimdoors/util/WeightedList.java b/src/main/java/org/dimdev/dimdoors/util/WeightedList.java new file mode 100644 index 00000000..0548f7d1 --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/util/WeightedList.java @@ -0,0 +1,39 @@ +package org.dimdev.dimdoors.util; + +import com.google.common.collect.Lists; + +import java.util.*; + +public class WeightedList, P> { + private final List list; + private final Random random = new Random(); + + public WeightedList() { + this.list = Lists.newArrayList(); + } + + public T getRandomWeighted(P parameters) { + int totalWeight = list.stream().mapToInt(weighted -> weighted.getWeight(parameters)).sum(); + int cursor = random.nextInt(totalWeight); + for (T weighted : list) { + cursor -= weighted.getWeight(parameters); + if (cursor <= 0) { + return weighted; // should never return an entry with weight 0, unless there are only weight 0 entries + } + } + return null; + } + + public boolean add(T t) { + return list.add(t); + } + + public boolean remove(T t){ + return list.remove(t); + } + + // TODO: make weightedList implement List instead + public List getList() { + return list; + } +} diff --git a/src/main/java/org/dimdev/dimdoors/util/WeightedSet.java b/src/main/java/org/dimdev/dimdoors/util/WeightedSet.java deleted file mode 100644 index 5ad459cf..00000000 --- a/src/main/java/org/dimdev/dimdoors/util/WeightedSet.java +++ /dev/null @@ -1,69 +0,0 @@ -package org.dimdev.dimdoors.util; - -import net.minecraft.util.Pair; - -import java.util.*; -import java.util.stream.Collectors; - -public class WeightedSet { - private final TreeSet> set; - private final int defaultWeight; - private int totalWeight = 0; - private boolean dirty = false; - private final Random random = new Random(); - - public WeightedSet() { - this(1); - } - - //TODO: ensure default Weight is >= 0? - public WeightedSet(int defaultWeight) { - this.set = new TreeSet<>((pair1, pair2) -> pair2.getRight().compareTo(pair1.getRight())); - this.defaultWeight = defaultWeight; - } - - private void markDirty() { - dirty = true; - } - - private void updateTotalWeight() { - if (dirty) totalWeight = set.stream().mapToInt(Pair::getRight).sum(); - } - - public T getRandomWeighted() { - updateTotalWeight(); - int cursor = random.nextInt(totalWeight); - for (Pair pair : set) { - cursor -= pair.getRight(); - if (cursor <= 0) { - return pair.getLeft(); // should never return an entry with weight 0, unless there are only weight 0 entries - } - } - throw new RuntimeException(); // either the list is empty, or it somehow - } - - // TODO: ensure weight is >= 0? How about a negativeWeightException? - public boolean add(T t, Integer weight) { - if (set.add(new Pair<>(t, weight))) { - markDirty(); - return true; - } - return false; - } - - public boolean add(T t) { - return add(t, defaultWeight); - } - - public boolean remove(T t){ - if (set.remove(set.stream().filter(pair -> pair.getLeft().equals(t)).findFirst().orElse(null))) { - markDirty(); - return true; - } - return false; - } - - public List getObjectList() { - return set.stream().map(Pair::getLeft).collect(Collectors.toList()); - } -}