Compare commits

...

6 Commits

Author SHA1 Message Date
Vladislav Kuznetsov cc09ee124b PlayerData persistent state + added new stats 2024-04-14 16:14:15 +03:00
Vladislav Kuznetsov 7536863a00 Networking new 2024-04-13 20:47:51 +03:00
Eugene Rybalkin 0d02dbc463 fixed merge 2024-04-13 18:23:06 +03:00
Eugene Rybalkin 6b2af0560a Merge remote-tracking branch 'origin/zoomerio_dev' 2024-04-13 18:20:10 +03:00
corkscrew 36087cd3ce fix unused imports
build / build (17) (push) Has been cancelled Details
build / build (21) (push) Has been cancelled Details
2024-04-13 17:49:40 +03:00
corkscrew 29b82b7b36 Basic networking
build / build (17) (push) Waiting to run Details
build / build (21) (push) Waiting to run Details
2024-04-13 17:41:15 +03:00
10 changed files with 290 additions and 23 deletions

View File

@ -1,30 +1,24 @@
package com.youpe.test;
import com.youpe.test.event.TestHudRender;
import com.youpe.test.event.DirtBrokenAfter;
import com.youpe.test.event.JoinServerHandler;
import com.youpe.test.item.ModItems;
import com.youpe.test.item.custom.CustomItem;
import com.youpe.test.networking.ModNetworkingManager;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.fabricmc.fabric.api.registry.FuelRegistry;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormat;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroups;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.Blocks;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.util.Rarity;
import org.joml.Matrix4f;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.mojang.blaze3d.systems.RenderSystem;
import com.youpe.test.server.PlayerData;
import com.youpe.test.server.StateSaverAndLoader;
public class Testing implements ModInitializer {
@ -35,7 +29,11 @@ public class Testing implements ModInitializer {
@Override
public void onInitialize() {
LOGGER.info("Hello Fabric world!");
ModNetworkingManager.registerC2SPackets();
ModItems.registerModItems();
PlayerBlockBreakEvents.AFTER.register(new DirtBrokenAfter());
ServerPlayConnectionEvents.JOIN.register(new JoinServerHandler());
}
}

View File

@ -3,15 +3,25 @@ package com.youpe.test;
import com.youpe.test.event.KeyInputHandler;
import com.youpe.test.event.TestHudRender;
import com.youpe.test.networking.ModNetworkingManager;
import com.youpe.test.server.PlayerData;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.minecraft.text.Text;
public class TestingClient implements ClientModInitializer{
public static PlayerData playerData = new PlayerData();
@Override
public void onInitializeClient() {
KeyInputHandler.register();
ModNetworkingManager.registerS2CPackets();
KeyInputHandler.registerKeyInputs();
TestHudRender.registerModRenders();
}
}

View File

@ -0,0 +1,49 @@
package com.youpe.test.event;
import com.youpe.test.networking.ModNetworkingManager;
import com.youpe.test.server.PlayerData;
import com.youpe.test.server.StateSaverAndLoader;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class DirtBrokenAfter implements PlayerBlockBreakEvents.After {
@Override
public void afterBlockBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity) {
if (state.getBlock() == Blocks.GRASS_BLOCK || state.getBlock() == Blocks.DIRT) {
MinecraftServer server = world.getServer();
StateSaverAndLoader serverState = StateSaverAndLoader.getServerState(server);
// Increment the amount of dirt blocks that have been broken
serverState.totalDirtBlocksBroken += 1;
PlayerData playerState = StateSaverAndLoader.getPlayerState(player);
playerState.dirtBlocksBroken += 1;
// Send a packet to the client
PacketByteBuf data = PacketByteBufs.create();
data.writeInt(serverState.totalDirtBlocksBroken);
data.writeInt(playerState.dirtBlocksBroken);
ServerPlayerEntity playerEntity = server.getPlayerManager().getPlayer(player.getUuid());
server.execute(() -> {
ServerPlayNetworking.send(playerEntity, ModNetworkingManager.DIRT_BROKEN, data);
});
}
}
}

View File

@ -0,0 +1,33 @@
package com.youpe.test.event;
import com.youpe.test.networking.ModNetworkingManager;
import com.youpe.test.server.PlayerData;
import com.youpe.test.server.StateSaverAndLoader;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayNetworkHandler;
public class JoinServerHandler implements ServerPlayConnectionEvents.Join {
@Override
public void onPlayReady(ServerPlayNetworkHandler handler, PacketSender sender, MinecraftServer server) {
PlayerData playerState = StateSaverAndLoader.getPlayerState(handler.getPlayer());
PacketByteBuf data = PacketByteBufs.create();
data.writeInt(playerState.dirtBlocksBroken);
data.writeInt(playerState.level);
data.writeFloat(playerState.exp);
data.writeFloat(playerState.strength);
data.writeFloat(playerState.dexterity);
data.writeFloat(playerState.intelligence);
data.writeString(playerState.className);
server.execute(() -> {
ServerPlayNetworking.send(handler.getPlayer(), ModNetworkingManager.INIT_SYNC, data);
});
}
}

View File

@ -2,8 +2,6 @@ package com.youpe.test.event;
import com.youpe.test.Testing;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.youpe.test.client.GUI;
@ -22,6 +20,7 @@ public class KeyInputHandler {
public static KeyBinding modkey;
public static void registerKeyInputs() {
registerKeyBindings();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (modkey.wasPressed()) {
Testing.LOGGER.info("NAZHAL PIZDEC BLYA");
@ -31,7 +30,7 @@ public class KeyInputHandler {
});
}
public static void register() {
public static void registerKeyBindings() {
modkey = KeyBindingHelper.registerKeyBinding(new KeyBinding(
KEY_TEST,
InputUtil.Type.KEYSYM,

View File

@ -0,0 +1,22 @@
package com.youpe.test.networking;
import com.youpe.test.Testing;
import com.youpe.test.networking.packet.DirtBrokenS2CPacket;
import com.youpe.test.networking.packet.InitSyncS2CPacket;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.util.Identifier;
public class ModNetworkingManager {
public static final Identifier DIRT_BROKEN = new Identifier(Testing.MOD_ID, "msg_dirt_broken");
public static final Identifier INIT_SYNC = new Identifier(Testing.MOD_ID, "msg_init_sync");
public static void registerC2SPackets(){
}
public static void registerS2CPackets(){
ClientPlayNetworking.registerGlobalReceiver(DIRT_BROKEN, DirtBrokenS2CPacket::receive);
ClientPlayNetworking.registerGlobalReceiver(INIT_SYNC, InitSyncS2CPacket::receive);
}
}

View File

@ -0,0 +1,20 @@
package com.youpe.test.networking.packet;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
public class DirtBrokenS2CPacket {
public static void receive(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) {
int totalDirtBlocksBroken = buf.readInt();
int playerSpecificDirtBlocksBroken = buf.readInt();
client.execute(() -> {
client.player.sendMessage(Text.literal("Total dirt blocks broken: " + totalDirtBlocksBroken));
client.player.sendMessage(Text.literal("Player specific dirt blocks broken: " + playerSpecificDirtBlocksBroken));
});
}
}

View File

@ -0,0 +1,25 @@
package com.youpe.test.networking.packet;
import com.youpe.test.TestingClient;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
public class InitSyncS2CPacket {
public static void receive(MinecraftClient client, ClientPlayNetworkHandler handler, PacketByteBuf buf, PacketSender responseSender) {
TestingClient.playerData.dirtBlocksBroken = buf.readInt();
TestingClient.playerData.level = buf.readInt();
TestingClient.playerData.exp = buf.readFloat();
TestingClient.playerData.strength = buf.readFloat();
TestingClient.playerData.dexterity = buf.readFloat();
TestingClient.playerData.intelligence = buf.readFloat();
TestingClient.playerData.className = buf.readString();
client.execute(() -> {
client.player.sendMessage(Text.literal("Your broken dirt on this server: " + TestingClient.playerData.dirtBlocksBroken), false);
});
}
}

View File

@ -0,0 +1,14 @@
package com.youpe.test.server;
public class PlayerData {
public int dirtBlocksBroken = 0;
public int level = 0;
public float exp = 0;
public String className = "base";
public float strength = 1;
public float dexterity = 1;
public float intelligence = 1;
}

View File

@ -0,0 +1,97 @@
package com.youpe.test.server;
import java.util.HashMap;
import java.util.UUID;
import com.youpe.test.Testing;
import net.minecraft.entity.LivingEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.PersistentState;
import net.minecraft.world.PersistentStateManager;
import net.minecraft.world.World;
public class StateSaverAndLoader extends PersistentState {
public Integer totalDirtBlocksBroken = 0;
public HashMap<UUID, PlayerData> players = new HashMap<>();
@Override
public NbtCompound writeNbt(NbtCompound nbt) {
nbt.putInt("totalDirtBlocksBroken", totalDirtBlocksBroken);
NbtCompound playersNbt = new NbtCompound();
players.forEach((uuid, playerData) -> {
NbtCompound playerNbt = new NbtCompound();
// Player stats
playerNbt.putInt("dirtBlocksBroken", playerData.dirtBlocksBroken);
playerNbt.putInt("level", playerData.level);
playerNbt.putFloat("exp", playerData.exp);
playerNbt.putFloat("strength", playerData.strength);
playerNbt.putFloat("dexterity", playerData.dexterity);
playerNbt.putFloat("intelligence", playerData.intelligence);
playerNbt.putString("className", playerData.className);
playersNbt.put(uuid.toString(), playerNbt);
});
nbt.put("players", playersNbt);
return nbt;
}
public static StateSaverAndLoader createFromNbt(NbtCompound tag) {
StateSaverAndLoader state = new StateSaverAndLoader();
state.totalDirtBlocksBroken = tag.getInt("totalDirtBlocksBroken");
NbtCompound playersNbt = tag.getCompound("players");
playersNbt.getKeys().forEach((key) -> {
PlayerData playerData = new PlayerData();
playerData.dirtBlocksBroken = playersNbt.getCompound(key).getInt("dirtBlocksBroken");
playerData.level = playersNbt.getCompound(key).getInt("level");
playerData.exp = playersNbt.getCompound(key).getFloat("exp");
playerData.strength = playersNbt.getCompound(key).getFloat("strength");
playerData.dexterity = playersNbt.getCompound(key).getFloat("dexterity");
playerData.intelligence = playersNbt.getCompound(key).getFloat("intelligence");
playerData.className = playersNbt.getCompound(key).getString("className");
UUID uuid = UUID.fromString(key);
state.players.put(uuid, playerData);
});
return state;
}
public static StateSaverAndLoader getServerState(MinecraftServer server) {
// (Note: arbitrary choice to use 'World.OVERWORLD' instead of 'World.END' or 'World.NETHER'. Any work)
PersistentStateManager persistentStateManager = server.getWorld(World.OVERWORLD).getPersistentStateManager();
// The first time the following 'getOrCreate' function is called, it creates a brand new 'StateSaverAndLoader' and
// stores it inside the 'PersistentStateManager'. The subsequent calls to 'getOrCreate' pass in the saved
// 'StateSaverAndLoader' NBT on disk to our function 'StateSaverAndLoader::createFromNbt'.
StateSaverAndLoader state = persistentStateManager.getOrCreate(StateSaverAndLoader::createFromNbt, StateSaverAndLoader::new, Testing.MOD_ID);
// If state is not marked dirty, when Minecraft closes, 'writeNbt' won't be called and therefore nothing will be saved.
// Technically it's 'cleaner' if you only mark state as dirty when there was actually a change, but the vast majority
// of mod writers are just going to be confused when their data isn't being saved, and so it's best just to 'markDirty' for them.
// Besides, it's literally just setting a bool to true, and the only time there's a 'cost' is when the file is written to disk when
// there were no actual change to any of the mods state (INCREDIBLY RARE).
state.markDirty();
return state;
}
public static PlayerData getPlayerState(LivingEntity player) {
StateSaverAndLoader serverState = getServerState(player.getWorld().getServer());
// Either get the player by the uuid, or we don't have data for him yet, make a new player state
PlayerData playerState = serverState.players.computeIfAbsent(player.getUuid(), uuid -> new PlayerData());
return playerState;
}
}