Skip to content

Commit

Permalink
2.5.0 (see commit description)
Browse files Browse the repository at this point in the history
- (feat) compat with LambDynamicLights
  - When LambDynamicLights is installed, you will be able to put light sources into your Utility Belt and they will illuminate the world around you.
  - If you have suggestions for other dynamic lights mods to add compat for, please open an issue on GitHub.
  - Closes #56
- (fix) issue when unequipping belt while you are using it
- (fix) general stability improvements
- (fix) the belt will now pop out all of its items when it is broken
  - This means that Netherite tools will not be lost if the belt burns in lava
- (feat) add X/Y offset config options for the belt hotbar for more granular control over its position

NOTE: THIS COMMIT IS NOT GPG SIGNED BECAUSE MY COMPUTER IS BEING ANNOYINH
  • Loading branch information
Jamalam360 committed Oct 26, 2024
1 parent 6e68b2b commit f915d4e
Show file tree
Hide file tree
Showing 17 changed files with 148 additions and 43 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
- When LambDynamicLights is installed, you will be able to put light sources into your Utility Belt and they will illuminate the world around you.
- If you have suggestions for other dynamic lights mods to add compat for, please open an issue on GitHub.
- Closes #56
- (fix) issue when unequipping belt while you are using it
- (fix) general stability improvements
- (fix) the belt will now pop out all of its items when it is broken
- This means that Netherite tools will not be lost if the belt burns in lava
- (feat) add X/Y offset config options for the belt hotbar for more granular control over its position
1 change: 1 addition & 0 deletions common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dependencies {
modImplementation(libs.accessories.common) {
exclude group: "mezz.jei"
}
modImplementation libs.owo.lib.fabric // Dependency of Accessories

compileOnly libs.mixin.extras.common
annotationProcessor libs.mixin.extras.common
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class Config implements ConfigExtensions<Config> {
public boolean useSneakSwapping = true;
public HotbarKeyBehaviour hotbarKeyBehaviour = HotbarKeyBehaviour.SWITCH_BELT_SLOT;
public Position hotbarPosition = Position.MIDDLE_LEFT;
public int hotbarOffsetX = 0;
public int hotbarOffsetY = 0;

@Override
public List<Link> getLinks() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@ public static void init() {

UtilityBelt.MENU_TYPE.listen(menu -> MenuRegistry.registerScreenFactory(UtilityBelt.MENU_TYPE.get(), UtilityBeltScreen::new));
UtilityBelt.UTILITY_BELT_ITEM.listen(belt -> AccessoriesRendererRegistry.registerRenderer(belt, BeltRenderer::new));
UtilityBelt.UTILITY_BELT_UNEQUIP_EVENT.register((stack, reference) -> {
if (reference.entity() instanceof Player player && player.level().isClientSide) {
var manager = StateManager.getStateManager(player);
manager.setInBelt(player, false);
manager.setSelectedBeltSlot(player, 0);
ClientNetworking.sendNewStateToServer(false, 0, false);
}
});
ClientNetworking.init();
StateManager.setClientInstance(new ClientStateManager());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package io.github.jamalam360.utility_belt.client.network;

import dev.architectury.networking.NetworkManager;
import io.github.jamalam360.utility_belt.UtilityBelt;
import io.github.jamalam360.utility_belt.UtilityBeltInventory;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.*;
import io.github.jamalam360.utility_belt.state.StateManager;
import io.github.jamalam360.utility_belt.UtilityBeltInventory.Mutable;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.C2SOpenScreen;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.C2SUpdateState;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.S2CSetBeltSlot;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.S2CSetHotbarSlot;
import io.github.jamalam360.utility_belt.network.UtilityBeltPackets.S2CUpdateBeltInventory;
import io.github.jamalam360.utility_belt.client.UtilityBeltClient;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;

@Environment(EnvType.CLIENT)
public class ClientNetworking {
Expand All @@ -21,6 +20,7 @@ public static void init() {
NetworkManager.registerReceiver(NetworkManager.Side.S2C, UtilityBeltPackets.S2C_SET_BELT_SLOT, S2CSetBeltSlot.STREAM_CODEC, ClientNetworking::handleSetBeltSlot);
NetworkManager.registerReceiver(NetworkManager.Side.S2C, UtilityBeltPackets.S2C_SET_HOTBAR_SLOT, S2CSetHotbarSlot.STREAM_CODEC, ClientNetworking::handleSetHotbarSlot);
NetworkManager.registerReceiver(NetworkManager.Side.S2C, UtilityBeltPackets.S2C_UPDATE_BELT_INVENTORY, S2CUpdateBeltInventory.STREAM_CODEC, ClientNetworking::handleUpdateBeltInventory);
NetworkManager.registerReceiver(NetworkManager.Side.S2C, UtilityBeltPackets.S2C_BELT_UNEQUIPPED, S2CBeltUnequipped.STREAM_CODEC, ClientNetworking::handleBeltUnequipped);
}

public static void sendNewStateToServer(boolean inBelt, int slot, boolean swapItems) {
Expand All @@ -39,7 +39,15 @@ public static void sendOpenScreenToServer() {
private static void handleSetBeltSlot(S2CSetBeltSlot payload, NetworkManager.PacketContext ctx) {
ctx.queue(() -> {
Player player = ctx.getPlayer();
StateManager.getStateManager(player).setSelectedBeltSlot(player, payload.slot());
StateManager manager = StateManager.getStateManager(player);
UtilityBeltInventory inventory = manager.getInventory(player);

if (payload.slot() < 0 || payload.slot() >= inventory.getContainerSize()) {
UtilityBelt.LOGGER.warn("Ignoring request from server to set an invalid belt slot: {}", payload.slot());
return;
}

manager.setSelectedBeltSlot(player, payload.slot());
});
}

Expand All @@ -53,4 +61,12 @@ private static void handleUpdateBeltInventory(S2CUpdateBeltInventory payload, Ne
StateManager.getStateManager(player).setInventory(player, new Mutable(payload.inventory()));
});
}

private static void handleBeltUnequipped(S2CBeltUnequipped packet, NetworkManager.PacketContext ctx) {
ctx.queue(() -> {
Player player = ctx.getPlayer();
StateManager.getStateManager(player).setInBelt(player, false);
StateManager.getStateManager(player).setSelectedBeltSlot(player, 0);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ public static void render(GuiGraphics graphics, DeltaTracker deltaTracker) {
case MIDDLE_LEFT, MIDDLE_RIGHT -> scaledHeight / 2 - 44;
case BOTTOM_LEFT, BOTTOM_RIGHT -> scaledHeight - 84;
};

x += UtilityBeltClient.CONFIG.get().hotbarOffsetX;
y += UtilityBeltClient.CONFIG.get().hotbarOffsetY;

RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShader(GameRenderer::getPositionTexShader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import io.github.jamalam360.utility_belt.UtilityBelt;

import java.util.function.Supplier;

import io.wispforest.accessories.api.client.AccessoryRenderer;
import io.wispforest.accessories.api.slot.SlotReference;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.LivingEntity;
Expand All @@ -21,18 +25,27 @@
@Environment(EnvType.CLIENT)
public class BeltRenderer implements AccessoryRenderer {

private static final ResourceLocation TEXTURE = UtilityBelt.id("textures/entity/belt.png");
private static final Supplier<HumanoidModel<LivingEntity>> MODEL = Suppliers.memoize(() ->
new BeltModel(BeltModel.createLayerDefinition().bakeRoot())
);

@Override
public <M extends LivingEntity> void render(ItemStack stack, SlotReference reference, PoseStack matrices, EntityModel<M> model, MultiBufferSource multiBufferSource, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) {
HumanoidModel<LivingEntity> beltModel = MODEL.get();
beltModel.setupAnim(reference.entity(), limbSwing, limbSwingAmount, partialTicks, ageInTicks, headPitch);
beltModel.prepareMobModel(reference.entity(), limbSwing, limbSwingAmount, partialTicks);
AccessoryRenderer.followBodyRotations(reference.entity(), beltModel);
VertexConsumer vertexConsumer = multiBufferSource.getBuffer(beltModel.renderType(TEXTURE));
beltModel.renderToBuffer(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY);
}
private static final ResourceLocation TEXTURE = UtilityBelt.id("textures/entity/belt.png");
private static final Supplier<HumanoidModel<LivingEntity>> MODEL = Suppliers.memoize(() ->
new BeltModel(BeltModel.createLayerDefinition().bakeRoot())
);

@Override
public <M extends LivingEntity> void render(ItemStack stack, SlotReference reference, PoseStack matrices, EntityModel<M> model, MultiBufferSource multiBufferSource, int light, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch) {
HumanoidModel<LivingEntity> beltModel = MODEL.get();
beltModel.setupAnim(reference.entity(), limbSwing, limbSwingAmount, partialTicks, ageInTicks, headPitch);
beltModel.prepareMobModel(reference.entity(), limbSwing, limbSwingAmount, partialTicks);
followBodyRotations(reference.entity(), beltModel);
VertexConsumer vertexConsumer = multiBufferSource.getBuffer(beltModel.renderType(TEXTURE));
beltModel.renderToBuffer(matrices, vertexConsumer, light, OverlayTexture.NO_OVERLAY);
}

@SuppressWarnings("unchecked")
private static void followBodyRotations(LivingEntity entity, HumanoidModel<LivingEntity> model) {
EntityRenderer<? super LivingEntity> render = Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(entity);

if (render instanceof LivingEntityRenderer<?, ?> renderer && renderer.getModel() instanceof HumanoidModel<?> entityModel) {
((HumanoidModel<LivingEntity>) entityModel).copyPropertiesTo(model);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ public class UtilityBelt {
DataComponentType.<UtilityBeltInventory>builder().persistent(UtilityBeltInventory.CODEC).cacheEncoding().build()
);
public static final RegistrySupplier<MenuType<UtilityBeltMenu>> MENU_TYPE = MENUS.register("utility_belt", () -> new MenuType<>(UtilityBeltMenu::new, FeatureFlagSet.of()));

public static final Event<UtilityBeltUnequipEvent> UTILITY_BELT_UNEQUIP_EVENT = EventFactory.createLoop();

public static void init() {
JamLib.checkForJarRenaming(UtilityBelt.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
import java.util.List;
import java.util.function.Consumer;

import io.github.jamalam360.utility_belt.network.ServerNetworking;
import io.github.jamalam360.utility_belt.state.StateManager;
import io.wispforest.accessories.api.AccessoryItem;
import io.wispforest.accessories.api.slot.SlotEntryReference;
import io.wispforest.accessories.api.slot.SlotReference;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.SlotAccess;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ClickAction;
import net.minecraft.world.inventory.Slot;
Expand Down Expand Up @@ -156,9 +159,25 @@ public boolean overrideOtherStackedOnMe(ItemStack belt, ItemStack otherStack, Sl
return true;
}

@Override
public void onDestroyed(ItemEntity itemEntity) {
super.onDestroyed(itemEntity);
UtilityBeltInventory inv = getInventory(itemEntity.getItem());

for (ItemStack stack : inv.items()) {
if (!stack.isEmpty()) {
itemEntity.spawnAtLocation(stack);
}
}
}

@Override
public void onUnequip(ItemStack stack, SlotReference reference) {
UtilityBelt.UTILITY_BELT_UNEQUIP_EVENT.invoker().onUnequip(stack, reference);
if (reference.entity() instanceof ServerPlayer player) {
StateManager.getStateManager(player).setInBelt(player, false);
StateManager.getStateManager(player).setSelectedBeltSlot(player, 0);
ServerNetworking.sendBeltUnequippedToClient(player);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import net.minecraft.tags.TagEntry;
import net.minecraft.tags.TagLoader;
import net.minecraft.world.item.Item;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
Expand All @@ -20,11 +22,17 @@

@Mixin(TagLoader.class)
public class TagLoaderMixin {
@Shadow @Final private String directory;

@Inject(
method = "load",
at = @At("TAIL")
)
private void utilitybelt$injectDynamicTags(ResourceManager resourceManager, CallbackInfoReturnable<Map<ResourceLocation, List<TagLoader.EntryWithSource>>> cir) {
if (!this.directory.equals("tags/item")) {
return;
}

Map<ResourceLocation, List<TagLoader.EntryWithSource>> map = cir.getReturnValue();
List<TagLoader.EntryWithSource> list = map.computeIfAbsent(UtilityBelt.ALLOWED_IN_UTILITY_BELT.location(), id -> new ArrayList<>());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ private static void registerServerPayloadTypes() {
NetworkManager.registerS2CPayloadType(UtilityBeltPackets.S2C_SET_BELT_SLOT, UtilityBeltPackets.S2CSetBeltSlot.STREAM_CODEC);
NetworkManager.registerS2CPayloadType(UtilityBeltPackets.S2C_SET_HOTBAR_SLOT, UtilityBeltPackets.S2CSetHotbarSlot.STREAM_CODEC);
NetworkManager.registerS2CPayloadType(UtilityBeltPackets.S2C_UPDATE_BELT_INVENTORY, UtilityBeltPackets.S2CUpdateBeltInventory.STREAM_CODEC);
NetworkManager.registerS2CPayloadType(UtilityBeltPackets.S2C_BELT_UNEQUIPPED, UtilityBeltPackets.S2CBeltUnequipped.STREAM_CODEC);
}

public static void sendInventoryToClient(ServerPlayer player, UtilityBeltInventory inventory) {
NetworkManager.sendToPlayer(player, new UtilityBeltPackets.S2CUpdateBeltInventory(inventory));
}

public static void sendBeltUnequippedToClient(ServerPlayer player) {
NetworkManager.sendToPlayer(player, new UtilityBeltPackets.S2CBeltUnequipped());
}

private static void handleUpdateState(C2SUpdateState payload, NetworkManager.PacketContext ctx) {
boolean inBelt = payload.inBelt();
Expand All @@ -46,7 +51,13 @@ private static void handleUpdateState(C2SUpdateState payload, NetworkManager.Pac
int beltSlot = slot;
StateManager stateManager = StateManager.getStateManager(player);
stateManager.setInBelt(player, inBelt);
stateManager.setSelectedBeltSlot(player, beltSlot);

if (beltSlot < 0 || beltSlot >= stateManager.getInventory(player).getContainerSize()) {
UtilityBelt.LOGGER.warn("Ignoring request from client to set an invalid belt slot: {}", beltSlot);
} else {
stateManager.setSelectedBeltSlot(player, beltSlot);
}

player.swing(InteractionHand.MAIN_HAND, true);

if (swap) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class UtilityBeltPackets {
public static final CustomPacketPayload.Type<S2CSetBeltSlot> S2C_SET_BELT_SLOT = new CustomPacketPayload.Type<>(UtilityBelt.id("set_belt_slot"));
public static final CustomPacketPayload.Type<S2CSetHotbarSlot> S2C_SET_HOTBAR_SLOT = new CustomPacketPayload.Type<>(UtilityBelt.id("set_hotbar_slot"));
public static final CustomPacketPayload.Type<S2CUpdateBeltInventory> S2C_UPDATE_BELT_INVENTORY = new CustomPacketPayload.Type<>(UtilityBelt.id("update_belt_inventory"));
public static final CustomPacketPayload.Type<S2CBeltUnequipped> S2C_BELT_UNEQUIPPED = new CustomPacketPayload.Type<>(UtilityBelt.id("belt_unequipped"));

public record C2SUpdateState(boolean inBelt, int slot, boolean swapItems) implements CustomPacketPayload {

Expand Down Expand Up @@ -80,4 +81,14 @@ public Type<? extends CustomPacketPayload> type() {
return S2C_UPDATE_BELT_INVENTORY;
}
}

public record S2CBeltUnequipped() implements CustomPacketPayload {

public static final StreamCodec<RegistryFriendlyByteBuf, S2CBeltUnequipped> STREAM_CODEC = StreamCodec.unit(new S2CBeltUnequipped());

@Override
public Type<? extends CustomPacketPayload> type() {
return S2C_BELT_UNEQUIPPED;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
package io.github.jamalam360.utility_belt.util;

import com.google.common.base.Suppliers;
import dev.architectury.platform.Platform;
import io.github.jamalam360.utility_belt.UtilityBelt;
import net.minecraft.resources.ResourceLocation;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;

public class DynamicTags {
private static final String LAMB_DYNAMIC_LIGHTS = "lambdynlights";
private static List<ResourceLocation> extraItems = null;

public static List<ResourceLocation> getExtraItemsAllowedInUtilityBelt() {
List<ResourceLocation> list = new ArrayList<>();

if (Platform.isModLoaded(LAMB_DYNAMIC_LIGHTS)) {
UtilityBelt.LOGGER.info("Registering extra Utility Belt entries for LambDynamicLights compatibility.");
list.add(minecraft("torch"));
list.add(minecraft("redstone_torch"));
list.add(minecraft("soul_torch"));
list.add(minecraft("lantern"));
if (extraItems == null) {
List<ResourceLocation> list = new ArrayList<>();

if (Platform.isModLoaded(LAMB_DYNAMIC_LIGHTS)) {
UtilityBelt.LOGGER.info("Registering extra Utility Belt entries for LambDynamicLights compatibility.");
list.add(minecraft("torch"));
list.add(minecraft("redstone_torch"));
list.add(minecraft("soul_torch"));
list.add(minecraft("lantern"));
}

extraItems = list;
}

return list;
return extraItems;
}

private static ResourceLocation minecraft(String path) {
Expand Down
4 changes: 4 additions & 0 deletions common/src/main/resources/assets/utility_belt/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
"config.utility_belt.hotbarPosition.top_right": "Top Right",
"config.utility_belt.hotbarPosition.middle_right": "Middle Right",
"config.utility_belt.hotbarPosition.bottom_right": "Bottom Right",
"config.utility_belt.hotbarOffsetX": "Hotbar Offset X",
"config.utility_belt.hotbarOffsetX.tooltip": "The horizontal offset in pixels of the hotbar from the base position. Use for fine-tuning the hotbar position.",
"config.utility_belt.hotbarOffsetY": "Hotbar Offset Y",
"config.utility_belt.hotbarOffsetY.tooltip": "The vertical offset in pixels of the hotbar from the base position. Use for fine-tuning the hotbar position.",
"config.utility_belt.hotbarKeyBehaviour": "Hotbar Key Behaviour While in Belt",
"config.utility_belt.hotbarKeyBehaviour.tooltip": "When set to 'Switch Back', pressing the hotbar key while in the belt will switch back to the hotbar. When set to 'Switch Belt Slot', pressing the hotbar key will switch to the corresponding belt slot.",
"config.utility_belt.hotbarKeyBehaviour.switch_back_to_hotbar": "Switch Back",
Expand Down
2 changes: 2 additions & 0 deletions fabric/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ dependencies {
modImplementation libs.architectury.fabric
modImplementation libs.jamlib.fabric
modImplementation libs.accessories.fabric
modImplementation libs.owo.lib.fabric // Dependency of Accessories
modRuntimeOnly libs.modmenu

// Compat
modImplementation libs.lambdynamiclights
modRuntimeOnly libs.sodium

common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
Expand Down
Loading

0 comments on commit f915d4e

Please sign in to comment.