Skip to content

Commit

Permalink
添加新的数据设计
Browse files Browse the repository at this point in the history
- 现在可以像 1.21 版本的 DataComponent 那样,给女仆实体添加自定义、可同步的数据了
  • Loading branch information
TartaricAcid committed Oct 9, 2024
1 parent 5936cf1 commit 145556d
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 11 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ dependencies {

implementation fg.deobf("maven.modrinth:torohealth-damage-indicators-updated:1.20.1-forge-1")

runtimeOnly fg.deobf("curse.maven:aquaculture-60028:5585290")

annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.github.tartaricacid.touhoulittlemaid.client.renderer.entity.EntityMaidRenderer;
import com.github.tartaricacid.touhoulittlemaid.client.renderer.entity.GeckoEntityMaidRenderer;
import com.github.tartaricacid.touhoulittlemaid.entity.backpack.BackpackManager;
import com.github.tartaricacid.touhoulittlemaid.entity.data.TaskDataRegister;
import com.github.tartaricacid.touhoulittlemaid.entity.task.TaskManager;
import com.github.tartaricacid.touhoulittlemaid.entity.task.meal.MaidMealManager;
import com.github.tartaricacid.touhoulittlemaid.inventory.chest.ChestManager;
Expand Down Expand Up @@ -63,6 +64,14 @@ default void addChestType(ChestManager manager) {
default void addMaidMeal(MaidMealManager manager) {
}

/**
* 注册任务数据,任务数据是一种可以自定义添加到女仆上的数据
*
* @param register 注册器
*/
default void registerTaskData(TaskDataRegister register) {
}

/**
* 添加女仆相关提示
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.github.tartaricacid.touhoulittlemaid.api.entity.data;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;

public interface TaskDataKey<T> {
/**
* 该 Data 的注册名,用于在存储 NBT 作为 KEY
*/
ResourceLocation getKey();

/**
* 存储成 NBT
*/
CompoundTag writeSaveData(T data);

/**
* 从 NBT 里读取为数据
*/
T readSaveData(CompoundTag compound);

/**
* 网络同步,因为网络占用带宽,所以不一定代表服务端所有的数据都需要同步到客户端
*/
default CompoundTag writeSyncData(T data) {
return this.writeSaveData(data);
}

/**
* 网络同步,客户端读取方法
*/
default T readSyncData(CompoundTag compound) {
return this.readSaveData(compound);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.github.tartaricacid.touhoulittlemaid.entity.data;

import com.github.tartaricacid.touhoulittlemaid.api.entity.data.TaskDataKey;
import it.unimi.dsi.fastutil.objects.Reference2ObjectMap;
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Optional;

public final class MaidTaskDataMaps {
private static final String TAG_NAME = "MaidTaskDataMaps";
private final Reference2ObjectMap<TaskDataKey<?>, Optional<?>> dataMaps = new Reference2ObjectOpenHashMap<>();

@Nullable
@SuppressWarnings("all")
public <T> T getData(TaskDataKey<T> dataKey) {
Optional<T> optional = (Optional<T>) dataMaps.get(dataKey);
if (optional != null && optional.isPresent()) {
return optional.get();
}
return null;
}

public <T> T getOrCreateData(TaskDataKey<T> dataKey, T defaultValue) {
if (dataMaps.containsKey(dataKey)) {
T data = this.getData(dataKey);
if (data != null) {
return data;
}
}
dataMaps.put(dataKey, Optional.of(defaultValue));
return defaultValue;
}

public <T> void setData(TaskDataKey<?> dataKey, T value) {
dataMaps.put(dataKey, Optional.of(value));
}

@SuppressWarnings("all")
public void writeSaveData(CompoundTag entityTag) {
CompoundTag dataTags = readOrCreateTag(entityTag);
dataMaps.forEach((key, value) -> {
TaskDataKey dataKey = key;
value.ifPresent(data -> {
CompoundTag saveData = dataKey.writeSaveData(data);
dataTags.put(key.getKey().toString(), saveData);
});
});
}

public void readSaveData(CompoundTag entityTag) {
dataMaps.clear();
CompoundTag dataTags = readOrCreateTag(entityTag);
for (String key : dataTags.getAllKeys()) {
TaskDataKey<?> dataKey = TaskDataRegister.getValue(new ResourceLocation(key));
if (dataKey != null) {
CompoundTag tag = dataTags.getCompound(key);
dataMaps.put(dataKey, Optional.of(dataKey.readSaveData(tag)));
}
}
}

@SuppressWarnings("all")
public CompoundTag getUpdateTag() {
CompoundTag taskTags = new CompoundTag();
dataMaps.forEach((key, value) -> {
TaskDataKey dataKey = key;
value.ifPresent(data -> {
CompoundTag syncData = dataKey.writeSyncData(data);
taskTags.put(key.getKey().toString(), syncData);
});
});
return taskTags;
}

@OnlyIn(Dist.CLIENT)
public void readFromServer(CompoundTag taskTags) {
dataMaps.clear();
for (String key : taskTags.getAllKeys()) {
TaskDataKey<?> dataKey = TaskDataRegister.getValue(new ResourceLocation(key));
if (dataKey != null) {
CompoundTag tag = taskTags.getCompound(key);
dataMaps.put(dataKey, Optional.of(dataKey.readSyncData(tag)));
}
}
}

@NotNull
private CompoundTag readOrCreateTag(CompoundTag entityTag) {
if (entityTag.contains(TAG_NAME)) {
return entityTag.getCompound(TAG_NAME);
} else {
CompoundTag dataTags = new CompoundTag();
entityTag.put(TAG_NAME, dataTags);
return dataTags;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.github.tartaricacid.touhoulittlemaid.entity.data;

import com.github.tartaricacid.touhoulittlemaid.TouhouLittleMaid;
import com.github.tartaricacid.touhoulittlemaid.api.ILittleMaid;
import com.github.tartaricacid.touhoulittlemaid.api.entity.data.TaskDataKey;
import com.github.tartaricacid.touhoulittlemaid.init.InitTaskData;
import com.google.common.collect.Maps;
import com.mojang.serialization.Codec;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;

import java.util.Map;

public class TaskDataRegister {
private static final Map<ResourceLocation, TaskDataKey<?>> MAPS = Maps.newHashMap();

public static void init() {
TaskDataRegister register = new TaskDataRegister();
// 注册本模组自己的数据
InitTaskData.registerAll(register);
// 注册第三方模组添加的数据
for (ILittleMaid littleMaid : TouhouLittleMaid.EXTENSIONS) {
littleMaid.registerTaskData(register);
}
}

@SuppressWarnings("all")
public static <T> TaskDataKey<T> getValue(ResourceLocation key) {
return (TaskDataKey<T>) MAPS.get(key);
}

public <T> TaskDataKey<T> register(ResourceLocation key, Codec<T> codec) {
return register(key, codec, codec);
}

public <T> TaskDataKey<T> register(ResourceLocation key, Codec<T> saveCodec, Codec<T> syncCodec) {
TaskDataKey<T> value = new TaskDataKey<>() {
@Override
public ResourceLocation getKey() {
return key;
}

@Override
public CompoundTag writeSaveData(T data) {
return saveCodec.encodeStart(NbtOps.INSTANCE, data)
.resultOrPartial(TouhouLittleMaid.LOGGER::error)
.map(tag -> (CompoundTag) tag)
.orElse(new CompoundTag());
}

@Override
public T readSaveData(CompoundTag compound) {
return saveCodec.parse(NbtOps.INSTANCE, compound)
.resultOrPartial(TouhouLittleMaid.LOGGER::error)
.orElse(null);
}

@Override
public CompoundTag writeSyncData(T data) {
return syncCodec.encodeStart(NbtOps.INSTANCE, data)
.resultOrPartial(TouhouLittleMaid.LOGGER::error)
.map(tag -> (CompoundTag) tag)
.orElse(new CompoundTag());
}

@Override
public T readSyncData(CompoundTag compound) {
return syncCodec.parse(NbtOps.INSTANCE, compound)
.resultOrPartial(TouhouLittleMaid.LOGGER::error)
.orElse(null);
}
};
return register(value);
}

public <T> TaskDataKey<T> register(TaskDataKey<T> value) {
MAPS.put(value.getKey(), value);
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.github.tartaricacid.touhoulittlemaid.entity.data.inner;

import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.item.ItemStack;

public record TestData(ItemStack stack, boolean test, int number) {
public static final Codec<TestData> CODEC = RecordCodecBuilder.create(instance -> instance.group(
ItemStack.CODEC.fieldOf("Item").forGetter(TestData::stack),
Codec.BOOL.fieldOf("Test").forGetter(TestData::test),
Codec.INT.fieldOf("Number").forGetter(TestData::number)
).apply(instance, TestData::new));
}
Loading

0 comments on commit 145556d

Please sign in to comment.