diff options
32 files changed, 812 insertions, 932 deletions
diff --git a/build.gradle b/build.gradle index beb2d59..c037977 100644 --- a/build.gradle +++ b/build.gradle @@ -1,43 +1,20 @@ -buildscript { - repositories { - maven { url = 'https://files.minecraftforge.net/maven' } - maven { url = "https://repo.spongepowered.org/maven" } - jcenter() - mavenCentral() - } - dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true - classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT' - } +plugins { + id 'fabric-loom' version '0.9-SNAPSHOT' + id 'maven-publish' } -apply plugin: 'net.minecraftforge.gradle' -apply plugin: 'org.spongepowered.mixin' -apply plugin: 'eclipse' - -archivesBaseName = project.name + '-' + project.mcVersion -java.toolchain.languageVersion = JavaLanguageVersion.of(16) +sourceCompatibility = JavaVersion.VERSION_16 +targetCompatibility = JavaVersion.VERSION_16 -mixin { - add sourceSets.main, "${project.name.toLowerCase()}.refmap.json" -} - -minecraft { - mappings channel: 'official', version: project.mcVersion - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') +archivesBaseName = project.name + '-' + project.mcVersion - runs { - client = { - properties 'forge.logging.markers': '' - properties 'forge.logging.console.level': 'debug' - properties 'terminal.ansi': 'true' - workingDirectory project.file('run').canonicalPath - source sourceSets.main +sourceSets.main.java.srcDirs += 'java' +sourceSets.main.resources.srcDirs += 'resources' - arg "-mixin.debug=true" - arg "-mixin.checks.interfaces=true" - arg "-mixin.config=${project.name}.mixins.json".toLowerCase() - } +repositories { + maven { + name = "CurseMaven" + url = "https://www.cursemaven.com" } } @@ -50,11 +27,29 @@ sourceSets { } dependencies { - minecraft "net.minecraftforge:forge:${project.mcVersion}-${project.forgeVersion}" - annotationProcessor 'org.spongepowered:mixin:0.8.4:processor' + minecraft "com.mojang:minecraft:${project.mcVersion}" + mappings loom.officialMojangMappings() + modImplementation "net.fabricmc:fabric-loader:${project.loaderVersion}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabricVersion}" +} + +loom { + accessWidenerPath = file("src/main/resources/${project.name.toLowerCase()}.accesswidener") +} + +tasks.withType(JavaCompile).configureEach { + it.options.encoding = "UTF-8" + it.options.release = 16 +} + +java { + withSourcesJar() } jar { + from("LICENSE") { + rename { "${it}_${project.archivesBaseName}"} + } manifest { attributes(["Specification-Title": project.name, "Specification-Vendor": project.author, @@ -62,7 +57,6 @@ jar { "Implementation-Title": project.name, "Implementation-Version": project.version, "Implementation-Vendor" : project.author, - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), - "MixinConfigs": "${project.name.toLowerCase()}.mixins.json"],) + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")],) } } diff --git a/gradle.properties b/gradle.properties index 6139b1a..bf173b9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,5 +7,7 @@ name=${rootProject.name} group=com.anthonyhilyard.${name.toLowerCase()} author=anthonyhilyard version=1.0.16 + mcVersion=1.17.1 -forgeVersion=37.0.90 +fabricVersion=0.39.2+1.17 +loaderVersion=0.11.6 @@ -1,7 +1,7 @@ -#!/bin/sh +#!/usr/bin/env sh # -# Copyright © 2015-2021 the original authors. +# Copyright 2015 the original author or authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,101 +17,67 @@ # ############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# +## +## Gradle start up script for UN*X +## ############################################################################## # Attempt to set APP_HOME - # Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} +APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum +MAX_FD="maximum" warn () { echo "$*" -} >&2 +} die () { echo echo "$*" echo exit 1 -} >&2 +} # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MSYS* | MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -121,9 +87,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java + JAVACMD="$JAVA_HOME/jre/sh/java" else - JAVACMD=$JAVA_HOME/bin/java + JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -132,7 +98,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD=java + JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -140,95 +106,80 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi fi -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg + i=`expr $i + 1` done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" exec "$JAVACMD" "$@" diff --git a/settings.gradle b/settings.gradle index d318b0e..7af9f6d 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,12 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + gradlePluginPortal() + } +} + // Set the root project name so that the workspace folder name doesn't mess stuff up. rootProject.name = "Iceberg"
\ No newline at end of file diff --git a/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java index 3a860a2..6361d20 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java +++ b/src/main/java/com/anthonyhilyard/iceberg/IcebergClient.java @@ -1,26 +1,12 @@ package com.anthonyhilyard.iceberg; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; -import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.fabricmc.api.ClientModInitializer; -@Mod.EventBusSubscriber(modid = Loader.MODID, bus = Bus.MOD, value = Dist.CLIENT) -public class IcebergClient +public class IcebergClient implements ClientModInitializer { - public IcebergClient() + @Override + public void onInitializeClient() { - } - - public void onClientSetup(FMLClientSetupEvent event) - { - event.enqueueWork(new Runnable() - { - @Override - public void run() - { - - } - }); + } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java b/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java index 4ad4e48..227da6f 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java +++ b/src/main/java/com/anthonyhilyard/iceberg/IcebergServer.java @@ -1,13 +1,12 @@ package com.anthonyhilyard.iceberg; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.fabricmc.api.DedicatedServerModInitializer; -@Mod.EventBusSubscriber(modid = Loader.MODID, bus = Bus.MOD, value = Dist.DEDICATED_SERVER) -public class IcebergServer +public class IcebergServer implements DedicatedServerModInitializer { - public IcebergServer() + @Override + public void onInitializeServer() { + } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/Loader.java b/src/main/java/com/anthonyhilyard/iceberg/Loader.java index 49e9d9c..d8c3af5 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/Loader.java +++ b/src/main/java/com/anthonyhilyard/iceberg/Loader.java @@ -1,47 +1,18 @@ package com.anthonyhilyard.iceberg; -import com.anthonyhilyard.iceberg.network.IcebergNetworkProtocol; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.IExtensionPoint; -import net.minecraftforge.fml.ModLoadingContext; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.fml.loading.FMLEnvironment; +import net.fabricmc.api.ModInitializer; -@Mod(Loader.MODID) -public class Loader +public class Loader implements ModInitializer { public static final String MODID = "iceberg"; public static final Logger LOGGER = LogManager.getLogger(MODID); - public Loader() + @Override + public void onInitialize() { - if (FMLEnvironment.dist == Dist.CLIENT) - { - IcebergClient mod = new IcebergClient(); - FMLJavaModLoadingContext.get().getModEventBus().addListener(mod::onClientSetup); - } - else - { - new IcebergServer(); - } - - // Register the network protocol. - IcebergNetworkProtocol.register(); - - ModLoadingContext.get().registerExtensionPoint(IExtensionPoint.DisplayTest.class, () -> new IExtensionPoint.DisplayTest(() -> "ANY", (remote, isServer) -> true)); - } - - @SubscribeEvent - public void onCommonSetup(FMLCommonSetupEvent event) - { - } // Event testing. diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/CriterionCallback.java b/src/main/java/com/anthonyhilyard/iceberg/events/CriterionCallback.java new file mode 100644 index 0000000..f46f082 --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/events/CriterionCallback.java @@ -0,0 +1,23 @@ +package com.anthonyhilyard.iceberg.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.advancements.Advancement; +import net.minecraft.world.entity.player.Player; + +/** + * This event is fired when a player is granted an advancement criterion. + */ +public interface CriterionCallback +{ + Event<CriterionCallback> EVENT = EventFactory.createArrayBacked(CriterionCallback.class, + (listeners) -> (player, advancement, criterionKey) -> { + for (CriterionCallback listener : listeners) + { + listener.awardCriterion(player, advancement, criterionKey); + } + } + ); + + public void awardCriterion(Player player, Advancement advancement, String criterionKey); +} diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java deleted file mode 100644 index fed7ec2..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/events/CriterionEvent.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.anthonyhilyard.iceberg.events; - -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraft.advancements.Advancement; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.MinecraftForge; - -/** - * This event is fired when a player is granted an advancement criterion. - * <br> - * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br> - * <br> - * This event does not have a result. {@link HasResult}<br> - * <br> - * This event is fired on the {@link MinecraftForge#EVENT_BUS}. - */ -public class CriterionEvent extends PlayerEvent -{ - private final Advancement advancement; - private final String criterionKey; - - public CriterionEvent(Player player, Advancement advancement, String criterionKey) - { - super(player); - this.advancement = advancement; - this.criterionKey = criterionKey; - } - - public Advancement getAdvancement() - { - return advancement; - } - - public String getCriterionKey() - { - return criterionKey; - } -} diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java deleted file mode 100644 index d2abcb2..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvent.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.anthonyhilyard.iceberg.events; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.event.entity.EntityEvent; - -public class EntityFluidEvent extends EntityEvent -{ - private final Fluid fluid; - - private EntityFluidEvent(Entity entity, Fluid fluid) - { - super(entity); - this.fluid = fluid; - } - - public Fluid getFluid() - { - return fluid; - } - - /** - * This event is fired when an entity enters a fluid to at least eye-level. - * If this is a player, they will see the "submerged in fluid" effect at this point. - * <br> - * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br> - * <br> - * This event does not have a result. {@link HasResult}<br> - * <br> - * This event is fired on the {@link MinecraftForge#EVENT_BUS}. - */ - public static class Entered extends EntityFluidEvent - { - public Entered(Entity entity, Fluid fluid) - { - super(entity, fluid); - } - } - - /** - * This event is fired when an entity was previously submerged in a fluid to at least eye-level and no longer are. - * If this is a player, they will no longer see the "submerged in fluid" effect at this point. - * <br> - * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br> - * <br> - * This event does not have a result. {@link HasResult}<br> - * <br> - * This event is fired on the {@link MinecraftForge#EVENT_BUS}. - */ - public static class Exited extends EntityFluidEvent - { - public Exited(Entity entity, Fluid fluid) - { - super(entity, fluid); - } - } -} diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvents.java b/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvents.java new file mode 100644 index 0000000..3ffea9a --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/events/EntityFluidEvents.java @@ -0,0 +1,44 @@ +package com.anthonyhilyard.iceberg.events; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.material.Fluid; + + +public final class EntityFluidEvents +{ + public EntityFluidEvents() { } + + /** + * Called when an Entity enters a new fluid. + */ + public static final Event<EntityFluidEvents.Entered> ENTERED = EventFactory.createArrayBacked(EntityFluidEvents.Entered.class, callbacks -> (entity, fluid) -> { + for (EntityFluidEvents.Entered callback : callbacks) + { + callback.onEntered(entity, fluid); + } + }); + + /** + * Called when an Entity exits a fluid. + */ + public static final Event<EntityFluidEvents.Exited> EXITED = EventFactory.createArrayBacked(EntityFluidEvents.Exited.class, callbacks -> (entity, fluid) -> { + for (EntityFluidEvents.Exited callback : callbacks) + { + callback.onExited(entity, fluid); + } + }); + + @FunctionalInterface + public interface Entered + { + void onEntered(Entity entity, Fluid fluid); + } + + @FunctionalInterface + public interface Exited + { + void onExited(Entity entity, Fluid fluid); + } +}
\ No newline at end of file diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupCallback.java b/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupCallback.java new file mode 100644 index 0000000..5f56eb9 --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupCallback.java @@ -0,0 +1,24 @@ +package com.anthonyhilyard.iceberg.events; + +import java.util.UUID; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.world.item.ItemStack; + +/** + * This event is fired right before a player picks up a new item. This event fires on the logical client. + */ +public interface NewItemPickupCallback +{ + Event<NewItemPickupCallback> EVENT = EventFactory.createArrayBacked(NewItemPickupCallback.class, + (listeners) -> (playerUUID, itemStack) -> { + for (NewItemPickupCallback listener : listeners) + { + listener.onItemPickup(playerUUID, itemStack); + } + } + ); + + public void onItemPickup(UUID playerUUID, ItemStack itemStack); +}
\ No newline at end of file diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java deleted file mode 100644 index 48f2faf..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/events/NewItemPickupEvent.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.anthonyhilyard.iceberg.events; - -import net.minecraftforge.event.entity.player.PlayerEvent; - -import java.util.UUID; - -import net.minecraft.client.Minecraft; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.MinecraftForge; - -/** - * This event is fired right before a player picks up a new item. Unlike EntityItemPickupEvent, this event fires on the logical client. - * <br> - * This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.<br> - * <br> - * This event does not have a result. {@link HasResult}<br> - * <br> - * This event is fired on the {@link MinecraftForge#EVENT_BUS}. - */ -public class NewItemPickupEvent extends PlayerEvent -{ - private final ItemStack itemStack; - - public NewItemPickupEvent(Player player, ItemStack itemStack) - { - super(player); - this.itemStack = itemStack; - } - - @SuppressWarnings("resource") - public NewItemPickupEvent(UUID playerUUID, ItemStack itemStack) - { - this(Minecraft.getInstance().level.getPlayerByUUID(playerUUID), itemStack); - } - - public ItemStack getItemStack() - { - return itemStack; - } -} diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java b/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java new file mode 100644 index 0000000..1ef654d --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipEvents.java @@ -0,0 +1,65 @@ +package com.anthonyhilyard.iceberg.events; + +import java.util.List; + +import com.mojang.blaze3d.vertex.PoseStack; + +import net.fabricmc.fabric.api.event.Event; +import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.item.ItemStack; + +public final class RenderTooltipEvents +{ + public RenderTooltipEvents() { } + + public static final Event<RenderTooltipEvents.Pre> PRE = EventFactory.createArrayBacked(RenderTooltipEvents.Pre.class, + callbacks -> (stack, components, poseStack, x, y, screenWidth, screenHeight, maxWidth, font, comparison) -> { + for (RenderTooltipEvents.Pre callback : callbacks) + { + InteractionResult result = callback.onPre(stack, components, poseStack, x, y, screenWidth, screenHeight, maxWidth, font, comparison); + + if (result != InteractionResult.PASS) + { + return result; + } + } + return InteractionResult.PASS; + }); + + public static final Event<RenderTooltipEvents.Color> COLOR = EventFactory.createArrayBacked(RenderTooltipEvents.Color.class, + callbacks -> (stack, components, poseStack, x, y, font, background, borderStart, borderEnd, comparison) -> { + for (RenderTooltipEvents.Color callback : callbacks) + { + callback.onColor(stack, components, poseStack, x, y, font, background, borderStart, borderEnd, comparison); + } + }); + + public static final Event<RenderTooltipEvents.Post> POST = EventFactory.createArrayBacked(RenderTooltipEvents.Post.class, + callbacks -> (stack, components, poseStack, x, y, font, width, height, comparison) -> { + for (RenderTooltipEvents.Post callback : callbacks) + { + callback.onPost(stack, components, poseStack, x, y, font, width, height, comparison); + } + }); + + @FunctionalInterface + public interface Pre + { + InteractionResult onPre(ItemStack stack, List<ClientTooltipComponent> components, PoseStack poseStack, int x, int y, int screenWidth, int screenHeight, int maxWidth, Font font, boolean comparison); + } + + @FunctionalInterface + public interface Color + { + void onColor(ItemStack stack, List<ClientTooltipComponent> components, PoseStack poseStack, int x, int y, Font font, int background, int borderStart, int borderEnd, boolean comparison); + } + + @FunctionalInterface + public interface Post + { + void onPost(ItemStack stack, List<ClientTooltipComponent> components, PoseStack poseStack, int x, int y, Font font, int width, int height, boolean comparison); + } +} diff --git a/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipExtEvent.java b/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipExtEvent.java deleted file mode 100644 index 3ca2d37..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/events/RenderTooltipExtEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.anthonyhilyard.iceberg.events; - -import java.util.List; - -import com.mojang.blaze3d.vertex.PoseStack; - -import net.minecraft.client.gui.Font; -import net.minecraft.world.item.ItemStack; -import net.minecraft.network.chat.FormattedText; -import net.minecraftforge.client.event.RenderTooltipEvent; - -public class RenderTooltipExtEvent -{ - public static class Pre extends RenderTooltipEvent.Pre - { - private boolean comparisonTooltip = false; - - @SuppressWarnings("removal") - public Pre(ItemStack stack, List<? extends FormattedText> lines, PoseStack PoseStack, int x, int y, int screenWidth, int screenHeight, int maxWidth, Font font, boolean comparison) - { - super(stack, lines, PoseStack, x, y, screenWidth, screenHeight, maxWidth, font); - comparisonTooltip = comparison; - } - public boolean isComparison() { return comparisonTooltip; } - } - - @SuppressWarnings("removal") - public static class PostBackground extends RenderTooltipEvent.PostBackground - { - private boolean comparisonTooltip = false; - - public PostBackground(ItemStack stack, List<? extends FormattedText> textLines, PoseStack PoseStack, int x, int y, Font font, int width, int height, boolean comparison) - { - super(stack, textLines, PoseStack, x, y, font, width, height); - comparisonTooltip = comparison; - } - public boolean isComparison() { return comparisonTooltip; } - } - - @SuppressWarnings("removal") - public static class PostText extends RenderTooltipEvent.PostText - { - private boolean comparisonTooltip = false; - - public PostText(ItemStack stack, List<? extends FormattedText> textLines, PoseStack PoseStack, int x, int y, Font font, int width, int height, boolean comparison) - { - super(stack, textLines, PoseStack, x, y, font, width, height); - comparisonTooltip = comparison; - } - public boolean isComparison() { return comparisonTooltip; } - } - - public static class Color extends RenderTooltipEvent.Color - { - private boolean comparisonTooltip = false; - - @SuppressWarnings("removal") - public Color(ItemStack stack, List<? extends FormattedText> textLines, PoseStack PoseStack, int x, int y, Font font, int background, int borderStart, int borderEnd, boolean comparison) - { - super(stack, textLines, PoseStack, x, y, font, background, borderStart, borderEnd); - comparisonTooltip = comparison; - } - public boolean isComparison() { return comparisonTooltip; } - } -} diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java index ba3a69e..5d02156 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java +++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/EntityMixin.java @@ -2,7 +2,7 @@ package com.anthonyhilyard.iceberg.mixin; import java.util.Objects; -import com.anthonyhilyard.iceberg.events.EntityFluidEvent; +import com.anthonyhilyard.iceberg.events.EntityFluidEvents; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -14,18 +14,15 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.material.Fluid; import net.minecraft.tags.Tag; -import net.minecraftforge.common.MinecraftForge; @Mixin(Entity.class) -public class EntityMixin extends net.minecraftforge.common.capabilities.CapabilityProvider<Entity> +public class EntityMixin { private Fluid previousFluidOnEyes = null; @Shadow protected Tag<Fluid> fluidOnEyes; - protected EntityMixin(Class<Entity> baseClass) { super(baseClass); } - @Inject(method = "updateFluidOnEyes", at = @At(value = "RETURN")) public void onUpdateFluidOnEyes(CallbackInfo callbackInfo) { @@ -38,7 +35,7 @@ public class EntityMixin extends net.minecraftforge.common.capabilities.Capabili // We were submerged in a fluid that we no longer are. if (previousFluidOnEyes != null) { - MinecraftForge.EVENT_BUS.post(new EntityFluidEvent.Exited((Entity)(Object)this, previousFluidOnEyes)); + EntityFluidEvents.EXITED.invoker().onExited((Entity)(Object)this, previousFluidOnEyes); } previousFluidOnEyes = null; } @@ -59,7 +56,7 @@ public class EntityMixin extends net.minecraftforge.common.capabilities.Capabili // We are now submerged in a fluid that doesn't match the previous one. if (currentFluid != null) { - MinecraftForge.EVENT_BUS.post(new EntityFluidEvent.Entered((Entity)(Object)this, currentFluid)); + EntityFluidEvents.ENTERED.invoker().onEntered((Entity)(Object)this, currentFluid); } } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java deleted file mode 100644 index 2dbc247..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/mixin/ForgeEventFactoryMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.anthonyhilyard.iceberg.mixin; - -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.fml.loading.FMLEnvironment; -import net.minecraftforge.fmllegacy.network.PacketDistributor; - -import com.anthonyhilyard.iceberg.network.IcebergNetworkProtocol; -import com.anthonyhilyard.iceberg.network.NewItemPickupEventPacket; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(ForgeEventFactory.class) -public class ForgeEventFactoryMixin -{ - @Inject(method = { "onItemPickup(Lnet/minecraft/world/entity/item/ItemEntity;Lnet/minecraft/world/entity/player/Player;)I" }, - at = { @At("HEAD") }, remap = false) - private static void onItemPickup(ItemEntity entityItem, Player player, CallbackInfoReturnable<Integer> info) - { - if (player instanceof ServerPlayer && FMLEnvironment.dist.isDedicatedServer()) - { - IcebergNetworkProtocol.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer)player), new NewItemPickupEventPacket(player.getUUID(), entityItem.getItem())); - } - } -} diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ItemEntityMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ItemEntityMixin.java new file mode 100644 index 0000000..05540c9 --- /dev/null +++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ItemEntityMixin.java @@ -0,0 +1,28 @@ +package com.anthonyhilyard.iceberg.mixin; + +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.server.level.ServerPlayer; + +import com.anthonyhilyard.iceberg.network.IcebergNetworkProtocol; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemEntity.class) +public class ItemEntityMixin +{ + @Inject(method = { "playerTouch" }, + at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;take(Lnet/minecraft/world/entity/Entity;I)V", ordinal = 0, shift = Shift.AFTER)) + private void onPlayerTouch(Player player, CallbackInfo info) + { + if (player instanceof ServerPlayer) + { + IcebergNetworkProtocol.sendItemPickupEvent((ServerPlayer)player, ((ItemEntity)(Object)this).getItem()); + } + } +} diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java index ad52b94..568036e 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java +++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/PlayerAdvancementsMixin.java @@ -1,6 +1,6 @@ package com.anthonyhilyard.iceberg.mixin; -import com.anthonyhilyard.iceberg.events.CriterionEvent; +import com.anthonyhilyard.iceberg.events.CriterionCallback; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -12,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import net.minecraft.advancements.Advancement; import net.minecraft.server.PlayerAdvancements; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.common.MinecraftForge; @Mixin(PlayerAdvancements.class) public class PlayerAdvancementsMixin @@ -25,7 +24,7 @@ public class PlayerAdvancementsMixin { if (success) { - MinecraftForge.EVENT_BUS.post(new CriterionEvent(player, advancement, criterionKey)); + CriterionCallback.EVENT.invoker().awardCriterion(player, advancement, criterionKey); } } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java b/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java index bbd2d6b..225499f 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java +++ b/src/main/java/com/anthonyhilyard/iceberg/mixin/ScreenMixin.java @@ -2,7 +2,7 @@ package com.anthonyhilyard.iceberg.mixin; import java.util.List; -import com.anthonyhilyard.iceberg.util.StringRecomposer; +import com.anthonyhilyard.iceberg.events.RenderTooltipEvents; import com.google.common.collect.Lists; import com.mojang.blaze3d.vertex.PoseStack; @@ -19,11 +19,10 @@ import net.minecraft.client.gui.Font; import net.minecraft.client.gui.components.events.AbstractContainerEventHandler; import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.client.ForgeHooksClient; -import net.minecraftforge.client.event.RenderTooltipEvent; -import net.minecraftforge.common.MinecraftForge; @Mixin(Screen.class) public class ScreenMixin extends AbstractContainerEventHandler @@ -31,25 +30,23 @@ public class ScreenMixin extends AbstractContainerEventHandler @Shadow protected Font font = null; - @Shadow(remap = false) - private Font tooltipFont = null; - - @Shadow(remap = false) - private ItemStack tooltipStack = ItemStack.EMPTY; - @Final @Shadow private final List<GuiEventListener> children = Lists.newArrayList(); - @SuppressWarnings("removal") + @SuppressWarnings("unchecked") @Inject(method = "renderTooltipInternal", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/ItemRenderer;blitOffset:F", ordinal = 2, shift = Shift.AFTER), locals = LocalCapture.CAPTURE_FAILEXCEPTION) - private void renderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, CallbackInfo info, RenderTooltipEvent.Pre pre, int tooltipWidth, int tooltipHeight, int postX, int postY) + private void renderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> components, int x, int y, CallbackInfo info, int tooltipWidth, int tooltipHeight, int postX, int postY) { if (!components.isEmpty()) { - MinecraftForge.EVENT_BUS.post(new RenderTooltipEvent.PostText(tooltipStack, StringRecomposer.recompose(components), poseStack, postX, postY, ForgeHooksClient.getTooltipFont(tooltipFont, tooltipStack, font), tooltipWidth, tooltipHeight)); + if ((Screen)(Object)this instanceof AbstractContainerScreen) + { + ItemStack tooltipStack = ((AbstractContainerScreen<AbstractContainerMenu>)(Object)this).hoveredSlot.getItem(); + RenderTooltipEvents.POST.invoker().onPost(tooltipStack, components, poseStack, x, y, font, tooltipWidth, tooltipHeight, false); + } } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java b/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java index 4b5db06..232ed7b 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java +++ b/src/main/java/com/anthonyhilyard/iceberg/network/IcebergNetworkProtocol.java @@ -2,29 +2,49 @@ package com.anthonyhilyard.iceberg.network; import com.anthonyhilyard.iceberg.Loader; +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs; +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; +import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.fmllegacy.network.NetworkRegistry; -import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +// import net.minecraftforge.fmllegacy.network.NetworkRegistry; +// import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; -public class IcebergNetworkProtocol +public final class IcebergNetworkProtocol { - private static final String NETWORK_PROTOCOL_VERSION = "1"; + //private static final String NETWORK_PROTOCOL_VERSION = "1"; + private static final ResourceLocation IDENTIFIER = new ResourceLocation(Loader.MODID, "main"); + + // public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( + // new ResourceLocation(Loader.MODID, "main"), () -> NETWORK_PROTOCOL_VERSION, + // NETWORK_PROTOCOL_VERSION::equals, NETWORK_PROTOCOL_VERSION::equals + // ); - public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( - new ResourceLocation(Loader.MODID, "main"), () -> NETWORK_PROTOCOL_VERSION, - NETWORK_PROTOCOL_VERSION::equals, NETWORK_PROTOCOL_VERSION::equals - ); + // public static final void register() + // { + // int messageID = 0; - public static final void register() + // CHANNEL.registerMessage( + // messageID++, + // NewItemPickupEventPacket.class, + // NewItemPickupEventPacket::encode, + // NewItemPickupEventPacket::decode, + // NewItemPickupEventPacket::handle + // ); + // } + + public static void sendItemPickupEvent(ServerPlayer player, ItemStack item) { - int messageID = 0; + if (!player.level.isClientSide) + { + // Build buffer. + FriendlyByteBuf buffer = PacketByteBufs.create(); + buffer.writeUUID(player.getUUID()); + buffer.writeItem(item); - CHANNEL.registerMessage( - messageID++, - NewItemPickupEventPacket.class, - NewItemPickupEventPacket::encode, - NewItemPickupEventPacket::decode, - NewItemPickupEventPacket::handle - ); + // Send packet. + ServerPlayNetworking.send(player, IDENTIFIER, buffer); + } } } diff --git a/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java b/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java deleted file mode 100644 index b99a36d..0000000 --- a/src/main/java/com/anthonyhilyard/iceberg/network/NewItemPickupEventPacket.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.anthonyhilyard.iceberg.network; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fmllegacy.network.NetworkEvent; - -import java.util.UUID; -import java.util.function.Supplier; - -import com.anthonyhilyard.iceberg.events.NewItemPickupEvent; - - -public final class NewItemPickupEventPacket -{ - private final UUID playerUUID; - private final ItemStack item; - - public NewItemPickupEventPacket(final UUID playerUUID, final ItemStack item) - { - this.playerUUID = playerUUID; - this.item = item; - } - - public static void encode(final NewItemPickupEventPacket msg, final FriendlyByteBuf packetBuffer) - { - packetBuffer.writeUUID(msg.playerUUID); - packetBuffer.writeItem(msg.item); - } - - public static NewItemPickupEventPacket decode(final FriendlyByteBuf packetBuffer) - { - return new NewItemPickupEventPacket(packetBuffer.readUUID(), packetBuffer.readItem()); - } - - public static void handle(final NewItemPickupEventPacket msg, final Supplier<NetworkEvent.Context> contextSupplier) - { - final NetworkEvent.Context context = contextSupplier.get(); - context.enqueueWork(() -> { - MinecraftForge.EVENT_BUS.post(new NewItemPickupEvent(msg.playerUUID, msg.item)); - }); - context.setPacketHandled(true); - } - -}
\ No newline at end of file diff --git a/src/main/java/com/anthonyhilyard/iceberg/registry/AutoRegistry.java b/src/main/java/com/anthonyhilyard/iceberg/registry/AutoRegistry.java index 59803ae..c6dbcc3 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/registry/AutoRegistry.java +++ b/src/main/java/com/anthonyhilyard/iceberg/registry/AutoRegistry.java @@ -1,178 +1,195 @@ -package com.anthonyhilyard.iceberg.registry; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.function.Consumer; -import java.util.function.Supplier; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.attributes.AttributeSupplier; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.sounds.SoundEvent; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.IForgeRegistry; -import net.minecraftforge.registries.IForgeRegistryEntry; -import net.minecraftforge.event.entity.EntityAttributeCreationEvent; - -/** - * Extend this class to have all registerable fields be automatically registered in Forge. Easy. (Just no renderers.) - */ -public abstract class AutoRegistry -{ - protected static String MODID = null; - - private static boolean entityCreationRegistered = false; - - private static Map<EntityType<?>, Supplier<AttributeSupplier.Builder>> entityAttributes = new HashMap<>(); - - private static Map<String, EntityType<? extends Entity>> registeredEntityTypes = new HashMap<>(); - - public static void init(String ModID) - { - MODID = ModID; - } - - @SuppressWarnings("unchecked") - protected AutoRegistry() - { - try - { - // Iterate through every built-in Forge registry... - for (Field field : ForgeRegistries.class.getDeclaredFields()) - { - Object fieldObj = field.get(null); - if (fieldObj instanceof IForgeRegistry) - { - // Grab the registry's supertype and add a generic listener for registry events. - Class<IForgeRegistryEntry<?>> clazz = (Class<IForgeRegistryEntry<?>>)((IForgeRegistry<?>)fieldObj).getRegistrySuperType(); - FMLJavaModLoadingContext.get().getModEventBus().addGenericListener(clazz, (Consumer<RegistryEvent.Register<? extends IForgeRegistryEntry<?>>>)(e) -> registerAllOfType(clazz, e) ); - } - } - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - - public static boolean isEntityTypeRegistered(String name) - { - return registeredEntityTypes.containsKey(name); - } - - @SuppressWarnings("unchecked") - public static <T extends Entity> EntityType<T> getEntityType(String name) - { - return (EntityType<T>) registeredEntityTypes.getOrDefault(name, null); - } - - @SuppressWarnings("unchecked") - private final <T extends IForgeRegistryEntry<T>> void registerAllOfType(Class<IForgeRegistryEntry<?>> type, RegistryEvent.Register<T> event) - { - try - { - // Loop through all fields we've declared and register them. - for (Field field : this.getClass().getDeclaredFields()) - { - // Grab the field and check if it is a Forge registry-compatible type. - Object obj = field.get(this); - if (type.isAssignableFrom(obj.getClass())) - { - // If this is an entity type field and we haven't already registered for the entity creation event, do so now. - if (obj instanceof EntityType && !entityCreationRegistered) - { - FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onEntityCreation); - entityCreationRegistered = true; - } - - // If this field has a registry name, register it now. - T entry = (T)obj; - if (entry != null && entry.getRegistryName() != null) - { - event.getRegistry().register(entry); - } - } - } - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - - protected static <T extends Entity> EntityType<T> registerEntity(String name, EntityType.Builder<T> builder) - { - return registerEntity(name, builder, (Supplier<AttributeSupplier.Builder>)null); - } - - @SuppressWarnings("unchecked") - protected static <T extends Entity> EntityType<T> registerEntity(String name, EntityType.Builder<T> builder, Supplier<AttributeSupplier.Builder> attributes) - { - if (MODID == null) - { - throw new RuntimeException("AutoRegistry was not initialized with mod id!"); - } - - // Build the entity type. - ResourceLocation resourceLocation = new ResourceLocation(MODID, name); - EntityType<T> entityType = (EntityType<T>) builder.build(name).setRegistryName(resourceLocation); - - // Add this entity type to the registered hashmap. - registeredEntityTypes.put(name, entityType); - - // Store mob attributes if provided. These will be added in the attribute creation event below. - if (attributes != null) - { - entityAttributes.put(entityType, attributes); - } - - return entityType; - } - - protected static SoundEvent registerSound(String name) - { - if (MODID == null) - { - throw new RuntimeException("AutoRegistry was not initialized with mod id!"); - } - - ResourceLocation resourceLocation = new ResourceLocation(MODID, name); - return new SoundEvent(resourceLocation).setRegistryName(resourceLocation); - } - - @SuppressWarnings("unchecked") - private void onEntityCreation(EntityAttributeCreationEvent event) - { - for (Field field : this.getClass().getDeclaredFields()) - { - try - { - // Grab the field and check if it is a Forge registry-compatible type. - Object obj = field.get(this); - if (EntityType.class.isAssignableFrom(obj.getClass()) && entityAttributes.containsKey(obj)) - { - EntityType<? extends LivingEntity> entityType = (EntityType<? extends LivingEntity>) obj; - if (entityType != null) - { - event.put(entityType, entityAttributes.get(obj).get().build()); - } - } - } - catch (ClassCastException e) - { - // The class cast exception likely just means that we tried to convert an EntityType with generic type - // parameter of something other than a LivingEntity subclass. This is fine, so continue. - continue; - } - catch (IllegalAccessException e) - { - throw new RuntimeException(e); - } - } - } -}
\ No newline at end of file +// package com.anthonyhilyard.iceberg.registry; + +// import java.lang.reflect.Field; +// import java.lang.reflect.ParameterizedType; +// import java.lang.reflect.TypeVariable; +// import java.util.HashMap; +// import java.util.Map; +// import java.util.function.Consumer; +// import java.util.function.Supplier; + +// import com.anthonyhilyard.iceberg.Loader; + +// import net.minecraft.world.entity.Entity; +// import net.minecraft.world.entity.EntityType; +// import net.minecraft.world.entity.LivingEntity; +// import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +// import net.minecraft.world.item.Item; +// import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback; +// import net.minecraft.core.Registry; +// import net.minecraft.resources.ResourceLocation; +// import net.minecraft.sounds.SoundEvent; +// import net.minecraftforge.event.RegistryEvent; +// import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +// import net.minecraftforge.registries.ForgeRegistries; +// import net.minecraftforge.registries.IForgeRegistry; +// import net.minecraftforge.registries.IForgeRegistryEntry; +// import net.minecraftforge.event.entity.EntityAttributeCreationEvent; + +// /** +// * Extend this class to have all registerable fields be automatically registered in Forge. Easy. (Just no renderers.) +// */ +// public abstract class AutoRegistry +// { +// protected static String MODID = null; + +// private static boolean entityCreationRegistered = false; + +// private static Map<EntityType<?>, Supplier<AttributeSupplier.Builder>> entityAttributes = new HashMap<>(); + +// private static Map<String, EntityType<? extends Entity>> registeredEntityTypes = new HashMap<>(); + +// private static Map<Class<?>, Registry<?>> registryMap = new HashMap<>(); + +// public static void init(String ModID) +// { +// MODID = ModID; +// } + +// @SuppressWarnings("unchecked") +// protected AutoRegistry() +// { +// try +// { +// // Iterate through every built-in registry... +// for (Field field : Registry.class.getDeclaredFields()) +// { +// Object fieldObj = field.get(null); +// if (fieldObj instanceof Registry) +// { +// // Grab the registry's supertype and add a generic listener for registry events. +// Class<?> clazz = (Class<?>)((ParameterizedType)fieldObj.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; +// registryMap.put(clazz, (Registry<?>)fieldObj); +// Loader.LOGGER.info("Adding to registry map: {}, {}", clazz.getName(), fieldObj.getClass().getName()); +// } +// } +// } +// catch (Exception e) +// { +// throw new RuntimeException(e); +// } +// } + +// public static boolean isEntityTypeRegistered(String name) +// { +// return registeredEntityTypes.containsKey(name); +// } + +// @SuppressWarnings("unchecked") +// public static <T extends Entity> EntityType<T> getEntityType(String name) +// { +// return (EntityType<T>) registeredEntityTypes.getOrDefault(name, null); +// } + +// private final class __<T> { private __() {} } + +// @SuppressWarnings("unchecked") +// private final <T> void registerAllOfType(Class<Registry<T>> type) +// { +// try +// { +// // Loop through all fields we've declared and register them. +// for (Field field : this.getClass().getDeclaredFields()) +// { +// // Grab the field and check if it is a Forge registry-compatible type. +// Object obj = field.get(this); +// if (type.isAssignableFrom(obj.getClass())) +// { +// // If this is an entity type field and we haven't already registered for the entity creation event, do so now. +// if (obj instanceof EntityType && !entityCreationRegistered) +// { +// //FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onEntityCreation); +// entityCreationRegistered = true; +// } + +// // If this field has a registry name, register it now. +// T entry = (T)obj; +// if (entry != null) +// { +// Class<T> clazz = (Class<T>) new __<T>().getClass().getTypeParameters()[0].getClass(); +// Registry<? super T> registry = (Registry<? super T>) registryMap.get(clazz); +// if (registry != null) +// { +// Registry.register(registry, "", entry); +// } +// } +// } +// } +// } +// catch (Exception e) +// { +// throw new RuntimeException(e); +// } +// } + +// protected static <T extends Entity> EntityType<T> registerEntity(String name, EntityType.Builder<T> builder) +// { +// return registerEntity(name, builder, (Supplier<AttributeSupplier.Builder>)null); +// } + +// @SuppressWarnings("unchecked") +// protected static <T extends Entity> EntityType<T> registerEntity(String name, EntityType.Builder<T> builder, Supplier<AttributeSupplier.Builder> attributes) +// { +// if (MODID == null) +// { +// throw new RuntimeException("AutoRegistry was not initialized with mod id!"); +// } + +// // Build the entity type. +// ResourceLocation resourceLocation = new ResourceLocation(MODID, name); +// EntityType<T> entityType = (EntityType<T>) builder.build(name).setRegistryName(resourceLocation); + +// // Add this entity type to the registered hashmap. +// registeredEntityTypes.put(name, entityType); + +// // Store mob attributes if provided. These will be added in the attribute creation event below. +// if (attributes != null) +// { +// entityAttributes.put(entityType, attributes); +// } + +// return entityType; +// } + +// protected static SoundEvent registerSound(String name) +// { +// if (MODID == null) +// { +// throw new RuntimeException("AutoRegistry was not initialized with mod id!"); +// } + +// ResourceLocation resourceLocation = new ResourceLocation(MODID, name); +// return new SoundEvent(resourceLocation).setRegistryName(resourceLocation); +// } + +// @SuppressWarnings("unchecked") +// private void onEntityCreation(EntityAttributeCreationEvent event) +// { +// for (Field field : this.getClass().getDeclaredFields()) +// { +// try +// { +// // Grab the field and check if it is a Forge registry-compatible type. +// Object obj = field.get(this); +// if (EntityType.class.isAssignableFrom(obj.getClass()) && entityAttributes.containsKey(obj)) +// { +// EntityType<? extends LivingEntity> entityType = (EntityType<? extends LivingEntity>) obj; +// if (entityType != null) +// { +// event.put(entityType, entityAttributes.get(obj).get().build()); +// } +// } +// } +// catch (ClassCastException e) +// { +// // The class cast exception likely just means that we tried to convert an EntityType with generic type +// // parameter of something other than a LivingEntity subclass. This is fine, so continue. +// continue; +// } +// catch (IllegalAccessException e) +// { +// throw new RuntimeException(e); +// } +// } +// } +// }
\ No newline at end of file diff --git a/src/main/java/com/anthonyhilyard/iceberg/registry/RendererRegistrar.java b/src/main/java/com/anthonyhilyard/iceberg/registry/RendererRegistrar.java index 1b0a053..89d096a 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/registry/RendererRegistrar.java +++ b/src/main/java/com/anthonyhilyard/iceberg/registry/RendererRegistrar.java @@ -1,36 +1,36 @@ -package com.anthonyhilyard.iceberg.registry; +// package com.anthonyhilyard.iceberg.registry; -import java.util.HashMap; -import java.util.Map; +// import java.util.HashMap; +// import java.util.Map; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraftforge.client.event.EntityRenderersEvent; +// import net.minecraft.world.entity.Entity; +// import net.minecraft.world.entity.EntityType; +// import net.minecraft.client.renderer.entity.EntityRendererProvider; +// import net.minecraftforge.client.event.EntityRenderersEvent; -public abstract class RendererRegistrar -{ - private static Map<EntityType<? extends Entity>, EntityRendererProvider<?>> entityRenderers = new HashMap<>(); +// public abstract class RendererRegistrar +// { +// private static Map<EntityType<? extends Entity>, EntityRendererProvider<?>> entityRenderers = new HashMap<>(); - protected static <T extends Entity> void registerRenderer(String name, EntityRendererProvider<T> rendererProvider) - { - if (AutoRegistry.isEntityTypeRegistered(name)) - { - // Store this renderer provider. - entityRenderers.put(AutoRegistry.getEntityType(name), rendererProvider); - } - else - { - throw new RuntimeException("Tried to register a renderer for an unregistered entity type! Make sure you register renderers after entities."); - } - } +// protected static <T extends Entity> void registerRenderer(String name, EntityRendererProvider<T> rendererProvider) +// { +// if (AutoRegistry.isEntityTypeRegistered(name)) +// { +// // Store this renderer provider. +// entityRenderers.put(AutoRegistry.getEntityType(name), rendererProvider); +// } +// else +// { +// throw new RuntimeException("Tried to register a renderer for an unregistered entity type! Make sure you register renderers after entities."); +// } +// } - @SuppressWarnings({"unchecked", "unused"}) - private <T extends Entity> void onEntityCreation(EntityRenderersEvent.RegisterRenderers event) - { - for (EntityType<? extends Entity> entityType : entityRenderers.keySet()) - { - event.registerEntityRenderer((EntityType<T>)entityType, (EntityRendererProvider<T>)entityRenderers.get(entityType)); - } - } -} +// @SuppressWarnings({"unchecked", "unused"}) +// private <T extends Entity> void onEntityCreation(EntityRenderersEvent.RegisterRenderers event) +// { +// for (EntityType<? extends Entity> entityType : entityRenderers.keySet()) +// { +// event.registerEntityRenderer((EntityType<T>)entityType, (EntityRendererProvider<T>)entityRenderers.get(entityType)); +// } +// } +// } diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/GuiHelper.java b/src/main/java/com/anthonyhilyard/iceberg/util/GuiHelper.java index b87c057..f9395d3 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/util/GuiHelper.java +++ b/src/main/java/com/anthonyhilyard/iceberg/util/GuiHelper.java @@ -10,6 +10,22 @@ import com.mojang.math.Matrix4f; public class GuiHelper { + public static void drawGradientRect(Matrix4f mat, BufferBuilder bufferBuilder, int left, int top, int right, int bottom, int zLevel, int startColor, int endColor) + { + float startAlpha = (float)(startColor >> 24 & 255) / 255.0F; + float startRed = (float)(startColor >> 16 & 255) / 255.0F; + float startGreen = (float)(startColor >> 8 & 255) / 255.0F; + float startBlue = (float)(startColor & 255) / 255.0F; + float endAlpha = (float)(endColor >> 24 & 255) / 255.0F; + float endRed = (float)(endColor >> 16 & 255) / 255.0F; + float endGreen = (float)(endColor >> 8 & 255) / 255.0F; + float endBlue = (float)(endColor & 255) / 255.0F; + bufferBuilder.vertex(mat, right, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + bufferBuilder.vertex(mat, left, top, zLevel).color(startRed, startGreen, startBlue, startAlpha).endVertex(); + bufferBuilder.vertex(mat, left, bottom, zLevel).color( endRed, endGreen, endBlue, endAlpha).endVertex(); + bufferBuilder.vertex(mat, right, bottom, zLevel).color( endRed, endGreen, endBlue, endAlpha).endVertex(); + } + public static void drawGradientRectHorizontal(Matrix4f mat, int zLevel, int left, int top, int right, int bottom, int startColor, int endColor) { float startAlpha = (float)(startColor >> 24 & 255) / 255.0F; diff --git a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java index fe24e44..4d27f16 100644 --- a/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java +++ b/src/main/java/com/anthonyhilyard/iceberg/util/Tooltips.java @@ -1,39 +1,49 @@ package com.anthonyhilyard.iceberg.util; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; -import javax.annotation.Nonnull; - -import com.anthonyhilyard.iceberg.events.RenderTooltipExtEvent; +import com.anthonyhilyard.iceberg.events.RenderTooltipEvents; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.systems.RenderSystem; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTextTooltip; +import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.Rect2i; -import net.minecraft.client.renderer.MultiBufferSource.BufferSource; +import net.minecraft.client.renderer.entity.ItemRenderer; +import net.minecraft.client.renderer.texture.TextureManager; import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; + +import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import com.mojang.math.Matrix4f; import net.minecraft.network.chat.FormattedText; import net.minecraft.locale.Language; import net.minecraft.network.chat.Style; -import net.minecraftforge.client.event.RenderTooltipEvent; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.fmlclient.gui.GuiUtils; public class Tooltips { + private static ItemRenderer itemRenderer = null; + private static TextureManager textureManager = null; + public static class TooltipInfo { private int tooltipWidth = 0; private int titleLines = 1; private Font font; - private List<? extends FormattedText> lines = new ArrayList<>(); + private List<ClientTooltipComponent> lines = new ArrayList<>(); - public TooltipInfo(List<? extends FormattedText> lines, Font font) + public TooltipInfo(List<ClientTooltipComponent> lines, Font font) { this.lines = lines; this.font = font; @@ -42,16 +52,16 @@ public class Tooltips public int getTooltipWidth() { return tooltipWidth; } public int getTitleLines() { return titleLines; } public Font getFont() { return font; } - public List<? extends FormattedText> getLines() { return lines; } + public List<ClientTooltipComponent> getLines() { return lines; } public void setFont(Font font) { this.font = font; } public int getMaxLineWidth() { int textWidth = 0; - for (FormattedText textLine : lines) + for (ClientTooltipComponent component : lines) { - int textLineWidth = font.width(textLine); + int textLineWidth = component.getWidth(font); if (textLineWidth > textWidth) { textWidth = textLineWidth; @@ -60,22 +70,44 @@ public class Tooltips return textWidth; } + private List<ClientTextTooltip> splitComponent(ClientTextTooltip component, int maxWidth, Font font) + { + FormattedText text = FormattedText.composite(StringRecomposer.recompose(Arrays.asList(component))); + List<FormattedText> wrappedLines = font.getSplitter().splitLines(text, maxWidth, Style.EMPTY); + List<ClientTextTooltip> result = new ArrayList<>(); + + for (FormattedText wrappedLine : wrappedLines) + { + result.add(new ClientTextTooltip(Language.getInstance().getVisualOrder(wrappedLine))); + } + + return result; + } + public void wrap(int maxWidth) { tooltipWidth = 0; - List<FormattedText> wrappedLines = new ArrayList<>(); + List<ClientTooltipComponent> wrappedLines = new ArrayList<>(); for (int i = 0; i < lines.size(); i++) { - FormattedText textLine = lines.get(i); - List<FormattedText> wrappedLine = font.getSplitter().splitLines(textLine, maxWidth, Style.EMPTY); + ClientTooltipComponent textLine = lines.get(i); + + // Only wrap text lines. + // TODO: What to do with images that are too big? + if (!(textLine instanceof ClientTextTooltip)) + { + continue; + } + + List<ClientTextTooltip> wrappedLine = splitComponent((ClientTextTooltip)textLine, maxWidth, font); if (i == 0) { titleLines = wrappedLine.size(); } - for (FormattedText line : wrappedLine) + for (ClientTooltipComponent line : wrappedLine) { - int lineWidth = font.width(line); + int lineWidth = line.getWidth(font); if (lineWidth > tooltipWidth) { tooltipWidth = lineWidth; @@ -88,19 +120,25 @@ public class Tooltips } } - public static void renderItemTooltip(@Nonnull final ItemStack stack, PoseStack mStack, TooltipInfo info, + public static void init(Minecraft minecraft) + { + itemRenderer = minecraft.getItemRenderer(); + textureManager = minecraft.getTextureManager(); + } + + public static void renderItemTooltip(final ItemStack stack, PoseStack mStack, TooltipInfo info, Rect2i rect, int screenWidth, int screenHeight, int backgroundColor, int borderColorStart, int borderColorEnd) { renderItemTooltip(stack, mStack, info, rect, screenWidth, screenHeight, backgroundColor, borderColorStart, borderColorEnd, false); } - @SuppressWarnings("removal") - public static void renderItemTooltip(@Nonnull final ItemStack stack, PoseStack mStack, TooltipInfo info, + //private void renderTooltipInternal(PoseStack poseStack, List<ClientTooltipComponent> list, int x, int y) + public static void renderItemTooltip(final ItemStack stack, PoseStack poseStack, TooltipInfo info, Rect2i rect, int screenWidth, int screenHeight, int backgroundColor, int borderColorStart, int borderColorEnd, boolean comparison) { - if (info.getLines().isEmpty()) + if (info.lines.isEmpty()) { return; } @@ -109,33 +147,24 @@ public class Tooltips int rectY = rect.getY() + 18; int maxTextWidth = rect.getWidth() - 8; - RenderTooltipExtEvent.Pre event = new RenderTooltipExtEvent.Pre(stack, info.getLines(), mStack, rectX, rectY, screenWidth, screenHeight, maxTextWidth, info.getFont(), comparison); - if (MinecraftForge.EVENT_BUS.post(event)) + InteractionResult result = RenderTooltipEvents.PRE.invoker().onPre(stack, info.getLines(), poseStack, rectX, rectY, screenWidth, screenHeight, maxTextWidth, info.getFont(), comparison); + if (result != InteractionResult.PASS) { return; } - rectX = event.getX(); - rectY = event.getY(); - screenWidth = event.getScreenWidth(); - screenHeight = event.getScreenHeight(); - maxTextWidth = event.getMaxWidth(); - info.setFont(event.getFontRenderer()); - - RenderSystem.disableDepthTest(); - int tooltipTextWidth = info.getMaxLineWidth(); - boolean needsWrap = false; int tooltipX = rectX + 12; + int tooltipTextWidth = info.getMaxLineWidth(); if (tooltipX + tooltipTextWidth + 4 > screenWidth) { tooltipX = rectX - 16 - tooltipTextWidth; - if (tooltipX < 4) // if the tooltip doesn't fit on the screen + if (tooltipX < 4) { if (rectX > screenWidth / 2) { - tooltipTextWidth = rectX - 12 - 8; + tooltipTextWidth = rectX - 20; } else { @@ -179,59 +208,67 @@ public class Tooltips tooltipY = screenHeight - tooltipHeight - 4; } - final int zLevel = 400; - RenderTooltipExtEvent.Color colorEvent = new RenderTooltipExtEvent.Color(stack, info.getLines(), mStack, tooltipX, tooltipY, info.getFont(), backgroundColor, borderColorStart, borderColorEnd, comparison); - MinecraftForge.EVENT_BUS.post(colorEvent); - backgroundColor = colorEvent.getBackground(); - borderColorStart = colorEvent.getBorderStart(); - borderColorEnd = colorEvent.getBorderEnd(); - - mStack.pushPose(); - Matrix4f mat = mStack.last().pose(); - - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, backgroundColor, backgroundColor); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, backgroundColor, backgroundColor); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, backgroundColor, backgroundColor); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, borderColorStart, borderColorEnd); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, borderColorStart, borderColorStart); - GuiUtils.drawGradientRect(mat, zLevel, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, borderColorEnd, borderColorEnd); - - MinecraftForge.EVENT_BUS.post(new RenderTooltipEvent.PostBackground(stack, info.getLines(), mStack, tooltipX, tooltipY, info.getFont(), tooltipTextWidth, tooltipHeight)); - - BufferSource renderType = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); - mStack.translate(0.0D, 0.0D, zLevel); - - int tooltipTop = tooltipY; - - for (int lineNumber = 0; lineNumber < info.getLines().size(); ++lineNumber) + poseStack.pushPose(); + int bgColor = 0xF0100010; + int borderStart = 0x505000FF; + int borderEnd = 0x5028007F; + + RenderTooltipEvents.COLOR.invoker().onColor(stack, info.lines, poseStack, tooltipX, tooltipY, info.getFont(), bgColor, borderStart, borderEnd, comparison); + + float f = itemRenderer.blitOffset; + itemRenderer.blitOffset = 400.0F; + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferBuilder = tesselator.getBuilder(); + RenderSystem.setShader(GameRenderer::getPositionColorShader); + bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR); + Matrix4f mat = poseStack.last().pose(); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY - 4, tooltipX + tooltipTextWidth + 3, tooltipY - 3, 400, bgColor, bgColor); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY + tooltipHeight + 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 4, 400, bgColor, bgColor); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, 400, bgColor, bgColor); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 4, tooltipY - 3, tooltipX - 3, tooltipY + tooltipHeight + 3, 400, bgColor, bgColor); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX + tooltipTextWidth + 3, tooltipY - 3, tooltipX + tooltipTextWidth + 4, tooltipY + tooltipHeight + 3, 400, bgColor, bgColor); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY - 3 + 1, tooltipX - 3 + 1, tooltipY + tooltipHeight + 3 - 1, 400, borderStart, borderEnd); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX + tooltipTextWidth + 2, tooltipY - 3 + 1, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3 - 1, 400, borderStart, borderEnd); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY - 3, tooltipX + tooltipTextWidth + 3, tooltipY - 3 + 1, 400, borderStart, borderStart); + GuiHelper.drawGradientRect(mat, bufferBuilder, tooltipX - 3, tooltipY + tooltipHeight + 2, tooltipX + tooltipTextWidth + 3, tooltipY + tooltipHeight + 3, 400, borderEnd, borderEnd); + RenderSystem.enableDepthTest(); + RenderSystem.disableTexture(); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + bufferBuilder.end(); + BufferUploader.end(bufferBuilder); + RenderSystem.disableBlend(); + RenderSystem.enableTexture(); + + MultiBufferSource.BufferSource bufferSource = MultiBufferSource.immediate(Tesselator.getInstance().getBuilder()); + poseStack.translate(0.0D, 0.0D, 400.0D); + int v = tooltipY; + + ClientTooltipComponent clientTooltipComponent3; + for (int i = 0; i < info.getLines().size(); ++i) { - FormattedText line = info.getLines().get(lineNumber); - if (line != null) - { - info.getFont().drawInBatch(Language.getInstance().getVisualOrder(line), (float)tooltipX, (float)tooltipY, -1, true, mat, renderType, false, 0, 15728880); - } + clientTooltipComponent3 = (ClientTooltipComponent)info.getLines().get(i); + clientTooltipComponent3.renderText(info.getFont(), tooltipX, v, mat, bufferSource); + v += clientTooltipComponent3.getHeight() + (i == 0 ? 2 : 0); + } - if (lineNumber + 1 == info.getTitleLines()) - { - tooltipY += 2; - } + bufferSource.endBatch(); + poseStack.popPose(); + v = tooltipY; - tooltipY += 10; + for (int i = 0; i < info.getLines().size(); ++i) + { + clientTooltipComponent3 = (ClientTooltipComponent)info.getLines().get(i); + clientTooltipComponent3.renderImage(info.getFont(), tooltipX, v, poseStack, itemRenderer, 400, textureManager); + v += clientTooltipComponent3.getHeight() + (i == 0 ? 2 : 0); } - renderType.endBatch(); - mStack.popPose(); - - MinecraftForge.EVENT_BUS.post(new RenderTooltipExtEvent.PostText(stack, info.getLines(), mStack, tooltipX, tooltipTop, info.getFont(), tooltipTextWidth, tooltipHeight, comparison)); + itemRenderer.blitOffset = f; - RenderSystem.enableDepthTest(); + RenderTooltipEvents.POST.invoker().onPost(stack, info.getLines(), poseStack, tooltipX, tooltipY, info.getFont(), tooltipTextWidth, tooltipHeight, comparison); } - @SuppressWarnings("removal") - public static Rect2i calculateRect(final ItemStack stack, PoseStack mStack, List<? extends FormattedText> textLines, int mouseX, int mouseY, + public static Rect2i calculateRect(final ItemStack stack, PoseStack mStack, List<ClientTooltipComponent> textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth, Font font) { Rect2i rect = new Rect2i(0, 0, 0, 0); @@ -240,25 +277,11 @@ public class Tooltips return rect; } - // Generate a tooltip event even though we aren't rendering anything in case the event handlers are modifying the input values. - RenderTooltipEvent.Pre event = new RenderTooltipEvent.Pre(stack, textLines, mStack, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, font); - if (MinecraftForge.EVENT_BUS.post(event)) - { - return rect; - } - - mouseX = event.getX(); - mouseY = event.getY(); - screenWidth = event.getScreenWidth(); - screenHeight = event.getScreenHeight(); - maxTextWidth = event.getMaxWidth(); - font = event.getFontRenderer(); - int tooltipTextWidth = 0; - for (FormattedText textLine : textLines) + for (ClientTooltipComponent textLine : textLines) { - int textLineWidth = font.width(textLine); + int textLineWidth = textLine.getWidth(font); if (textLineWidth > tooltipTextWidth) { tooltipTextWidth = textLineWidth; @@ -294,29 +317,11 @@ public class Tooltips if (needsWrap) { - int wrappedTooltipWidth = 0; - List<FormattedText> wrappedTextLines = new ArrayList<>(); - for (int i = 0; i < textLines.size(); i++) - { - FormattedText textLine = textLines.get(i); - List<FormattedText> wrappedLine = font.getSplitter().splitLines(textLine, tooltipTextWidth, Style.EMPTY); - if (i == 0) - { - titleLinesCount = wrappedLine.size(); - } - - for (FormattedText line : wrappedLine) - { - int lineWidth = font.width(line); - if (lineWidth > wrappedTooltipWidth) - { - wrappedTooltipWidth = lineWidth; - } - wrappedTextLines.add(line); - } - } - tooltipTextWidth = wrappedTooltipWidth; - textLines = wrappedTextLines; + TooltipInfo info = new TooltipInfo(textLines, font); + info.wrap(tooltipTextWidth); + + tooltipTextWidth = info.tooltipWidth; + textLines = info.lines; if (mouseX > screenWidth / 2) { diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg deleted file mode 100644 index b3edbd7..0000000 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ /dev/null @@ -1 +0,0 @@ -public net.minecraft.client.gui.screens.inventory.tooltip.ClientTextTooltip f_169936_ # text
\ No newline at end of file diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml deleted file mode 100644 index 7623938..0000000 --- a/src/main/resources/META-INF/mods.toml +++ /dev/null @@ -1,27 +0,0 @@ -modLoader="javafml" -loaderVersion="[37,)" -license="CC BY-NC-ND 4.0" - -[[mods]] -modId="iceberg" -version="${file.jarVersion}" -displayName="Iceberg" -displayURL="https://anthonyhilyard.com/" -updateJSONURL="https://mc-curse-update-checker.herokuapp.com/520110" -logoFile="icon.png" -authors="Grend" -description="A library containing events, helpers, and utilities to make modding easier." - -[[dependencies.iceberg]] - modId="forge" - mandatory=true - versionRange="[37,)" - ordering="NONE" - side="BOTH" - -[[dependencies.iceberg]] - modId="minecraft" - mandatory=true - versionRange="[1.17.1]" - ordering="NONE" - side="BOTH"
\ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..0920998 --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "id": "iceberg", + "version": "${version}", + + "name": "Iceberg", + "description": "A library containing events, helpers, and utilities to make modding easier.", + "authors": [ "Grend" ], + "contact": { + "homepage": "https://anthonyhilyard.com/", + "sources": "https://github.com/AHilyard/Iceberg", + "discord": "https://discord.gg/S5NQjbXPnb" + }, + + "license": "CC BY-NC-ND 4.0", + "icon": "icon.png", + + "environment": "*", + + "entrypoints": { }, + "accessWidener": "iceberg.accesswidener", + + "depends": { + "fabricloader": ">=0.11.3", + "fabric": "*", + "minecraft": "1.17.x", + "java": ">=16" + }, + "custom": { + "modupdater": { + "strategy": "curseforge", + "projectID": 539382, + "strict": false + }, + "modmenu": { + "links": { + "modmenu.discord": "https://discord.gg/S5NQjbXPnb" + } + } + } +} diff --git a/src/main/resources/iceberg.accesswidener b/src/main/resources/iceberg.accesswidener new file mode 100644 index 0000000..144309a --- /dev/null +++ b/src/main/resources/iceberg.accesswidener @@ -0,0 +1,3 @@ +accessWidener v1 named +accessible field net/minecraft/client/gui/screens/inventory/tooltip/ClientTextTooltip text Lnet/minecraft/util/FormattedCharSequence; +accessible field net/minecraft/client/gui/screens/inventory/AbstractContainerScreen hoveredSlot Lnet/minecraft/world/inventory/Slot;
\ No newline at end of file diff --git a/src/main/resources/iceberg.mixins.json b/src/main/resources/iceberg.mixins.json index d81f759..82d2362 100644 --- a/src/main/resources/iceberg.mixins.json +++ b/src/main/resources/iceberg.mixins.json @@ -8,7 +8,7 @@ "PlayerAdvancementsMixin" ], "server": [ - "ForgeEventFactoryMixin" + "ItemEntityMixin" ], "client": [ "ScreenMixin" diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta deleted file mode 100644 index 709504e..0000000 --- a/src/main/resources/pack.mcmeta +++ /dev/null @@ -1,7 +0,0 @@ -{ - "pack": { - "description": "iceberg resources", - "pack_format": 6, - "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." - } -} |