Networking test, player capability is now networked to them

This commit is contained in:
DBotThePony 2021-08-11 12:55:18 +07:00
parent 8cec0e3724
commit 7087705f22
Signed by: DBot
GPG Key ID: DCC23B5715498507
12 changed files with 496 additions and 95 deletions

View File

@ -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<BlockEntityAndroidStation> ANDROID_STATION_BUILDER = BlockEntityType.Builder.of(BlockEntityAndroidStation::new, ANDROID_STATION);
public static BlockEntityType<BlockEntityAndroidStation> 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<IAndroidCapability> 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<IAndroidCapability> 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);
}
}

View File

@ -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<CompoundTag> {
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<IMatteryEnergyStorage> 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<IEnergyStorage> 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<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY);
Optional<IMatteryEnergyStorage> 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<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY);
Optional<IEnergyStorage> 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<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY);
Optional<IMatteryEnergyStorage> 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<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY);
Optional<IEnergyStorage> 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<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY);
Optional<IMatteryEnergyStorage> 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<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY);
Optional<IEnergyStorage> 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<IMatteryEnergyStorage> get_mattery = battery.getCapability(MatteryCapability.ENERGY);
Optional<IMatteryEnergyStorage> 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<IEnergyStorage> get_energy = battery.getCapability(CapabilityEnergy.ENERGY);
Optional<IEnergyStorage> 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<IAndroidCapability> resolver = LazyOptional.of(() -> this).cast();
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MatteryCapability.ANDROID) {
return LazyOptional.of(() -> this).cast();
return resolver.cast();
}
return LazyOptional.empty();

View File

@ -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());
}
}
}

View File

@ -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);
}

View File

@ -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<IAndroidCapability> 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));
}
}

View File

@ -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<NetworkEvent.Context> 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;
}
}

View File

@ -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<NetworkEvent.Context> ctx) {
if (Minecraft.getInstance().player != null) {
Minecraft.getInstance().player.getCapability(MatteryCapability.ANDROID)
.orElseThrow(() -> new IllegalStateException("Local player has no android capability yet"))
.readChanges(packet);
}
}
}

View File

@ -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)
);
}
}

View File

@ -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);
}
}

View File

@ -41,18 +41,15 @@ public class PoweredMachineScreen<T extends PoweredMachineMenu> 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<T extends PoweredMachineMenu> 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) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 869 B