Skip to content

Commit

Permalink
Added a basic hero class and a registry to hold them, they can be add…
Browse files Browse the repository at this point in the history
…ed with datapacks
  • Loading branch information
Duzos committed Jan 22, 2024
1 parent 006c031 commit 18ad2cf
Show file tree
Hide file tree
Showing 6 changed files with 269 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/main/java/mc/duzo/timeless/TimelessHeroes.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package mc.duzo.timeless;

import mc.duzo.timeless.heroes.HeroRegistry;
import mc.duzo.timeless.network.TimelessServerNetworking;
import net.fabricmc.api.ModInitializer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TimelessHeroes implements ModInitializer {
public static final String MODID = "timeless";
public static final Logger LOGGER = LoggerFactory.getLogger(MODID);
public static final String MOD_ID = "timeless";
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);

@Override
public void onInitialize() {
TimelessServerNetworking.init();

HeroRegistry.init();
}
}
41 changes: 41 additions & 0 deletions src/main/java/mc/duzo/timeless/heroes/DatapackHero.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package mc.duzo.timeless.heroes;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.serialization.Codec;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import mc.duzo.timeless.TimelessHeroes;
import net.minecraft.util.Identifier;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.atomic.AtomicReference;

public class DatapackHero extends HeroSchema {
public static final Codec<HeroSchema> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
Identifier.CODEC.fieldOf("id").forGetter(HeroSchema::id)
).apply(instance, DatapackHero::new)
);

protected DatapackHero(Identifier id) {
super(id);
}

public static HeroSchema fromInputStream(InputStream stream) {
return fromJson(JsonParser.parseReader(new InputStreamReader(stream)).getAsJsonObject());
}
public static HeroSchema fromJson(JsonObject json) {
AtomicReference<HeroSchema> created = new AtomicReference<>();

CODEC.decode(JsonOps.INSTANCE, json)
.get()
.ifLeft(desktop -> { created.set(desktop.getFirst()); })
.ifRight(err -> { created.set(null);
TimelessHeroes.LOGGER.error("Error decoding datapack hero: " + err);
});

return created.get();
}
}
87 changes: 87 additions & 0 deletions src/main/java/mc/duzo/timeless/heroes/HeroRegistry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package mc.duzo.timeless.heroes;

import mc.duzo.timeless.TimelessHeroes;
import mc.duzo.timeless.network.TimelessServerNetworking;
import mc.duzo.timeless.network.packets.SyncHeroesPacket;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;

import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

public class HeroRegistry {
private static final HashMap<Identifier, HeroSchema> REGISTRY = new HashMap<>();

public static void register(HeroSchema schema, Identifier id) {
REGISTRY.put(id, schema);
}
public static void register(HeroSchema schema) {
register(schema, schema.id());
}

public static Collection<HeroSchema> values() {
return REGISTRY.values();
}
public static Iterator<HeroSchema> iterator() {
return REGISTRY.values().iterator();
}
public static int size() {
return REGISTRY.size();
}

private static void clear() {
REGISTRY.clear();
}

// I dont think this is necessary?
private static void syncToAll() {
TimelessServerNetworking.sendToAll(new SyncHeroesPacket(REGISTRY.values()));
}
private static void syncToClient(ServerPlayerEntity player) {
TimelessServerNetworking.send(new SyncHeroesPacket(REGISTRY.values()), player);
}

public static void init() {
clear();

// ServerPlayConnectionEvents.JOIN.register((handler, sender, server) -> syncToClient(handler.getPlayer()));

// Reading Datapack Heroes
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new SimpleSynchronousResourceReloadListener() {
@Override
public Identifier getFabricId() {
return new Identifier(TimelessHeroes.MOD_ID, "heroes");
}

@Override
public void reload(ResourceManager manager) {
clear();

for (Identifier id : manager.findResources("heroes", file -> file.getPath().endsWith(".json")).keySet()) {
try (InputStream stream = manager.getResource(id).get().getInputStream()) {
HeroSchema created = DatapackHero.fromInputStream(stream);

if (created == null) {
stream.close();
continue;
}

register(created);
stream.close();
TimelessHeroes.LOGGER.info("Loaded datapack hero: " + created.id().toString());
// syncToAll();

} catch (Exception e) {
TimelessHeroes.LOGGER.error("Error while loading resource json: " + id.toString(), e);
}
}
}
});
}
}
30 changes: 30 additions & 0 deletions src/main/java/mc/duzo/timeless/heroes/HeroSchema.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package mc.duzo.timeless.heroes;

import net.minecraft.util.Identifier;

public abstract class HeroSchema {
protected final Identifier id;

protected HeroSchema(Identifier id) {
this.id = id;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() == null || getClass() != o.getClass()) return false;

HeroSchema that = (HeroSchema) o;

return id.equals(that.id);
}

@Override
public int hashCode() {
return id.hashCode();
}

public Identifier id() {
return this.id;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package mc.duzo.timeless.network;

import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;

public class TimelessServerNetworking {
private static MinecraftServer SERVER;

public static void init() {
ServerWorldEvents.UNLOAD.register(((server, world) -> SERVER = server));
ServerLifecycleEvents.SERVER_STARTED.register(server -> SERVER = server);
ServerLifecycleEvents.SERVER_STOPPED.register(server -> SERVER = null);
}

public static MinecraftServer server() {
return SERVER;
}

public static void send(FabricPacket packet, ServerPlayerEntity player) {
ServerPlayNetworking.send(player, packet);
}

public static void sendToAll(FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.all(server())) {
send(packet, player);
}
}
public static void sendToTracking(BlockEntity target, FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.tracking(target)) {
send(packet, player);
}
}
public static void sendToTracking(Entity target, FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.tracking(target)) {
send(packet, player);
}
}
public static void sendToWorld(ServerWorld target, FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.world(target)) {
send(packet, player);
}
}
public static void sendToNearby(ServerWorld world, Vec3d target, double radius, FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.around(world, target, radius)) {
send(packet, player);
}
}
public static void sendToNearby(ServerWorld world, Vec3i target, double radius, FabricPacket packet) {
for (ServerPlayerEntity player : PlayerLookup.around(world, target, radius)) {
send(packet, player);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mc.duzo.timeless.network.packets;

import mc.duzo.timeless.TimelessHeroes;
import mc.duzo.timeless.heroes.DatapackHero;
import mc.duzo.timeless.heroes.HeroSchema;
import net.fabricmc.fabric.api.networking.v1.FabricPacket;
import net.fabricmc.fabric.api.networking.v1.PacketType;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public record SyncHeroesPacket(Collection<HeroSchema> heroes) implements FabricPacket {
public static final PacketType<SyncHeroesPacket> TYPE = PacketType.create(new Identifier(TimelessHeroes.MOD_ID, "sync_heroes"), SyncHeroesPacket::new);

public SyncHeroesPacket(PacketByteBuf buf) {
this(readHeroes(buf.readInt(), buf));
}
@Override
public void write(PacketByteBuf buf) {
buf.writeInt(this.heroes.size());

for (HeroSchema schema : this.heroes) {
buf.encodeAsJson(DatapackHero.CODEC, schema);
}
}
public static Collection<HeroSchema> readHeroes(int size, PacketByteBuf buf) {
List<HeroSchema> list = new ArrayList<>();

for (int i = 0; i < size; ++i) {
list.add(buf.decodeAsJson(DatapackHero.CODEC));
}

return list;
}
@Override
public PacketType<?> getType() {
return TYPE ;
}
}

0 comments on commit 18ad2cf

Please sign in to comment.