diff --git a/src/main/java/me/melontini/andromeda/modules/items/magnet/items/MagnetItem.java b/src/main/java/me/melontini/andromeda/modules/items/magnet/items/MagnetItem.java index e7386bac..371d5c1b 100644 --- a/src/main/java/me/melontini/andromeda/modules/items/magnet/items/MagnetItem.java +++ b/src/main/java/me/melontini/andromeda/modules/items/magnet/items/MagnetItem.java @@ -71,7 +71,7 @@ public class MagnetItem extends Item { this.playRemoveOneSound(player); } else { addFirst(stack, otherStack); - itemParticles(otherStack, player); + Support.run(EnvType.CLIENT, () -> () -> itemParticles(otherStack, player)); this.playInsertSound(player); } return true; -- 2.51.2 From 1ffc0160c2a5cdc97471c1596bdd991f18a68ba4 Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Mon, 25 Dec 2023 15:11:14 +0700 Subject: [PATCH 2/7] Add `andromeda:default` to data configs. --- .../andromeda/common/config/DataConfigs.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java b/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java index 72d2d3ed..d8fd0fea 100644 --- a/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java +++ b/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java @@ -24,12 +24,15 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; +import static me.melontini.andromeda.util.CommonValues.MODID; + public class DataConfigs extends JsonDataLoader { public DataConfigs() { super(new Gson(), "andromeda/scoped_config"); } public static Map, Set, ? extends BasicConfig>>>> CONFIGS; + private static final Identifier DEFAULT = new Identifier(MODID, "default"); @Override public CompletableFuture apply(Map data, ResourceManager manager, Profiler profiler, Executor executor) { @@ -127,6 +130,21 @@ public class DataConfigs extends JsonDataLoader { } static void applyDataPacks(BasicConfig config, Module m, Identifier id) { + var defaultData = DataConfigs.CONFIGS.get(DEFAULT); + if (defaultData != null) { + var forModule = defaultData.get(m); + if (forModule != null) { + for (Tuple, ? extends BasicConfig> tuple : forModule) { + tuple.left().forEach((field) -> { + try { + field.set(config, field.get(tuple.right())); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to apply config data for module '%s'".formatted(m.meta().id()), e); + } + }); + } + } + } var data = DataConfigs.CONFIGS.get(id); if (data != null) { var forModule = data.get(m); -- 2.51.2 From 0fe5f4799ac297171920a8127ee2e84f0ea4e2a0 Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:45:40 +0700 Subject: [PATCH 3/7] Support `WORLD` configs in data pack. There's no real reason to do this, but whatever. --- .../andromeda/base/annotations/Unscoped.java | 2 +- .../andromeda/common/config/DataConfigs.java | 135 ++++++++++-------- 2 files changed, 77 insertions(+), 60 deletions(-) diff --git a/src/main/java/me/melontini/andromeda/base/annotations/Unscoped.java b/src/main/java/me/melontini/andromeda/base/annotations/Unscoped.java index b1b6636b..9d0192db 100644 --- a/src/main/java/me/melontini/andromeda/base/annotations/Unscoped.java +++ b/src/main/java/me/melontini/andromeda/base/annotations/Unscoped.java @@ -6,6 +6,6 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) +@Target({ElementType.TYPE, ElementType.FIELD}) public @interface Unscoped { } diff --git a/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java b/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java index d8fd0fea..88cff6fc 100644 --- a/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java +++ b/src/main/java/me/melontini/andromeda/common/config/DataConfigs.java @@ -1,16 +1,20 @@ package me.melontini.andromeda.common.config; import com.google.gson.Gson; +import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import me.melontini.andromeda.base.Environment; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import me.melontini.andromeda.base.Module; import me.melontini.andromeda.base.ModuleManager; +import me.melontini.andromeda.base.annotations.Unscoped; import me.melontini.andromeda.base.config.BasicConfig; import me.melontini.andromeda.common.registries.Common; import me.melontini.andromeda.common.util.JsonDataLoader; import me.melontini.dark_matter.api.base.util.MakeSure; import me.melontini.dark_matter.api.base.util.Utilities; -import me.melontini.dark_matter.api.base.util.classes.Tuple; import net.minecraft.resource.ResourceManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; @@ -20,7 +24,9 @@ import net.minecraft.util.profiler.Profiler; import net.minecraft.world.World; import java.lang.reflect.Field; -import java.util.*; +import java.util.Collection; +import java.util.Map; +import java.util.Set; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -31,55 +37,76 @@ public class DataConfigs extends JsonDataLoader { super(new Gson(), "andromeda/scoped_config"); } - public static Map, Set, ? extends BasicConfig>>>> CONFIGS; + public static Map, Set>> CONFIGS; + public static Map, Set> DEFAULT_CONFIGS; private static final Identifier DEFAULT = new Identifier(MODID, "default"); @Override public CompletableFuture apply(Map data, ResourceManager manager, Profiler profiler, Executor executor) { return CompletableFuture.supplyAsync(() -> { - Map, Set, ? extends BasicConfig>>>>> configs = new HashMap<>(); + Map, Set>>> configs = new Object2ObjectOpenHashMap<>(); data.forEach((id, object) -> { var m = ModuleManager.get().getModule(id.getPath()).orElseThrow(() -> new IllegalStateException("Invalid module path '%s'! The module must be enabled!".formatted(id.getPath()))); - if (m.config().scope != BasicConfig.Scope.DIMENSION) - throw new IllegalStateException("Invalid module scope `%s` for '%s'! Must be '%s'".formatted(m.config().scope, m.meta().id(), BasicConfig.Scope.DIMENSION)); - var cls = ModuleManager.get().getConfigClass(m.getClass()); - object.entrySet().forEach(entry -> { - var map = configs.computeIfAbsent(Identifier.tryParse(entry.getKey()), string -> new HashMap<>()); - map.computeIfAbsent(m, module -> new LinkedHashSet<>()).add(CompletableFuture.supplyAsync(() -> { - try { - var instance = this.gson.fromJson(entry.getValue(), cls); - Set config = new HashSet<>(); - entry.getValue().getAsJsonObject().entrySet().forEach(entry2 -> { - try { - config.add(cls.getField(entry2.getKey())); - } catch (NoSuchFieldException e) { - throw new RuntimeException("Failed to load config data for module '%s'".formatted(m.meta().id()), e); - } - }); - return Tuple.of(config, instance); - } catch (Exception e) { - throw new RuntimeException("Failed to load config data for module '%s'".formatted(m.meta().id()), e); - } - }, Util.getMainWorkerExecutor())); - }); + + if (m.config().scope == BasicConfig.Scope.WORLD) { + if (!object.has(DEFAULT.toString()) || object.size() > 1) + throw new IllegalStateException("'%s' modules only support '%s' as their dimension!".formatted(BasicConfig.Scope.WORLD, DEFAULT)); + + var map = configs.computeIfAbsent(DEFAULT, identifier -> new Reference2ObjectOpenHashMap<>()); + map.computeIfAbsent(m, module -> new ReferenceLinkedOpenHashSet<>()) + .add(makeFuture(this.gson, m, cls, object.get(DEFAULT.toString()))); + } else { + object.entrySet().forEach(entry -> { + var map = configs.computeIfAbsent(Identifier.tryParse(entry.getKey()), string -> new Reference2ObjectOpenHashMap<>()); + map.computeIfAbsent(m, module -> new ReferenceLinkedOpenHashSet<>()) + .add(makeFuture(this.gson, m, cls, entry.getValue())); + }); + } }); return CompletableFuture.allOf(configs.values().stream().flatMap(map -> map.values().stream()) .flatMap(Collection::stream).toArray(CompletableFuture[]::new)).handle((unused, throwable) -> configs); }, executor).thenAcceptAsync(map -> { - var p = Utilities.supplyUnchecked(map::get); - Map, Set, ? extends BasicConfig>>>> configs = new HashMap<>(); - p.forEach((identifier, moduleSetMap) -> { - var n = configs.computeIfAbsent(identifier, id -> new HashMap<>()); + var futures = Utilities.supplyUnchecked(map::get); + Map, Set>> configs = new Object2ObjectOpenHashMap<>(); + futures.forEach((identifier, moduleSetMap) -> { + var n = configs.computeIfAbsent(identifier, id -> new Object2ObjectOpenHashMap<>()); moduleSetMap.forEach((module, completableFutures) -> { - var set = n.computeIfAbsent(module, m -> new LinkedHashSet<>()); + var set = n.computeIfAbsent(module, m -> new ReferenceLinkedOpenHashSet<>()); completableFutures.forEach(future -> set.add(future.join())); }); }); + DEFAULT_CONFIGS = configs.get(DEFAULT); + configs.remove(DEFAULT); CONFIGS = configs; }, executor); } + private static CompletableFuture makeFuture(Gson gson, Module m, Class cls, JsonElement element) { + return CompletableFuture.supplyAsync(() -> { + try { + var instance = gson.fromJson(element, cls); + Set config = new ReferenceOpenHashSet<>(); + element.getAsJsonObject().entrySet().forEach(entry2 -> { + try { + var f = cls.getField(entry2.getKey()); + if (f.isAnnotationPresent(Unscoped.class)) + throw new IllegalStateException("Attempted to modify an unscoped field '%s'!".formatted(entry2.getKey())); + config.add(f); + } catch (NoSuchFieldException e) { + throw new RuntimeException("Failed to load config data for module '%s'".formatted(m.meta().id()), e); + } + }); + return new Data(config, instance); + } catch (Exception e) { + throw new RuntimeException("Failed to load config data for module '%s'".formatted(m.meta().id()), e); + } + }, Util.getMainWorkerExecutor()); + } + + public record Data(Set fields, BasicConfig config) { + } + @Override public Identifier getFabricId() { return Common.id("data_configs"); @@ -89,10 +116,8 @@ public class DataConfigs extends JsonDataLoader { MakeSure.notNull(DataConfigs.CONFIGS); ScopedConfigs.get(world); - Set> futures = new HashSet<>(); + Set> futures = new ReferenceOpenHashSet<>(); for (Module module : ModuleManager.get().loaded()) { - if (module.meta().environment() == Environment.CLIENT) continue; //Those are always GLOBAL. - switch (module.config().scope) { case WORLD -> futures.add(CompletableFuture.runAsync(() -> { if (world.getRegistryKey().equals(World.OVERWORLD)) @@ -110,10 +135,8 @@ public class DataConfigs extends JsonDataLoader { server.getWorlds().forEach(ScopedConfigs::get); - Set> futures = new HashSet<>(); + Set> futures = new ReferenceOpenHashSet<>(); for (Module module : ModuleManager.get().loaded()) { - if (module.meta().environment() == Environment.CLIENT) continue; //Those are always GLOBAL. - switch (module.config().scope) { case WORLD -> futures.add(CompletableFuture.runAsync(() -> { ServerWorld world = server.getWorld(World.OVERWORLD); @@ -129,35 +152,29 @@ public class DataConfigs extends JsonDataLoader { CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join(); } + private static void apply(BasicConfig config, Data data) { + data.fields().forEach((field) -> { + try { + field.set(config, field.get(data.config())); + } catch (IllegalAccessException e) { + throw new RuntimeException("Failed to apply config data for module '%s'".formatted(config.getClass().getSimpleName()), e); + } + }); + } + static void applyDataPacks(BasicConfig config, Module m, Identifier id) { - var defaultData = DataConfigs.CONFIGS.get(DEFAULT); - if (defaultData != null) { - var forModule = defaultData.get(m); + if (DEFAULT_CONFIGS != null) { + var forModule = DEFAULT_CONFIGS.get(m); if (forModule != null) { - for (Tuple, ? extends BasicConfig> tuple : forModule) { - tuple.left().forEach((field) -> { - try { - field.set(config, field.get(tuple.right())); - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to apply config data for module '%s'".formatted(m.meta().id()), e); - } - }); - } + for (Data tuple : forModule) apply(config, tuple); } } + var data = DataConfigs.CONFIGS.get(id); if (data != null) { var forModule = data.get(m); if (forModule != null) { - for (Tuple, ? extends BasicConfig> tuple : forModule) { - tuple.left().forEach((field) -> { - try { - field.set(config, field.get(tuple.right())); - } catch (IllegalAccessException e) { - throw new RuntimeException("Failed to apply config data for module '%s'".formatted(m.meta().id()), e); - } - }); - } + for (Data tuple : forModule) apply(config, tuple); } } } -- 2.51.2 From 055e37902e0b1b0b29e31fb024eb895a0e5dbe84 Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Tue, 26 Dec 2023 00:49:05 +0700 Subject: [PATCH 4/7] Okay, I folded. --- build.gradle | 2 +- .../util/mixin/AndromedaMixinPlugin.java | 5 -- .../andromeda/util/mixin/FrameworkPatch.java | 60 ------------------- 3 files changed, 1 insertion(+), 66 deletions(-) delete mode 100644 src/main/java/me/melontini/andromeda/util/mixin/FrameworkPatch.java diff --git a/build.gradle b/build.gradle index 71eba47f..b309bcca 100644 --- a/build.gradle +++ b/build.gradle @@ -31,7 +31,7 @@ dependencies { // Fabric API. This is technically optional, but you probably want it anyway. modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - def dmModules = ["base", "minecraft", "analytics", "analytics-crashes", "analytics-mixpanel", "content", "danger", "mirage", "glitter"] + def dmModules = ["base", "minecraft", "analytics", "analytics-crashes", "analytics-mixpanel", "content", "mirage", "glitter"] for (final def module in dmModules) { modApi include("me.melontini.dark-matter:dark-matter-${module}:${project.dark_matter}") } diff --git a/src/main/java/me/melontini/andromeda/util/mixin/AndromedaMixinPlugin.java b/src/main/java/me/melontini/andromeda/util/mixin/AndromedaMixinPlugin.java index 761075a8..48ddded8 100644 --- a/src/main/java/me/melontini/andromeda/util/mixin/AndromedaMixinPlugin.java +++ b/src/main/java/me/melontini/andromeda/util/mixin/AndromedaMixinPlugin.java @@ -19,11 +19,6 @@ public class AndromedaMixinPlugin extends ExtendablePlugin { AndromedaMixins.getClassPath().addUrl(this.getClass().getProtectionDomain().getCodeSource().getLocation()); Debug.load(); - try { - FrameworkPatch.patch(); - } catch (Throwable e) { - LOGGER.error("Failed to patch the mixin framework!", e); - } Mixins.registerErrorHandlerClass(ErrorHandler.class.getName()); } diff --git a/src/main/java/me/melontini/andromeda/util/mixin/FrameworkPatch.java b/src/main/java/me/melontini/andromeda/util/mixin/FrameworkPatch.java deleted file mode 100644 index bbe23308..00000000 --- a/src/main/java/me/melontini/andromeda/util/mixin/FrameworkPatch.java +++ /dev/null @@ -1,60 +0,0 @@ -package me.melontini.andromeda.util.mixin; - -import lombok.CustomLog; -import lombok.SneakyThrows; -import me.melontini.dark_matter.api.danger.instrumentation.InstrumentationAccess; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.TryCatchBlockNode; -import org.spongepowered.asm.mixin.throwables.MixinError; - -import java.util.List; - -@CustomLog -public class FrameworkPatch { - - @SneakyThrows - public static void patch() { - if (InstrumentationAccess.canInstrument()) { - LOGGER.info("Definitely up to a lot of good"); - Class cls = Class.forName("org.spongepowered.asm.mixin.transformer.MixinApplicatorStandard"); - InstrumentationAccess.retransform(classNode -> { - MethodNode node = classNode.methods.stream().filter(mn -> "apply".equals(mn.name) && "(Ljava/util/SortedSet;)V".equals(mn.desc)).findFirst().orElse(null); - if (node == null) { - LOGGER.warn("Failed to find 'apply' method in class {}", classNode.name); - return classNode; - } - - List possibleTry = node.tryCatchBlocks.stream().filter(tryCatchBlockNode -> "java/lang/Exception".equals(tryCatchBlockNode.type)).toList(); - List possibleUpperTry = node.tryCatchBlocks.stream().filter(tryCatchBlockNode -> "org/spongepowered/asm/mixin/transformer/throwables/InvalidMixinException".equals(tryCatchBlockNode.type)).toList(); - - TryCatchBlockNode tryCatch = possibleTry.stream().filter(blockNode -> { - for (TryCatchBlockNode upperTryCatch : possibleUpperTry) { - if (blockNode.start == upperTryCatch.start && blockNode.end == upperTryCatch.end) { - return true; - } - } - return false; - }).findFirst().orElse(null); - - if (tryCatch == null) { - LOGGER.warn("Failed to find required try-catch block in class {}", classNode.name); - return classNode; - } - - final String mixinError = Type.getInternalName(MixinError.class); - TryCatchBlockNode ourTryCatch = node.tryCatchBlocks.stream().filter(blockNode -> - mixinError.equals(blockNode.type) && blockNode.start == tryCatch.start && blockNode.end == tryCatch.end).findFirst().orElse(null); - if (ourTryCatch != null) { - LOGGER.warn("Required try-catch block already exists in class {}", classNode.name); - return classNode; - } - - //https://github.com/SpongePowered/Mixin/pull/640 - node.tryCatchBlocks.add(new TryCatchBlockNode(tryCatch.start, tryCatch.end, tryCatch.handler, mixinError)); - - return classNode; - }, cls); - } - } -} -- 2.51.2 From b75572a347a1029bddfa3874d6d44680cc30e6b8 Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:35:32 +0700 Subject: [PATCH 5/7] De-hardcode item frame tooltips in preparation for new tooltip types. --- .../item_frame_tooltips/client/Client.java | 88 ++++++++++++------- .../andromeda/util/mixin/ErrorHandler.java | 3 +- 2 files changed, 56 insertions(+), 35 deletions(-) diff --git a/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java b/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java index 138ff197..920b5feb 100644 --- a/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java +++ b/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java @@ -8,19 +8,24 @@ import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback; import net.fabricmc.fabric.api.client.rendering.v1.TooltipComponentCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.tooltip.TooltipComponent; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.entity.decoration.ItemFrameEntity; -import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.MathHelper; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; import java.util.stream.Collectors; public class Client { - private static ItemStack frameStack = ItemStack.EMPTY; + private static Supplier> action; private static float tooltipFlow; private static float oldTooltipFlow; @@ -31,57 +36,74 @@ public class Client { var cast = client.crosshairTarget; getCast(cast); oldTooltipFlow = tooltipFlow; - tooltipFlow = !frameStack.isEmpty() ? MathHelper.lerp(0.25f, tooltipFlow, 1) : + tooltipFlow = action != null ? MathHelper.lerp(0.25f, tooltipFlow, 1) : MathHelper.lerp(0.1f, tooltipFlow, 0); if (Math.abs(tooltipFlow) < 1.0E-5F) tooltipFlow = 0; }); } + public static void registerEntityTooltip(Predicate predicate, Function> function) { + ENTITY_LOOKUP.put(predicate, function); + } + private static void inGameTooltips() { HudRenderCallback.EVENT.register((matrices, delta) -> { if (MinecraftClient.getInstance().currentScreen == null) { var client = MinecraftClient.getInstance(); - if (!frameStack.isEmpty()) { - float flow = MathHelper.lerp(client.getTickDelta(), oldTooltipFlow, tooltipFlow); - matrices.push(); - matrices.translate(0, 0, -450); - matrices.scale(1, 1, 1); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.setShaderColor(1, 1, 1, Math.min(flow, 0.8f)); - var list = DrawUtil.getFakeScreen().getTooltipFromItem(frameStack); - //list.add(AndromedaTexts.ITEM_IN_FRAME); - List list1 = list.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList()); - - frameStack.getTooltipData().ifPresent(datax -> list1.add(1, Utilities.supply(() -> { - TooltipComponent component = TooltipComponentCallback.EVENT.invoker().getComponent(datax); - if (component == null) component = TooltipComponent.of(datax); - return component; - }))); - - int j = 0; - for (TooltipComponent tooltipComponent : list1) { - j += tooltipComponent.getHeight(); - } - - DrawUtil.renderTooltipFromComponents(matrices, list1, ((client.getWindow().getScaledWidth() / 2f) - (flow * 15)) + 15, ((client.getWindow().getScaledHeight() - j) / 2f) + 12); - RenderSystem.setShaderColor(1, 1, 1, 1); - RenderSystem.disableBlend(); - matrices.pop(); + if (action != null) { + renderFromComponents(client, matrices, action.get()); } } }); + + registerEntityTooltip(entityHitResult -> entityHitResult.getEntity() instanceof ItemFrameEntity ife && !ife.getHeldItemStack().isEmpty(), entityHitResult -> { + var frameStack = ((ItemFrameEntity) entityHitResult.getEntity()).getHeldItemStack(); + var list = DrawUtil.getFakeScreen().getTooltipFromItem(frameStack); + List components = list.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList()); + + frameStack.getTooltipData().ifPresent(datax -> components.add(1, Utilities.supply(() -> { + TooltipComponent component = TooltipComponentCallback.EVENT.invoker().getComponent(datax); + if (component == null) component = TooltipComponent.of(datax); + return component; + }))); + return components; + }); } + private static final Map, Function>> ENTITY_LOOKUP = new HashMap<>(); + private static void getCast(HitResult cast) { + if (cast != null) if (cast.getType() == HitResult.Type.ENTITY) { EntityHitResult hitResult = (EntityHitResult) cast; - if (hitResult.getEntity() instanceof ItemFrameEntity itemFrameEntity) { - frameStack = itemFrameEntity.getHeldItemStack(); + var opt = ENTITY_LOOKUP.entrySet().stream().filter(p -> p.getKey().test(hitResult)).findFirst(); + if (opt.isPresent()) { + action = () -> opt.get().getValue().apply(hitResult); return; } } - frameStack = ItemStack.EMPTY; + action = null; + } + + private static void renderFromComponents(MinecraftClient client, MatrixStack matrices, List components) { + float flow = MathHelper.lerp(client.getTickDelta(), oldTooltipFlow, tooltipFlow); + + matrices.push(); + matrices.translate(0, 0, -450); + matrices.scale(1, 1, 1); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShaderColor(1, 1, 1, Math.min(flow, 0.8f)); + + int j = 0; + for (TooltipComponent tooltipComponent : components) { + j += tooltipComponent.getHeight(); + } + + DrawUtil.renderTooltipFromComponents(matrices, components, ((client.getWindow().getScaledWidth() / 2f) - (flow * 15)) + 15, ((client.getWindow().getScaledHeight() - j) / 2f) + 12); + RenderSystem.setShaderColor(1, 1, 1, 1); + RenderSystem.disableBlend(); + matrices.pop(); } } diff --git a/src/main/java/me/melontini/andromeda/util/mixin/ErrorHandler.java b/src/main/java/me/melontini/andromeda/util/mixin/ErrorHandler.java index 528766ef..3ab8937c 100644 --- a/src/main/java/me/melontini/andromeda/util/mixin/ErrorHandler.java +++ b/src/main/java/me/melontini/andromeda/util/mixin/ErrorHandler.java @@ -5,7 +5,6 @@ import me.melontini.andromeda.base.ModuleManager; import me.melontini.andromeda.common.util.CrashHandler; import me.melontini.andromeda.util.AndromedaLog; import me.melontini.andromeda.util.Debug; -import me.melontini.andromeda.util.exceptions.MixinVerifyError; import net.fabricmc.loader.api.FabricLoader; import org.spongepowered.asm.mixin.extensibility.IMixinConfig; import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler; @@ -28,7 +27,7 @@ public class ErrorHandler implements IMixinErrorHandler { if (Debug.hasKey(Debug.Keys.SKIP_MIXIN_ERROR_HANDLER)) return action; if (action == ErrorAction.ERROR) { - if (mixin.getClassName().startsWith("me.melontini.andromeda") && !(th instanceof MixinVerifyError)) + if (mixin.getClassName().startsWith("me.melontini.andromeda")) CrashHandler.handleCrash(true, th, "Failed to " + phase + " " + mixin.getClassName(), FabricLoader.getInstance().getEnvironmentType()); ModuleManager.get().moduleFromConfig(mixin.getConfig().getName()).ifPresent(module -> { -- 2.51.2 From a85a276778063086c195ebc4f141d3f699993c2c Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Tue, 26 Dec 2023 01:42:00 +0700 Subject: [PATCH 6/7] CHANGELOG.md and bump version. --- CHANGELOG.md | 9 ++++----- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a5525a7..7fe2f57e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,7 @@ ## Alpha warning! -* Fixed legacy config migration when both config versions are present. -* Scoped config are no longer created or stored for disabled modules. -* Module setup and Scoped Configs setup should be a bit faster now. -* Removed Connector notice. -* Updated Chinese translation. Courtesy of [Rad586](https://github.com/Rad586). \ No newline at end of file +* Added `andromeda:default` to data pack configs. This will be applied to all dimensions before dimension specific + configs. Can be used to set `enabled` to `false` on all dimensions. +* Data pack configs now support `WORLD` scopes. +* Fixed right-clicking the magnet crashing the dedicated server. \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index ab54df51..d04f3426 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ minecraft_version=1.19.2 yarn_mappings=1.19.2+build.28 loader_version=0.15.0 # Mod Properties -mod_version=1.4.1-1.19.2 +mod_version=1.4.2-1.19.2 maven_group=me.melontini archives_base_name=andromeda # Dependencies -- 2.51.2 From 0eed2b0836c30b4e835320117fdb3b99e06c6147 Mon Sep 17 00:00:00 2001 From: melontini <104443436+melontini@users.noreply.github.com> Date: Tue, 26 Dec 2023 12:59:40 +0700 Subject: [PATCH 7/7] A few checks to avoid empty tooltips. --- .../modules/gui/item_frame_tooltips/client/Client.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java b/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java index 920b5feb..4d5bde49 100644 --- a/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java +++ b/src/main/java/me/melontini/andromeda/modules/gui/item_frame_tooltips/client/Client.java @@ -15,6 +15,7 @@ import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.MathHelper; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,6 +60,8 @@ public class Client { registerEntityTooltip(entityHitResult -> entityHitResult.getEntity() instanceof ItemFrameEntity ife && !ife.getHeldItemStack().isEmpty(), entityHitResult -> { var frameStack = ((ItemFrameEntity) entityHitResult.getEntity()).getHeldItemStack(); + if (frameStack.isEmpty()) return Collections.emptyList(); + var list = DrawUtil.getFakeScreen().getTooltipFromItem(frameStack); List components = list.stream().map(Text::asOrderedText).map(TooltipComponent::of).collect(Collectors.toList()); @@ -87,6 +90,8 @@ public class Client { } private static void renderFromComponents(MinecraftClient client, MatrixStack matrices, List components) { + if (components.isEmpty()) return; + float flow = MathHelper.lerp(client.getTickDelta(), oldTooltipFlow, tooltipFlow); matrices.push();