mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-28 15:38:00 +01:00
147 lines
No EOL
4.5 KiB
Java
147 lines
No EOL
4.5 KiB
Java
package com.minelittlepony.unicopia.entity;
|
|
|
|
import java.util.*;
|
|
import java.util.function.Predicate;
|
|
import java.util.stream.Stream;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
import com.minelittlepony.unicopia.util.*;
|
|
|
|
import net.minecraft.entity.LivingEntity;
|
|
import net.minecraft.item.ItemConvertible;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NbtCompound;
|
|
import net.minecraft.util.Identifier;
|
|
import net.minecraft.registry.Registries;
|
|
|
|
public class ItemTracker implements NbtSerialisable, Copyable<ItemTracker>, Tickable, TrinketsDelegate.Inventory {
|
|
public static final long TICKS = 1;
|
|
public static final long SECONDS = 20 * TICKS;
|
|
public static final long HOURS = 1000 * TICKS;
|
|
public static final long DAYS = 24 * HOURS;
|
|
|
|
public static String formatTicks(long ticks) {
|
|
long days = ticks / (SECONDS * 60 * 24);
|
|
ticks %= (SECONDS * 60 * 60 * 24);
|
|
long hours = ticks / (SECONDS * 60 * 60);
|
|
ticks %= (SECONDS * 60 * 60);
|
|
long minutes = ticks / (SECONDS * 60);
|
|
ticks %= (SECONDS * 60);
|
|
long seconds = ticks / SECONDS;
|
|
return String.format("%dd, %dh %dm %ds", days, hours, minutes, seconds);
|
|
}
|
|
|
|
private final Map<Trackable, Long> items = new HashMap<>();
|
|
|
|
public static Predicate<LivingEntity> wearing(Trackable charm, Predicate<Long> range) {
|
|
return e -> Living.getOrEmpty(e)
|
|
.map(Living::getArmour)
|
|
.map(a -> a.getTicks(charm))
|
|
.filter(range)
|
|
.isPresent();
|
|
}
|
|
|
|
public static Predicate<Long> between(long minTime, long maxTime) {
|
|
return before(maxTime).and(after(minTime));
|
|
}
|
|
|
|
public static Predicate<Long> before(long maxTime) {
|
|
return ticks -> ticks <= maxTime;
|
|
}
|
|
|
|
public static Predicate<Long> after(long maxTime) {
|
|
return ticks -> ticks <= maxTime;
|
|
}
|
|
|
|
private final Living<?> living;
|
|
|
|
public ItemTracker(Living<?> living) {
|
|
this.living = living;
|
|
}
|
|
|
|
@Override
|
|
public LivingEntity asEntity() {
|
|
return living.asEntity();
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
update(living.getArmourStacks());
|
|
}
|
|
|
|
private void update(Stream<ItemStack> stacks) {
|
|
final Set<Trackable> found = new HashSet<>();
|
|
final Set<ItemStack> foundStacks = new HashSet<>();
|
|
|
|
stacks.forEach(stack -> {
|
|
if (stack.getItem() instanceof Trackable trackable) {
|
|
if (items.compute(trackable, (item, prev) -> prev == null ? 1 : prev + 1) == 1) {
|
|
trackable.onEquipped(this.living);
|
|
}
|
|
found.add(trackable);
|
|
foundStacks.add(stack);
|
|
}
|
|
});
|
|
|
|
items.entrySet().removeIf(e -> {
|
|
if (!found.contains(e.getKey())) {
|
|
e.getKey().onUnequipped(living, e.getValue());
|
|
return true;
|
|
}
|
|
return false;
|
|
});
|
|
|
|
if (!(living instanceof Pony)) {
|
|
foundStacks.forEach(stack -> {
|
|
stack.inventoryTick(living.asWorld(), living.asEntity(), 0, false);
|
|
});
|
|
}
|
|
}
|
|
|
|
public long forceRemove(Trackable charm) {
|
|
@Nullable Long time = items.remove(charm);
|
|
return time == null ? 0 : time;
|
|
}
|
|
|
|
public long getTicks(Trackable charm) {
|
|
return items.getOrDefault(charm.asItem(), 0L);
|
|
}
|
|
|
|
public boolean contains(Trackable charm) {
|
|
return getTicks(charm) > 0;
|
|
}
|
|
|
|
@Override
|
|
public void toNBT(NbtCompound compound) {
|
|
items.forEach((charm, count) -> {
|
|
compound.putLong(Registries.ITEM.getId(charm.asItem()).toString(), count);
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void fromNBT(NbtCompound compound) {
|
|
items.clear();
|
|
compound.getKeys().stream().map(Identifier::tryParse)
|
|
.filter(Objects::nonNull)
|
|
.map(id -> Map.entry(Registries.ITEM.get(id), compound.getLong(id.toString())))
|
|
.filter(i -> i.getKey() instanceof Trackable && i.getValue() > 0)
|
|
.forEach(item -> items.put((Trackable)item.getKey(), item.getValue()));
|
|
}
|
|
|
|
@Override
|
|
public void copyFrom(ItemTracker other, boolean alive) {
|
|
items.clear();
|
|
if (alive) {
|
|
items.putAll(other.items);
|
|
}
|
|
}
|
|
|
|
public interface Trackable extends ItemConvertible {
|
|
void onUnequipped(Living<?> living, long timeWorn);
|
|
|
|
void onEquipped(Living<?> living);
|
|
}
|
|
} |