2022-12-09 21:45:49 +01:00
|
|
|
package com.minelittlepony.unicopia.entity;
|
|
|
|
|
|
|
|
import java.util.*;
|
2022-12-09 22:19:45 +01:00
|
|
|
import java.util.function.Predicate;
|
2022-12-09 21:45:49 +01:00
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
2022-12-19 16:10:09 +01:00
|
|
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
2022-12-26 20:21:18 +01:00
|
|
|
import com.minelittlepony.unicopia.trinkets.TrinketsDelegate;
|
2022-12-25 23:21:34 +01:00
|
|
|
import com.minelittlepony.unicopia.util.*;
|
2022-12-09 21:45:49 +01:00
|
|
|
|
2022-12-09 22:19:45 +01:00
|
|
|
import net.minecraft.entity.LivingEntity;
|
2022-12-09 21:45:49 +01:00
|
|
|
import net.minecraft.item.ItemConvertible;
|
|
|
|
import net.minecraft.item.ItemStack;
|
|
|
|
import net.minecraft.nbt.NbtCompound;
|
|
|
|
import net.minecraft.util.Identifier;
|
2022-12-18 22:07:24 +01:00
|
|
|
import net.minecraft.registry.Registries;
|
2022-12-09 21:45:49 +01:00
|
|
|
|
2022-12-26 20:21:18 +01:00
|
|
|
public class ItemTracker implements NbtSerialisable, Copyable<ItemTracker>, Tickable, TrinketsDelegate.Inventory {
|
2022-12-09 21:45:49 +01:00
|
|
|
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;
|
|
|
|
|
2022-12-13 21:32:47 +01:00
|
|
|
public static String formatTicks(long ticks) {
|
2022-12-15 10:15:11 +01:00
|
|
|
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);
|
2022-12-13 21:32:47 +01:00
|
|
|
long seconds = ticks / SECONDS;
|
2022-12-15 10:15:11 +01:00
|
|
|
return String.format("%dd, %dh %dm %ds", days, hours, minutes, seconds);
|
2022-12-13 21:32:47 +01:00
|
|
|
}
|
|
|
|
|
2022-12-09 21:45:49 +01:00
|
|
|
private final Map<Trackable, Long> items = new HashMap<>();
|
|
|
|
|
2022-12-09 22:19:45 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-12-25 23:21:34 +01:00
|
|
|
private final Living<?> living;
|
|
|
|
|
|
|
|
public ItemTracker(Living<?> living) {
|
|
|
|
this.living = living;
|
|
|
|
}
|
|
|
|
|
2022-12-26 20:21:18 +01:00
|
|
|
@Override
|
|
|
|
public LivingEntity asEntity() {
|
|
|
|
return living.asEntity();
|
|
|
|
}
|
|
|
|
|
2022-12-25 23:21:34 +01:00
|
|
|
@Override
|
|
|
|
public void tick() {
|
|
|
|
update(living, living.getArmourStacks());
|
|
|
|
}
|
|
|
|
|
2022-12-26 20:21:18 +01:00
|
|
|
private void update(Living<?> living, Stream<ItemStack> stacks) {
|
2022-12-09 21:45:49 +01:00
|
|
|
final Set<Trackable> found = new HashSet<>();
|
|
|
|
final Set<ItemStack> foundStacks = new HashSet<>();
|
|
|
|
stacks.forEach(stack -> {
|
|
|
|
if (stack.getItem() instanceof Trackable trackable) {
|
|
|
|
items.compute(trackable, (item, prev) -> prev == null ? 1 : prev + 1);
|
|
|
|
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;
|
|
|
|
});
|
|
|
|
|
2022-12-19 16:10:09 +01:00
|
|
|
if (!(living instanceof Pony)) {
|
2022-12-09 21:45:49 +01:00
|
|
|
foundStacks.forEach(stack -> {
|
|
|
|
if (getTicks((Trackable)stack.getItem()) == 1) {
|
2022-12-19 18:13:15 +01:00
|
|
|
stack.inventoryTick(living.asWorld(), living.asEntity(), 0, false);
|
2022-12-09 21:45:49 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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) -> {
|
2022-12-18 22:07:24 +01:00
|
|
|
compound.putLong(Registries.ITEM.getId(charm.asItem()).toString(), count);
|
2022-12-09 21:45:49 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void fromNBT(NbtCompound compound) {
|
|
|
|
items.clear();
|
|
|
|
compound.getKeys().stream().map(Identifier::tryParse)
|
|
|
|
.filter(Objects::nonNull)
|
2022-12-18 22:07:24 +01:00
|
|
|
.map(id -> Map.entry(Registries.ITEM.get(id), compound.getLong(id.toString())))
|
2022-12-09 21:45:49 +01:00
|
|
|
.filter(i -> i.getKey() instanceof Trackable && i.getValue() > 0)
|
|
|
|
.forEach(item -> items.put((Trackable)item.getKey(), item.getValue()));
|
|
|
|
}
|
|
|
|
|
2022-12-10 01:16:23 +01:00
|
|
|
@Override
|
2023-01-27 19:06:06 +01:00
|
|
|
public void copyFrom(ItemTracker other, boolean alive) {
|
2022-12-10 01:16:23 +01:00
|
|
|
items.clear();
|
2023-01-27 19:06:06 +01:00
|
|
|
if (alive) {
|
|
|
|
items.putAll(other.items);
|
|
|
|
}
|
2022-12-10 01:16:23 +01:00
|
|
|
}
|
|
|
|
|
2022-12-09 21:45:49 +01:00
|
|
|
public interface Trackable extends ItemConvertible {
|
|
|
|
void onUnequipped(Living<?> living, long timeWorn);
|
|
|
|
|
|
|
|
void onEquipped(Living<?> living);
|
|
|
|
}
|
|
|
|
}
|