Skip to content

Commit

Permalink
Blueprint player data and client configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
andantet committed Nov 14, 2023
1 parent 29825c8 commit 87b9abb
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 29 deletions.
7 changes: 0 additions & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ repositories {
}
}

sourceSets {
test {
compileClasspath += main.compileClasspath
runtimeClasspath += main.runtimeClasspath
}
}

dependencies {
minecraft "com.mojang:minecraft:$minecraft_version"
mappings "net.fabricmc:yarn:$minecraft_version+build.$yarn_build:v2"
Expand Down
15 changes: 13 additions & 2 deletions src/client/kotlin/net/mcbrawls/blueprint/BlueprintClient.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package net.mcbrawls.blueprint

import net.fabricmc.api.ClientModInitializer
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
import net.mcbrawls.blueprint.network.BlueprintConfigC2SPacket

object BlueprintClient : ClientModInitializer {
override fun onInitializeClient() {
}
override fun onInitializeClient() {
ClientPlayConnectionEvents.JOIN.register { handler, _, _ ->
// send initial config packet to server
val packet = BlueprintConfigC2SPacket(
renderParticles = false
)

handler.sendPacket(ServerPlayNetworking.createS2CPacket(packet))
}
}
}
15 changes: 0 additions & 15 deletions src/main/java/net/mcbrawls/blueprint/mixin/ExampleMixin.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package net.mcbrawls.blueprint.mixin;

import dev.andante.codex.CodexKt;
import net.mcbrawls.blueprint.BlueprintMod;
import net.mcbrawls.blueprint.player.BlueprintPlayerAccessor;
import net.mcbrawls.blueprint.player.BlueprintPlayerData;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.server.network.ServerPlayerEntity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

/**
* A mixin to manage blueprint player data on the server player.
*/
@Mixin(ServerPlayerEntity.class)
public class ServerPlayerEntityMixin implements BlueprintPlayerAccessor {
@Unique
private static final String BLUEPRINT_KEY = BlueprintMod.MOD_ID;

@Unique
@Nullable
private BlueprintPlayerData blueprintPlayerData = null;

@Inject(method = "copyFrom", at = @At("TAIL"))
private void copyBlueprintData(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) {
// copy old blueprint data to new player
this.blueprintPlayerData = BlueprintPlayerData.Companion.getBlueprintData(oldPlayer);
}

@Inject(method = "writeCustomDataToNbt", at = @At("TAIL"))
private void writeBlueprintNbt(NbtCompound nbt, CallbackInfo info) {
if (this.blueprintPlayerData != null) {
// write blueprint data to nbt
NbtElement blueprintNbt = CodexKt.encodeQuick(BlueprintPlayerData.Companion.getCODEC(), NbtOps.INSTANCE, this.blueprintPlayerData);
nbt.put(BLUEPRINT_KEY, blueprintNbt);
}
}

@Inject(method = "readCustomDataFromNbt", at = @At("TAIL"))
private void readBlueprintNbt(NbtCompound nbt, CallbackInfo info) {
// read blueprint data from nbt
NbtElement blueprintNbt = nbt.getCompound(BLUEPRINT_KEY);
this.blueprintPlayerData = CodexKt.decodeQuick(BlueprintPlayerData.Companion.getCODEC(), NbtOps.INSTANCE, blueprintNbt);
}

@Unique
@Override
public @Nullable BlueprintPlayerData getBlueprintPlayerData() {
return this.blueprintPlayerData;
}

@Unique
@Override
public void setBlueprintPlayerData(@Nullable BlueprintPlayerData data) {
this.blueprintPlayerData = data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.mcbrawls.blueprint.player;

import org.jetbrains.annotations.Nullable;

public interface BlueprintPlayerAccessor {
default @Nullable BlueprintPlayerData getBlueprintPlayerData() {
throw new AssertionError();
}

default void setBlueprintPlayerData(@Nullable BlueprintPlayerData data) {
throw new AssertionError();
}
}
37 changes: 34 additions & 3 deletions src/main/kotlin/net/mcbrawls/blueprint/BlueprintMod.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
package net.mcbrawls.blueprint

import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
import net.mcbrawls.blueprint.command.BlueprintCommand
import net.mcbrawls.blueprint.network.BlueprintConfigC2SPacket
import net.mcbrawls.blueprint.player.BlueprintPlayerData.Companion.blueprintData
import org.slf4j.LoggerFactory

object BlueprintMod : ModInitializer {
Expand All @@ -9,7 +14,33 @@ object BlueprintMod : ModInitializer {

val logger = LoggerFactory.getLogger(MOD_NAME)

override fun onInitialize() {
logger.info("Initializing $MOD_NAME")
}
private var isPlayerDataSavingEnabled = false

override fun onInitialize() {
logger.info("Initializing $MOD_NAME")

// register config packet receiver
ServerPlayNetworking.registerGlobalReceiver(BlueprintConfigC2SPacket.TYPE) { packet, player, _ ->
player.blueprintData = packet.createBlueprintPlayerData()
}

// register commands
CommandRegistrationCallback.EVENT.register { dispatcher, _, environment ->
BlueprintCommand.register(dispatcher, environment)
}
}

/**
* Enables whether blueprint data, such as user configuration, is saved to the player's data file.
*/
fun enablePlayerDataSaving() {
isPlayerDataSavingEnabled = true
}

/**
* Whether blueprint data is saved to players' data files.
*/
fun isPlayerDataSavingEnabled(): Boolean {
return isPlayerDataSavingEnabled
}
}
16 changes: 16 additions & 0 deletions src/main/kotlin/net/mcbrawls/blueprint/command/BlueprintCommand.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.mcbrawls.blueprint.command

import com.mojang.brigadier.CommandDispatcher
import net.minecraft.server.command.CommandManager.RegistrationEnvironment
import net.minecraft.server.command.CommandManager.literal
import net.minecraft.server.command.ServerCommandSource

object BlueprintCommand {
fun register(dispatcher: CommandDispatcher<ServerCommandSource>, environment: RegistrationEnvironment) {
val builder = literal("blueprint")

//

dispatcher.register(builder)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package net.mcbrawls.blueprint.network

import net.fabricmc.fabric.api.networking.v1.FabricPacket
import net.fabricmc.fabric.api.networking.v1.PacketType
import net.mcbrawls.blueprint.BlueprintMod
import net.mcbrawls.blueprint.player.BlueprintPlayerData
import net.minecraft.network.PacketByteBuf
import net.minecraft.util.Identifier

/**
* A packet sent by the client to modify its blueprint configuration.
*/
data class BlueprintConfigC2SPacket(
/**
* Whether the server should render blueprint particles.
*/
val renderParticles: Boolean,
) : FabricPacket {
constructor(buf: PacketByteBuf) : this(
buf.readBoolean()
)

override fun write(buf: PacketByteBuf) {
buf.writeBoolean(renderParticles)
}

override fun getType(): PacketType<*> {
return TYPE
}

/**
* Creates blueprint player data from this packet.
*/
fun createBlueprintPlayerData(): BlueprintPlayerData {
return BlueprintPlayerData(renderParticles)
}

companion object {
/**
* The type of the config packet.
*/
val TYPE: PacketType<BlueprintConfigC2SPacket> = PacketType.create(
Identifier(BlueprintMod.MOD_ID, "config"),
::BlueprintConfigC2SPacket
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.mcbrawls.blueprint.player

import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.server.network.ServerPlayerEntity

/**
* Blueprint data attached to the player entity.
*/
data class BlueprintPlayerData(
/**
* Whether the server should render blueprint particles.
*/
var renderParticles: Boolean,
) {
companion object {
/**
* The codec for blueprint player data.
*/
val CODEC: Codec<BlueprintPlayerData> = RecordCodecBuilder.create { instance ->
instance.group(
Codec.BOOL
.fieldOf("render_particles")
.forGetter(BlueprintPlayerData::renderParticles)
).apply(instance, ::BlueprintPlayerData)
}

/**
* The blueprint player data for this player.
*/
var ServerPlayerEntity.blueprintData: BlueprintPlayerData?
get() {
val that = this as BlueprintPlayerAccessor
return that.blueprintPlayerData
}

set(value) {
val that = this as BlueprintPlayerAccessor
that.blueprintPlayerData = value
}
}
}
4 changes: 2 additions & 2 deletions src/main/resources/blueprint.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"package": "net.mcbrawls.blueprint.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"ExampleMixin"
"ServerPlayerEntityMixin"
],
"injectors": {
"defaultRequire": 1
}
}
}
5 changes: 5 additions & 0 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
"environment": "client"
}
],
"loom:injected_interfaces": {
"net/minecraft/class_3222": [
"net/mcbrawls/blueprint/player/BlueprintPlayerAccessor"
]
},
"depends": {
"minecraft": "~1.20.2",
"java": ">=17",
Expand Down

0 comments on commit 87b9abb

Please sign in to comment.