├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src ├── demo ├── java │ └── top │ │ └── hookan │ │ └── cocoa │ │ └── demo │ │ ├── Demo.java │ │ ├── block │ │ ├── BlockDemo.java │ │ └── DemoBlocks.java │ │ ├── core │ │ ├── Container.java │ │ ├── Core.java │ │ └── Hooks.java │ │ └── proxy │ │ ├── ClientProxy.java │ │ └── CommonProxy.java └── resources │ ├── META-INF │ └── MANIFEST.MF │ ├── assets │ └── cocoa_api_demo │ │ ├── blockstates │ │ └── demo.json │ │ ├── models │ │ ├── block │ │ │ └── demo.json │ │ └── item │ │ │ └── demo.json │ │ ├── texture │ │ ├── test.gif │ │ └── test1.gif │ │ ├── textures │ │ └── blocks │ │ │ └── demo.png │ │ └── ttf │ │ └── test.ttc │ └── pack.mcmeta └── main ├── java └── top │ └── hookan │ └── cocoa │ ├── CocoaAPI.java │ ├── core │ ├── CocoaTransformer.java │ ├── CoreContainer.java │ ├── CoreHooks.java │ ├── CorePlugin.java │ └── annotation │ │ └── CocoaHook.java │ ├── gui │ ├── CComponent.java │ ├── CContainer.java │ ├── CContainerManager.java │ ├── CGui.java │ ├── CPanel.java │ ├── CocoaGuiUtils.java │ ├── GifRender.java │ ├── TTFRender.java │ └── event │ │ ├── CComponentEvent.java │ │ └── CocoaGuiEvent.java │ └── registry │ ├── RegistryHandler.java │ └── annotation │ └── CocoaReg.java └── resources ├── META-INF └── MANIFEST.MF ├── mcmod.info └── pack.mcmeta /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | 13 | build 14 | run 15 | out 16 | bin 17 | eclipse 18 | *.ipr 19 | *.iws 20 | *.iml 21 | .gradle 22 | .idea -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 hookan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cocoa API For Minecraft 1.12.2 2 | 3 | Cocoa API是一个基于Forge API的mod,可以帮助modder更方便地开发mod。 4 | 5 | 分为三个部分: 6 | 7 | * 核心(Core) 8 | * 注册(Registry) 9 | * 界面(GUI) 10 | 11 | 目前还属于开发阶段。 12 | 13 | 本项目使用MIT协议开源,在使用时请遵守MIT协议。 -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() { 4 | url = 'http://jcenter.bintray.com/' 5 | } 6 | maven { 7 | name = 'forge' 8 | url = 'http://files.minecraftforge.net/maven' 9 | } 10 | maven { 11 | url = 'http://repository.jboss.org/nexus/content/groups/public' 12 | } 13 | } 14 | dependencies { 15 | classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' 16 | } 17 | } 18 | allprojects { 19 | repositories { 20 | jcenter() { 21 | url = 'http://jcenter.bintray.com/' 22 | } 23 | maven { 24 | url 'http://repository.jboss.org/nexus/content/groups/public' 25 | } 26 | } 27 | } 28 | apply plugin: 'net.minecraftforge.gradle.forge' 29 | 30 | version = System.getenv("BUILD_NUMBER") != null ? mod_version + "." + System.getenv("BUILD_NUMBER") : mod_version 31 | group = "top.hookan.cocoa" 32 | archivesBaseName = "Cocoa" 33 | 34 | sourceCompatibility = targetCompatibility = '1.8' 35 | compileJava { 36 | sourceCompatibility = targetCompatibility = '1.8' 37 | } 38 | 39 | sourceSets { 40 | main { 41 | java { 42 | srcDir 'src/main/java/' 43 | } 44 | resources { 45 | srcDir "src/main/resources/" 46 | } 47 | } 48 | test { 49 | java { 50 | srcDir 'src/demo/java/' 51 | } 52 | resources { 53 | srcDir "src/demo/resources/" 54 | } 55 | } 56 | } 57 | 58 | task deobfJar(type: Jar) { 59 | from sourceSets.main.output 60 | classifier = 'deobf' 61 | manifest { 62 | attributes 'FMLCorePlugin': project.group + '.core.CorePlugin', 63 | 'FMLCorePluginContainsFMLMod': 'true' 64 | } 65 | } 66 | 67 | task testJar(type: Jar) { 68 | from sourceSets.test.output 69 | classifier = 'demo' 70 | manifest { 71 | attributes 'FMLCorePlugin': project.group + '.demo.core.Core', 72 | 'FMLCorePluginContainsFMLMod': 'true' 73 | } 74 | } 75 | 76 | artifacts { 77 | archives deobfJar 78 | archives testJar 79 | } 80 | 81 | idea { 82 | module { 83 | sourceDirs += sourceSets.main.allSource.getSrcDirs() 84 | sourceDirs += sourceSets.test.allSource.getSrcDirs() 85 | } 86 | } 87 | 88 | minecraft { 89 | version = "1.12.2-14.23.4.2705" 90 | runDir = "run" 91 | mappings = "snapshot_20171003" 92 | 93 | replace "@version@", project.version 94 | } 95 | 96 | dependencies { 97 | } 98 | 99 | processResources { 100 | inputs.property "version", project.version 101 | inputs.property "mcversion", project.minecraft.version 102 | from(sourceSets.main.resources.srcDirs) { 103 | include 'mcmod.info' 104 | 105 | expand 'version':project.version, 'mcversion':project.minecraft.version 106 | } 107 | 108 | from(sourceSets.main.resources.srcDirs) { 109 | exclude 'mcmod.info' 110 | } 111 | } 112 | 113 | jar { 114 | manifest { 115 | attributes 'FMLCorePlugin': project.group + '.core.CorePlugin', 116 | 'FMLCorePluginContainsFMLMod': 'true' 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 2 | # This is required to provide enough memory for the Minecraft decompilation process. 3 | org.gradle.jvmargs=-Xmx3G 4 | 5 | mod_version=0.2.0 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCCocoaUI/CocoaAPI/4414aecb9b037d41e976264051bbf708b7986fd0/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Sep 14 12:28:28 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/Demo.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo; 2 | 3 | import net.minecraftforge.fml.common.Mod; 4 | import net.minecraftforge.fml.common.SidedProxy; 5 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 6 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 7 | import top.hookan.cocoa.demo.proxy.CommonProxy; 8 | 9 | @Mod(modid = Demo.MODID, name = Demo.NAME, dependencies = "required-after:cocoa_api;") 10 | public class Demo 11 | { 12 | public static final String MODID = "cocoa_api_demo"; 13 | public static final String NAME = "Cocoa API Demo"; 14 | 15 | @Mod.Instance(MODID) 16 | public static Demo instance; 17 | 18 | @SidedProxy(clientSide = "top.hookan.cocoa.demo.proxy.ClientProxy", 19 | serverSide = "top.hookan.cocoa.demo.proxy.CommonProxy") 20 | public static CommonProxy proxy; 21 | 22 | @Mod.EventHandler 23 | public void preInit(FMLPreInitializationEvent event) 24 | { 25 | proxy.preInit(event); 26 | } 27 | 28 | @Mod.EventHandler 29 | public void init(FMLInitializationEvent event) 30 | { 31 | proxy.init(event); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/block/BlockDemo.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.block; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.block.material.Material; 5 | import net.minecraft.creativetab.CreativeTabs; 6 | 7 | public class BlockDemo extends Block 8 | { 9 | public BlockDemo() 10 | { 11 | super(Material.ROCK); 12 | setUnlocalizedName("demo"); 13 | setCreativeTab(CreativeTabs.FOOD); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/block/DemoBlocks.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.block; 2 | 3 | import net.minecraft.block.Block; 4 | import net.minecraft.creativetab.CreativeTabs; 5 | import top.hookan.cocoa.demo.Demo; 6 | import top.hookan.cocoa.registry.annotation.CocoaReg; 7 | 8 | @CocoaReg(Demo.class) 9 | public class DemoBlocks 10 | { 11 | @CocoaReg.Reg("demo") 12 | @CocoaReg.ModelReg("demo") 13 | @CocoaReg.OreDicReg("demo") 14 | public static Block demoBlock = new BlockDemo().setCreativeTab(CreativeTabs.FOOD); 15 | } -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/core/Container.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.core; 2 | 3 | import com.google.common.eventbus.EventBus; 4 | import net.minecraftforge.fml.common.DummyModContainer; 5 | import net.minecraftforge.fml.common.LoadController; 6 | import net.minecraftforge.fml.common.ModMetadata; 7 | 8 | import java.util.Arrays; 9 | 10 | public class Container extends DummyModContainer 11 | { 12 | public Container() 13 | { 14 | super(new ModMetadata()); 15 | ModMetadata meta = getMetadata(); 16 | meta.modId = "cocoa_api_demo_core"; 17 | meta.name = "Cocoa API Demo Core"; 18 | meta.authorList = Arrays.asList("huangtian_hookan","KevinWalker"); 19 | } 20 | 21 | public boolean registerBus(EventBus bus, LoadController controller) 22 | { 23 | return true; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/core/Core.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.core; 2 | 3 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 4 | 5 | import javax.annotation.Nullable; 6 | import java.util.Map; 7 | 8 | @IFMLLoadingPlugin.MCVersion("1.12.2") 9 | @IFMLLoadingPlugin.Name("cocoa_api_demo_core") 10 | @IFMLLoadingPlugin.DependsOn("cocoa_api_core") 11 | public class Core implements IFMLLoadingPlugin 12 | { 13 | public String[] getASMTransformerClass() 14 | { 15 | return new String[]{"top.hookan.cocoa.demo.core.Hooks"}; 16 | } 17 | 18 | public String getModContainerClass() 19 | { 20 | return "top.hookan.cocoa.demo.core.Container"; 21 | } 22 | 23 | public String getSetupClass() 24 | { 25 | return null; 26 | } 27 | 28 | public void injectData(Map data) 29 | { 30 | 31 | } 32 | 33 | public String getAccessTransformerClass() 34 | { 35 | return null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/core/Hooks.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.core; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.GuiMainMenu; 5 | import net.minecraft.util.text.TextComponentString; 6 | import org.lwjgl.opengl.GL11; 7 | import top.hookan.cocoa.core.CocoaTransformer; 8 | import top.hookan.cocoa.core.annotation.CocoaHook; 9 | import top.hookan.cocoa.demo.proxy.ClientProxy; 10 | 11 | public class Hooks extends CocoaTransformer 12 | { 13 | @CocoaHook(owner = "net.minecraft.client.Minecraft", 14 | mcp = "clickMouse:()V", 15 | notch = "aA:()V", 16 | type = CocoaHook.HookType.END) 17 | public static void testFun1(Minecraft mc) 18 | { 19 | if (mc.player != null) mc.player.sendMessage(new TextComponentString("玩家点击鼠标 END")); 20 | } 21 | 22 | @CocoaHook(owner = "net.minecraft.client.Minecraft", 23 | mcp = "clickMouse:()V", 24 | notch = "aA:()V", 25 | type = CocoaHook.HookType.BEGIN) 26 | public static void testFun2(Minecraft mc) 27 | { 28 | if (mc.player != null) mc.player.sendMessage(new TextComponentString("玩家点击鼠标 BEGIN")); 29 | } 30 | 31 | private static int frame = 0; 32 | private static int frame1 = 0; 33 | 34 | @CocoaHook(owner = "net.minecraft.client.gui.GuiMainMenu", 35 | mcp = "drawScreen:(IIF)V", 36 | notch = "drawScreen:(IIF)V", 37 | type = CocoaHook.HookType.END) 38 | public static void testDraw(GuiMainMenu mainMenu, int mouseX, int mouseY, float partialTicks) 39 | { 40 | 41 | ClientProxy.testTTF.drawString("沉寂大佬欺负我嘤嘤嘤QAQ\u00A7aABCDEFG\u00A7cabcdefg", 0, 0, 0xFFFFFF00); 42 | 43 | GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); 44 | ClientProxy.testGif.doDraw(frame, 0, 20, 64, 64, 0, 0, 1, 1, 1, 1); 45 | frame++; 46 | if (frame >= ClientProxy.testGif.getFrames()) frame = 0; 47 | 48 | GL11.glEnable(GL11.GL_BLEND); 49 | GL11.glEnable(GL11.GL_ALPHA_TEST); 50 | ClientProxy.test1Gif.doDraw(frame1, mainMenu.width - 105 , mainMenu.height/2 - 45 , 105, 120, 0, 0, 105, 120, 105, 120); 51 | GL11.glDisable(GL11.GL_BLEND); 52 | GL11.glDisable(GL11.GL_ALPHA_TEST); 53 | frame1++; 54 | if (frame1 >= ClientProxy.test1Gif.getFrames()) frame1 = 0; 55 | 56 | 57 | 58 | /*GL11.glDisable(GL11.GL_TEXTURE_2D); 59 | 60 | GL11.glColor3f(1.0f, 1.0f, 1.0f); 61 | GL11.glBegin(GL11.GL_QUADS); 62 | GL11.glVertex2f(0.0f, 0.0f); 63 | GL11.glVertex2f(0.0f, 20.0f); 64 | GL11.glVertex2f(20.0f, 20.0f); 65 | GL11.glVertex2f(20.0f, 0.0f); 66 | GL11.glEnd(); 67 | 68 | GL11.glEnable(GL11.GL_TEXTURE_2D);*/ 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/proxy/ClientProxy.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.proxy; 2 | 3 | import net.minecraft.util.ResourceLocation; 4 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 5 | import top.hookan.cocoa.demo.Demo; 6 | import top.hookan.cocoa.gui.CocoaGuiUtils; 7 | import top.hookan.cocoa.gui.GifRender; 8 | import top.hookan.cocoa.gui.TTFRender; 9 | 10 | import java.awt.*; 11 | import java.io.IOException; 12 | 13 | public class ClientProxy extends CommonProxy 14 | { 15 | public static TTFRender testTTF; 16 | public static GifRender testGif; 17 | public static GifRender test1Gif; 18 | 19 | public void init(FMLInitializationEvent event) 20 | { 21 | super.init(event); 22 | try 23 | { 24 | testTTF = CocoaGuiUtils.loadTTF(new ResourceLocation(Demo.MODID, "ttf/test.ttc"), "test"); 25 | testGif = CocoaGuiUtils.loadGif(new ResourceLocation(Demo.MODID, "texture/test.gif"), "test"); 26 | test1Gif = CocoaGuiUtils.loadGif(new ResourceLocation(Demo.MODID, "texture/test1.gif"), "test1"); 27 | } 28 | catch (IOException e) 29 | { 30 | e.printStackTrace(); 31 | } 32 | catch (FontFormatException e) 33 | { 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/demo/java/top/hookan/cocoa/demo/proxy/CommonProxy.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.demo.proxy; 2 | 3 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 4 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 5 | 6 | public class CommonProxy 7 | { 8 | public void preInit(FMLPreInitializationEvent event) 9 | { 10 | 11 | } 12 | 13 | public void init(FMLInitializationEvent event) 14 | { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/demo/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | FMLCorePlugin: top.hookan.cocoa.demo.core.Core 3 | -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/blockstates/demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "variants": { 3 | "normal": { "model": "cocoa_api_demo:demo" } 4 | } 5 | } -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/models/block/demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "block/cube_all", 3 | "textures": { 4 | "all": "cocoa_api_demo:blocks/demo" 5 | } 6 | } -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/models/item/demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "parent": "cocoa_api_demo:block/demo", 3 | "display": { 4 | "thirdperson": { 5 | "rotation": [ 10, -45, 170 ], 6 | "translation": [ 0, 1.5, -2.75 ], 7 | "scale": [ 0.375, 0.375, 0.375 ] 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/texture/test.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCCocoaUI/CocoaAPI/4414aecb9b037d41e976264051bbf708b7986fd0/src/demo/resources/assets/cocoa_api_demo/texture/test.gif -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/texture/test1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCCocoaUI/CocoaAPI/4414aecb9b037d41e976264051bbf708b7986fd0/src/demo/resources/assets/cocoa_api_demo/texture/test1.gif -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/textures/blocks/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCCocoaUI/CocoaAPI/4414aecb9b037d41e976264051bbf708b7986fd0/src/demo/resources/assets/cocoa_api_demo/textures/blocks/demo.png -------------------------------------------------------------------------------- /src/demo/resources/assets/cocoa_api_demo/ttf/test.ttc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MCCocoaUI/CocoaAPI/4414aecb9b037d41e976264051bbf708b7986fd0/src/demo/resources/assets/cocoa_api_demo/ttf/test.ttc -------------------------------------------------------------------------------- /src/demo/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "cocoa_api_demo resources", 4 | "pack_format": 3 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/CocoaAPI.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa; 2 | 3 | import net.minecraftforge.fml.common.Mod; 4 | 5 | @Mod(modid = CocoaAPI.MODID, name = CocoaAPI.NAME, version = CocoaAPI.VERSION, acceptedMinecraftVersions = "[1.12.2,)") 6 | public class CocoaAPI 7 | { 8 | public static final String MODID = "cocoa_api"; 9 | public static final String NAME = "Cocoa API"; 10 | public static final String VERSION = "@version@"; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/core/CocoaTransformer.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.core; 2 | 3 | import net.minecraft.launchwrapper.IClassTransformer; 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.ClassWriter; 6 | import org.objectweb.asm.Opcodes; 7 | import org.objectweb.asm.tree.*; 8 | import top.hookan.cocoa.core.annotation.CocoaHook; 9 | 10 | import java.io.InputStream; 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | public abstract class CocoaTransformer implements IClassTransformer 15 | { 16 | private Set hookSet; 17 | private Set transformClassSet; 18 | 19 | public CocoaTransformer() 20 | { 21 | hookSet = new HashSet<>(); 22 | transformClassSet = new HashSet<>(); 23 | String path = getClass().getName().replace('.', '/'); 24 | try (InputStream input = getClass().getResourceAsStream("/" + path + ".class")) 25 | { 26 | ClassNode classNode = new ClassNode(); 27 | ClassReader reader = new ClassReader(input); 28 | reader.accept(classNode, 0); 29 | for (MethodNode methodNode : classNode.methods) 30 | { 31 | if (methodNode.visibleAnnotations == null) continue; 32 | for (AnnotationNode annNode : methodNode.visibleAnnotations) 33 | { 34 | if (annNode.desc.equals("Ltop/hookan/cocoa/core/annotation/CocoaHook;")) 35 | { 36 | Object objs[] = annNode.values.toArray(); 37 | Hook hook = new Hook(); 38 | hook.hookOwner = path; 39 | hook.hookName = methodNode.name; 40 | hook.hookDesc = methodNode.desc; 41 | String args[]; 42 | for (int i = 0; i < objs.length; i += 2) 43 | { 44 | switch (objs[i].toString()) 45 | { 46 | case "owner": 47 | hook.owner = objs[i + 1].toString(); 48 | transformClassSet.add(objs[i + 1].toString()); 49 | break; 50 | case "mcp": 51 | args = objs[i + 1].toString().split(":"); 52 | hook.mcpName = args[0]; 53 | hook.mcpDesc = args[1]; 54 | break; 55 | case "notch": 56 | args = objs[i + 1].toString().split(":"); 57 | hook.notchName = args[0]; 58 | hook.notchDesc = args[1]; 59 | break; 60 | case "type": 61 | args = (String[]) objs[i + 1]; 62 | if (args[1].equals("BEGIN_WITH_RETURN")) 63 | { 64 | hook.type = CocoaHook.HookType.BEGIN_WITH_RETURN; 65 | } 66 | else if (args[1].equals("BEGIN")) 67 | { 68 | hook.type = CocoaHook.HookType.BEGIN; 69 | } 70 | else if (args[1].equals("END")) 71 | { 72 | hook.type = CocoaHook.HookType.END; 73 | } 74 | else 75 | { 76 | hook.type = CocoaHook.HookType.EXTRA_LOAD; 77 | } 78 | break; 79 | case "extra": 80 | hook.extra = objs[i + 1].toString(); 81 | break; 82 | } 83 | } 84 | hookSet.add(hook); 85 | break; 86 | } 87 | } 88 | } 89 | } 90 | catch (Exception e) 91 | { 92 | e.printStackTrace(); 93 | } 94 | } 95 | 96 | public byte[] transform(String name, String transformedName, byte[] basicClass) 97 | { 98 | if (!transformClassSet.contains(name)) return basicClass; 99 | 100 | ClassNode classNode = new ClassNode(); 101 | ClassReader reader = new ClassReader(basicClass); 102 | reader.accept(classNode, 0); 103 | 104 | Set acHookSet = new HashSet<>(); 105 | for (Hook hook : hookSet) 106 | { 107 | if (hook.owner.equals(transformedName)) acHookSet.add(hook); 108 | } 109 | 110 | for (MethodNode methodNode : classNode.methods) 111 | { 112 | for (Hook hook : acHookSet) 113 | { 114 | if (hook.mcpName.equals(methodNode.name) && hook.mcpDesc.equals(methodNode.desc) || 115 | hook.notchName.equals(methodNode.name) && hook.notchDesc.equals(methodNode.desc)) 116 | { 117 | InsnList insnList = new InsnList(); 118 | if ((methodNode.access & Opcodes.ACC_STATIC) != 0) 119 | { 120 | String desc = methodNode.desc; 121 | char[] chars = desc.toCharArray(); 122 | int var = 0; 123 | for (int i = 1; i < chars.length; i++) 124 | { 125 | if (chars[i] == 'L') 126 | { 127 | insnList.add(new VarInsnNode(Opcodes.ALOAD, var)); 128 | var++; 129 | while (chars[i] != ';') i++; 130 | } 131 | else if (chars[i] == 'B' || chars[i] == 'S' || chars[i] == 'I' || chars[i] == 'Z' || 132 | chars[i] == 'C') 133 | { 134 | insnList.add(new VarInsnNode(Opcodes.ILOAD, var)); 135 | var++; 136 | } 137 | else if (chars[i] == 'J') 138 | { 139 | insnList.add(new VarInsnNode(Opcodes.LLOAD, var)); 140 | var += 2; 141 | } 142 | else if (chars[i] == 'F') 143 | { 144 | insnList.add(new VarInsnNode(Opcodes.FLOAD, var)); 145 | var++; 146 | } 147 | else if (chars[i] == 'D') 148 | { 149 | insnList.add(new VarInsnNode(Opcodes.DLOAD, var)); 150 | var += 2; 151 | } 152 | else if (chars[i] == ')') break; 153 | } 154 | methodNode.maxStack += var; 155 | } 156 | else 157 | { 158 | insnList.add(new VarInsnNode(Opcodes.ALOAD, 0)); 159 | String desc = methodNode.desc; 160 | char[] chars = desc.toCharArray(); 161 | int var = 1; 162 | for (int i = 1; i < chars.length; i++) 163 | { 164 | if (chars[i] == 'L') 165 | { 166 | insnList.add(new VarInsnNode(Opcodes.ALOAD, var)); 167 | var++; 168 | while (chars[i] != ';') i++; 169 | } 170 | else if (chars[i] == 'B' || chars[i] == 'S' || chars[i] == 'I' || chars[i] == 'Z' || 171 | chars[i] == 'C') 172 | { 173 | insnList.add(new VarInsnNode(Opcodes.ILOAD, var)); 174 | var++; 175 | } 176 | else if (chars[i] == 'J') 177 | { 178 | insnList.add(new VarInsnNode(Opcodes.LLOAD, var)); 179 | var += 2; 180 | } 181 | else if (chars[i] == 'F') 182 | { 183 | insnList.add(new VarInsnNode(Opcodes.FLOAD, var)); 184 | var++; 185 | } 186 | else if (chars[i] == 'D') 187 | { 188 | insnList.add(new VarInsnNode(Opcodes.DLOAD, var)); 189 | var += 2; 190 | } 191 | else if (chars[i] == ')') break; 192 | } 193 | methodNode.maxStack += var; 194 | } 195 | MethodInsnNode mInsnNode = new MethodInsnNode(Opcodes.INVOKESTATIC, hook.hookOwner, hook 196 | .hookName, hook.hookDesc, false); 197 | insnList.add(mInsnNode); 198 | switch (hook.type) 199 | { 200 | case BEGIN_WITH_RETURN: 201 | AbstractInsnNode returnNode = new InsnNode(methodNode.instructions.getLast().getPrevious 202 | ().getOpcode()); 203 | insnList.add(returnNode); 204 | methodNode.instructions = insnList; 205 | break; 206 | case BEGIN: 207 | if (methodNode.name.equals("")) 208 | { 209 | for (AbstractInsnNode aNode : methodNode.instructions.toArray()) 210 | { 211 | if (aNode.getOpcode() == Opcodes.INVOKESPECIAL) 212 | { 213 | methodNode.instructions.insert(aNode, insnList); 214 | break; 215 | } 216 | } 217 | } 218 | else 219 | { 220 | methodNode.instructions.insert(methodNode.instructions.getFirst().getNext(), insnList); 221 | } 222 | break; 223 | case END: 224 | methodNode.instructions.insertBefore(methodNode.instructions.getLast().getPrevious(), 225 | insnList); 226 | break; 227 | case EXTRA_LOAD: 228 | String args[] = hook.extra.split("_"); 229 | int opc = Integer.MIN_VALUE; 230 | switch (args[0]) 231 | { 232 | case "ALOAD": 233 | opc = Opcodes.ASTORE; 234 | insnList.insertBefore(insnList.getLast(), new VarInsnNode(Opcodes.ALOAD, Integer 235 | .parseInt(args[1]))); 236 | break; 237 | case "ILOAD": 238 | opc = Opcodes.ISTORE; 239 | insnList.insertBefore(insnList.getLast(), new VarInsnNode(Opcodes.ILOAD, Integer 240 | .parseInt(args[1]))); 241 | break; 242 | case "LLOAD": 243 | opc = Opcodes.LSTORE; 244 | insnList.insertBefore(insnList.getLast(), new VarInsnNode(Opcodes.LLOAD, Integer 245 | .parseInt(args[1]))); 246 | break; 247 | case "FLOAD": 248 | opc = Opcodes.FSTORE; 249 | insnList.insertBefore(insnList.getLast(), new VarInsnNode(Opcodes.FLOAD, Integer 250 | .parseInt(args[1]))); 251 | break; 252 | case "DLOAD": 253 | opc = Opcodes.DSTORE; 254 | insnList.insertBefore(insnList.getLast(), new VarInsnNode(Opcodes.DLOAD, Integer 255 | .parseInt(args[1]))); 256 | break; 257 | } 258 | for (AbstractInsnNode aNode : methodNode.instructions.toArray()) 259 | { 260 | if (aNode.getOpcode() == opc) 261 | { 262 | methodNode.instructions.insert(aNode, insnList); 263 | break; 264 | } 265 | } 266 | break; 267 | } 268 | } 269 | } 270 | } 271 | ClassWriter writer = new ClassWriter(Opcodes.ASM5); 272 | classNode.accept(writer); 273 | byte[] transformedClass = writer.toByteArray(); 274 | return transformedClass; 275 | } 276 | 277 | private static class Hook 278 | { 279 | String hookName; 280 | String hookOwner; 281 | String hookDesc; 282 | String owner; 283 | String mcpName; 284 | String mcpDesc; 285 | String notchName; 286 | String notchDesc; 287 | String extra; 288 | CocoaHook.HookType type; 289 | } 290 | } 291 | 292 | 293 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/core/CoreContainer.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.core; 2 | 3 | import com.google.common.eventbus.EventBus; 4 | import net.minecraftforge.fml.common.DummyModContainer; 5 | import net.minecraftforge.fml.common.LoadController; 6 | import net.minecraftforge.fml.common.ModMetadata; 7 | import top.hookan.cocoa.registry.RegistryHandler; 8 | 9 | import java.util.Arrays; 10 | 11 | public class CoreContainer extends DummyModContainer 12 | { 13 | public CoreContainer() 14 | { 15 | super(new ModMetadata()); 16 | ModMetadata meta = getMetadata(); 17 | meta.modId = "cocoa_api_core"; 18 | meta.name = "Cocoa API Core"; 19 | meta.version = "@version@"; 20 | meta.authorList = Arrays.asList("huangtian_hookan"); 21 | meta.description = "Cocoa API Core."; 22 | } 23 | 24 | public boolean registerBus(EventBus bus, LoadController controller) 25 | { 26 | bus.register(new RegistryHandler()); 27 | return true; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/core/CoreHooks.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.core; 2 | 3 | import net.minecraftforge.fml.common.discovery.asm.ASMModParser; 4 | import org.objectweb.asm.ClassReader; 5 | import org.objectweb.asm.tree.ClassNode; 6 | import top.hookan.cocoa.core.annotation.CocoaHook; 7 | import top.hookan.cocoa.registry.RegistryHandler; 8 | 9 | import java.io.InputStream; 10 | 11 | public class CoreHooks extends CocoaTransformer 12 | { 13 | @CocoaHook(owner = "net.minecraftforge.fml.common.discovery.asm.ASMModParser", 14 | mcp = ":(Ljava/io/InputStream;)V", 15 | notch = ":(Ljava/io/InputStream;)V", 16 | type = CocoaHook.HookType.EXTRA_LOAD, 17 | extra = "ALOAD_2") 18 | public static void checkClass(ASMModParser parser, InputStream input, ClassReader reader) 19 | { 20 | try 21 | { 22 | ClassNode classNode = new ClassNode(); 23 | reader.accept(classNode, 0); 24 | 25 | RegistryHandler.checkClass(classNode); 26 | } 27 | catch (Exception e) 28 | { 29 | e.printStackTrace(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/core/CorePlugin.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.core; 2 | 3 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 4 | 5 | import java.util.Map; 6 | 7 | @IFMLLoadingPlugin.MCVersion("1.12.2") 8 | @IFMLLoadingPlugin.Name("cocoa_api_core") 9 | public class CorePlugin implements IFMLLoadingPlugin 10 | { 11 | public String[] getASMTransformerClass() 12 | { 13 | return new String[]{"top.hookan.cocoa.core.CoreHooks"}; 14 | } 15 | 16 | public String getModContainerClass() 17 | { 18 | return "top.hookan.cocoa.core.CoreContainer"; 19 | } 20 | 21 | public String getSetupClass() 22 | { 23 | return null; 24 | } 25 | 26 | public void injectData(Map data) 27 | { 28 | 29 | } 30 | 31 | public String getAccessTransformerClass() 32 | { 33 | return null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/core/annotation/CocoaHook.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.core.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.METHOD) 10 | public @interface CocoaHook 11 | { 12 | String owner(); 13 | 14 | String mcp(); 15 | 16 | String notch(); 17 | 18 | HookType type(); 19 | 20 | String extra() default ""; 21 | 22 | enum HookType 23 | { 24 | BEGIN, 25 | BEGIN_WITH_RETURN, 26 | END, 27 | EXTRA_LOAD 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CComponent.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import top.hookan.cocoa.gui.event.CComponentEvent; 5 | 6 | public abstract class CComponent 7 | { 8 | public String name; 9 | public double x; 10 | public double y; 11 | public double width; 12 | public double height; 13 | public boolean hover; 14 | public final String type; 15 | protected boolean didMouseEnter; 16 | protected Minecraft mc; 17 | 18 | public CComponent(String type) 19 | { 20 | this.type = type; 21 | mc = Minecraft.getMinecraft(); 22 | } 23 | 24 | public abstract void doDraw(); 25 | 26 | void onMouseEntered(int mouseX, int mouseY) 27 | { 28 | didMouseEnter = true; 29 | mc.addScheduledTask(() -> CocoaGuiUtils.EVENT_BUS.post(new CComponentEvent.MouseEntered(this, mouseX, mouseY))); 30 | } 31 | 32 | void onMouseExited(int mouseX, int mouseY) 33 | { 34 | didMouseEnter = false; 35 | mc.addScheduledTask(() -> CocoaGuiUtils.EVENT_BUS.post(new CComponentEvent.MouseEntered(this, mouseX, mouseY))); 36 | } 37 | 38 | protected void onMousePressed(int mouseX, int mouseY) 39 | { 40 | CocoaGuiUtils.EVENT_BUS.post(new CComponentEvent.MousePressed(this, mouseX, mouseY)); 41 | } 42 | 43 | void onMouseReleased(int mouseX, int mouseY) 44 | { 45 | if (!didMouseEnter) return; 46 | CComponentEvent.MouseReleased event = new CComponentEvent.MouseReleased(this, mouseX, mouseY); 47 | CocoaGuiUtils.EVENT_BUS.post(event); 48 | if (event.isCanceled()) return; 49 | onMouseClicked(mouseX, mouseY); 50 | } 51 | 52 | protected void onMouseClicked(int mouseX, int mouseY) 53 | { 54 | 55 | } 56 | 57 | boolean isMouseIn(int mouseX, int mouseY) 58 | { 59 | return mouseX >= x && mouseY <= y && mouseX - x <= width && mouseY - y <= height; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CContainer.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | public abstract class CContainer extends CComponent 7 | { 8 | protected CContainerManager manager; 9 | 10 | protected Set components; 11 | 12 | public CContainer(String type) 13 | { 14 | super(type); 15 | components = new HashSet<>(); 16 | } 17 | 18 | void setManager(CContainerManager manager) 19 | { 20 | this.manager = manager; 21 | } 22 | 23 | public void doDraw() 24 | { 25 | manager.pushContainer(this); 26 | 27 | if (!components.isEmpty()) 28 | { 29 | for (CComponent component : components) 30 | { 31 | if (component instanceof CContainer) 32 | ((CContainer) component).setManager(manager); 33 | component.doDraw(); 34 | } 35 | } 36 | 37 | manager.popContainer(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CContainerManager.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import java.util.Stack; 4 | 5 | public class CContainerManager 6 | { 7 | private Stack containerStack = new Stack<>(); 8 | 9 | 10 | public void pushContainer(CContainer container) 11 | { 12 | containerStack.push(container); 13 | 14 | } 15 | 16 | public void popContainer() 17 | { 18 | containerStack.pop(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CGui.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import net.minecraft.client.gui.GuiScreen; 4 | 5 | import java.util.List; 6 | 7 | public class CGui extends GuiScreen 8 | { 9 | public CGui() 10 | { 11 | 12 | } 13 | 14 | private CContainerManager containerManager; 15 | private List components; 16 | 17 | public void initGui() 18 | { 19 | containerManager = new CContainerManager(); 20 | 21 | } 22 | 23 | public void drawScreen(int mouseX, int mouseY, float partialTicks) 24 | { 25 | for (CComponent component : components) 26 | { 27 | if (component.didMouseEnter) 28 | { 29 | if (!component.isMouseIn(mouseX, mouseY)) 30 | component.onMouseExited(mouseX, mouseY); 31 | } 32 | else 33 | { 34 | if (component.isMouseIn(mouseX, mouseY)) 35 | component.onMouseEntered(mouseX, mouseY); 36 | } 37 | } 38 | 39 | for (CComponent component : components) 40 | { 41 | if (component instanceof CContainer) 42 | ((CContainer) component).setManager(containerManager); 43 | component.doDraw(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CPanel.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | public class CPanel extends CContainer 4 | { 5 | public CPanel() 6 | { 7 | super("Panel"); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/CocoaGuiUtils.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import com.google.common.eventbus.EventBus; 4 | import net.minecraft.client.Minecraft; 5 | import net.minecraft.client.resources.IResourcePack; 6 | import net.minecraft.util.ResourceLocation; 7 | import org.lwjgl.opengl.GL11; 8 | 9 | import java.awt.*; 10 | import java.io.IOException; 11 | import java.io.InputStream; 12 | 13 | public class CocoaGuiUtils 14 | { 15 | private static IResourcePack mcPack = Minecraft.getMinecraft().mcDefaultResourcePack; 16 | 17 | public static final EventBus EVENT_BUS = new EventBus(); 18 | 19 | public static TTFRender loadTTF(InputStream input, String name) throws IOException, FontFormatException 20 | { 21 | return new TTFRender(input, name); 22 | } 23 | 24 | public static TTFRender loadTTF(ResourceLocation location, String name) throws IOException, FontFormatException 25 | { 26 | return loadTTF(mcPack.getInputStream(location), name); 27 | } 28 | 29 | public static GifRender loadGif(InputStream input, String name) throws IOException 30 | { 31 | return new GifRender(input, name); 32 | } 33 | 34 | public static GifRender loadGif(ResourceLocation location, String name) throws IOException 35 | { 36 | return loadGif(mcPack.getInputStream(location), name); 37 | } 38 | 39 | public static void drawPic(double x, double y, double w, double h, double u, double v, double tw, double th, 40 | double twm, double thm) 41 | { 42 | GL11.glBegin(GL11.GL_QUADS); 43 | GL11.glTexCoord2d(u / twm, v / twm); 44 | GL11.glVertex2d(x, y); 45 | GL11.glTexCoord2d(u / twm, (v + th) / thm); 46 | GL11.glVertex2d(x, y + h); 47 | GL11.glTexCoord2d((u + tw) / twm, (v + th) / thm); 48 | GL11.glVertex2d(x + w, y + h); 49 | GL11.glTexCoord2d((u + tw) / twm, v / thm); 50 | GL11.glVertex2d(x + w, y); 51 | GL11.glEnd(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/GifRender.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.renderer.texture.DynamicTexture; 5 | import net.minecraft.client.renderer.texture.TextureManager; 6 | import net.minecraft.util.ResourceLocation; 7 | import top.hookan.cocoa.CocoaAPI; 8 | 9 | import javax.imageio.ImageIO; 10 | import javax.imageio.ImageReader; 11 | import javax.imageio.stream.ImageInputStream; 12 | import java.awt.image.BufferedImage; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.util.Iterator; 16 | 17 | public class GifRender 18 | { 19 | private int frames = 0; 20 | private ResourceLocation framesRL[]; 21 | private TextureManager renderEngine; 22 | 23 | GifRender(InputStream input, String name) throws IOException 24 | { 25 | ImageInputStream stream = ImageIO.createImageInputStream(input); 26 | Iterator readers = ImageIO.getImageReaders(stream); 27 | renderEngine = Minecraft.getMinecraft().renderEngine; 28 | if (readers.hasNext()) 29 | { 30 | ImageReader reader = readers.next(); 31 | reader.setInput(stream); 32 | frames = reader.getNumImages(true); 33 | framesRL = new ResourceLocation[frames]; 34 | for (int i = 0; i < frames; i++) 35 | { 36 | framesRL[i] = new ResourceLocation(CocoaAPI.MODID, "gif_" + name + "_" + i); 37 | BufferedImage image = reader.read(i); 38 | DynamicTexture dt = new DynamicTexture(image.getWidth(), image.getHeight()); 39 | renderEngine.loadTexture(framesRL[i], dt); 40 | image.getRGB(0, 0, image.getWidth(), image.getHeight(), dt.getTextureData(), 0, image.getWidth()); 41 | dt.updateDynamicTexture(); 42 | } 43 | } 44 | } 45 | 46 | public int getFrames() 47 | { 48 | return frames; 49 | } 50 | 51 | public void bindFrame(int frame) 52 | { 53 | if (frame >= frames) return; 54 | renderEngine.bindTexture(framesRL[frame]); 55 | } 56 | 57 | public void doDraw(int frame, double x, double y, double w, double h, double u, double v, double tw, double th, 58 | double twm, double thm) 59 | { 60 | if (frame >= frames) return; 61 | bindFrame(frame); 62 | CocoaGuiUtils.drawPic(x, y, w, h, u, v, tw, th, twm, thm); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/TTFRender.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.gui.FontRenderer; 5 | import net.minecraft.client.renderer.texture.DynamicTexture; 6 | import net.minecraft.client.renderer.texture.TextureManager; 7 | import net.minecraft.util.ResourceLocation; 8 | import net.minecraftforge.fml.relauncher.Side; 9 | import net.minecraftforge.fml.relauncher.SideOnly; 10 | import org.lwjgl.opengl.GL11; 11 | import top.hookan.cocoa.CocoaAPI; 12 | 13 | import java.awt.*; 14 | import java.awt.image.BufferedImage; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | import java.util.UUID; 20 | 21 | @SideOnly(Side.CLIENT) 22 | public class TTFRender extends FontRenderer 23 | { 24 | private Font ttf; 25 | private String fontName; 26 | private TextureManager renderEngine = Minecraft.getMinecraft().renderEngine; 27 | private Map charMap = new HashMap<>(); 28 | private FontMetrics fontMetrics; 29 | 30 | TTFRender(InputStream ttfInput, String fontName) throws IOException, FontFormatException 31 | { 32 | super(Minecraft.getMinecraft().gameSettings, new ResourceLocation("textures/font/ascii.png"), Minecraft 33 | .getMinecraft().renderEngine, true); 34 | ttf = Font.createFont(Font.TRUETYPE_FONT, ttfInput); 35 | ttfInput.close(); 36 | ttf = ttf.deriveFont(48.0f); 37 | this.fontName = fontName; 38 | fontMetrics = new Label().getFontMetrics(ttf); 39 | } 40 | 41 | private ResourceLocation getResourceLocation(char c) 42 | { 43 | if (charMap.containsKey(c)) return charMap.get(c); 44 | String str = String.valueOf(c); 45 | 46 | int width = 64; 47 | int height = 64; 48 | 49 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 50 | Graphics g = image.getGraphics(); 51 | g.setClip(0, 0, width, height); 52 | g.setColor(Color.white); 53 | g.setFont(ttf); 54 | Rectangle clip = g.getClipBounds(); 55 | 56 | int ascent = fontMetrics.getAscent(); 57 | int descent = fontMetrics.getDescent(); 58 | int y = (clip.height - (ascent + descent)) / 2 + ascent; 59 | 60 | g.drawString(str, 0, y); 61 | g.dispose(); 62 | 63 | ResourceLocation rl = new ResourceLocation(CocoaAPI.MODID, "font_" + fontName + "_" + UUID.randomUUID()); 64 | DynamicTexture dt = new DynamicTexture(image.getWidth(), image.getHeight()); 65 | renderEngine.loadTexture(rl, dt); 66 | image.getRGB(0, 0, image.getWidth(), image.getHeight(), dt.getTextureData(), 0, image.getWidth()); 67 | dt.updateDynamicTexture(); 68 | charMap.put(c, rl); 69 | return rl; 70 | } 71 | 72 | 73 | protected float renderUnicodeChar(char ch, boolean italic) 74 | { 75 | boolean f = ttf.canDisplay(ch); 76 | if (!f) return super.renderUnicodeChar(ch, italic); 77 | 78 | renderEngine.bindTexture(getResourceLocation(ch)); 79 | 80 | GL11.glEnable(GL11.GL_BLEND); 81 | GL11.glEnable(GL11.GL_ALPHA_TEST); 82 | 83 | CocoaGuiUtils.drawPic(this.posX, this.posY, 15, 15, 0, 0, 1, 1, 1, 1); 84 | 85 | GL11.glDisable(GL11.GL_ALPHA_TEST); 86 | GL11.glDisable(GL11.GL_BLEND); 87 | 88 | return 15f * fontMetrics.charWidth(ch) / 64.0f; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/event/CComponentEvent.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui.event; 2 | 3 | import net.minecraftforge.fml.common.eventhandler.Cancelable; 4 | import top.hookan.cocoa.gui.CComponent; 5 | 6 | public class CComponentEvent extends CocoaGuiEvent 7 | { 8 | public final CComponent component; 9 | 10 | public CComponentEvent(CComponent component) 11 | { 12 | this.component = component; 13 | } 14 | 15 | public static class MousePressed extends CComponentEvent 16 | { 17 | public final int mouseX; 18 | public final int mouseY; 19 | 20 | public MousePressed(CComponent component, int mouseX, int mouseY) 21 | { 22 | super(component); 23 | this.mouseX = mouseX; 24 | this.mouseY = mouseY; 25 | } 26 | } 27 | 28 | @Cancelable 29 | public static class MouseReleased extends CComponentEvent 30 | { 31 | public final int mouseX; 32 | public final int mouseY; 33 | 34 | public MouseReleased(CComponent component, int mouseX, int mouseY) 35 | { 36 | super(component); 37 | this.mouseX = mouseX; 38 | this.mouseY = mouseY; 39 | } 40 | } 41 | 42 | public static class MouseEntered extends CComponentEvent 43 | { 44 | public final int mouseX; 45 | public final int mouseY; 46 | 47 | public MouseEntered(CComponent component, int mouseX, int mouseY) 48 | { 49 | super(component); 50 | this.mouseX = mouseX; 51 | this.mouseY = mouseY; 52 | } 53 | } 54 | 55 | public static class MouseExited extends CComponentEvent 56 | { 57 | public final int mouseX; 58 | public final int mouseY; 59 | 60 | public MouseExited(CComponent component, int mouseX, int mouseY) 61 | { 62 | super(component); 63 | this.mouseX = mouseX; 64 | this.mouseY = mouseY; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/gui/event/CocoaGuiEvent.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.gui.event; 2 | 3 | import net.minecraftforge.fml.common.eventhandler.Event; 4 | 5 | public class CocoaGuiEvent extends Event 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/registry/RegistryHandler.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.registry; 2 | 3 | import com.google.common.eventbus.Subscribe; 4 | import net.minecraft.block.Block; 5 | import net.minecraft.client.renderer.block.model.ModelResourceLocation; 6 | import net.minecraft.command.ICommand; 7 | import net.minecraft.item.Item; 8 | import net.minecraft.item.ItemBlock; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.world.DimensionType; 11 | import net.minecraftforge.client.model.ModelLoader; 12 | import net.minecraftforge.common.DimensionManager; 13 | import net.minecraftforge.fml.common.Mod; 14 | import net.minecraftforge.fml.common.event.FMLInitializationEvent; 15 | import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; 16 | import net.minecraftforge.fml.common.event.FMLServerStartingEvent; 17 | import net.minecraftforge.fml.common.registry.ForgeRegistries; 18 | import net.minecraftforge.fml.common.registry.GameRegistry; 19 | import net.minecraftforge.oredict.OreDictionary; 20 | import net.minecraftforge.registries.IForgeRegistryEntry; 21 | import org.objectweb.asm.tree.AnnotationNode; 22 | import org.objectweb.asm.tree.ClassNode; 23 | import top.hookan.cocoa.registry.annotation.CocoaReg; 24 | 25 | import java.lang.reflect.Field; 26 | import java.util.ArrayList; 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | public class RegistryHandler 32 | { 33 | private static List regClassNameList = new ArrayList<>(); 34 | private List regClassList = new ArrayList<>(); 35 | private Map regClassModidMap = new HashMap<>(); 36 | private Map regClassModObjList = new HashMap<>(); 37 | 38 | public static void checkClass(ClassNode classNode) 39 | { 40 | if (classNode.visibleAnnotations == null) return; 41 | for (AnnotationNode annNode : classNode.visibleAnnotations) 42 | { 43 | if (annNode.desc.equals("Ltop/hookan/cocoa/registry/annotation/CocoaReg;")) 44 | { 45 | regClassNameList.add(classNode.name.replaceAll("/", ".")); 46 | break; 47 | } 48 | } 49 | } 50 | 51 | @Subscribe 52 | public void preInit(FMLPreInitializationEvent event) 53 | { 54 | for (String name : regClassNameList) 55 | { 56 | try 57 | { 58 | Class clazz = Class.forName(name); 59 | clazz.getClassLoader().loadClass(name); 60 | regClassList.add(clazz); 61 | CocoaReg reg = (CocoaReg) clazz.getAnnotation(CocoaReg.class); 62 | Mod modinfo = (Mod) reg.value().getAnnotation(Mod.class); 63 | if (modinfo == null) continue; 64 | regClassModidMap.put(clazz, modinfo.modid()); 65 | Object modObj = null; 66 | for (Field field : reg.value().getFields()) 67 | { 68 | if (field.getAnnotation(Mod.Instance.class) != null) 69 | { 70 | modObj = field.get(null); 71 | break; 72 | } 73 | } 74 | regClassModObjList.put(clazz, modObj); 75 | } 76 | catch (Exception e) 77 | { 78 | e.printStackTrace(); 79 | } 80 | } 81 | 82 | for (Class clazz : regClassList) 83 | { 84 | try 85 | { 86 | for (Field field : clazz.getFields()) 87 | { 88 | String modid = regClassModidMap.get(clazz); 89 | if (field.getAnnotation(CocoaReg.Reg.class) != null) 90 | { 91 | CocoaReg.Reg regInfo = field.getAnnotation(CocoaReg.Reg.class); 92 | Object obj = field.get(null); 93 | if (obj instanceof IForgeRegistryEntry.Impl) 94 | { 95 | 96 | GameRegistry.findRegistry(((IForgeRegistryEntry.Impl) obj).getRegistryType()).register(( 97 | (IForgeRegistryEntry.Impl) obj).setRegistryName(modid + ":" + regInfo.value())); 98 | System.out.println(((IForgeRegistryEntry.Impl) obj).getRegistryName()); 99 | System.out.println(modid + ":" + regInfo.value()); 100 | } 101 | if (obj instanceof Block) 102 | { 103 | ForgeRegistries.ITEMS.register(new ItemBlock((Block) obj).setRegistryName(modid + ":" + 104 | regInfo.value())); 105 | } 106 | } 107 | if (event.getSide().isClient()) 108 | { 109 | if (field.getAnnotation(CocoaReg.ModelReg.class) != null) 110 | { 111 | CocoaReg.ModelReg regInfo = field.getAnnotation(CocoaReg.ModelReg.class); 112 | Object obj = field.get(null); 113 | if (obj instanceof Block) 114 | { 115 | ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock((Block) obj), 0, 116 | new ModelResourceLocation(modid + ":" + regInfo.value(), "inventory")); 117 | } 118 | if (obj instanceof Item) 119 | { 120 | ModelLoader.setCustomModelResourceLocation((Item) obj, 0, 121 | new ModelResourceLocation(modid + ":" + regInfo.value(), "inventory")); 122 | } 123 | } 124 | } 125 | } 126 | } 127 | catch (Exception e) 128 | { 129 | e.printStackTrace(); 130 | } 131 | } 132 | 133 | 134 | } 135 | 136 | @Subscribe 137 | public void init(FMLInitializationEvent event) 138 | { 139 | for (Class clazz : regClassList) 140 | { 141 | try 142 | { 143 | for (Field field : clazz.getFields()) 144 | { 145 | if (field.getAnnotation(CocoaReg.OreDicReg.class) != null) 146 | { 147 | CocoaReg.OreDicReg oredicInfo = field.getAnnotation(CocoaReg.OreDicReg.class); 148 | Object obj = field.get(null); 149 | if (obj instanceof Item) 150 | { 151 | OreDictionary.registerOre(oredicInfo.value(), (Item) obj); 152 | } 153 | else if (obj instanceof Block) 154 | { 155 | OreDictionary.registerOre(oredicInfo.value(), (Block) obj); 156 | } 157 | else if (obj instanceof ItemStack) 158 | { 159 | OreDictionary.registerOre(oredicInfo.value(), (ItemStack) obj); 160 | } 161 | } 162 | if (field.getAnnotation(CocoaReg.DimReg.class) != null) 163 | { 164 | CocoaReg.DimReg dimInfo = field.getAnnotation(CocoaReg.DimReg.class); 165 | DimensionManager.registerDimension(dimInfo.value(), (DimensionType) field.get(null)); 166 | } 167 | } 168 | } 169 | catch (Exception e) 170 | { 171 | e.printStackTrace(); 172 | } 173 | } 174 | } 175 | 176 | @Subscribe 177 | public void serverStarting(FMLServerStartingEvent event) 178 | { 179 | for (Class clazz : regClassList) 180 | { 181 | try 182 | { 183 | for (Field field : clazz.getFields()) 184 | { 185 | if (field.getAnnotation(CocoaReg.CommandReg.class) != null) 186 | { 187 | event.registerServerCommand((ICommand) field.get(null)); 188 | } 189 | } 190 | } 191 | catch (Exception e) 192 | { 193 | e.printStackTrace(); 194 | } 195 | } 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /src/main/java/top/hookan/cocoa/registry/annotation/CocoaReg.java: -------------------------------------------------------------------------------- 1 | package top.hookan.cocoa.registry.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface CocoaReg 11 | { 12 | /** 13 | * Main class of mod 14 | */ 15 | Class value(); 16 | 17 | /** 18 | * Register impl 19 | */ 20 | @Retention(RetentionPolicy.RUNTIME) 21 | @Target(ElementType.FIELD) 22 | @interface Reg 23 | { 24 | /** 25 | * Register name 26 | */ 27 | String value(); 28 | } 29 | 30 | /** 31 | * Register item model and block model 32 | */ 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Target(ElementType.FIELD) 35 | @interface ModelReg 36 | { 37 | /** 38 | * Item or block model name 39 | */ 40 | String value(); 41 | } 42 | 43 | /** 44 | * Register ore dictionary 45 | */ 46 | @Retention(RetentionPolicy.RUNTIME) 47 | @Target(ElementType.FIELD) 48 | @interface OreDicReg 49 | { 50 | /** 51 | * Ore dictionary name 52 | */ 53 | String value(); 54 | } 55 | 56 | /** 57 | * Register dimension 58 | */ 59 | @Retention(RetentionPolicy.RUNTIME) 60 | @Target(ElementType.FIELD) 61 | @interface DimReg 62 | { 63 | /** 64 | * ID of dimension 65 | */ 66 | int value(); 67 | } 68 | 69 | /** 70 | * Register command 71 | */ 72 | @Retention(RetentionPolicy.RUNTIME) 73 | @Target(ElementType.FIELD) 74 | @interface CommandReg 75 | { 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | FMLCorePlugin: top.hookan.cocoa.core.CorePlugin 3 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "cocoa_api", 4 | "name": "Cocoa API", 5 | "description": "A mod API.", 6 | "version": "${version}", 7 | "mcversion": "${mcversion}", 8 | "url": "https://cocoa.hookan.top", 9 | "authorList": ["huangtian_hookan","KevinWalker"], 10 | "logoFile": "", 11 | "screenshots": [], 12 | "dependencies": [] 13 | } 14 | ] 15 | -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "cocoa_api resources", 4 | "pack_format": 3 5 | } 6 | } 7 | --------------------------------------------------------------------------------