Follow along with the video below to see how to install our site as a web app on your home screen.
Примечание: This feature may not be available in some browsers.
имя файла....напримерчто подразумевается под именем файла
"open_chunks"toLong(), и потом используешь как хочешь.Мне бы пример кода что бы понятнее было
ServerPlayNetworking.send(playerEntity, DIRT_BROKEN, data); а у меня ServerPlayNetworking.send требует @NotNull net.minecraft.server.network.ServerPlayerEntity player, @NotNull net.minecraft.network.packet.CustomPayload payloadPersistentState(Смотри RaidManager, он сохраняет целые рейды), туда ты сохраняешь(а потом и оттуда загружаешь) то что тебе нужно. PersistentState)PersistentState.((YourPersistentStateGetter) someServerWorld).getData()...package net.catg.zonedefender.Objects;
import net.minecraft.datafixer.DataFixTypes;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.PersistentState;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.registry.RegistryWrapper;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class OpenChunkManager extends PersistentState {
private final Map<ChunkPos, OpenChunk> openChunks = new HashMap<>();
private final ServerWorld world;
// Конструктор для инициализации с миром
public OpenChunkManager(ServerWorld world) {
this.world = world;
}
// Статический метод для получения типа состояния PersistentState
public static PersistentState.Type<OpenChunkManager> getPersistentStateType(ServerWorld world) {
return new PersistentState.Type<>(
() -> new OpenChunkManager(world),
(nbt, registryLookup) -> fromNbt(world, nbt),
DataFixTypes.CHUNK
);
}
// Метод для загрузки данных из NBT
public static OpenChunkManager fromNbt(ServerWorld world, NbtCompound nbt) {
OpenChunkManager openChunkManager = new OpenChunkManager(world);
NbtList nbtList = nbt.getList("OpenChunks", 10);
for (int i = 0; i < nbtList.size(); ++i) {
NbtCompound chunkNbt = nbtList.getCompound(i);
ChunkPos chunkPos = new ChunkPos(chunkNbt.getInt("ChunkX"), chunkNbt.getInt("ChunkZ"));
OpenChunk openChunk = new OpenChunk(chunkPos, chunkNbt.getBoolean("IsActive"));
openChunkManager.openChunks.put(chunkPos, openChunk);
}
return openChunkManager;
}
// Метод для сохранения состояния в NBT
public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
NbtList nbtList = new NbtList();
for (OpenChunk openChunk : openChunks.values()) {
NbtCompound chunkNbt = new NbtCompound();
chunkNbt.putInt("ChunkX", openChunk.getChunkPos().x);
chunkNbt.putInt("ChunkZ", openChunk.getChunkPos().z);
chunkNbt.putBoolean("IsActive", openChunk.isActive());
nbtList.add(chunkNbt);
}
nbt.put("OpenChunks", nbtList);
return nbt;
}
// Метод для добавления чанк в список
public void addOpenChunk(ChunkPos chunkPos) {
if (!openChunks.containsKey(chunkPos)) {
openChunks.put(chunkPos, new OpenChunk(chunkPos, true));
this.markDirty();
}
}
// Метод для удаления чанк из списка
public void removeOpenChunk(ChunkPos chunkPos) {
if (openChunks.containsKey(chunkPos)) {
openChunks.remove(chunkPos);
this.markDirty();
}
}
// Метод для обновления чанков каждый тик
public void tick() {
for (OpenChunk openChunk : openChunks.values()) {
openChunk.tick(world);
}
}
// Геттеры
public Map<ChunkPos, OpenChunk> getOpenChunks() {
return openChunks;
}
public ServerWorld getWorld() {
return world;
}
}
package net.catg.zonedefender.Objects;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.World;
import net.minecraft.particle.DustParticleEffect;
import org.joml.Vector3f;
public class OpenChunk {
private ChunkPos chunkPos; // Позиция чанка
private boolean isActive;
private int tickCounter = 0; // Счётчик тиков
// Конструктор для создания объекта с конкретными данными
public OpenChunk(ChunkPos chunkPos, boolean isActive) {
this.chunkPos = chunkPos;
this.isActive = isActive;
}
// Конструктор для загрузки из NBT
public OpenChunk(NbtCompound nbt) {
this.chunkPos = new ChunkPos(nbt.getInt("ChunkX"), nbt.getInt("ChunkZ"));
this.isActive = nbt.getBoolean("IsActive");
}
// Метод для сохранения данных в NBT
public NbtCompound toNbt(NbtCompound nbt) {
nbt.putInt("ChunkX", this.chunkPos.x);
nbt.putInt("ChunkZ", this.chunkPos.z);
nbt.putBoolean("IsActive", this.isActive);
return nbt;
}
// Метод для генерации частиц на границе чанка
public void generateParticles(World world) {
int minX = this.chunkPos.getStartX();
int minZ = this.chunkPos.getStartZ();
int maxX = this.chunkPos.getEndX();
int maxZ = this.chunkPos.getEndZ();
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
// Определяем высоту поверхности на текущей позиции
int surfaceY = world.getTopY(net.minecraft.world.Heightmap.Type.MOTION_BLOCKING, x, z);
// Если точка на границе чанка
if (x == minX || x == maxX || z == minZ || z == maxZ) {
world.addParticle(
new DustParticleEffect(new Vector3f(0.0F, 1.0F, 0.0F), 1.0F), // Зелёные частицы
x + 0.5, surfaceY + 0.5, z + 0.5, // Координаты
0, 0, 0 // Скорость
);
}
}
}
}
// Метод tick, вызывающий частицы каждые 5 тиков
public void tick(World world) {
if (++tickCounter >= 5) {
tickCounter = 0; // Сброс счётчика
generateParticles(world); // Вызываем генерацию частиц
}
}
// Геттеры
public ChunkPos getChunkPos() {
return chunkPos;
}
public boolean isActive() {
return isActive;
}
}
getPersistentStateType уже всё загружает, если ты зарегистрировал OpenChunkManager.DataFixTypes.CHUNK поменяй на то что в рейдах было. (этот тип определяет откуда загружается nbt для DataFixer'ов).в главном классе мода?1.getPersistentStateTypeуже всё загружает, если ты зарегистрировалOpenChunkManager
Нет.в главном классе мода?
Для регистрации:
1. Создаешь интерфейс с метод getData(с помощью него будешь получать свойPersistentState)
2. Создаешь миксин на ServerWorld который наследует твой интерфейс.
3. В конструктор @Inject и определяешь свойPersistentState.
4.((YourPersistentStateGetter) someServerWorld).getData()...
package net.catg.zonedefender;
import net.catg.zonedefender.Objects.OpenChunkManager;
import net.catg.zonedefender.PersistentStateGetter;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.ChunkPos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Random;
public class ZoneDefender implements ModInitializer {
public static final String MOD_ID = "zonedefender";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
private boolean initialChunkCreated = false; // Флаг для проверки, создан ли начальный OpenChunk
@Override
public void onInitialize() {
// Регистрация событий тика
LOGGER.info("Иницилизируем!");
ServerTickEvents.END_WORLD_TICK.register(this::onWorldTick);
}
private void onWorldTick(ServerWorld world) {
PersistentStateGetter getter = (PersistentStateGetter) world;
OpenChunkManager chunkManager = getter.getData();
// Создаем начальный OpenChunk, если он еще не был создан
if (!initialChunkCreated) {
LOGGER.info("Вызываем!");
createInitialChunk(chunkManager);
initialChunkCreated = true; // Помечаем, что начальный OpenChunk создан
}
// Вызываем метод tick для обновления OpenChunks
chunkManager.tick();
}
private void createInitialChunk(OpenChunkManager chunkManager) {
ZoneDefender.LOGGER.info("Чанки: " + chunkManager.getOpenChunks());
LOGGER.info("Начинаем создание...");
if (!chunkManager.containsChunk(new ChunkPos(0, 0))) {
chunkManager.addChunk(new ChunkPos(0, 0));
chunkManager.addChunk(new ChunkPos(1, 0));
chunkManager.addChunk(new ChunkPos(-1, 0));
LOGGER.info("Создан начальный OpenChunk на начальной позиции");
}
else {
LOGGER.info("Уже ЕЕЕЕСТЬ");
}
}
}
package net.catg.zonedefender.Objects;
import net.catg.zonedefender.ZoneDefender;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.particle.DustParticleEffect;
import org.joml.Vector3f;
public class OpenChunk {
private ChunkPos chunkPos; // Позиция чанка
private boolean isActive;
private int tickCounter = 0; // Счётчик тиков
// Конструктор для создания объекта с конкретными данными
public OpenChunk(ChunkPos chunkPos, boolean isActive) {
this.chunkPos = chunkPos;
this.isActive = isActive;
}
// Конструктор для загрузки из NBT
public OpenChunk(NbtCompound nbt) {
this.chunkPos = new ChunkPos(nbt.getInt("ChunkX"), nbt.getInt("ChunkZ"));
this.isActive = nbt.getBoolean("IsActive");
}
// Метод для сохранения данных в NBT
public NbtCompound toNbt(NbtCompound nbt) {
nbt.putInt("ChunkX", this.chunkPos.x);
nbt.putInt("ChunkZ", this.chunkPos.z);
nbt.putBoolean("IsActive", this.isActive);
return nbt;
}
// Метод для генерации частиц на границе чанка
public void generateParticles(ServerWorld world) {
int minX = this.chunkPos.getStartX();
int minZ = this.chunkPos.getStartZ();
int maxX = this.chunkPos.getEndX();
int maxZ = this.chunkPos.getEndZ();
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
// Определяем высоту поверхности на текущей позиции
int surfaceY = world.getTopY(Heightmap.Type.MOTION_BLOCKING, x, z);
// Если точка на границе чанка
if (x == minX || x == maxX || z == minZ || z == maxZ) {
// Выводим позицию частицы (BlockPos)
BlockPos particlePos = new BlockPos(x, surfaceY, z);
// Серверный вызов spawnParticles
world.spawnParticles(
new DustParticleEffect(new Vector3f(0.0F, 1.0F, 0.0F), 1.0F), // Зелёные частицы
x + 0.5, surfaceY + 0.5, z + 0.5, // Координаты
1, // Количество частиц
0.0, 0.0, 0.0, // Разброс
0.0 // Скорость
);
}
}
}
}
// Метод tick, вызывающий частицы каждые 5 тиков
public void tick(World world) {
if (++tickCounter >= 5) {
tickCounter = 0; // Сброс счётчика
generateParticles((ServerWorld) world); // Вызываем генерацию частиц
}
}
// Геттеры
public ChunkPos getChunkPos() {
return chunkPos;
}
public boolean isActive() {
return isActive;
}
}
package net.catg.zonedefender.Objects;
import net.catg.zonedefender.ZoneDefender;
import net.minecraft.datafixer.DataFixTypes;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.PersistentState;
import net.minecraft.registry.RegistryWrapper;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class OpenChunkManager extends PersistentState {
private final Map<ChunkPos, OpenChunk> openChunks = new HashMap<>();
private final ServerWorld world;
// Конструктор для инициализации с миром
public OpenChunkManager(ServerWorld world) {
this.world = world;
this.createInitialChunk(); // Создаем начальный OpenChunk
}
// Статический метод для получения типа состояния PersistentState
public static PersistentState.Type<OpenChunkManager> getPersistentStateType(ServerWorld world) {
return new PersistentState.Type<>(
() -> new OpenChunkManager(world),
(nbt, registryLookup) -> fromNbt(world, nbt),
DataFixTypes.SAVED_DATA_RAIDS
);
}
// Метод для загрузки данных из NBT
public static OpenChunkManager fromNbt(ServerWorld world, NbtCompound nbt) {
OpenChunkManager openChunkManager = new OpenChunkManager(world);
NbtList nbtList = nbt.getList("OpenChunks", 10);
for (int i = 0; i < nbtList.size(); ++i) {
NbtCompound chunkNbt = nbtList.getCompound(i);
ChunkPos chunkPos = new ChunkPos(chunkNbt.getInt("ChunkX"), chunkNbt.getInt("ChunkZ"));
OpenChunk openChunk = new OpenChunk(chunkPos, chunkNbt.getBoolean("IsActive"));
openChunkManager.openChunks.put(chunkPos, openChunk);
}
return openChunkManager;
}
// Метод для сохранения состояния в NBT
public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registryLookup) {
NbtList nbtList = new NbtList();
for (OpenChunk openChunk : openChunks.values()) {
NbtCompound chunkNbt = new NbtCompound();
chunkNbt.putInt("ChunkX", openChunk.getChunkPos().x);
chunkNbt.putInt("ChunkZ", openChunk.getChunkPos().z);
chunkNbt.putBoolean("IsActive", openChunk.isActive());
nbtList.add(chunkNbt);
}
nbt.put("OpenChunks", nbtList);
return nbt;
}
// Метод для создания начального чанка
private void createInitialChunk() {
Random random = new Random();
ChunkPos chunkPos;
// Генерация случайного чанка в диапазоне от -10 до 10
do {
int x = random.nextInt(21) - 10; // Диапазон от -10 до 10
int z = random.nextInt(21) - 10;
chunkPos = new ChunkPos(x, z);
} while (this.containsChunk(chunkPos)); // Проверяем, существует ли такой OpenChunk
// Добавляем новый OpenChunk в менеджер
this.addChunk(chunkPos);
}
// Метод для добавления чанка
public void addChunk(ChunkPos chunkPos) {
if (!openChunks.containsKey(chunkPos)) {
openChunks.put(chunkPos, new OpenChunk(chunkPos, true));
this.markDirty();
}
}
// Метод для проверки наличия чанка
public boolean containsChunk(ChunkPos chunkPos) {
return openChunks.containsKey(chunkPos);
}
// Метод для обновления чанков каждый тик
public void tick() {
for (OpenChunk openChunk : openChunks.values()) {
openChunk.tick(world);
}
}
// Геттеры
public Map<ChunkPos, OpenChunk> getOpenChunks() {
return openChunks;
}
public ServerWorld getWorld() {
return world;
}
}
package net.catg.zonedefender.mixin;
import net.catg.zonedefender.PersistentStateGetter;
import net.catg.zonedefender.Objects.OpenChunkManager;
import net.catg.zonedefender.ZoneDefender;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.PersistentState;
import net.minecraft.nbt.NbtCompound;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.At;
@Mixin(ServerWorld.class)
public abstract class ServerWorldMixin implements PersistentStateGetter {
private OpenChunkManager openChunkManager;
// Внедрение конструктора и инициализация PersistentState
@Inject(method = "<init>", at = @At("RETURN"))
private void onWorldInitialized(CallbackInfo ci) {
this.openChunkManager = new OpenChunkManager((ServerWorld) (Object) this); // Инициализация OpenChunkManager
}
@Override
public OpenChunkManager getData() {
return openChunkManager; // Возвращаем экземпляр OpenChunkManager
}
// Сохранение состояния OpenChunkManager в NBT
public void saveToNBT(NbtCompound nbt) {
if (openChunkManager != null) {
openChunkManager.writeNbt(nbt, null); // Сохраняем состояние
}
}
}
package net.catg.zonedefender;
import net.catg.zonedefender.Objects.OpenChunkManager;
public interface PersistentStateGetter {
OpenChunkManager getData();
}
this.openChunkManager = new OpenChunkManager((ServerWorld) (Object) this);//Создаёт или получает файл
this.openChunkManager = this.getPersistentStateManager().getOrCreate(OpenChunkManager.getPersistentStateType(this), "имя_файла");
Cannot resolve method 'getPersistentStateManager' in 'ServerWorldMixin', а как ServerWorld получить?Та хоспади...а как ServerWorld получить?
(ServerWorld) (Object) thisбери из ServerWorld'getPersistentStateManager'
"имя_файла" что подразумевается под именем файлаимя файла....напримерчто подразумевается под именем файла
"open_chunks"