Skip to content

Commit 7bf10fe

Browse files
committed
feat: add files
1 parent fb75368 commit 7bf10fe

20 files changed

+436
-41
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
<img align="right" height="128" width="128" alt="" loading="lazy" decoding="async" src="./src/main/resources/icon.png"/>
22

3-
# Playground
3+
# Bit by Bit
44

5-
This is the beginning of awesome mods!
5+
Eat foods Bit by Bit. Save the rest for later or split it with your friends.
66

77
> **Important**
88
> Required [Babric](https://github.com/Turnip-Labs/babric-instance-repo/releases) to run the mod.
99
10-
## Features
10+
## Credits
1111

12-
- Feature #1
13-
- Feature #2
14-
- Feature #3
12+
- Eating sound by Mojang
13+
- SoundHelper by [@UselessBullets/PrismaticLibe](https://github.com/UselessBullets/BTA_Babric_PrismaticLibe)

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ loader_version=0.14.19-babric.1-bta
1010
# halplibe_version=2.3.0
1111

1212
# Mod
13-
mod_version=1.0.0
13+
mod_version=1.2.0
1414
mod_group=rootenginear
15-
mod_name=playground
15+
mod_name=bitbybit
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package rootenginear.bitbybit;
2+
3+
import net.fabricmc.api.ModInitializer;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import rootenginear.bitbybit.utils.SoundHelper;
7+
8+
public class BitByBit implements ModInitializer {
9+
public static final String MOD_ID = "bitbybit";
10+
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
11+
12+
@Override
13+
public void onInitialize() {
14+
SoundHelper.addSound(MOD_ID, "eat1.ogg");
15+
SoundHelper.addSound(MOD_ID, "eat2.ogg");
16+
SoundHelper.addSound(MOD_ID, "eat3.ogg");
17+
18+
LOGGER.info("Bit by Bit initialized.");
19+
}
20+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.core.entity.animal.EntityWolf;
4+
import net.minecraft.core.entity.player.EntityPlayer;
5+
import net.minecraft.core.item.ItemFood;
6+
import net.minecraft.core.item.ItemStack;
7+
import net.minecraft.core.player.gamemode.Gamemode;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.injection.At;
10+
import org.spongepowered.asm.mixin.injection.Redirect;
11+
12+
@Mixin(value = {EntityWolf.class}, remap = false)
13+
public class EntityWolfMixin {
14+
@Redirect(
15+
method = "interact(Lnet/minecraft/core/entity/player/EntityPlayer;)Z",
16+
at = @At(
17+
value = "INVOKE",
18+
target = "Lnet/minecraft/core/entity/player/EntityPlayer;getGamemode()Lnet/minecraft/core/player/gamemode/Gamemode;"
19+
)
20+
)
21+
private Gamemode nibbleFood(EntityPlayer entityplayer) {
22+
ItemStack itemstack = entityplayer.inventory.getCurrentItem();
23+
24+
if (entityplayer.getGamemode().consumeBlocks) {
25+
itemstack.damageItem(1, entityplayer);
26+
if (((ItemFood) itemstack.getItem()).getHealAmount() == 0) {
27+
return Gamemode.survival;
28+
}
29+
}
30+
return Gamemode.creative;
31+
}
32+
33+
@Redirect(
34+
method = "interact(Lnet/minecraft/core/entity/player/EntityPlayer;)Z",
35+
at = @At(
36+
value = "INVOKE",
37+
target = "Lnet/minecraft/core/item/ItemFood;getHealAmount()I"
38+
)
39+
)
40+
public int healFromNibble(ItemFood item) {
41+
return 1;
42+
}
43+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.client.Minecraft;
4+
import net.minecraft.core.entity.player.EntityPlayer;
5+
import net.minecraft.core.item.Item;
6+
import net.minecraft.core.item.ItemBucketIceCream;
7+
import net.minecraft.core.item.ItemStack;
8+
import net.minecraft.core.world.World;
9+
import org.spongepowered.asm.mixin.Mixin;
10+
import org.spongepowered.asm.mixin.Overwrite;
11+
import org.spongepowered.asm.mixin.Shadow;
12+
import org.spongepowered.asm.mixin.Unique;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16+
import rootenginear.bitbybit.mixin.adapter.ItemAccessor;
17+
import rootenginear.bitbybit.utils.ItemFoodEatEffect;
18+
19+
@Mixin(value = {ItemBucketIceCream.class}, remap = false)
20+
public class ItemBucketIceCreamOverride {
21+
@Shadow
22+
protected int healAmount;
23+
24+
@Inject(method = "<init>", at = @At("RETURN"))
25+
private void init(CallbackInfo ci) {
26+
((ItemAccessor) this).setFoodMaxDamage(healAmount);
27+
}
28+
29+
@Unique
30+
public boolean consumeFood(ItemStack itemstack, EntityPlayer entityplayer) {
31+
if (itemstack.stackSize <= 0) return false;
32+
33+
if (entityplayer.getGamemode().consumeBlocks) {
34+
itemstack.damageItem(1, entityplayer);
35+
if (itemstack.getItemDamageForDisplay() == healAmount) {
36+
--itemstack.stackSize;
37+
}
38+
}
39+
return true;
40+
}
41+
42+
/**
43+
* @author rootEnginear.bitbybit
44+
* @reason Make food eat bit by bit
45+
*/
46+
@Overwrite
47+
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer) {
48+
if (entityplayer.health < 20 && consumeFood(itemstack, entityplayer)) {
49+
ItemFoodEatEffect.playEatEffect(itemstack, world, entityplayer);
50+
entityplayer.heal(1);
51+
}
52+
if (itemstack.stackSize == 0) return new ItemStack(Item.bucket);
53+
return itemstack;
54+
}
55+
56+
/**
57+
* @author rootEnginear.bitbybit
58+
* @reason Show how much leftover heals
59+
* @implNote Somewhat buggy in multiplayer
60+
*/
61+
@Overwrite
62+
public int getHealAmount() {
63+
ItemStack currentItem = Minecraft.getMinecraft(Minecraft.class).thePlayer.inventory.getCurrentItem();
64+
int damage = 0;
65+
if (currentItem != null) damage = currentItem.getItemDamageForDisplay();
66+
return healAmount - damage;
67+
}
68+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.client.Minecraft;
4+
import net.minecraft.core.entity.player.EntityPlayer;
5+
import net.minecraft.core.item.ItemFood;
6+
import net.minecraft.core.item.ItemStack;
7+
import net.minecraft.core.world.World;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Overwrite;
10+
import org.spongepowered.asm.mixin.Shadow;
11+
import org.spongepowered.asm.mixin.Unique;
12+
import org.spongepowered.asm.mixin.injection.At;
13+
import org.spongepowered.asm.mixin.injection.Inject;
14+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15+
import rootenginear.bitbybit.mixin.adapter.ItemAccessor;
16+
import rootenginear.bitbybit.utils.ItemFoodEatEffect;
17+
18+
@Mixin(value = {ItemFood.class}, remap = false)
19+
public class ItemFoodOverride {
20+
@Shadow
21+
protected int healAmount;
22+
23+
@Inject(method = "<init>", at = @At("RETURN"))
24+
private void init(CallbackInfo ci) {
25+
((ItemAccessor) this).setFoodMaxDamage(healAmount);
26+
}
27+
28+
@Unique
29+
public boolean consumeFood(ItemStack itemstack, EntityPlayer entityplayer) {
30+
if (itemstack.stackSize <= 0) return false;
31+
32+
if (entityplayer.getGamemode().consumeBlocks) {
33+
itemstack.damageItem(1, entityplayer);
34+
if (itemstack.getItemDamageForDisplay() == healAmount) {
35+
--itemstack.stackSize;
36+
}
37+
}
38+
return true;
39+
}
40+
41+
/**
42+
* @author rootEnginear.bitbybit
43+
* @reason Make food eat bit by bit
44+
*/
45+
@Overwrite
46+
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer) {
47+
if (entityplayer.health < 20 && consumeFood(itemstack, entityplayer)) {
48+
ItemFoodEatEffect.playEatEffect(itemstack, world, entityplayer);
49+
entityplayer.heal(1);
50+
}
51+
return itemstack;
52+
}
53+
54+
/**
55+
* @author rootEnginear.bitbybit
56+
* @reason Show how much leftover heals
57+
* @implNote Somewhat buggy in multiplayer
58+
*/
59+
@Overwrite
60+
public int getHealAmount() {
61+
ItemStack currentItem = Minecraft.getMinecraft(Minecraft.class).thePlayer.inventory.getCurrentItem();
62+
int damage = 0;
63+
if (currentItem != null) damage = currentItem.getItemDamageForDisplay();
64+
return healAmount - damage;
65+
}
66+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.core.item.ItemFoodStackable;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.injection.At;
6+
import org.spongepowered.asm.mixin.injection.Inject;
7+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
8+
import rootenginear.bitbybit.mixin.adapter.ItemAccessor;
9+
10+
@Mixin(value = {ItemFoodStackable.class}, remap = false)
11+
public abstract class ItemFoodStackableOverride {
12+
@Inject(method = "<init>", at = @At("RETURN"))
13+
private void init(CallbackInfo ci) {
14+
((ItemAccessor) this).setMaxStackSize(1);
15+
}
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.core.entity.player.EntityPlayer;
4+
import net.minecraft.core.item.Item;
5+
import net.minecraft.core.item.ItemSoup;
6+
import net.minecraft.core.item.ItemStack;
7+
import net.minecraft.core.world.World;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Overwrite;
10+
11+
@Mixin(value = {ItemSoup.class}, remap = false)
12+
public class ItemSoupOverride extends ItemFoodOverride {
13+
/**
14+
* @author rootEnginear.bitbybit
15+
* @reason Make food eat bit by bit
16+
*/
17+
@Overwrite
18+
public ItemStack onItemRightClick(ItemStack itemstack, World world, EntityPlayer entityplayer) {
19+
super.onItemRightClick(itemstack, world, entityplayer);
20+
if (itemstack.stackSize == 0) return new ItemStack(Item.bowl);
21+
return itemstack;
22+
}
23+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package rootenginear.bitbybit.mixin;
2+
3+
import net.minecraft.client.Minecraft;
4+
import net.minecraft.client.render.RenderGlobal;
5+
import net.minecraft.core.entity.fx.EntitySlimeFX;
6+
import net.minecraft.core.item.Item;
7+
import net.minecraft.core.world.World;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Shadow;
10+
import org.spongepowered.asm.mixin.injection.At;
11+
import org.spongepowered.asm.mixin.injection.Inject;
12+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
13+
14+
import java.util.regex.Matcher;
15+
import java.util.regex.Pattern;
16+
17+
@Mixin(value = {RenderGlobal.class}, remap = false)
18+
public class RenderGlobalMixin {
19+
@Shadow
20+
private Minecraft mc;
21+
22+
@Shadow
23+
private World worldObj;
24+
25+
@Inject(method = "addParticle(Ljava/lang/String;DDDDDDD)V", at = @At("HEAD"), cancellable = true)
26+
public void addFoodParticle(String particleId, double x, double y, double z, double motionX, double motionY, double motionZ, double maxDistance, CallbackInfo ci) {
27+
Pattern foodItemPattern = Pattern.compile("bitbybit\\.(.+)");
28+
Matcher foodMatch = foodItemPattern.matcher(particleId);
29+
if (foodMatch.matches() && this.mc != null && this.mc.activeCamera != null && this.mc.effectRenderer != null) {
30+
double d6 = this.mc.activeCamera.getX() - x;
31+
double d7 = this.mc.activeCamera.getY() - y;
32+
double d8 = this.mc.activeCamera.getZ() - z;
33+
if (!(d6 * d6 + d7 * d7 + d8 * d8 > maxDistance * maxDistance)) {
34+
this.mc.effectRenderer.addEffect(new EntitySlimeFX(this.worldObj, x, y, z, Item.itemsList[Integer.parseInt(foodMatch.group(1))]));
35+
}
36+
ci.cancel();
37+
}
38+
}
39+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package rootenginear.bitbybit.mixin.adapter;
2+
3+
import net.minecraft.core.item.Item;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.gen.Accessor;
6+
import org.spongepowered.asm.mixin.gen.Invoker;
7+
8+
@Mixin(value = {Item.class}, remap = false)
9+
public interface ItemAccessor {
10+
@Invoker("setMaxDamage")
11+
Item setFoodMaxDamage(int i);
12+
13+
@Accessor("maxStackSize")
14+
void setMaxStackSize(int maxStackSize);
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package rootenginear.bitbybit.utils;
2+
3+
import net.minecraft.core.entity.player.EntityPlayer;
4+
import net.minecraft.core.item.ItemStack;
5+
import net.minecraft.core.world.World;
6+
7+
import java.util.Random;
8+
9+
public class ItemFoodEatEffect {
10+
public static void playEatEffect(ItemStack itemstack, World world, EntityPlayer entityplayer) {
11+
final Random rand = new Random();
12+
13+
final double yRotRad = entityplayer.yRot * Math.PI / 180.0F;
14+
final double xRotRad = entityplayer.xRot * Math.PI / 180.0F;
15+
16+
final double mouthDistConst = 0.3F;
17+
final double mouthShift = Math.cos(xRotRad) * mouthDistConst;
18+
final double xShift = Math.sin(yRotRad) * mouthShift;
19+
final double zShift = Math.cos(yRotRad) * mouthShift;
20+
final double yShift = Math.sin(xRotRad) * 0.3F;
21+
22+
for (int i = 0; i < 2; i++) {
23+
world.spawnParticle("bitbybit." + itemstack.getItem().id, entityplayer.x - xShift, entityplayer.y - 0.2F - yShift, entityplayer.z + zShift, 0.0, 0.0, 0.0);
24+
}
25+
26+
final float volume = ((float) (rand.nextInt(3) + 1)) / 0.5F;
27+
final float pitch = ((float) rand.nextInt(5)) / 10.0F + 0.8F;
28+
29+
world.playSoundAtEntity(entityplayer, "bitbybit.eat", volume, pitch);
30+
}
31+
}

0 commit comments

Comments
 (0)