Skip to content

Commit

Permalink
add Player capability with networking and hud overlay
Browse files Browse the repository at this point in the history
Cleanliness
  • Loading branch information
LucasPlacentino committed Dec 31, 2022
1 parent 555ecb7 commit b60f4ee
Show file tree
Hide file tree
Showing 9 changed files with 366 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/main/java/com/obsilab/mcsc/cleanliness/PlayerCleanliness.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.obsilab.mcsc.cleanliness;

import net.minecraft.nbt.CompoundTag;

public class PlayerCleanliness {
private int cleanliness;
private final int MIN_CLEANLINESS = 0;
private final int MAX_CLEANLINESS = 10;

public PlayerCleanliness(int cleanliness) {
this.cleanliness = cleanliness;
}

public int getCleanliness() {
return cleanliness;
}

public void addCleanliness(int add) {
this.cleanliness = Math.min(cleanliness + add, MAX_CLEANLINESS);
}

public void subCleanliness(int sub) {
this.cleanliness = Math.max(cleanliness - sub, MIN_CLEANLINESS);
}

public void copyFrom(PlayerCleanliness source) {
this.cleanliness = source.cleanliness;
}

public void saveNBTData(CompoundTag nbt) {
nbt.putInt("cleanliness", cleanliness);
}

public void loadNBTData(CompoundTag nbt) {
cleanliness = nbt.getInt("cleanliness");
}

/*
public void setCleanliness(int cleanliness) {
this.cleanliness = cleanliness;
}
*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.obsilab.mcsc.cleanliness;

import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.util.LazyOptional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class PlayerCleanlinessProvider implements ICapabilityProvider, INBTSerializable<CompoundTag> {

public static Capability<PlayerCleanliness> PLAYER_CLEANLINESS = CapabilityManager.get(new CapabilityToken<PlayerCleanliness>() { });

private PlayerCleanliness cleanliness = null;
private final LazyOptional<PlayerCleanliness> optional = LazyOptional.of(this::createPlayerCleanliness);

private PlayerCleanliness createPlayerCleanliness() {
if(this.cleanliness == null) {
this.cleanliness = new PlayerCleanliness(0); //? argument empty
}
return this.cleanliness;
}

@Override
public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
if (cap == PLAYER_CLEANLINESS) {
return optional.cast();
}
return LazyOptional.empty();
}

@Override
public CompoundTag serializeNBT() {
CompoundTag nbt = new CompoundTag();
createPlayerCleanliness().saveNBTData(nbt);
return nbt;
}

@Override
public void deserializeNBT(CompoundTag nbt) {
createPlayerCleanliness().loadNBTData(nbt);
}
}
60 changes: 60 additions & 0 deletions src/main/java/com/obsilab/mcsc/client/CleanlinessHudOverlay.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.obsilab.mcsc.client;

import com.mojang.blaze3d.systems.RenderSystem;
import com.obsilab.mcsc.MCSC;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.gui.overlay.IGuiOverlay;

public class CleanlinessHudOverlay {
private static final ResourceLocation CLEAN = new ResourceLocation(MCSC.MOD_ID,
"textures/cleanliness/clean.png"); // or "textures/gui/clean.png"
private static final ResourceLocation NOT_CLEAN = new ResourceLocation(MCSC.MOD_ID,
"textures/cleanliness/not_clean.png"); // or "textures/gui/not_clean.png"

public static final IGuiOverlay HUD_CLEANLINESS = ((gui, poseStack, partialTick, width, height) -> {
// draw overlay if this player is on survival mode or adventure mode
//if (!(Minecraft.getInstance().player.isSpectator() || Minecraft.getInstance().player.isCreative())) {
if(!gui.getMinecraft().options.hideGui && gui.shouldDrawSurvivalElements()) {
int x = width / 2;
int y = height ;

RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, NOT_CLEAN);
for(int i = 0; i < 10; i++) {
GuiComponent.blit(poseStack,
x-64 * (i+9), // x
y-54, // y
0, // offset x
0, // offset y
12, // size of what we're drawing x
12, // size of what we're drawing y
12, // size of the image that we're drawing x (reduced from 16x16 ?)
12 // size of the image that we're drawing y
);
}


RenderSystem.setShaderTexture(0, CLEAN);
for(int i = 0; i < 10; i++) {
if(ClientCleanlinessData.getPlayerCleanliness() > i) {
GuiComponent.blit(poseStack,
x-64 * (i+9), // x
y-54, // y
0, // offset x
0, // offset y
12, // size of what we're drawing x
12, // size of what we're drawing y
12, // size of the image that we're drawing x (reduced from 16x16 ?)
12 // size of the image that we're drawing y
);
} else {
break;
}
}
}
});

}
15 changes: 15 additions & 0 deletions src/main/java/com/obsilab/mcsc/client/ClientCleanlinessData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.obsilab.mcsc.client;

public class ClientCleanlinessData {
private static int playerCleanliness;

public static void set(int cleanliness) {
ClientCleanlinessData.playerCleanliness = cleanliness;
// playerCleanliness = cleanliness; //? why not this ?
}

public static int getPlayerCleanliness() {
return playerCleanliness;
}

}
18 changes: 18 additions & 0 deletions src/main/java/com/obsilab/mcsc/event/ClientEvents.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.obsilab.mcsc.event;

import com.obsilab.mcsc.MCSC;
import com.obsilab.mcsc.client.CleanlinessHudOverlay;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RegisterGuiOverlaysEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

public class ClientEvents {
@Mod.EventBusSubscriber(modid = MCSC.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public static class ClientModBusEvents {
@SubscribeEvent
public static void registerGuiOverlay(RegisterGuiOverlaysEvent event) {
event.registerAboveAll("cleanliness", CleanlinessHudOverlay.HUD_CLEANLINESS);
}
}
}
84 changes: 84 additions & 0 deletions src/main/java/com/obsilab/mcsc/event/ModEvents.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.obsilab.mcsc.event;


import com.obsilab.mcsc.MCSC;
import com.obsilab.mcsc.cleanliness.PlayerCleanliness;
import com.obsilab.mcsc.cleanliness.PlayerCleanlinessProvider;
import com.obsilab.mcsc.networking.ModMessages;
import com.obsilab.mcsc.networking.packet.CleanlinessDataSyncS2CPacket;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod;

@Mod.EventBusSubscriber(modid = MCSC.MOD_ID)
public class ModEvents {

// TODO ?

@SubscribeEvent
public static void onAttachCapabilitiesPlayer(AttachCapabilitiesEvent<Entity> event) {
if (event.getObject() instanceof Player) {
if(!event.getObject().getCapability(PlayerCleanlinessProvider.PLAYER_CLEANLINESS).isPresent()) {
event.addCapability(new ResourceLocation(MCSC.MOD_ID, "properties"), new PlayerCleanlinessProvider());
}
}
}

@SubscribeEvent
public static void onPlayerCloned(PlayerEvent.Clone event) {
if (event.isWasDeath()) {
event.getOriginal().getCapability(PlayerCleanlinessProvider.PLAYER_CLEANLINESS).ifPresent(oldStore -> {
event.getOriginal().getCapability(PlayerCleanlinessProvider.PLAYER_CLEANLINESS).ifPresent(newStore -> {
newStore.copyFrom(oldStore);
});
});
}
}

@SubscribeEvent
public static void onRegisterCapabilities(RegisterCapabilitiesEvent event) {
event.register(PlayerCleanliness.class);
}

@SubscribeEvent
public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
if (event.side == LogicalSide.SERVER) {
event.player.getCapability(PlayerCleanlinessProvider.PLAYER_CLEANLINESS).ifPresent(cleanliness -> {
// example : reduce cleanliness with time
if (cleanliness.getCleanliness() > 0 && event.player.getRandom().nextFloat() < 0.005f) { // Once every 10 seconds on average
cleanliness.subCleanliness(1);

// optional send chat message :
event.player.sendSystemMessage(Component.literal("Cleanliness reduced").withStyle(ChatFormatting.GRAY));

ModMessages.sendToPlayer(new CleanlinessDataSyncS2CPacket(cleanliness.getCleanliness()), ((ServerPlayer) event.player));
}

});
}
}

@SubscribeEvent
public static void onPlayerJoinWorld(EntityJoinLevelEvent event) {
if(!event.getLevel().isClientSide()) {
if(event.getEntity() instanceof ServerPlayer player) {
player.getCapability(PlayerCleanlinessProvider.PLAYER_CLEANLINESS).ifPresent(cleanliness -> {
ModMessages.sendToPlayer(new CleanlinessDataSyncS2CPacket(cleanliness.getCleanliness()), player);
});
}
}
}

}
52 changes: 52 additions & 0 deletions src/main/java/com/obsilab/mcsc/networking/ModMessages.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.obsilab.mcsc.networking;

import com.obsilab.mcsc.MCSC;
import com.obsilab.mcsc.networking.packet.CleanlinessC2SPacket;
import com.obsilab.mcsc.networking.packet.CleanlinessDataSyncS2CPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.network.NetworkDirection;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.PacketDistributor;
import net.minecraftforge.network.simple.SimpleChannel;

public class ModMessages {
private static SimpleChannel INSTANCE;

private static int packetId = 0;
private static int id() {
return packetId++;
}

public static void register() {
SimpleChannel net = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(MCSC.MOD_ID, "messages"))
.networkProtocolVersion(() -> "1.0")
.clientAcceptedVersions(s -> true)
.serverAcceptedVersions(s -> true)
.simpleChannel();

INSTANCE = net;

net.messageBuilder(CleanlinessDataSyncS2CPacket.class, id(), NetworkDirection.PLAY_TO_CLIENT) // /!\ PLAY_TO_CLIENT
.decoder(CleanlinessDataSyncS2CPacket::new)
.encoder(CleanlinessDataSyncS2CPacket::toBytes)
.consumerMainThread(CleanlinessDataSyncS2CPacket::handle)
.add();

}

public static <MSG> void sendToServer(MSG message) {
INSTANCE.sendToServer(message);
}

public static <MSG> void sendToPlayer(MSG message, ServerPlayer player) {
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
}

public static <MSG> void sendToClients(MSG message) {
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.obsilab.mcsc.networking.packet;

import com.obsilab.mcsc.networking.ModMessages;

public class CleanlinessC2SPacket {
// TODO

// somewhere:
// ModMessages.sendToPlayer(new CleanlinessDataSyncS2CPacket(cleanliness.getCleanliness()), player);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.obsilab.mcsc.networking.packet;


import com.obsilab.mcsc.client.ClientCleanlinessData;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;

import java.util.function.Supplier;

public class CleanlinessDataSyncS2CPacket {

private final int cleanliness;

public CleanlinessDataSyncS2CPacket(int cleanliness) {
this.cleanliness = cleanliness;
}

public CleanlinessDataSyncS2CPacket(FriendlyByteBuf buf) {
this.cleanliness = buf.readInt();
}

public void toBytes(FriendlyByteBuf buf) {
buf.writeInt(cleanliness);
}

public boolean handle(Supplier<NetworkEvent.Context> supplier) {
NetworkEvent.Context context = supplier.get();
context.enqueueWork(() -> {
// on the client!
ClientCleanlinessData.set(cleanliness);
});
return true;
}

// TODO
}

0 comments on commit b60f4ee

Please # to comment.