Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Statistics Functions #274

Open
wants to merge 11 commits into
base: 1.20
Choose a base branch
from
Open
139 changes: 139 additions & 0 deletions common/src/main/java/org/figuramc/figura/lua/api/HostAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@
import net.minecraft.client.multiplayer.PlayerInfo;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.NonNullList;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import org.figuramc.figura.FiguraMod;
import org.figuramc.figura.avatar.Avatar;
import org.figuramc.figura.avatar.AvatarManager;
Expand All @@ -28,6 +36,7 @@
import org.figuramc.figura.lua.LuaWhitelist;
import org.figuramc.figura.lua.api.entity.EntityAPI;
import org.figuramc.figura.lua.api.world.ItemStackAPI;
import org.figuramc.figura.lua.api.world.WorldAPI;
import org.figuramc.figura.lua.docs.LuaFieldDoc;
import org.figuramc.figura.lua.docs.LuaMethodDoc;
import org.figuramc.figura.lua.docs.LuaMethodOverload;
Expand Down Expand Up @@ -532,6 +541,136 @@ public List<Map<String, Object>> getStatusEffects() {

return list;
}
@LuaWhitelist
@LuaMethodDoc(
value = "host.update_statistics",
aliases = "updateStats"
)
public void updateStatistics() {
this.minecraft.getConnection().send(new ServerboundClientCommandPacket(ServerboundClientCommandPacket.Action.REQUEST_STATS)); // in theory, this cant nullptr; if it does, ill fix later
}
@LuaWhitelist
public void updateStats() {updateStatistics();}

@LuaWhitelist
@LuaMethodDoc(
value = "host.get_general_statistics",
aliases = "getGeneralStats"
)
public Map<String, Double> getGeneralStatistics() {
Map<String, Double> map = new HashMap<>();
LocalPlayer player = this.minecraft.player;
if (player == null || !isHost()) return map;
for (Stat<?> stat : Stats.CUSTOM) {
String name = stat.getName().replace("minecraft.custom:minecraft.",""); // turn registry to translation key
String formatted = stat.format(player.getStats().getValue(stat)).replaceAll("[^\\d.]", ""); // remove things that aren't digits or periods
double finalValue = Double.parseDouble(formatted);
map.put(name, finalValue);
}
return map;
}
@LuaWhitelist
public Map<String, Double> getGeneralStats() { return getGeneralStatistics(); }

@LuaWhitelist
@LuaMethodDoc(
value = "host.get_item_statistic",
aliases = "getItemStat",
overloads = {
@LuaMethodOverload(
argumentTypes = ItemStackAPI.class,
argumentNames = "item"
),
@LuaMethodOverload(
argumentTypes = {String.class},
argumentNames = "id"
)
}
)
public Map<String, Integer> getItemStatistic(Object id) {
Map<String, Integer> map = new HashMap<>();
LocalPlayer player = this.minecraft.player;
if (player == null || !isHost()) return map;
String itemKey;
ItemStackAPI stack;
if (id instanceof String) {
stack = WorldAPI.newItem(id.toString(), 1, null); // this handles errors for me and im lazy
itemKey = id.toString();
} else {
stack = (ItemStackAPI) id;
itemKey = BuiltInRegistries.ITEM.getKey(stack.itemStack.getItem()).toString();
}

int timesMined = 0; // init to 0 for if it's not a block
int timesBroken;
int timesCrafted;
int timesUsed;
int timesPickedUp;
int timesDropped;
if (stack.itemStack.getItem() instanceof BlockItem) {
Block block = stack.getBlockstate().blockState.getBlock();
Stat<Block> stat = Stats.BLOCK_MINED.get(block);
timesMined = player.getStats().getValue(stat);
}

Stat<Item> brokenStat = Stats.ITEM_BROKEN.get(stack.itemStack.getItem());
timesBroken = player.getStats().getValue(brokenStat);

Stat<Item> craftedStat = Stats.ITEM_CRAFTED.get(stack.itemStack.getItem());
timesCrafted = player.getStats().getValue(craftedStat);

Stat<Item> usedStat = Stats.ITEM_USED.get(stack.itemStack.getItem());
timesUsed = player.getStats().getValue(usedStat);

Stat<Item> pickedUpStat = Stats.ITEM_PICKED_UP.get(stack.itemStack.getItem());
timesPickedUp = player.getStats().getValue(pickedUpStat);

Stat<Item> droppedStat = Stats.ITEM_DROPPED.get(stack.itemStack.getItem());
timesDropped = player.getStats().getValue(droppedStat);


map.put("mined", timesMined);
map.put("crafted", timesCrafted);
map.put("used", timesUsed);
map.put("picked_up", timesPickedUp);
map.put("broken", timesBroken);
map.put("dropped", timesDropped);
return map;
}
@LuaWhitelist
public Map<String, Integer> getItemStat(Object id) { return getItemStatistic(id); }

@LuaWhitelist
@LuaMethodDoc(
value = "host.get_entity_statistic",
aliases = "get_entity_stat",
overloads = @LuaMethodOverload(
argumentTypes = String.class,
argumentNames = "type"
)
)
public Map<String, Integer> getEntityStatistic(String type) {
Map<String, Integer> map = new HashMap<>();
LocalPlayer player = this.minecraft.player;
if (player == null || !isHost()) return map;
Optional<EntityType<?>> entity = EntityType.byString(type);
if (entity.isPresent()) {
Stat<EntityType<?>> killedStat = Stats.ENTITY_KILLED.get(entity.get());
Stat<EntityType<?>> killedByStat = Stats.ENTITY_KILLED_BY.get(entity.get());

int timesKilled = player.getStats().getValue(killedStat);
int timesKilledBy = player.getStats().getValue(killedByStat);

map.put("killed", timesKilled);
map.put("killed_by", timesKilledBy);
}
else {
throw new LuaError("Invalid entity type " + type);
}
return map;
}
@LuaWhitelist
public Map<String, Integer> getEntityStat(String type) { return getEntityStatistic(type); }

@LuaWhitelist
@LuaMethodDoc("host.get_clipboard")
Expand Down
4 changes: 4 additions & 0 deletions common/src/main/resources/assets/figura/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,10 @@
"figura.docs.host.append_chat_history": "Appends the message on the recent chat history",
"figura.docs.host.get_chat_message": "Returns a table with information about a chat message\nTakes an index, where 1 means the last message on chat",
"figura.docs.host.set_chat_message": "Modifies a chat message with the given text\nTakes an index, were 1 means the last message on chat\nSetting the message to nil will effectively remove it from the chat",
"figura.docs.host.update_statistics": "Updates the player's statistics as if the statistics screen was opened",
"figura.docs.host.get_general_statistics": "Returns a table with general stats about the player\nThe table contains all values in the \"general\" section",
"figura.docs.host.get_item_statistic": "Returns a table with the item's stats in the \"items\" section\nTakes an ItemStack or a string with the item's id",
"figura.docs.host.get_entity_statistic": "Returns a table with the entity's stats in the \"mobs\" section\nTakes a string with the entity's type",
"figura.docs.host.swing_arm": "Animates swinging the player's arm\nIf the boolean is true, then the offhand is the one that swings",
"figura.docs.host.is_first_person": "Returns true if the camera is in first person mode",
"figura.docs.host.is_camera_backwards": "Returns true if the camera is facing backward",
Expand Down
Loading