A bit of general cleanup

This commit is contained in:
Sollace 2022-10-06 23:04:32 +02:00
parent 8f45fcf811
commit 7a8ba44f0d
5 changed files with 78 additions and 96 deletions

View file

@ -8,7 +8,6 @@ import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
@ -20,9 +19,9 @@ public interface TreeType {
TreeType NONE = new TreeTypeImpl(
Unicopia.id("none"),
false,
new Weighted<Supplier<ItemStack>>(),
Set.of(),
Set.of()
Set.of(),
Weighted.of()
);
Direction[] WIDE_DIRS = new Direction[] { Direction.UP, Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST };

View file

@ -1,7 +1,6 @@
package com.minelittlepony.unicopia.ability.data.tree;
import com.minelittlepony.unicopia.util.Weighted;
import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
@ -11,21 +10,13 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public final class TreeTypeImpl implements TreeType {
private final Identifier name;
private final boolean wideTrunk;
private final Set<Identifier> logs;
private final Set<Identifier> leaves;
private final Weighted<Supplier<ItemStack>> pool;
TreeTypeImpl(Identifier name, boolean wideTrunk, Weighted<Supplier<ItemStack>> pool, Set<Identifier> logs, Set<Identifier> leaves) {
this.name = name;
this.wideTrunk = wideTrunk;
this.pool = pool;
this.logs = logs;
this.leaves = leaves;
}
public record TreeTypeImpl (
Identifier name,
boolean wideTrunk,
Set<Identifier> logs,
Set<Identifier> leaves,
Supplier<Optional<Supplier<ItemStack>>> pool
) implements TreeType {
@Override
public boolean isLeaves(BlockState state) {
return findMatch(leaves, state) && isNonPersistent(state);
@ -46,20 +37,10 @@ public final class TreeTypeImpl implements TreeType {
return pool.get().map(Supplier::get).orElse(ItemStack.EMPTY);
}
@Override
public boolean equals(Object o) {
return o instanceof TreeTypeImpl && name.compareTo(((TreeTypeImpl)o).name) == 0;
}
private static boolean findMatch(Set<Identifier> ids, BlockState state) {
return ids.contains(Registry.BLOCK.getId(state.getBlock()));
}
@Override
public int hashCode() {
return name.hashCode();
}
static boolean isNonPersistent(BlockState state) {
return !state.contains(LeavesBlock.PERSISTENT) || !state.get(LeavesBlock.PERSISTENT);
}

View file

@ -65,18 +65,13 @@ public class TreeTypeLoader extends JsonDataLoader implements IdentifiableResour
wideTrunk = buffer.readBoolean();
}
private Weighted<Supplier<ItemStack>> getWeighted(Weighted<Supplier<ItemStack>> weighted) {
drops.forEach(drop -> drop.appendDrop(weighted));
return weighted;
}
public TreeType toTreeType(Identifier id) {
return new TreeTypeImpl(
id,
wideTrunk,
getWeighted(new Weighted<Supplier<ItemStack>>()),
Objects.requireNonNull(logs, "TreeType must have logs"),
Objects.requireNonNull(leaves, "TreeType must have leaves")
Objects.requireNonNull(leaves, "TreeType must have leaves"),
Weighted.of(weighted -> drops.forEach(drop -> drop.appendDrop(weighted)))
);
}
@ -96,7 +91,7 @@ public class TreeTypeLoader extends JsonDataLoader implements IdentifiableResour
item = buffer.readIdentifier();
}
void appendDrop(Weighted<Supplier<ItemStack>> weighted) {
void appendDrop(Weighted.Builder<Supplier<ItemStack>> weighted) {
Registry.ITEM.getOrEmpty(item).ifPresent(item -> {
weighted.put(weight, item::getDefaultStack);
});

View file

@ -1,7 +1,7 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.function.Supplier;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.AbstractAreaEffectSpell;
@ -32,12 +32,13 @@ import net.minecraft.world.WorldEvents;
* An area-effect spell that summons the undead.
*/
public class NecromancySpell extends AbstractAreaEffectSpell {
private final Weighted<EntityType<? extends LivingEntity>> spawnPool = new Weighted<EntityType<? extends LivingEntity>>()
private final Supplier<Optional<EntityType<? extends LivingEntity>>> spawnPool = new Weighted.Builder<EntityType<? extends LivingEntity>>()
.put(7, EntityType.ZOMBIE)
.put(4, EntityType.HUSK)
.put(3, EntityType.DROWNED)
.put(2, EntityType.ZOMBIFIED_PIGLIN)
.put(1, EntityType.ZOMBIE_VILLAGER);
.put(1, EntityType.ZOMBIE_VILLAGER)
.build();
private final List<EntityReference<LivingEntity>> summonedEntities = new ArrayList<>();

View file

@ -1,80 +1,86 @@
package com.minelittlepony.unicopia.util;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jetbrains.annotations.NotNull;
import com.google.common.collect.Lists;
import net.minecraft.util.Pair;
public class Weighted<T> {
public final class Weighted {
private static final Supplier<Optional<?>> EMPTY = Optional::empty;
private static final Random rand = new Random();
private float totalWeight = 0;
private final List<Entry> entries = Lists.newArrayList();
public static <T> Weighted<T> of(Consumer<Weighted<T>> constructor) {
Weighted<T> result = new Weighted<>();
@SuppressWarnings("unchecked")
public static <T> Supplier<Optional<T>> of() {
return (Supplier<Optional<T>>)(Object)EMPTY;
}
public static <T> Supplier<Optional<T>> of(Consumer<Weighted.Builder<T>> constructor) {
Weighted.Builder<T> result = new Weighted.Builder<>();
constructor.accept(result);
return result;
return result.build();
}
public Weighted<T> put(int weight, @NotNull T value) {
entries.add(new Entry(weight, value));
public final static class Builder<T> {
private static final Random RANDOM = new Random();
totalWeight += weight;
private float totalWeight = 0;
recalculate();
private final List<Pair<WeightedValue<T>, Range>> entries = new ArrayList<>();
return this;
}
private void recalculate() {
float rangeStart = 0;
for (Entry i : entries) {
i.min = rangeStart;
i.max = rangeStart + (i.weight/totalWeight);
rangeStart = i.max;
}
}
public Optional<T> get() {
if (entries.isEmpty()) {
return Optional.empty();
public Builder<T> putAll(Map<Integer, T> map) {
map.forEach(this::put);
return this;
}
float random = rand.nextFloat();
public Builder<T> put(int weight, @NotNull T value) {
entries.add(new Pair<>(new WeightedValue<>(weight, value), new Range()));
return entries.stream()
.filter(i -> random >= i.min && random <= i.max)
.map(Entry::getResult)
.findFirst();
}
totalWeight += weight;
class Entry {
float rangeStart = 0;
final float weight;
for (var i : entries) {
rangeStart = i.getRight().set(rangeStart, (i.getLeft().weight() / totalWeight));
}
final T result;
float min;
float max;
Entry(int weight, T result) {
this.weight = weight;
this.result = result;
return this;
}
T getResult() {
return result;
public Supplier<Optional<T>> build() {
if (entries.isEmpty()) {
return of();
}
if (entries.size() == 1) {
final var val = Optional.ofNullable(entries.get(0).getLeft().result());
return () -> val;
}
final var entries = new ArrayList<>(this.entries);
return () -> {
final float pointer = RANDOM.nextFloat();
return entries.stream()
.filter(i -> i.getRight().isIn(pointer))
.map(i -> i.getLeft().result())
.findFirst();
};
}
private record WeightedValue<T> (float weight, T result) {}
private final class Range {
float min;
float max;
public boolean isIn(float pointer) {
return pointer >= min && pointer <= max;
}
public float set(float start, float size) {
min = start;
max = start + size;
return max;
}
}
}
}