Networking test, player capability is now networked to them
This commit is contained in:
parent
8cec0e3724
commit
7087705f22
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 |
Binary file not shown.
Loading…
Reference in New Issue
Block a user