From 7087705f22086fcf5072f6ce5dcd1e387107e1e3 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 11 Aug 2021 12:55:18 +0700 Subject: [PATCH] Networking test, player capability is now networked to them --- .../mc/otm/OverdriveThatMatters.java | 87 +++++++- .../mc/otm/capability/AndroidCapability.java | 200 ++++++++++++------ .../capability/AndroidCapabilityPlayer.java | 76 +++++++ .../mc/otm/capability/IAndroidCapability.java | 6 + .../mc/otm/capability/MatteryCapability.java | 26 +-- .../AndroidCapabilityChangePacket.java | 100 +++++++++ ...tAndroidCapabilityChangePacketHandler.java | 18 ++ .../mc/otm/network/MatteryNetwork.java | 33 +++ .../mc/otm/network/NetworkHelper.java | 26 +++ .../mc/otm/screen/PoweredMachineScreen.java | 19 +- .../textures/gui/player_gui.png | Bin 0 -> 869 bytes .../textures/gui/player_gui.xcf | Bin 0 -> 5273 bytes 12 files changed, 496 insertions(+), 95 deletions(-) create mode 100644 src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapabilityPlayer.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/network/AndroidCapabilityChangePacket.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/network/ClientAndroidCapabilityChangePacketHandler.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetwork.java create mode 100644 src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/player_gui.png create mode 100644 src/main/resources/assets/overdrive_that_matters/textures/gui/player_gui.xcf diff --git a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java index 95c66034f..4be580d96 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java +++ b/src/main/java/ru/dbotthepony/mc/otm/OverdriveThatMatters.java @@ -1,9 +1,13 @@ package ru.dbotthepony.mc.otm; +import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.BlockItem; @@ -11,10 +15,12 @@ import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.client.gui.ForgeIngameGui; import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.InterModComms; @@ -29,11 +35,15 @@ import org.apache.logging.log4j.Logger; import ru.dbotthepony.mc.otm.block.BlockAndroidStation; import ru.dbotthepony.mc.otm.block.entity.BlockEntityAndroidStation; import ru.dbotthepony.mc.otm.capability.AndroidCapability; +import ru.dbotthepony.mc.otm.capability.AndroidCapabilityPlayer; import ru.dbotthepony.mc.otm.capability.IAndroidCapability; import ru.dbotthepony.mc.otm.capability.MatteryCapability; import ru.dbotthepony.mc.otm.menu.AndroidStationMenu; +import ru.dbotthepony.mc.otm.network.MatteryNetwork; import ru.dbotthepony.mc.otm.screen.AndroidStationScreen; +import java.math.BigDecimal; +import java.util.Optional; import java.util.stream.Collectors; // The value here should match an entry in the META-INF/mods.toml file @@ -43,6 +53,8 @@ public class OverdriveThatMatters { public static final String MOD_ID = "overdrive_that_matters"; public static final Logger LOGGER = LogManager.getLogger(); + public static final ResourceLocation PLAYER_GUI_LOCATION = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/player_gui.png"); + public static Block ANDROID_STATION = new BlockAndroidStation(); public static BlockEntityType.Builder ANDROID_STATION_BUILDER = BlockEntityType.Builder.of(BlockEntityAndroidStation::new, ANDROID_STATION); public static BlockEntityType ANDROID_STATION_FACTORY = null; @@ -69,6 +81,8 @@ public class OverdriveThatMatters { private void setup(final FMLCommonSetupEvent event) { // some preinit code + MatteryCapability.register(); + MatteryNetwork.register(); } private void enqueueIMC(final InterModEnqueueEvent event) { @@ -97,20 +111,79 @@ public class OverdriveThatMatters { return; } - event.addCapability(android_cap_location, new AndroidCapability((Player) event.getObject())); + event.addCapability(android_cap_location, new AndroidCapabilityPlayer((Player) event.getObject())); + } + + @SubscribeEvent + public void onPostTick(TickEvent.ServerTickEvent event) { + if (event.phase == TickEvent.Phase.END) { + + } } @SubscribeEvent public void onLivingTick(LivingEvent.LivingUpdateEvent event) { if (event.getEntity() instanceof ServerPlayer ply) { - LazyOptional capability = ply.getCapability(MatteryCapability.ANDROID); + ply.getCapability(MatteryCapability.ANDROID).ifPresent(IAndroidCapability::tick); + } else if (event.getEntity() instanceof LocalPlayer ply) { + ply.getCapability(MatteryCapability.ANDROID).ifPresent(IAndroidCapability::tickClient); + } + } - if (!capability.isPresent()) { - return; + @SubscribeEvent + public void onLayerRenderEvent(RenderGameOverlayEvent.PreLayer event) { + if (event.getOverlay() != ForgeIngameGui.FOOD_LEVEL_ELEMENT) + return; + + Minecraft mc = Minecraft.getInstance(); + LocalPlayer ply = mc.player; + + if (ply == null) + return; + + if ( + ply.getVehicle() instanceof LivingEntity || + mc.options.hideGui || + !mc.gameMode.canHurtPlayer() || + !(mc.getCameraEntity() instanceof Player) + ) + return; + + Optional lazy = ply.getCapability(MatteryCapability.ANDROID).resolve(); + + if (lazy.isPresent() && mc.gui instanceof ForgeIngameGui gui) { + event.setCanceled(true); + IAndroidCapability android = lazy.get(); + + float level; + + if (android.getMaxBatteryLevel().compareTo(BigDecimal.ZERO) == 0) { + level = 0f; + } else { + level = android.getBatteryLevel().divide(android.getMaxBatteryLevel(), MatteryCapability.ROUND_RULES).floatValue(); + + if (level >= 0.98f) + level = 1f; } - IAndroidCapability android = capability.resolve().get(); - android.tick(); + gui.setupOverlayRenderState(true, false); + + RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); + RenderSystem.setShaderTexture(0, PLAYER_GUI_LOCATION); + + int width = event.getWindow().getGuiScaledWidth(); + int height = event.getWindow().getGuiScaledHeight(); + + int left = width / 2 + 10; + int top = height - gui.right_height; + + gui.right_height += 10; + + // Stack, x, y, blitOffset?, (float) image_x, (float) image_y, rect_x, rect_y, total_image_width, total_image_height + // Stack, x, y, image_x, image_y, rect_x, rect_y + gui.blit(event.getMatrixStack(), left, top, 0, 0, 80, 9); + int shift_left = (int) Math.ceil(level * 80f - 0.5f); + gui.blit(event.getMatrixStack(), left + 80 - shift_left, top, 0, 9, shift_left, 9); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapability.java index 6813c0ceb..653f5b32f 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapability.java @@ -13,16 +13,23 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.energy.IEnergyStorage; import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.network.AndroidCapabilityChangePacket; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.math.BigDecimal; +import java.util.Optional; +import java.util.Random; public class AndroidCapability implements ICapabilityProvider, IAndroidCapability, INBTSerializable { - private final LivingEntity ent; - private BigDecimal energy_stored = new BigDecimal(0); - private BigDecimal energy_stored_max = new BigDecimal(32000); - private ItemStack battery = ItemStack.EMPTY; + protected final LivingEntity ent; + protected BigDecimal energy_stored = new BigDecimal(0); + protected BigDecimal energy_stored_max = new BigDecimal(32000); + protected ItemStack battery = ItemStack.EMPTY; + + private BigDecimal network_energy = new BigDecimal(-1); + private BigDecimal network_energy_max = new BigDecimal(-1); + private ItemStack network_battery = ItemStack.EMPTY; public static final BigDecimal ENERGY_FOR_HUNGER_POINT = new BigDecimal(200); @@ -52,46 +59,79 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit battery = ItemStack.of(compound.getCompound("battery")); } + protected void tickNetwork() { + + } + + @Override + @Nullable + public AndroidCapabilityChangePacket writeChanges() { + AndroidCapabilityChangePacket packet = null; + + if (!energy_stored.equals(network_energy)) { + network_energy = energy_stored; + packet = new AndroidCapabilityChangePacket(); + packet.energyChanged(network_energy); + } + + if (!energy_stored_max.equals(network_energy_max)) { + network_energy_max = energy_stored_max; + if (packet == null) packet = new AndroidCapabilityChangePacket(); + packet.maxEnergyChanged(energy_stored_max); + } + + if (!network_battery.equals(battery, false)) { + network_battery = battery.copy(); + if (packet == null) packet = new AndroidCapabilityChangePacket(); + packet.batteryStackChanged(battery); + } + + return packet; + } + + @Override + public void readChanges(AndroidCapabilityChangePacket packet) { + if (packet.energy != null) + energy_stored = packet.energy; + + if (packet.max_energy != null) + energy_stored_max = packet.max_energy; + + if (packet.battery != null) + battery = packet.battery; + } + + @Override + public void tickClient() { + + } + @Override public void tick() { - if (ent instanceof ServerPlayer) { - FoodData stats = ((ServerPlayer) ent).getFoodData(); + tickInner(); + tickNetwork(); + } - if (stats.needsFood()) { - int food_points_missing = 20 - stats.getFoodLevel(); - boolean food_changed = false; - float saturation_points_missing = 20F - stats.getSaturationLevel(); - boolean saturation_changed = false; + protected void tickInner() { + if (!battery.isEmpty()) { + BigDecimal demand = energy_stored_max.subtract(energy_stored, MatteryCapability.ROUND_RULES); - while (food_points_missing > 0) { - if (this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).equals(ENERGY_FOR_HUNGER_POINT)) { - this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); - food_points_missing--; - food_changed = true; - } else { - break; + if (demand.compareTo(BigDecimal.ZERO) > 0) { + Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); + + if (get_mattery.isPresent()) { + demand = demand.subtract(get_mattery.get().extractEnergyInner(demand, false), MatteryCapability.ROUND_RULES); + } + + if (demand.compareTo(BigDecimal.ONE) >= 0) { + Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); + + if (get_energy.isPresent()) { + demand = demand.subtract(MatteryCapability.drainFE(get_energy.get(), demand, false), MatteryCapability.ROUND_RULES); } } - while (saturation_points_missing >= 1F) { - if (this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).equals(ENERGY_FOR_HUNGER_POINT)) { - this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); - saturation_points_missing--; - saturation_changed = true; - } else { - break; - } - } - - if (food_changed) { - stats.setFoodLevel(20 - food_points_missing); - } - - if (saturation_changed) { - stats.setSaturation(20F - saturation_points_missing); - } - - OverdriveThatMatters.LOGGER.info("New power level {}", getBatteryLevel()); + energy_stored = energy_stored_max.subtract(demand); } } } @@ -105,61 +145,99 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit @Nonnull @Override public BigDecimal extractEnergyInner(BigDecimal howMuch, boolean simulate) { + BigDecimal drained = BigDecimal.ZERO; + if (battery != ItemStack.EMPTY) { - LazyOptional get_mattery = battery.getCapability(MatteryCapability.ENERGY); + Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); if (get_mattery.isPresent()) { - return get_mattery.resolve().get().extractEnergyInner(howMuch, simulate); + BigDecimal changed = get_mattery.get().extractEnergyOuter(howMuch, simulate); + + if (changed.compareTo(BigDecimal.ZERO) > 0) { + drained = drained.add(changed, MatteryCapability.ROUND_RULES); + howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES); + + if (howMuch.compareTo(BigDecimal.ZERO) <= 0) { + return drained; + } + } } if (howMuch.compareTo(BigDecimal.ONE) >= 0) { - LazyOptional get_energy = battery.getCapability(CapabilityEnergy.ENERGY); + Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); if (get_energy.isPresent()) { - int converted = howMuch.compareTo(MatteryCapability.INT_MAX_VALUE) <= 0 ? howMuch.intValue() : Integer.MAX_VALUE; - return new BigDecimal(get_energy.resolve().get().extractEnergy(converted, simulate)); + BigDecimal changed = MatteryCapability.drainFE(get_energy.get(), howMuch, simulate); + + if (changed.compareTo(BigDecimal.ZERO) > 0) { + drained = drained.add(changed, MatteryCapability.ROUND_RULES); + howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES); + + if (howMuch.compareTo(BigDecimal.ZERO) <= 0) { + return drained; + } + } } } } BigDecimal new_energy = energy_stored.subtract(howMuch, MatteryCapability.ROUND_RULES).max(BigDecimal.ZERO); - BigDecimal diff = energy_stored.subtract(new_energy, MatteryCapability.ROUND_RULES); + drained = drained.add(energy_stored.subtract(new_energy, MatteryCapability.ROUND_RULES)); if (!simulate) { energy_stored = new_energy; } - return diff; + return drained; } @Nonnull @Override public BigDecimal receiveEnergyOuter(BigDecimal howMuch, boolean simulate) { + BigDecimal received = BigDecimal.ZERO; + if (battery != ItemStack.EMPTY) { - LazyOptional get_mattery = battery.getCapability(MatteryCapability.ENERGY); + Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); if (get_mattery.isPresent()) { - return get_mattery.resolve().get().receiveEnergyOuter(howMuch, simulate); + BigDecimal changed = get_mattery.get().receiveEnergyOuter(howMuch, simulate); + + if (changed.compareTo(BigDecimal.ZERO) > 0) { + received = received.add(changed, MatteryCapability.ROUND_RULES); + howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES); + + if (howMuch.compareTo(BigDecimal.ZERO) <= 0) { + return received; + } + } } if (howMuch.compareTo(BigDecimal.ONE) >= 0) { - LazyOptional get_energy = battery.getCapability(CapabilityEnergy.ENERGY); + Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); if (get_energy.isPresent()) { - int converted = howMuch.compareTo(MatteryCapability.INT_MAX_VALUE) <= 0 ? howMuch.intValue() : Integer.MAX_VALUE; - return new BigDecimal(get_energy.resolve().get().receiveEnergy(converted, simulate)); + BigDecimal changed = MatteryCapability.floodFE(get_energy.get(), howMuch, simulate); + + if (changed.compareTo(BigDecimal.ZERO) > 0) { + received = received.add(changed, MatteryCapability.ROUND_RULES); + howMuch = howMuch.subtract(changed, MatteryCapability.ROUND_RULES); + + if (howMuch.compareTo(BigDecimal.ZERO) <= 0) { + return received; + } + } } } } BigDecimal new_energy = energy_stored.add(howMuch, MatteryCapability.ROUND_RULES).min(energy_stored_max); - BigDecimal diff = new_energy.subtract(energy_stored, MatteryCapability.ROUND_RULES); + received = received.add(new_energy.subtract(energy_stored, MatteryCapability.ROUND_RULES), MatteryCapability.ROUND_RULES); if (!simulate) { energy_stored = new_energy; } - return diff; + return received; } @Nonnull @@ -188,16 +266,16 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit @Nonnull public BigDecimal getBatteryLevel() { if (battery != ItemStack.EMPTY) { - LazyOptional get_mattery = battery.getCapability(MatteryCapability.ENERGY); + Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); if (get_mattery.isPresent()) { - return get_mattery.resolve().get().getBatteryLevel(); + return get_mattery.get().getBatteryLevel().add(energy_stored, MatteryCapability.ROUND_RULES); } - LazyOptional get_energy = battery.getCapability(CapabilityEnergy.ENERGY); + Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); if (get_energy.isPresent()) { - return new BigDecimal(get_energy.resolve().get().getEnergyStored()); + return new BigDecimal(get_energy.get().getEnergyStored()).add(energy_stored, MatteryCapability.ROUND_RULES); } } @@ -208,27 +286,29 @@ public class AndroidCapability implements ICapabilityProvider, IAndroidCapabilit @Nonnull public BigDecimal getMaxBatteryLevel() { if (battery != ItemStack.EMPTY) { - LazyOptional get_mattery = battery.getCapability(MatteryCapability.ENERGY); + Optional get_mattery = battery.getCapability(MatteryCapability.ENERGY).resolve(); if (get_mattery.isPresent()) { - return get_mattery.resolve().get().getMaxBatteryLevel(); + return get_mattery.get().getMaxBatteryLevel().add(energy_stored_max, MatteryCapability.ROUND_RULES); } - LazyOptional get_energy = battery.getCapability(CapabilityEnergy.ENERGY); + Optional get_energy = battery.getCapability(CapabilityEnergy.ENERGY).resolve(); if (get_energy.isPresent()) { - return new BigDecimal(get_energy.resolve().get().getMaxEnergyStored()); + return new BigDecimal(get_energy.get().getMaxEnergyStored()).add(energy_stored_max, MatteryCapability.ROUND_RULES); } } return energy_stored_max; } + private final LazyOptional resolver = LazyOptional.of(() -> this).cast(); + @Nonnull @Override public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { if (cap == MatteryCapability.ANDROID) { - return LazyOptional.of(() -> this).cast(); + return resolver.cast(); } return LazyOptional.empty(); diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapabilityPlayer.java b/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapabilityPlayer.java new file mode 100644 index 000000000..da98e7df4 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/AndroidCapabilityPlayer.java @@ -0,0 +1,76 @@ +package ru.dbotthepony.mc.otm.capability; + +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.food.FoodData; +import net.minecraftforge.fmllegacy.network.PacketDistributor; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.network.AndroidCapabilityChangePacket; +import ru.dbotthepony.mc.otm.network.MatteryNetwork; + +import java.math.BigDecimal; +import java.util.Random; + +public class AndroidCapabilityPlayer extends AndroidCapability { + private final Player ply; + + public AndroidCapabilityPlayer(Player ent) { + super(ent); + ply = ent; + } + + @Override + protected void tickNetwork() { + AndroidCapabilityChangePacket packet = writeChanges(); + + if (packet != null) + MatteryNetwork.ANDROID_PLAYER.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) ent), packet); + } + + @Override + public void tickInner() { + super.tickInner(); + + extractEnergyInner(BigDecimal.valueOf(new Random().nextDouble()), false); + + FoodData stats = ply.getFoodData(); + + if (stats.needsFood()) { + int food_points_missing = 20 - stats.getFoodLevel(); + boolean food_changed = false; + float saturation_points_missing = 20F - stats.getSaturationLevel(); + boolean saturation_changed = false; + + while (food_points_missing > 0) { + if (this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).equals(ENERGY_FOR_HUNGER_POINT)) { + this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); + food_points_missing--; + food_changed = true; + } else { + break; + } + } + + while (saturation_points_missing >= 1F) { + if (this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, true).equals(ENERGY_FOR_HUNGER_POINT)) { + this.extractEnergyInner(ENERGY_FOR_HUNGER_POINT, false); + saturation_points_missing--; + saturation_changed = true; + } else { + break; + } + } + + if (food_changed) { + stats.setFoodLevel(20 - food_points_missing); + } + + if (saturation_changed) { + stats.setSaturation(20F - saturation_points_missing); + } + + OverdriveThatMatters.LOGGER.info("New power level {}", getBatteryLevel()); + } + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/IAndroidCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/IAndroidCapability.java index ad83e2798..216e447af 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/IAndroidCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/IAndroidCapability.java @@ -3,15 +3,21 @@ package ru.dbotthepony.mc.otm.capability; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.capabilities.ICapabilityProvider; +import ru.dbotthepony.mc.otm.network.AndroidCapabilityChangePacket; import javax.annotation.Nonnull; import javax.annotation.Nullable; public interface IAndroidCapability extends IMatteryEnergyStorage { void tick(); + void tickClient(); LivingEntity getEntity(); @Nonnull ItemStack getBatteryItemStack(); void setBatteryItemStack(@Nonnull ItemStack stack); + + // networking + AndroidCapabilityChangePacket writeChanges(); + void readChanges(AndroidCapabilityChangePacket packet); } diff --git a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java index c852c3341..4e0aa296a 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java +++ b/src/main/java/ru/dbotthepony/mc/otm/capability/MatteryCapability.java @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.energy.IEnergyStorage; import java.math.BigDecimal; @@ -15,6 +16,11 @@ public class MatteryCapability { @CapabilityInject(IAndroidCapability.class) public static Capability ANDROID = null; + public static void register() { + CapabilityManager.INSTANCE.register(IAndroidCapability.class); + CapabilityManager.INSTANCE.register(IMatteryEnergyStorage.class); + } + public static final MathContext ROUND_RULES = new MathContext(16, RoundingMode.HALF_UP); public static final BigDecimal INT_MAX_VALUE = new BigDecimal(Integer.MAX_VALUE); @@ -27,27 +33,13 @@ public class MatteryCapability { if (howMuch.compareTo(BigDecimal.ONE) < 0) return BigDecimal.ZERO; - int howMuchInt; - - if (howMuch.compareTo(INT_MAX_VALUE) > 0) - howMuchInt = Integer.MAX_VALUE; - else - howMuchInt = howMuch.intValue(); - - return new BigDecimal(capability.extractEnergy(howMuchInt, simulate)); + return new BigDecimal(capability.extractEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.intValue(), simulate)); } - public static BigDecimal fillFE(IEnergyStorage capability, BigDecimal howMuch, boolean simulate) { + public static BigDecimal floodFE(IEnergyStorage capability, BigDecimal howMuch, boolean simulate) { if (howMuch.compareTo(BigDecimal.ONE) < 0) return BigDecimal.ZERO; - int howMuchInt; - - if (howMuch.compareTo(INT_MAX_VALUE) > 0) - howMuchInt = Integer.MAX_VALUE; - else - howMuchInt = howMuch.intValue(); - - return new BigDecimal(capability.receiveEnergy(howMuchInt, simulate)); + return new BigDecimal(capability.receiveEnergy(howMuch.compareTo(INT_MAX_VALUE) > 0 ? Integer.MAX_VALUE : howMuch.intValue(), simulate)); } } diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/AndroidCapabilityChangePacket.java b/src/main/java/ru/dbotthepony/mc/otm/network/AndroidCapabilityChangePacket.java new file mode 100644 index 000000000..ac6703a7a --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/AndroidCapabilityChangePacket.java @@ -0,0 +1,100 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import net.minecraftforge.fmllegacy.network.PacketDistributor; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.function.Supplier; + +public class AndroidCapabilityChangePacket { + public enum ChangeType { + TERMINATION, + ENERGY_CHANGED, + MAX_ENERGY_CHANGED, + BATTERY_STACK_CHANGED, + } + + public static ChangeType[] CHANGE_MAP = new ChangeType[] { + ChangeType.TERMINATION, + ChangeType.ENERGY_CHANGED, + ChangeType.MAX_ENERGY_CHANGED, + ChangeType.BATTERY_STACK_CHANGED, + }; + + public BigDecimal energy; + public BigDecimal max_energy; + public ItemStack battery; + + public boolean isEmpty() { + return energy == null && max_energy == null && battery == null; + } + + // build state + public void energyChanged(BigDecimal energy) { + this.energy = energy; + } + + public void maxEnergyChanged(BigDecimal energy) { + this.max_energy = energy; + } + + public void batteryStackChanged(ItemStack stack) { + this.battery = stack; + } + + // encode state + public void encodeNetwork(FriendlyByteBuf buffer) { + if (energy != null) { + buffer.writeByte(ChangeType.ENERGY_CHANGED.ordinal()); + NetworkHelper.writeDecimal(buffer, energy); + } + + if (max_energy != null) { + buffer.writeByte(ChangeType.MAX_ENERGY_CHANGED.ordinal()); + NetworkHelper.writeDecimal(buffer, max_energy); + } + + if (battery != null) { + buffer.writeByte(ChangeType.BATTERY_STACK_CHANGED.ordinal()); + buffer.writeItem(battery); + } + + buffer.writeByte(ChangeType.TERMINATION.ordinal()); + } + + // handle state + public void handleMessage(Supplier context) { + context.get().setPacketHandled(true); + + context.get().enqueueWork(() -> { + DistExecutor.safeRunWhenOn(Dist.CLIENT, () -> () -> ClientAndroidCapabilityChangePacketHandler.handlePacket(this, context)); + }); + } + + // decode state + public static AndroidCapabilityChangePacket decodeNetwork(FriendlyByteBuf buffer) { + AndroidCapabilityChangePacket packet = new AndroidCapabilityChangePacket(); + + ChangeType read = CHANGE_MAP[buffer.readByte()]; + + while (read != ChangeType.TERMINATION) { + switch (read) { + case ENERGY_CHANGED -> packet.energy = NetworkHelper.readDecimal(buffer); + case MAX_ENERGY_CHANGED -> packet.max_energy = NetworkHelper.readDecimal(buffer); + case BATTERY_STACK_CHANGED -> packet.battery = buffer.readItem(); + } + + read = CHANGE_MAP[buffer.readByte()]; + } + + return packet; + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/ClientAndroidCapabilityChangePacketHandler.java b/src/main/java/ru/dbotthepony/mc/otm/network/ClientAndroidCapabilityChangePacketHandler.java new file mode 100644 index 000000000..0b7ba1b07 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/ClientAndroidCapabilityChangePacketHandler.java @@ -0,0 +1,18 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fmllegacy.network.NetworkEvent; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; +import ru.dbotthepony.mc.otm.capability.MatteryCapability; + +import java.util.function.Supplier; + +public class ClientAndroidCapabilityChangePacketHandler { + public static void handlePacket(AndroidCapabilityChangePacket packet, Supplier ctx) { + if (Minecraft.getInstance().player != null) { + Minecraft.getInstance().player.getCapability(MatteryCapability.ANDROID) + .orElseThrow(() -> new IllegalStateException("Local player has no android capability yet")) + .readChanges(packet); + } + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetwork.java b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetwork.java new file mode 100644 index 000000000..f00856452 --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/MatteryNetwork.java @@ -0,0 +1,33 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.fmllegacy.network.NetworkDirection; +import net.minecraftforge.fmllegacy.network.NetworkRegistry; +import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; +import ru.dbotthepony.mc.otm.OverdriveThatMatters; + +import java.util.Optional; + +public class MatteryNetwork { + private static final String PROTOCOL_VERSION = "1"; + + private static int next_network_id = 0; + + public static final SimpleChannel ANDROID_PLAYER = NetworkRegistry.newSimpleChannel( + new ResourceLocation(OverdriveThatMatters.MOD_ID, "android_player"), + () -> PROTOCOL_VERSION, + PROTOCOL_VERSION::equals, + PROTOCOL_VERSION::equals + ); + + public static void register() { + ANDROID_PLAYER.registerMessage( + next_network_id++, + AndroidCapabilityChangePacket.class, + AndroidCapabilityChangePacket::encodeNetwork, + AndroidCapabilityChangePacket::decodeNetwork, + AndroidCapabilityChangePacket::handleMessage, + Optional.of(NetworkDirection.PLAY_TO_CLIENT) + ); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java b/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java new file mode 100644 index 000000000..fc6de894e --- /dev/null +++ b/src/main/java/ru/dbotthepony/mc/otm/network/NetworkHelper.java @@ -0,0 +1,26 @@ +package ru.dbotthepony.mc.otm.network; + +import net.minecraft.network.FriendlyByteBuf; + +import java.math.BigDecimal; +import java.math.BigInteger; + +public class NetworkHelper { + public static BigDecimal readDecimal(FriendlyByteBuf buffer) { + int scale = buffer.readInt(); + int length = buffer.readByte() & 0xFF; + byte[] bytes = new byte[length]; + + for (int i = 0; i < length; i++) + bytes[i] = buffer.readByte(); + + return new BigDecimal(new BigInteger(bytes), scale); + } + + public static void writeDecimal(FriendlyByteBuf buffer, BigDecimal value) { + buffer.writeInt(value.scale()); + byte[] build = value.unscaledValue().toByteArray(); + buffer.writeByte(build.length); + for (byte b : build) buffer.writeByte(b); + } +} diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java b/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java index a8972818b..b43e2a319 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java +++ b/src/main/java/ru/dbotthepony/mc/otm/screen/PoweredMachineScreen.java @@ -41,18 +41,15 @@ public class PoweredMachineScreen extends Abstract BigDecimal energy = menu.energy.getDecimal(); BigDecimal max_energy = menu.max_energy.getDecimal(); - double level; + float level; if (max_energy.equals(BigDecimal.ZERO)) { - level = 0d; + level = 0f; } else { - level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).doubleValue(); - - if (level >= 0.98) - level = 1d; + level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).floatValue(); } - return List.of( + return List.of( // TODO: translation new TextComponent(String.format("Energy level: %.2f%%", level * 100d)), new TextComponent(String.format("%s / %s Mattery Energy", energy.toString(), max_energy.toString())) ); @@ -83,15 +80,15 @@ public class PoweredMachineScreen extends Abstract int i = (width - imageWidth) / 2; int j = (height - imageHeight) / 2; - double level; + float level; if (max_energy.equals(BigDecimal.ZERO)) { - level = 0d; + level = 0f; } else { - level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).doubleValue(); + level = energy.divide(max_energy, MatteryCapability.ROUND_RULES).floatValue(); if (level >= 0.98) - level = 1d; + level = 1f; } if (level > 0.01) { diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/player_gui.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/player_gui.png new file mode 100644 index 0000000000000000000000000000000000000000..62083e4e29f2b765fdc7554a9ca7f6377dfa9cdf GIT binary patch literal 869 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K5893O0R7}x|G$5xn)7d$|)7e>}peR2rGbfdS zL1SX=L|c!;0V1vb!AnE6_{szXI|JtGbaYvGiFPL}+#(uPYEb#I|H2YQ&%#2H7;e6Q zI$^Rgb4p7KL|G2X3z(a$yNYXm+_&U{(lPew-wW?qxBq^}+)_1jW!iCz1zFQ3b{#*G zljq8_N2x<^RU(h)nJdCCTX}4*U$?EP+28$1=Y4hkIyu#RqXX(f=Z)@e=(ygw++26= zXS>1~Q&n1j%&9oDfUQ%0r{3;A$9BHhaKQMmo0_S+jG91of|Zn65QR`$1(@e-%9PiL+R=2hx*RhiJjAsL#pfQLKqmT8dBk{3459?BQ|@hm#| z%{ZqR% z;o0ObQQqA$jC*e%I9lpG`Fq1@*#-YSr}Lbg_$S0^A;X^e7tNnG?2BGdeRXd1XPM>v z4sB^$OPFP3m=?R9iu+tqzM(en|Gms}@7Xijix!)u*2)6og)Pb3-33V3GyLyy> z96Y)!>B86K?T?#YJa;kQ!KnUEWloyVCtf+BMJkdHJCm5wzIslITCJM*Vy|@LN?kQz z!eC(#U~mAXkbfba^$htr91O&| z9gNRPebB_1)M$)Ji8qoyG+ug9Yx<-Z-Ze&TU%a%YQK7Ko|IhhncW796*r$@7$v5A3 z&VM=oIXm>6G?za*9y~rg5B*vJ70L0jvfB?XOqm6*AfL;MRIFd%?Mdd}+1n_j7 zWDEhV8Q=so0PZG@&UXPW0~&HLcU%7GU@qI1o5&xAA#?f>vHaMC+mL0`G z+(>LL0B)WE*oHbf4R6?B0FGk@FKHmQ-KOuc=~|l(+O*H6x7c)@P1l3Q`K;y!fpcU2 z5NRNGKWYOS@D7`{K7bk+vo+zxa;LNzm=~IGnsaRrafUO#OTM7Rc0TUbIC~4kI`Itg zJH($5pC|sF_$T7Ohz-uQ^~CoPhl!({8H=&bR-*!R{|0vU3j115RPhLR;;Y!bgkJ6b z>Anl=e*yRl8?#kBP+=9(v&NnH>h=$RVO@wBU2G5R<=Q}>DD$^QDnR#3>)Y8JyIS#| zftK6Eru(jLyvmAy3b4xC!iKA?H^LjB!2AY$4QoR8U1vI6hBhLI z4fbnKaLBwZZKfNK2y3)8U!mM7?E~F-d~b7G;A7&?*6@X)Ef4Z>{{-iT?}&dS{*$=K zIRJMMY=L`;A0qA~?k0YYc#QZZ;@5~zafYktAL7Eb%a^`7|M}T7b03}l;Js6Cy>aq^ z8Dn8b_*Y3*cRkwv*q)BgXsqk;C!XB9ci;X4&pg}R)7xvB6?NAm?Ynn(bjCE(yl?;0 z+#KiThrx`|70eh7=4ecV+)qJn9vzP_Y!Ckuksv#t9Ky*Cb9eW|53b4%;g(Q9qYby-wIXt&Bb%@tK3qZJL0AZu}*7h z57mf8xUIt7IIpdC%bf?B#Tc_t%sMYD1`o^_a~K^JfIj{iL-PPa>_+@hUn0@pKQNF? zriA38W+^oOckobOUjj^GYAKycX(*OagxJ4eN+br7sic^8q?R=j7PG>S{ z46{^-{ey8hM=C95mbgvK6fxzEvMHSr(u)))q%kRv>xUv!VjAMOFypqu7jnh6BtiBn z4%N_H<~zg;*`=(giXy0sil!*0Dk_lEke$j+=&GuyENLWgvZ5lpAy`lhO(YI6K^Dw3 zqUunV(HjMNV}2*-6-bVZV;JsG{su3c5mSQ-v0F=pPZMgu!c;{CPeHwDDws{d>WV51 zL9Iebg_sL#hDT5qHDpvc<%+C8AtJhqoI=c_EYjTIU8(|>Cn~>Vs2LAyu@uk3i#If< zxd_b7>)!b2)$6Wp>Z28}4bY|usAB}6(y@ZVJ^%jvx%n?aZL0rA5O6`|)_AF`OUtKI zwedQ)HNQ;!>KeW<)I|2C*SWpvUE(?7i^M+=|4eM