Initial commit
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
package net.fretux.mindmotion;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import net.fretux.mindmotion.event.CombatEvents;
|
||||
import net.fretux.mindmotion.event.PlayerTickHandler;
|
||||
import net.fretux.mindmotion.network.ModMessages;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Mod(AscendMindMotion.MODID)
|
||||
public class AscendMindMotion {
|
||||
public static final String MODID = "mindmotion";
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
|
||||
public AscendMindMotion() {
|
||||
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
modEventBus.addListener(this::commonSetup);
|
||||
MinecraftForge.EVENT_BUS.register(PlayerTickHandler.class);
|
||||
MinecraftForge.EVENT_BUS.register(CombatEvents.class);
|
||||
LOGGER.info("Ascend: Mind and Motion initialized!");
|
||||
}
|
||||
|
||||
private void commonSetup(final FMLCommonSetupEvent event) {
|
||||
ModMessages.register();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.fretux.mindmotion;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = AscendMindMotion.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
|
||||
public class Config
|
||||
{
|
||||
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
|
||||
|
||||
private static final ForgeConfigSpec.BooleanValue LOG_DIRT_BLOCK = BUILDER
|
||||
.comment("Whether to log the dirt block on common setup")
|
||||
.define("logDirtBlock", true);
|
||||
|
||||
private static final ForgeConfigSpec.IntValue MAGIC_NUMBER = BUILDER
|
||||
.comment("A magic number")
|
||||
.defineInRange("magicNumber", 42, 0, Integer.MAX_VALUE);
|
||||
|
||||
public static final ForgeConfigSpec.ConfigValue<String> MAGIC_NUMBER_INTRODUCTION = BUILDER
|
||||
.comment("What you want the introduction message to be for the magic number")
|
||||
.define("magicNumberIntroduction", "The magic number is... ");
|
||||
|
||||
private static final ForgeConfigSpec.ConfigValue<List<? extends String>> ITEM_STRINGS = BUILDER
|
||||
.comment("A list of items to log on common setup.")
|
||||
.defineListAllowEmpty("items", List.of("minecraft:iron_ingot"), Config::validateItemName);
|
||||
|
||||
static final ForgeConfigSpec SPEC = BUILDER.build();
|
||||
|
||||
public static boolean logDirtBlock;
|
||||
public static int magicNumber;
|
||||
public static String magicNumberIntroduction;
|
||||
public static Set<Item> items;
|
||||
|
||||
private static boolean validateItemName(final Object obj)
|
||||
{
|
||||
return obj instanceof final String itemName && ForgeRegistries.ITEMS.containsKey(new ResourceLocation(itemName));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
static void onLoad(final ModConfigEvent event)
|
||||
{
|
||||
logDirtBlock = LOG_DIRT_BLOCK.get();
|
||||
magicNumber = MAGIC_NUMBER.get();
|
||||
magicNumberIntroduction = MAGIC_NUMBER_INTRODUCTION.get();
|
||||
items = ITEM_STRINGS.get().stream()
|
||||
.map(itemName -> ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName)))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package net.fretux.mindmotion.client;
|
||||
|
||||
public class ClientData {
|
||||
public static float SANITY = 80f;
|
||||
public static float INSANITY = 0f;
|
||||
public static int TEMPO = 0;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package net.fretux.mindmotion.client;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderGuiOverlayEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "mindmotion", value = Dist.CLIENT)
|
||||
public class SanityTempoOverlay {
|
||||
|
||||
private static final int BAR_WIDTH = 102;
|
||||
private static final int BAR_HEIGHT = 9;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderOverlay(RenderGuiOverlayEvent.Post event) {
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.player == null || mc.options.hideGui) return;
|
||||
|
||||
GuiGraphics gui = event.getGuiGraphics();
|
||||
int width = event.getWindow().getGuiScaledWidth();
|
||||
int height = event.getWindow().getGuiScaledHeight();
|
||||
|
||||
int y = height - 48;
|
||||
int xTempo = 8;
|
||||
int xSanity = width - BAR_WIDTH - 8;
|
||||
|
||||
float sanity = ClientData.SANITY;
|
||||
float insanity = ClientData.INSANITY;
|
||||
float tempo = ClientData.TEMPO;
|
||||
|
||||
float sanityPercent = sanity / 80f;
|
||||
float insanityPercent = insanity / 80f; // same max as sanity (80)
|
||||
float tempoPercent = tempo / 120f;
|
||||
|
||||
int sanityFill = (int) (BAR_WIDTH * sanityPercent);
|
||||
int tempoFill = (int) (BAR_WIDTH * tempoPercent);
|
||||
int insanityFill = (int) (BAR_WIDTH * insanityPercent);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
|
||||
// --- TEMPO BAR ---
|
||||
drawRoundedBar(gui, xTempo, y, BAR_WIDTH, BAR_HEIGHT, 0xFF33AFFF, tempoFill);
|
||||
gui.drawString(mc.font, Component.literal("Tempo"), xTempo, y - 10, 0x66CCFF, false);
|
||||
|
||||
// --- SANITY OR INSANITY BAR ---
|
||||
boolean insaneMode = sanity <= 0;
|
||||
|
||||
if (!insaneMode) {
|
||||
// Normal sanity bar
|
||||
drawRoundedBar(gui, xSanity, y, BAR_WIDTH, BAR_HEIGHT, 0xFFFFFFFF, sanityFill);
|
||||
gui.drawString(mc.font, Component.literal("Sanity"), xSanity + BAR_WIDTH - 30, y - 10, 0xFFFFFF, false);
|
||||
} else {
|
||||
int purple = 0xFFAA33FF;
|
||||
int darkPurple = 0xFF6611AA;
|
||||
drawRoundedRect(gui, xSanity, y, BAR_WIDTH, BAR_HEIGHT, 0xDD000000);
|
||||
drawRoundedRect(gui, xSanity, y, insanityFill, BAR_HEIGHT, purple, darkPurple);
|
||||
gui.drawString(mc.font, Component.literal("Insanity"), xSanity + BAR_WIDTH - 42, y - 10, 0xCC66FF, false);
|
||||
}
|
||||
double mouseX = mc.mouseHandler.xpos() * width / (double) event.getWindow().getScreenWidth();
|
||||
double mouseY = mc.mouseHandler.ypos() * height / (double) event.getWindow().getScreenHeight();
|
||||
if (isMouseOver(mouseX, mouseY, xTempo, y, BAR_WIDTH, BAR_HEIGHT)) {
|
||||
String text = String.format("%.0f%%", tempoPercent * 100f);
|
||||
gui.drawCenteredString(mc.font, text, xTempo + BAR_WIDTH / 2, y - 12, 0x66CCFF);
|
||||
}
|
||||
if (isMouseOver(mouseX, mouseY, xSanity, y, BAR_WIDTH, BAR_HEIGHT)) {
|
||||
if (!insaneMode) {
|
||||
String text = String.format("%.0f%%", sanityPercent * 100f);
|
||||
gui.drawCenteredString(mc.font, text, xSanity + BAR_WIDTH / 2, y - 12, 0xFFFFFF);
|
||||
} else {
|
||||
String text = String.format("%.0f%%", insanityPercent * 100f);
|
||||
gui.drawCenteredString(mc.font, text, xSanity + BAR_WIDTH / 2, y - 12, 0xCC66FF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawRoundedBar(GuiGraphics gui, int x, int y, int width, int height, int color, int fillWidth) {
|
||||
int bg = 0xCC000000;
|
||||
drawRoundedRect(gui, x, y, width, height, bg);
|
||||
int top = color;
|
||||
int bottom = (color & 0x00FFFFFF) | 0xFF000000;
|
||||
drawRoundedRect(gui, x, y, fillWidth, height, top, bottom);
|
||||
}
|
||||
|
||||
private static void drawRoundedRect(GuiGraphics gui, int x, int y, int width, int height, int color) {
|
||||
gui.fill(x + 1, y, x + width - 1, y + height, color); // center
|
||||
gui.fill(x, y + 1, x + width, y + height - 1, color); // sides
|
||||
gui.fill(x + 1, y + 1, x + width - 1, y + height - 1, color);
|
||||
}
|
||||
|
||||
private static void drawRoundedRect(GuiGraphics gui, int x, int y, int width, int height, int topColor, int bottomColor) {
|
||||
gui.fillGradient(x + 1, y, x + width - 1, y + height, topColor, bottomColor);
|
||||
gui.fillGradient(x, y + 1, x + width, y + height - 1, topColor, bottomColor);
|
||||
}
|
||||
|
||||
private static boolean isMouseOver(double mx, double my, int x, int y, int w, int h) {
|
||||
return mx >= x && mx <= x + w && my >= y && my <= y + h;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package net.fretux.mindmotion.client.effects;
|
||||
|
||||
import net.fretux.mindmotion.client.ClientData;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.PostChain;
|
||||
import net.minecraft.client.renderer.PostPass;
|
||||
import net.minecraft.client.renderer.EffectInstance;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderLevelStageEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "mindmotion", value = Dist.CLIENT)
|
||||
public class SanityShaderHandler {
|
||||
|
||||
private static final ResourceLocation DESAT_EFFECT =
|
||||
new ResourceLocation("mindmotion", "shaders/post/desaturate.json");
|
||||
|
||||
private static float currentStrength = 0f;
|
||||
|
||||
// cache reflection so we don't look it up every frame
|
||||
private static Field passesField;
|
||||
|
||||
private static List<PostPass> getPasses(PostChain chain) throws IllegalAccessException, NoSuchFieldException {
|
||||
if (passesField == null) {
|
||||
passesField = PostChain.class.getDeclaredField("passes");
|
||||
passesField.setAccessible(true);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<PostPass> passes = (List<PostPass>) passesField.get(chain);
|
||||
return passes;
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onRenderWorld(RenderLevelStageEvent event) {
|
||||
// AFTER_LEVEL is the point where the full world image is ready
|
||||
if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_LEVEL) return;
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
if (mc.player == null || mc.level == null) return;
|
||||
|
||||
float sanity = ClientData.SANITY;
|
||||
float insanity = ClientData.INSANITY;
|
||||
float maxSanity = 80f;
|
||||
|
||||
float sanityPct = sanity / maxSanity;
|
||||
float insanityPct = insanity / maxSanity;
|
||||
|
||||
float baseDesat = 0f;
|
||||
if (sanityPct < 0.70f) {
|
||||
baseDesat = 1f - (sanityPct / 0.70f);
|
||||
}
|
||||
|
||||
float insanityBoost = 0.75f * insanityPct;
|
||||
float target = Math.max(baseDesat, insanityBoost);
|
||||
if (sanity <= 0f) target = 1f;
|
||||
|
||||
// smooth to avoid popping
|
||||
currentStrength += (target - currentStrength) * 0.08f;
|
||||
|
||||
// if essentially zero, shut the effect off completely
|
||||
if (currentStrength < 0.005f) {
|
||||
if (mc.gameRenderer.currentEffect() != null) {
|
||||
mc.gameRenderer.shutdownEffect();
|
||||
}
|
||||
currentStrength = 0f;
|
||||
return;
|
||||
}
|
||||
|
||||
// ensure our effect is loaded
|
||||
if (mc.gameRenderer.currentEffect() == null) {
|
||||
try {
|
||||
mc.gameRenderer.loadEffect(DESAT_EFFECT);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
PostChain chain = mc.gameRenderer.currentEffect();
|
||||
if (chain == null) return; // failed to load
|
||||
|
||||
// update the Desat uniform on all passes
|
||||
try {
|
||||
for (PostPass pass : getPasses(chain)) {
|
||||
EffectInstance effect = pass.getEffect();
|
||||
if (effect == null) continue;
|
||||
var uniform = effect.getUniform("Desat");
|
||||
if (uniform != null) {
|
||||
uniform.set(currentStrength);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
|
||||
if (!event.getEntity().level().isClientSide()) return;
|
||||
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
currentStrength = 0f;
|
||||
|
||||
mc.execute(() -> {
|
||||
if (mc.gameRenderer.currentEffect() != null) {
|
||||
mc.gameRenderer.shutdownEffect();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.fretux.mindmotion.event;
|
||||
|
||||
import net.fretux.mindmotion.player.PlayerCapabilityProvider;
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "mindmotion")
|
||||
public class CombatEvents {
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onEntityHurt(LivingHurtEvent event) {
|
||||
if (event.getEntity() instanceof net.minecraft.world.entity.player.Player player) {
|
||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> tempo.addTempo(3));
|
||||
PlayerTickHandler.markCombat(player);
|
||||
}
|
||||
|
||||
if (event.getSource().getEntity() instanceof net.minecraft.world.entity.player.Player attacker) {
|
||||
attacker.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> tempo.addTempo(4));
|
||||
PlayerTickHandler.markCombat(attacker);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.fretux.mindmotion.event;
|
||||
|
||||
import net.fretux.mindmotion.player.PlayerCapabilityProvider;
|
||||
import net.minecraftforge.event.entity.living.LivingHurtEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
public class CommonEvents {
|
||||
|
||||
@SubscribeEvent
|
||||
public void onPlayerHurt(LivingHurtEvent event) {
|
||||
if (!(event.getEntity() instanceof net.minecraft.world.entity.player.Player player)) return;
|
||||
|
||||
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(sanity -> sanity.reduceSanity(1));
|
||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> tempo.addTempo(4));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onClone(PlayerEvent.Clone event) {
|
||||
event.getOriginal().reviveCaps();
|
||||
event.getEntity().getCapability(PlayerCapabilityProvider.SANITY).ifPresent(newCap ->
|
||||
event.getOriginal().getCapability(PlayerCapabilityProvider.SANITY)
|
||||
.ifPresent(oldCap -> newCap.setSanity(oldCap.getSanity()))
|
||||
);
|
||||
event.getOriginal().invalidateCaps();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package net.fretux.mindmotion.event;
|
||||
|
||||
import net.fretux.mindmotion.network.ModMessages;
|
||||
import net.fretux.mindmotion.network.SyncStatsS2CPacket;
|
||||
import net.fretux.mindmotion.player.PlayerCapabilityProvider;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "mindmotion")
|
||||
public class PlayerTickHandler {
|
||||
|
||||
private static final int SANITY_TICK_INTERVAL = 20;
|
||||
private static final int TEMPO_TICK_INTERVAL = 15;
|
||||
private static final int COMBAT_DECAY_DELAY = 100;
|
||||
private static final Map<UUID, Integer> lastCombatTick = new ConcurrentHashMap<>();
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onPlayerTick(TickEvent.PlayerTickEvent event) {
|
||||
if (event.phase != TickEvent.Phase.END) return;
|
||||
Player player = event.player;
|
||||
if (player.level().isClientSide) return;
|
||||
|
||||
int tick = player.tickCount;
|
||||
boolean sanityTick = tick % SANITY_TICK_INTERVAL == 0;
|
||||
boolean tempoTick = tick % TEMPO_TICK_INTERVAL == 0;
|
||||
|
||||
if (sanityTick) handleSanityAndInsanity(player);
|
||||
if (tempoTick) handleTempoTick(player, tick);
|
||||
|
||||
if (player instanceof ServerPlayer serverPlayer && (sanityTick || tempoTick)) {
|
||||
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(sanity ->
|
||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo ->
|
||||
ModMessages.CHANNEL.sendTo(
|
||||
new SyncStatsS2CPacket(
|
||||
sanity.getSanity(),
|
||||
sanity.getInsanity(),
|
||||
tempo.getTempo()
|
||||
),
|
||||
serverPlayer.connection.connection,
|
||||
net.minecraftforge.network.NetworkDirection.PLAY_TO_CLIENT
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleSanityAndInsanity(Player player) {
|
||||
player.getCapability(PlayerCapabilityProvider.SANITY).ifPresent(sanity -> {
|
||||
float value = sanity.getSanity();
|
||||
float insanity = sanity.getInsanity();
|
||||
float delta = 0f;
|
||||
boolean inDark = player.level().getMaxLocalRawBrightness(player.blockPosition()) < 5;
|
||||
boolean inRain = player.level().isRainingAt(player.blockPosition());
|
||||
boolean isHungry = player.getFoodData().getFoodLevel() < 6;
|
||||
boolean nearLava = player.level().getBlockState(player.blockPosition().below()).is(Blocks.LAVA);
|
||||
boolean inWater = player.isInWater() && !player.isUnderWater();
|
||||
boolean underWater = player.isUnderWater();
|
||||
boolean sleeping = player.isSleeping();
|
||||
boolean inLight = player.level().getMaxLocalRawBrightness(player.blockPosition()) > 12;
|
||||
boolean nearTorch = player.level().getBlockState(player.blockPosition().above()).is(Blocks.TORCH);
|
||||
if (inDark) delta -= 0.02f;
|
||||
if (inRain) delta -= 0.04f;
|
||||
if (isHungry) delta -= 0.06f;
|
||||
if (nearLava) delta -= 0.05f;
|
||||
if (underWater) delta -= 0.04f;
|
||||
if (inWater && !underWater) delta -= 0.02f;
|
||||
if (inLight) delta += 0.03f;
|
||||
if (nearTorch) delta += 0.05f;
|
||||
if (sleeping) delta += 0.25f;
|
||||
if (player.getUseItem() != null && player.getUseItem().isEdible()) delta += 0.05f;
|
||||
sanity.setSanity(value + delta);
|
||||
if (sanity.getSanity() <= 0) {
|
||||
sanity.setSanity(0);
|
||||
sanity.setInsanity(Math.min(sanity.getMaxSanity(), insanity + 0.3f));
|
||||
if (sanity.getInsanity() >= sanity.getMaxSanity()) {
|
||||
player.kill();
|
||||
return;
|
||||
}
|
||||
} else if (sanity.getInsanity() > 0) {
|
||||
sanity.setInsanity(Math.max(0, insanity - 0.15f));
|
||||
}
|
||||
float percent = (value / sanity.getMaxSanity()) * 100f;
|
||||
if (percent <= 70 && percent > 50 && Math.random() < 0.03)
|
||||
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 40, 0)); // Shiver
|
||||
if (percent <= 30 && percent > 10 && Math.random() < 0.015) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 1));
|
||||
player.hurt(player.damageSources().magic(), 1f);
|
||||
}
|
||||
if (percent <= 10 && percent > 0 && Math.random() < 0.02) {
|
||||
player.hurt(player.damageSources().magic(), 2f);
|
||||
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 30, 1));
|
||||
}
|
||||
float insanityPercent = (insanity / sanity.getMaxSanity()) * 100f;
|
||||
if (insanityPercent > 0) {
|
||||
if (insanityPercent > 60 && Math.random() < 0.02) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60, 1));
|
||||
player.hurt(player.damageSources().magic(), 1f);
|
||||
}
|
||||
if (insanityPercent > 90 && Math.random() < 0.05) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 60, 2));
|
||||
player.hurt(player.damageSources().magic(), 2f);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void handleTempoTick(Player player, int currentTick) {
|
||||
player.getCapability(PlayerCapabilityProvider.TEMPO).ifPresent(tempo -> {
|
||||
int value = tempo.getTempo();
|
||||
int lastCombat = lastCombatTick.getOrDefault(player.getUUID(), -10000);
|
||||
int ticksSinceCombat = currentTick - lastCombat;
|
||||
|
||||
if (ticksSinceCombat > COMBAT_DECAY_DELAY && value > 0) {
|
||||
tempo.setTempo(value - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void markCombat(Player player) {
|
||||
lastCombatTick.put(player.getUUID(), player.tickCount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package net.fretux.mindmotion.network;
|
||||
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.network.NetworkDirection;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.network.simple.SimpleChannel;
|
||||
|
||||
import net.fretux.mindmotion.AscendMindMotion;
|
||||
|
||||
public class ModMessages {
|
||||
|
||||
private static final String PROTOCOL_VERSION = "1";
|
||||
public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel(
|
||||
new ResourceLocation(AscendMindMotion.MODID, "main"),
|
||||
() -> PROTOCOL_VERSION,
|
||||
PROTOCOL_VERSION::equals,
|
||||
PROTOCOL_VERSION::equals
|
||||
);
|
||||
|
||||
private static int id = 0;
|
||||
private static int nextId() { return id++; }
|
||||
|
||||
public static void register() {
|
||||
CHANNEL.messageBuilder(SyncStatsS2CPacket.class, nextId(), NetworkDirection.PLAY_TO_CLIENT)
|
||||
.encoder(SyncStatsS2CPacket::encode)
|
||||
.decoder(SyncStatsS2CPacket::decode)
|
||||
.consumerMainThread(SyncStatsS2CPacket::handle)
|
||||
.add();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package net.fretux.mindmotion.network;
|
||||
|
||||
import net.fretux.mindmotion.client.ClientData;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraftforge.network.NetworkEvent;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SyncStatsS2CPacket {
|
||||
private final float sanity;
|
||||
private final float insanity;
|
||||
private final int tempo;
|
||||
|
||||
public SyncStatsS2CPacket(float sanity, float insanity, int tempo) {
|
||||
this.sanity = sanity;
|
||||
this.insanity = insanity;
|
||||
this.tempo = tempo;
|
||||
}
|
||||
|
||||
public static void encode(SyncStatsS2CPacket msg, FriendlyByteBuf buf) {
|
||||
buf.writeFloat(msg.sanity);
|
||||
buf.writeFloat(msg.insanity);
|
||||
buf.writeInt(msg.tempo);
|
||||
}
|
||||
|
||||
public static SyncStatsS2CPacket decode(FriendlyByteBuf buf) {
|
||||
return new SyncStatsS2CPacket(buf.readFloat(), buf.readFloat(), buf.readInt());
|
||||
}
|
||||
|
||||
public static void handle(SyncStatsS2CPacket msg, Supplier<NetworkEvent.Context> ctx) {
|
||||
ctx.get().enqueueWork(() -> {
|
||||
ClientData.SANITY = msg.sanity;
|
||||
ClientData.INSANITY = msg.insanity;
|
||||
ClientData.TEMPO = msg.tempo;
|
||||
});
|
||||
ctx.get().setPacketHandled(true);
|
||||
System.out.println("[Client] Sanity: " + msg.sanity + ", Insanity: " + msg.insanity + ", Tempo: " + msg.tempo);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package net.fretux.mindmotion.player;
|
||||
|
||||
public interface ISanity {
|
||||
float getSanity();
|
||||
void setSanity(float sanity);
|
||||
float getInsanity();
|
||||
void setInsanity(float insanity);
|
||||
float getMaxSanity();
|
||||
void addSanity(float amount);
|
||||
void reduceSanity(float amount);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.fretux.mindmotion.player;
|
||||
|
||||
public interface ITempo {
|
||||
int getTempo();
|
||||
void setTempo(int tempo);
|
||||
int getMaxTempo();
|
||||
void addTempo(int amount);
|
||||
void reduceTempo(int amount);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package net.fretux.mindmotion.player;
|
||||
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.capabilities.*;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@Mod.EventBusSubscriber(modid = "mindmotion")
|
||||
public class PlayerCapabilityProvider {
|
||||
public static final Capability<ISanity> SANITY = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
public static final Capability<ITempo> TEMPO = CapabilityManager.get(new CapabilityToken<>(){});
|
||||
|
||||
@SubscribeEvent
|
||||
public static void attachCapabilities(AttachCapabilitiesEvent<?> event) {
|
||||
if (event.getObject() instanceof net.minecraft.world.entity.player.Player player) {
|
||||
event.addCapability(new ResourceLocation("mindmotion", "sanity"), new SanityProvider());
|
||||
event.addCapability(new ResourceLocation("mindmotion", "tempo"), new TempoProvider());
|
||||
}
|
||||
}
|
||||
|
||||
private static class SanityProvider implements ICapabilityProvider, ICapabilitySerializable<CompoundTag> {
|
||||
private final SanityCapability instance = new SanityCapability();
|
||||
private final LazyOptional<ISanity> optional = LazyOptional.of(() -> instance);
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
return cap == SANITY ? optional.cast() : LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putFloat("Sanity", instance.getSanity());
|
||||
tag.putFloat("Insanity", instance.getInsanity());
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
instance.setSanity(nbt.getFloat("Sanity"));
|
||||
instance.setInsanity(nbt.getFloat("Insanity"));
|
||||
}
|
||||
}
|
||||
|
||||
private static class TempoProvider implements ICapabilityProvider, ICapabilitySerializable<CompoundTag> {
|
||||
private final TempoCapability instance = new TempoCapability();
|
||||
private final LazyOptional<ITempo> optional = LazyOptional.of(() -> instance);
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
|
||||
return cap == TEMPO ? optional.cast() : LazyOptional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag serializeNBT() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putInt("Tempo", instance.getTempo());
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deserializeNBT(CompoundTag nbt) {
|
||||
instance.setTempo(nbt.getInt("Tempo"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.fretux.mindmotion.player;
|
||||
|
||||
public class SanityCapability implements ISanity {
|
||||
private float sanity = 80f;
|
||||
private float insanity = 0f;
|
||||
private final float maxSanity = 80f;
|
||||
|
||||
@Override
|
||||
public float getSanity() { return sanity; }
|
||||
@Override
|
||||
public void setSanity(float sanity) { this.sanity = Math.max(0, Math.min(maxSanity, sanity)); }
|
||||
|
||||
@Override
|
||||
public float getInsanity() { return insanity; }
|
||||
@Override
|
||||
public void setInsanity(float insanity) { this.insanity = Math.max(0, Math.min(maxSanity, insanity)); }
|
||||
|
||||
@Override
|
||||
public float getMaxSanity() { return maxSanity; }
|
||||
|
||||
@Override
|
||||
public void addSanity(float amount) { setSanity(this.sanity + amount); }
|
||||
@Override
|
||||
public void reduceSanity(float amount) { setSanity(this.sanity - amount); }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.fretux.mindmotion.player;
|
||||
|
||||
public class TempoCapability implements ITempo {
|
||||
private int tempo = 0;
|
||||
private final int maxTempo = 120;
|
||||
|
||||
@Override
|
||||
public int getTempo() { return tempo; }
|
||||
@Override
|
||||
public void setTempo(int tempo) { this.tempo = Math.max(0, Math.min(maxTempo, tempo)); }
|
||||
@Override
|
||||
public int getMaxTempo() { return maxTempo; }
|
||||
@Override
|
||||
public void addTempo(int amount) { setTempo(this.tempo + amount); }
|
||||
@Override
|
||||
public void reduceTempo(int amount) { setTempo(this.tempo - amount); }
|
||||
}
|
||||
Reference in New Issue
Block a user