Skip to content

Commit

Permalink
Experimental shulker stacking sync
Browse files Browse the repository at this point in the history
  • Loading branch information
kikugie committed Aug 19, 2024
1 parent 2134290 commit ce08810
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 28 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ dependencies {
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"

modRuntimeOnly modCompileOnly ("maven.modrinth:lithium:${project.lithium}")
modRuntimeOnly "curse.maven:carpet-349239:${project.carpet}"
modCompileOnly ("maven.modrinth:lithium:${project.lithium}")
modImplementation "curse.maven:carpet-349239:${project.carpet}"
}

processResources {
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ org.gradle.parallel=true
# check these on https://fabricmc.net/develop
minecraft_version=1.21
yarn_mappings=1.21+build.2
loader_version=0.15.11
loader_version=0.16.2

# Mod Properties
mod_version=1.3
mod_version=1.4
maven_group=dev.kikugie
archives_base_name=shulkerfix

Expand Down
16 changes: 16 additions & 0 deletions src/main/java/dev/kikugie/shulkerfix/ShulkerFixMod.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.kikugie.shulkerfix;

import dev.kikugie.shulkerfix.carpet.ShulkerFixExtension;
import net.fabricmc.api.ModInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ShulkerFixMod implements ModInitializer {
public static final Logger LOGGER = LoggerFactory.getLogger(ShulkerFixMod.class);
public static final String MOD_ID = "shulkerfix";

@Override
public void onInitialize() {
ShulkerFixExtension.init();
}
}
7 changes: 7 additions & 0 deletions src/main/java/dev/kikugie/shulkerfix/Util.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package dev.kikugie.shulkerfix;

import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;

public class Util {
public static boolean isShulkerBox(ItemStack stack) {
return stack.getItem() instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock;
}

public static boolean hasCustomMaxStackSize(ItemStack stack) {
int defaultStackSize = stack.getDefaultComponents().getOrDefault(DataComponentTypes.MAX_STACK_SIZE, 1);
int currentStackSize = stack.getOrDefault(DataComponentTypes.MAX_STACK_SIZE, 1);
return defaultStackSize != currentStackSize;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package dev.kikugie.shulkerfix.carpet;

import carpet.CarpetExtension;
import carpet.CarpetServer;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import dev.kikugie.shulkerfix.ShulkerFixMod;
import net.fabricmc.loader.api.FabricLoader;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.Collections;
import java.util.Map;

public class ShulkerFixExtension implements CarpetExtension {
public static final ShulkerFixExtension INSTANCE = new ShulkerFixExtension();

public static void init() {
CarpetServer.manageExtension(INSTANCE);
}

@Override
public String version() {
var container = FabricLoader.getInstance().getModContainer(ShulkerFixMod.MOD_ID);
return container.isPresent() ? container.get().getMetadata().getVersion().getFriendlyString() : "undefined";
}

@Override
public void onGameStarted() {
CarpetServer.settingsManager.parseSettingsClass(ShulkerFixSettings.class);
}

@Override
public Map<String, String> canHasTranslations(String lang) {
try (InputStream stream = ShulkerFixSettings.class.getClassLoader().getResourceAsStream("assets/shulkerfix/lang/%s.json".formatted(lang))) {
if (stream == null) return Collections.emptyMap();
Gson gson = new Gson();
TypeToken<Map<String, String>> token = new TypeToken<>() {};
Reader reader = new InputStreamReader(stream);
return gson.fromJson(reader, token.getType());
} catch (IOException e) {
ShulkerFixMod.LOGGER.error("Failed to decode mod language file %s.json".formatted(lang), e);
return Collections.emptyMap();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dev.kikugie.shulkerfix.carpet;

import carpet.api.settings.Rule;
import carpet.api.settings.RuleCategory;

public class ShulkerFixSettings {
public static final String SHULKERFIX = "shulkerfix";

@Rule(categories = {SHULKERFIX, RuleCategory.BUGFIX, RuleCategory.EXPERIMENTAL})
public static boolean clientShulkerSync = false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package dev.kikugie.shulkerfix.mixin;

import com.llamalad7.mixinextras.injector.ModifyReturnValue;
import dev.kikugie.shulkerfix.Util;
import dev.kikugie.shulkerfix.carpet.ShulkerFixSettings;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.NbtComponent;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Pseudo;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

/**
* Implementation from the <a href="https://github.com/ch-yx/fabric-carpet/blob/18d4f8fdc02069fb4d41cd28d703f8d7a6aa7579/src/main/java/carpet/mixins/ItemStack_stackableShulkerBoxesEncodeMixin.java">ch-yx fork</a>.
*/
@Pseudo
@Mixin(targets = "net.minecraft.item.ItemStack$1")
public class ItemStackCodecMixin {
@Unique
private static final String MARKER = "__carpet_data!!the_max_stack_size_tag_is_fake!__";

@ModifyVariable(method = "encode(Lnet/minecraft/network/RegistryByteBuf;Lnet/minecraft/item/ItemStack;)V", at = @At("HEAD"), argsOnly = true)
private ItemStack setModifiedStackSize(ItemStack stack) {
if (ShulkerFixSettings.clientShulkerSync &&
stack.getOrDefault(DataComponentTypes.MAX_STACK_SIZE, 1) < stack.getCount() &&
!stack.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT).contains(MARKER) &&
!Util.hasCustomMaxStackSize(stack)
) {
stack = stack.copy();
stack.set(DataComponentTypes.MAX_STACK_SIZE, stack.getMaxCount());
NbtComponent.set(DataComponentTypes.CUSTOM_DATA, stack, nbt -> nbt.putBoolean(MARKER, true));
}
return stack;
}

@ModifyReturnValue(method = "decode(Lnet/minecraft/network/RegistryByteBuf;)Lnet/minecraft/item/ItemStack;", at = @At("RETURN"))
private ItemStack getModifiedStackSize(ItemStack stack) {
// We still do decoding, in case the rule was disabled
if (stack.getOrDefault(DataComponentTypes.CUSTOM_DATA, NbtComponent.DEFAULT).contains(MARKER)) {
stack = stack.copy();
stack.set(DataComponentTypes.MAX_STACK_SIZE, stack.getDefaultComponents().get(DataComponentTypes.MAX_STACK_SIZE));
stack.capCount(stack.getMaxCount());
NbtComponent.set(DataComponentTypes.CUSTOM_DATA, stack, nbt -> nbt.remove(MARKER));
}
return stack;
}
}
5 changes: 5 additions & 0 deletions src/main/resources/assets/shulkerfix/lang/en_us.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"carpet.category.shulkerfix": "ShulkerFix",
"carpet.rule.clientShulkerSync.name": "Sync Stacked Shulker Count",
"carpet.rule.clientShulkerSync.desc": "Fixes displayed shulker amount on vanilla clients. See issue #1899 in Carpet's repo."
}
50 changes: 28 additions & 22 deletions src/main/resources/fabric.mod.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
{
"schemaVersion": 1,
"id": "shulkerfix",
"version": "${version}",
"name": "Stackable Shulker Fix",
"description": "Makes stackable shulker boxes unstackable by hoppers",
"authors": [
"KikuGIe"
],
"license": "MIT",
"environment": "*",
"mixins": [
"shulkerfix.mixins.json"
],
"depends": {
"fabricloader": ">=0.15",
"minecraft": ">=1.20.5",
"carpet": ">=1.4.140",
"java": ">=21"
},
"recommends": {
"lithium": ">=0.12"
}
"schemaVersion": 1,
"id": "shulkerfix",
"version": "${version}",
"name": "Stackable Shulker Fix",
"description": "Makes stackable shulker boxes unstackable by hoppers",
"authors": [
"KikuGIe"
],
"license": "MIT",
"environment": "*",
"mixins": [
"shulkerfix.mixins.json",
"shulkerfix-compat.mixins.json"
],
"entrypoints": {
"main": [
"dev.kikugie.shulkerfix.ShulkerFixMod"
]
},
"depends": {
"fabricloader": ">=0.15",
"minecraft": ">=1.20.5",
"carpet": ">=1.4.140",
"java": ">=21"
},
"recommends": {
"lithium": ">=0.12"
}
}
10 changes: 10 additions & 0 deletions src/main/resources/shulkerfix-compat.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"required": true,
"package": "dev.kikugie.shulkerfix.mixin",
"compatibilityLevel": "JAVA_21",
"mixins": [
"ItemStackCodecMixin",
"LithiumHopperHelperMixin",
"LithiumStackListMixin"
]
}
2 changes: 0 additions & 2 deletions src/main/resources/shulkerfix.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
"compatibilityLevel": "JAVA_21",
"mixins": [
"HopperBlockEntityMixin",
"LithiumHopperHelperMixin",
"LithiumStackListMixin",
"ScreenHandlerMixin"
],
"injectors": {
Expand Down

0 comments on commit ce08810

Please sign in to comment.