Skip to content

Commit

Permalink
feat: food system (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
IWareQ committed Jun 28, 2024
1 parent 44beeba commit 7c58197
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public final class AdventureSettings {
private boolean immutableWorld = false;
private boolean showNameTags = true;
private boolean autoJump = true;

private boolean dirty = false;

public AdventureSettings(EntityPlayer player) {
Expand Down Expand Up @@ -71,7 +72,7 @@ public void setAutoJump(boolean autoJump) {

public void sync() {
if (!dirty) return;
UpdateAdventureSettingsPacket packet = new UpdateAdventureSettingsPacket();
var packet = new UpdateAdventureSettingsPacket();
packet.setAutoJump(autoJump);
packet.setImmutableWorld(immutableWorld);
packet.setNoMvP(noMVP);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public interface EntityPlayerBaseComponent extends EntityBaseComponent, ChunkLoa

double BLOCK_INTERACT_MAX_DV_DIFF = 2.0;

float DEFAULT_MOVEMENT_SPEED = 0.1f;

boolean isSprinting();

void setSprinting(boolean sprinting);
Expand Down Expand Up @@ -147,9 +149,7 @@ default double getMaxInteractDistance() {
return getGameType() == GameType.CREATIVE ? 13 : 7;
}

float DEFAULT_MOVEMENT_SPEED = 0.1f;
float getMovementSpeed();

void setMovementSpeed(float speed);

float getMovementSpeed();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.allaymc.api.entity.component.player;

import org.allaymc.api.entity.component.EntityComponent;

/**
* Allay Project 28/06/2024
*
* @author IWareQ
*/
public interface EntityPlayerHungerComponent extends EntityComponent {
void tick();

int getFoodLevel();

void setFoodLevel(int foodLevel);

int getFoodSaturationLevel();

void setFoodSaturationLevel(int saturationLevel);

float getFoodTickTimer();

void setFoodTickTimer(float foodTickTimer);

float getFoodExhaustionLevel();

void setFoodExhaustionLevel(float foodExhaustionLevel);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@
import org.allaymc.api.entity.Entity;
import org.allaymc.api.entity.component.common.EntityContainerViewerComponent;
import org.allaymc.api.entity.component.common.EntityDamageComponent;
import org.allaymc.api.entity.component.player.EntityPlayerAttributeComponent;
import org.allaymc.api.entity.component.player.EntityPlayerBaseComponent;
import org.allaymc.api.entity.component.player.EntityPlayerContainerHolderComponent;
import org.allaymc.api.entity.component.player.EntityPlayerNetworkComponent;
import org.allaymc.api.entity.component.player.*;
import org.allaymc.api.eventbus.event.world.player.PlayerThrowItemEvent;
import org.allaymc.api.item.ItemStack;
import org.allaymc.api.utils.MathUtils;
Expand All @@ -29,7 +26,13 @@ public interface EntityPlayer extends
EntityPlayerAttributeComponent,
EntityPlayerContainerHolderComponent,
EntityContainerViewerComponent,
EntityDamageComponent {
EntityDamageComponent,
EntityPlayerHungerComponent {

@Override
default void tick() {
Entity.super.tick();
}

default <T extends Container> T getReachableContainer(FullContainerType<?> slotType) {
var container = getOpenedContainer(slotType);
Expand All @@ -50,13 +53,11 @@ default boolean tryDropItemInHand(int count) {
default boolean tryDropItem(FullContainerType<?> containerType, int slot, int count) {
var container = getReachableContainer(containerType);
if (container == null) return false;

var item = container.getItemStack(slot);
if (item.getItemType() == AIR_TYPE) {
return false;
}
if (item.getCount() < count) {
return false;
}
if (item.getItemType() == AIR_TYPE) return false;
if (item.getCount() < count) return false;

forceDropItem(container, slot, count);
return true;
}
Expand All @@ -65,9 +66,8 @@ default void forceDropItem(Container container, int slot, int count) {
var item = container.getItemStack(slot);
var event = new PlayerThrowItemEvent(this, item);
getWorld().getEventBus().callEvent(event);
if (event.isCancelled()) {
return;
}
if (event.isCancelled()) return;

ItemStack droppedItemStack;
if (item.getCount() > count) {
item.setCount(item.getCount() - count);
Expand All @@ -79,13 +79,19 @@ default void forceDropItem(Container container, int slot, int count) {
item = EMPTY_SLOT_PLACE_HOLDER;
container.setItemStack(slot, item);
}

dropItemInPlayerPos(droppedItemStack);
}

default void dropItemInPlayerPos(ItemStack itemStack) {
var playerLoc = getLocation();
var dimension = playerLoc.dimension();
dimension.dropItem(itemStack, playerLoc.add(0, this.getEyeHeight() - 0.25f, 0, new Vector3f()), MathUtils.getDirectionVector(playerLoc.yaw(), playerLoc.pitch()).mul(0.5f), 40);
dimension.dropItem(
itemStack,
playerLoc.add(0, this.getEyeHeight() - 0.25f, 0, new Vector3f()),
MathUtils.getDirectionVector(playerLoc.yaw(), playerLoc.pitch()).mul(0.5f),
40
);
}

default ItemStack getItemInHand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ public void prepareCommandTree(CommandTree tree) {
return context.success();
}, SenderType.PLAYER)
.root()
.key("food")
.exec((context, player) -> {
player.setFoodLevel(Math.min(20, player.getFoodLevel() + 5)); // bread 5 food
player.setFoodSaturationLevel(player.getFoodSaturationLevel() + 6); // bread 6 saturation
return context.success();
}, SenderType.PLAYER)
.root()
.key("setperm")
.str("perm")
.bool("value")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.allaymc.api.entity.component.event.PlayerLoggedInEvent;
import org.allaymc.api.entity.component.item.EntityItemBaseComponent;
import org.allaymc.api.entity.component.player.EntityPlayerBaseComponent;
import org.allaymc.api.entity.component.player.EntityPlayerHungerComponent;
import org.allaymc.api.entity.component.player.EntityPlayerNetworkComponent;
import org.allaymc.api.entity.init.EntityInitInfo;
import org.allaymc.api.entity.interfaces.EntityItem;
Expand Down Expand Up @@ -78,6 +79,8 @@ public class EntityPlayerBaseComponentImpl extends EntityBaseComponentImpl<Entit
protected EntityContainerHolderComponent containerHolderComponent;
@Dependency
protected EntityPlayerNetworkComponent networkComponent;
@Dependency
protected EntityPlayerHungerComponent hungerComponent;
@Getter
protected GameType gameType = GameType.CREATIVE;
@Getter
Expand Down Expand Up @@ -165,6 +168,7 @@ public void tick() {
super.tick();
syncData();
tryPickUpItems();
hungerComponent.tick();
}

protected void syncData() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package org.allaymc.server.entity.component.player;

import lombok.Getter;
import lombok.Setter;
import org.allaymc.api.component.annotation.ComponentIdentifier;
import org.allaymc.api.component.annotation.ComponentedObject;
import org.allaymc.api.entity.attribute.AttributeType;
import org.allaymc.api.entity.component.player.EntityPlayerHungerComponent;
import org.allaymc.api.entity.interfaces.EntityPlayer;
import org.allaymc.api.utils.Identifier;

/**
* Allay Project 28/06/2024
*
* @author IWareQ
* @see <a href="https://minecraft.wiki/w/Hunger">Hunger</a>
*/
@Getter
@Setter
public class EntityPlayerHungerComponentImpl implements EntityPlayerHungerComponent {
@ComponentIdentifier
public static final Identifier IDENTIFIER = new Identifier("minecraft:player_hunger_component");

@ComponentedObject
protected EntityPlayer player;

private int foodLevel = 20;
private int foodSaturationLevel = 20;

private float foodTickTimer;
private float foodExhaustionLevel = 5;

@Override
public void tick() {
if (player.isSpawned()) {
var needSend = false;

var hunger = player.getAttribute(AttributeType.PLAYER_HUNGER);
if (hunger.getCurrentValue() != foodLevel) {
hunger.setCurrentValue(foodLevel);
needSend = true;
}

var saturation = player.getAttribute(AttributeType.PLAYER_SATURATION);
if (saturation.getCurrentValue() != foodSaturationLevel) {
saturation.setCurrentValue(foodSaturationLevel);
needSend = true;
}

var exhaustion = player.getAttribute(AttributeType.PLAYER_EXHAUSTION);
if (exhaustion.getCurrentValue() != foodExhaustionLevel) {
exhaustion.setCurrentValue(foodExhaustionLevel);
needSend = true;
}

if (needSend) player.sendAttributesToClient();
}
}

@Override
public void setFoodTickTimer(float foodTickTimer) {
this.foodTickTimer = Math.max(foodTickTimer, 0);
}

@Override
public void setFoodExhaustionLevel(float foodExhaustionLevel) {
while (foodExhaustionLevel >= 4) {
foodExhaustionLevel -= 4;

Check warning on line 68 in Allay-Server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerHungerComponentImpl.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

Allay-Server/src/main/java/org/allaymc/server/entity/component/player/EntityPlayerHungerComponentImpl.java#L68

Avoid reassigning parameters such as 'foodExhaustionLevel'

if (this.foodSaturationLevel > 0) {
this.foodSaturationLevel--;
} else {
this.foodLevel = Math.max(--this.foodLevel, 0);
}
}

this.foodExhaustionLevel = foodExhaustionLevel;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public static void initPlayer() {
.addComponent(EntityPlayerContainerHolderComponentImpl::new, EntityPlayerContainerHolderComponentImpl.class)
.addComponent(EntityPlayerContainerViewerComponentImpl::new, EntityPlayerContainerViewerComponentImpl.class)
.addComponent(EntityPlayerDamageComponentImpl::new, EntityDamageComponentImpl.class)
.addComponent(EntityPlayerHungerComponentImpl::new, EntityPlayerHungerComponentImpl.class)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ public void handleSync(EntityPlayer player, InventoryTransactionPacket packet) {
dimension.sendBlockUpdateTo(blockStateReplaced, placeBlockPos, 0, player);
}
}

}
}
case ITEM_USE_CLICK_AIR -> {
Expand Down Expand Up @@ -114,11 +113,16 @@ public void handleSync(EntityPlayer player, InventoryTransactionPacket packet) {
}

// TODO: The current implementation is buggy
for (var action : packet.getActions()) {
if (!action.getSource().getType().equals(InventorySource.Type.WORLD_INTERACTION)) continue;
if (!action.getSource().getFlag().equals(InventorySource.Flag.DROP_ITEM)) continue;
var first = packet.getActions().getFirst();
var last = packet.getActions().getLast();
if (
first.getSource().getType() == InventorySource.Type.WORLD_INTERACTION &&
first.getSource().getFlag() == InventorySource.Flag.DROP_ITEM &&
last.getSource().getType() == InventorySource.Type.CONTAINER &&
last.getSource().getFlag() == InventorySource.Flag.NONE
) {
// Do not ask me why Mojang still use the old item transaction pk even the server-auth inv was enabled
var count = action.getToItem().getCount();
var count = first.getToItem().getCount();
player.tryDropItemInHand(count);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,13 @@ public void breakBlock(int x, int y, int z, ItemStack usedItem, EntityPlayer pla
pk.setPosition(Vector3f.from(x + 0.5f, y + 0.5f, z + 0.5f));
pk.setData(block.blockStateHash());
getChunkService().getChunkByLevelPos(x, z).addChunkPacket(pk);

block.getBehavior().onBreak(
new BlockStateWithPos(block, new Position3i(x, y, z, this), 0),
usedItem,
player
usedItem, player
);
setBlockState(x, y, z, AIR_TYPE.getDefaultState());
player.setFoodExhaustionLevel(player.getFoodExhaustionLevel() + 0.005f);
}

@Override
Expand Down

0 comments on commit 7c58197

Please sign in to comment.