├── .gitignore
├── COPYING
├── COPYING.LESSER
├── build.bat
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── src
└── main
├── java
└── me
│ └── ichun
│ └── mods
│ └── tabula
│ ├── client
│ ├── core
│ │ ├── ConfigClient.java
│ │ ├── EventHandlerClient.java
│ │ └── ResourceHelper.java
│ ├── export
│ │ ├── ExportList.java
│ │ └── types
│ │ │ ├── ExportBlockJson.java
│ │ │ ├── ExportHandInfo.java
│ │ │ ├── ExportHeadInfo.java
│ │ │ ├── ExportJava.java
│ │ │ ├── ExportProjectTexture.java
│ │ │ ├── ExportTextureMap.java
│ │ │ ├── handInfo
│ │ │ └── WindowExportHandInfo.java
│ │ │ └── headInfo
│ │ │ ├── ModelGooglyEye.java
│ │ │ └── PreviewRenderHandler.java
│ ├── gui
│ │ ├── IProjectInfo.java
│ │ ├── WorkspaceTabula.java
│ │ └── window
│ │ │ ├── WindowBoxInfo.java
│ │ │ ├── WindowChat.java
│ │ │ ├── WindowInputReceiver.java
│ │ │ ├── WindowModelTree.java
│ │ │ ├── WindowPartInfo.java
│ │ │ ├── WindowProjectNavigator.java
│ │ │ ├── WindowTexture.java
│ │ │ ├── WindowToolbar.java
│ │ │ ├── element
│ │ │ └── ElementProjectButton.java
│ │ │ └── popup
│ │ │ ├── WindowEditProject.java
│ │ │ ├── WindowExport.java
│ │ │ ├── WindowExportBlockJson.java
│ │ │ ├── WindowExportHeadInfo.java
│ │ │ ├── WindowExportJava.java
│ │ │ ├── WindowGhostProject.java
│ │ │ ├── WindowImportMCProject.java
│ │ │ ├── WindowImportProject.java
│ │ │ ├── WindowNewProject.java
│ │ │ ├── WindowNewTexture.java
│ │ │ ├── WindowOpenProject.java
│ │ │ ├── WindowSaveAs.java
│ │ │ └── WindowSaveOverwrite.java
│ ├── model
│ │ ├── ModelVoxel.java
│ │ └── ModelWaxTablet.java
│ ├── render
│ │ └── TileRendererTabulaRasa.java
│ └── tabula
│ │ └── Mainframe.java
│ └── common
│ ├── Tabula.java
│ ├── block
│ └── BlockTabulaRasa.java
│ ├── packet
│ ├── PacketChat.java
│ ├── PacketEditorStatus.java
│ ├── PacketKillSession.java
│ ├── PacketListenerChange.java
│ ├── PacketPing.java
│ ├── PacketProjectFragment.java
│ ├── PacketRequestProject.java
│ └── PacketRequestSession.java
│ └── tileentity
│ └── TileEntityTabulaRasa.java
└── resources
├── META-INF
└── mods.toml
├── PlayerGhost.tbl
├── assets
└── tabula
│ ├── blockstates
│ └── tabularasa.json
│ ├── lang
│ ├── de_de.json
│ ├── en_us.json
│ ├── fr_fr.json
│ ├── it_it.json
│ ├── pt_br.json
│ ├── pt_pt.json
│ └── zh_cn.json
│ ├── models
│ ├── block
│ │ └── tabularasa.json
│ └── item
│ │ └── tabularasa.json
│ └── textures
│ ├── blocks
│ └── tabularasa.png
│ ├── icon
│ ├── addeditor.png
│ ├── autolayout.png
│ ├── chat.png
│ ├── cleartexture.png
│ ├── copy.png
│ ├── cut.png
│ ├── delete.png
│ ├── edit.png
│ ├── editmeta.png
│ ├── exittabula.png
│ ├── export.png
│ ├── ghostmodel.png
│ ├── group.png
│ ├── hidetexture.png
│ ├── import.png
│ ├── importmc.png
│ ├── info.png
│ ├── model.png
│ ├── new.png
│ ├── newcube.png
│ ├── newgroup.png
│ ├── newtexture.png
│ ├── open.png
│ ├── paste.png
│ ├── pasteinplace.png
│ ├── pastewithoutchildren.png
│ ├── redo.png
│ ├── removeeditor.png
│ ├── save.png
│ ├── saveas.png
│ ├── settings.png
│ └── undo.png
│ ├── model
│ ├── cube.png
│ ├── modelgooglyeye.png
│ └── tabularasa.png
│ └── workspace
│ ├── grid16.png
│ └── orientationbase.png
├── data
└── tabula
│ ├── loot_tables
│ └── blocks
│ │ └── tabularasa.json
│ └── recipes
│ └── tabularasa.json
└── pack.mcmeta
/.gitignore:
--------------------------------------------------------------------------------
1 | # eclipse
2 | bin
3 | *.launch
4 | .settings
5 | .metadata
6 | .classpath
7 | .project
8 |
9 | # idea
10 | out
11 | *.ipr
12 | *.iws
13 | *.iml
14 | .idea
15 |
16 | # gradle
17 | build
18 | .gradle
19 | libs
20 | src/api
21 | logs
22 |
23 | # other
24 | eclipse
25 | run
26 |
27 | # java
28 | *.class
29 | *.war
30 | *.ear
--------------------------------------------------------------------------------
/COPYING.LESSER:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/build.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | start gradlew clean build
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | maven { url = 'https://files.minecraftforge.net/maven' }
4 | jcenter()
5 | mavenCentral()
6 | }
7 | dependencies {
8 | classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true
9 | }
10 | }
11 | apply plugin: 'net.minecraftforge.gradle'
12 | // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
13 | apply plugin: 'eclipse'
14 | apply plugin: 'maven-publish'
15 |
16 | version = '10.5.1'
17 | group = 'tabula'
18 | archivesBaseName = 'Tabula-1.16.5'
19 |
20 | java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8.
21 |
22 | println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
23 | minecraft {
24 | // The mappings can be changed at any time, and must be in the following format.
25 | // Channel: Version:
26 | // snapshot YYYYMMDD Snapshot are built nightly.
27 | // stable # Stables are built at the discretion of the MCP team.
28 | // official MCVersion Official field/method names from Mojang mapping files
29 | //
30 | // You must be aware of the Mojang license when using the 'official' mappings.
31 | // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
32 | //
33 | // Use non-default mappings at your own risk. they may not always work.
34 | // Simply re-run your setup task after changing the mappings to update your workspace.
35 | mappings channel: 'snapshot', version: '20210309-1.16.5'
36 | // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
37 |
38 | accessTransformer = file('src/api/resources/META-INF/accesstransformer.cfg')
39 |
40 | // Default run configurations.
41 | // These can be tweaked, removed, or duplicated as needed.
42 | runs {
43 | client {
44 | workingDirectory project.file('run')
45 |
46 | // Recommended logging data for a userdev environment
47 | property 'forge.logging.markers', 'REGISTRIES'
48 |
49 | // Recommended logging level for the console
50 | property 'forge.logging.console.level', 'info'
51 | source sourceSets.main
52 | }
53 |
54 | server {
55 | workingDirectory project.file('run')
56 |
57 | // Recommended logging data for a userdev environment
58 | property 'forge.logging.markers', 'REGISTRIES'
59 |
60 | // Recommended logging level for the console
61 | property 'forge.logging.console.level', 'info'
62 | source sourceSets.main
63 | }
64 | }
65 | }
66 |
67 | dependencies {
68 | // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
69 | // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
70 | // The userdev artifact is a special name and will get all sorts of transformations applied to it.
71 | minecraft 'net.minecraftforge:forge:1.16.5-36.0.55'
72 | implementation fg.deobf("ichunutil:iChunUtil:10.5.1")
73 |
74 | // You may put jars on which you depend on in ./libs or you may define them like so..
75 | // compile "some.group:artifact:version:classifier"
76 | // compile "some.group:artifact:version"
77 |
78 | // Real examples
79 | // compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
80 | // compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
81 |
82 | // The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
83 | // provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
84 |
85 | // These dependencies get remapped to your current MCP mappings
86 | // deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
87 |
88 | // For more info...
89 | // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
90 | // http://www.gradle.org/docs/current/userguide/dependency_management.html
91 |
92 | }
93 |
94 | repositories {
95 | mavenLocal()
96 | }
97 |
98 | // Example for how to get properties into the manifest for reading by the runtime..
99 | jar {
100 | manifest {
101 | attributes([
102 | "Specification-Title": "${group}",
103 | "Specification-Vendor": "iChun",
104 | "Specification-Version": "1", // We are version 1 of ourselves
105 | "Implementation-Title": project.name,
106 | "Implementation-Version": "${version}",
107 | "Implementation-Vendor" :"iChun",
108 | "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
109 | ])
110 | }
111 | }
--------------------------------------------------------------------------------
/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 | org.gradle.daemon=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.1-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
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 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/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 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
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 Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/core/ConfigClient.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.core;
2 |
3 | import me.ichun.mods.ichunutil.common.config.ConfigBase;
4 | import me.ichun.mods.ichunutil.common.config.annotations.CategoryDivider;
5 | import me.ichun.mods.ichunutil.common.config.annotations.Prop;
6 | import me.ichun.mods.tabula.common.Tabula;
7 | import net.minecraftforge.fml.config.ModConfig;
8 |
9 | import javax.annotation.Nonnull;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class ConfigClient extends ConfigBase
14 | {
15 | @CategoryDivider(name = "clientOnly")
16 | @Prop(min = -1, max = 8)
17 | public int forceGuiScale = 2;
18 |
19 | public boolean animateImports = true;
20 |
21 | public boolean addEntityTags = true;
22 |
23 | public boolean readEmptyNbt = true;
24 |
25 | @Prop(min = 0, max = 10)
26 | public int guiMaxDecimals = 2;
27 |
28 | public boolean renderWorkspaceBlock = true;
29 |
30 | public boolean renderWorkspaceGrid = true;
31 |
32 | public double workspaceGridSize = 7.25D;
33 |
34 | public boolean ignoreOldTabulaWarning = false;
35 |
36 | public boolean disableAutosaves = false;
37 |
38 | @Prop(min = 0, max = 200)
39 | public int maximumUndoStates = 40;
40 |
41 | @CategoryDivider(name = "multiplayer")
42 | public boolean chatSound = true;
43 |
44 | public boolean allowEveryoneToEdit = true;
45 |
46 | public List editors = new ArrayList<>();
47 |
48 |
49 | @Nonnull
50 | @Override
51 | public String getModId()
52 | {
53 | return Tabula.MOD_ID;
54 | }
55 |
56 | @Nonnull
57 | @Override
58 | public String getConfigName()
59 | {
60 | return Tabula.MOD_NAME;
61 | }
62 |
63 | @Nonnull
64 | @Override
65 | public ModConfig.Type getConfigType()
66 | {
67 | return ModConfig.Type.CLIENT;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/core/EventHandlerClient.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.core;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.TabulaPlugin;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import net.minecraft.client.Minecraft;
7 | import net.minecraft.client.gui.screen.MainMenuScreen;
8 | import net.minecraft.client.gui.screen.Screen;
9 | import net.minecraft.client.gui.widget.Widget;
10 | import net.minecraft.client.gui.widget.button.Button;
11 | import net.minecraft.util.text.ChatType;
12 | import net.minecraft.util.text.StringTextComponent;
13 | import net.minecraft.util.text.TranslationTextComponent;
14 | import net.minecraftforge.client.event.ClientChatReceivedEvent;
15 | import net.minecraftforge.client.event.GuiScreenEvent;
16 | import net.minecraftforge.eventbus.api.EventPriority;
17 | import net.minecraftforge.eventbus.api.SubscribeEvent;
18 |
19 | import java.awt.*;
20 | import java.util.HashSet;
21 |
22 | public class EventHandlerClient
23 | {
24 | @SubscribeEvent(priority = EventPriority.LOW)
25 | public void onInitGuiPost(GuiScreenEvent.InitGuiEvent.Post event)
26 | {
27 | if(event.getGui() instanceof MainMenuScreen)
28 | {
29 | int offsetX = 0;
30 | int offsetY = 0; //24?
31 | int btnX = event.getGui().width / 2 - 124 + offsetX;
32 | int btnY = event.getGui().height / 4 + 48 + 24 * 2 + offsetY;
33 | for(int i = 0; i < event.getWidgetList().size(); i++)
34 | {
35 | Widget button = event.getWidgetList().get(i);
36 | if(button instanceof Button && button.getMessage() instanceof TranslationTextComponent && ((TranslationTextComponent)button.getMessage()).getKey().equals("fml.menu.mods"))
37 | {
38 | btnX = button.x - 24;
39 | btnY = button.y;
40 | break;
41 | }
42 | }
43 | while(true)
44 | {
45 | if(btnX < 0)
46 | {
47 | if(offsetY <= -48) //give up
48 | {
49 | btnX = 0;
50 | btnY = 0;
51 | break;
52 | }
53 | else
54 | {
55 | offsetX = 0;
56 | offsetY -= 24;
57 | btnX = event.getGui().width / 2 - 124 + offsetX;
58 | btnY = event.getGui().height / 4 + 48 + 24 * 2 + offsetY;
59 | }
60 | }
61 |
62 | Rectangle btn = new Rectangle(btnX, btnY, 20, 20);//Thanks to heldplayer for this.
63 | boolean intersects = false;
64 | for(int i = 0; i < event.getWidgetList().size(); i++)
65 | {
66 | Widget button = event.getWidgetList().get(i);
67 | if(!intersects)
68 | {
69 | intersects = btn.intersects(new Rectangle(button.x, button.y, button.getWidth(), button.getHeight()));
70 | }
71 | }
72 |
73 | if(!intersects)
74 | {
75 | break;
76 | }
77 |
78 | btnX -= 24; // move to the left to try and find a free space.
79 | }
80 |
81 | event.addWidget(new Button(btnX, btnY, 20, 20, new StringTextComponent("T"), button -> {
82 | WorkspaceTabula screen = WorkspaceTabula.create(Minecraft.getInstance().getSession().getUsername());
83 | Minecraft.getInstance().displayGuiScreen(screen);
84 | }));
85 | }
86 | }
87 |
88 | @SubscribeEvent(priority = EventPriority.LOW)
89 | public void onClientChatReceived(ClientChatReceivedEvent event)
90 | {
91 | if(event.getType().equals(ChatType.CHAT) || event.getType().equals(ChatType.SYSTEM))
92 | {
93 | Screen screen = Minecraft.getInstance().currentScreen;
94 | if(screen instanceof WorkspaceTabula)
95 | {
96 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
97 | workspace.mainframe.receiveChat(event.getMessage().getString(), false);
98 | }
99 | }
100 | }
101 |
102 | public HashSet plugins = new HashSet<>();
103 |
104 | public void loadPlugin(String senderModId, TabulaPlugin o)
105 | {
106 | plugins.add(o);
107 | Tabula.LOGGER.info("Added plugin {} from {}", o.getClass().getSimpleName(), senderModId);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/core/ResourceHelper.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.core;
2 |
3 | import me.ichun.mods.tabula.common.Tabula;
4 | import net.minecraftforge.fml.loading.FMLPaths;
5 |
6 | import java.io.IOException;
7 | import java.nio.file.Files;
8 | import java.nio.file.Path;
9 |
10 | public class ResourceHelper
11 | {
12 | private static boolean init;
13 |
14 | private static Path workingDir;
15 |
16 | private static Path savesDir; //also used for imports
17 | private static Path texturesDir;
18 | private static Path exportsDir;
19 | private static Path autosaveDir;
20 |
21 | public static void init()
22 | {
23 | if(!init)
24 | {
25 | init = true;
26 |
27 | try
28 | {
29 | workingDir = FMLPaths.MODSDIR.get().resolve(Tabula.MOD_ID);
30 | if(!Files.exists(workingDir)) Files.createDirectory(workingDir);
31 |
32 | savesDir = workingDir.resolve("saves");
33 | if(!Files.exists(savesDir)) Files.createDirectory(savesDir);
34 |
35 | texturesDir = workingDir.resolve("textures");
36 | if(!Files.exists(texturesDir)) Files.createDirectory(texturesDir);
37 |
38 | exportsDir = workingDir.resolve("export");
39 | if(!Files.exists(exportsDir)) Files.createDirectory(exportsDir);
40 |
41 | autosaveDir = workingDir.resolve("autosave");
42 | if(!Files.exists(autosaveDir)) Files.createDirectory(autosaveDir);
43 | }
44 | catch(IOException e)
45 | {
46 | Tabula.LOGGER.fatal("Error initialising resources!");
47 | e.printStackTrace();
48 | }
49 | }
50 | }
51 |
52 | public static Path getWorkingDir()
53 | {
54 | return workingDir;
55 | }
56 |
57 | public static Path getSavesDir()
58 | {
59 | return savesDir;
60 | }
61 |
62 | public static Path getTexturesDir()
63 | {
64 | return texturesDir;
65 | }
66 |
67 | public static Path getExportsDir()
68 | {
69 | return exportsDir;
70 | }
71 |
72 | public static Path getAutosaveDir()
73 | {
74 | return autosaveDir;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/ExportList.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
4 | import me.ichun.mods.tabula.client.export.types.*;
5 |
6 | import java.util.Comparator;
7 | import java.util.TreeMap;
8 |
9 | public final class ExportList
10 | {
11 | public static final TreeMap EXPORTERS = new TreeMap(Comparator.naturalOrder()) {{
12 | put("blockJson", new ExportBlockJson());
13 | put("handInfo", new ExportHandInfo());
14 | put("headInfo", new ExportHeadInfo());
15 | put("javaClass", new ExportJava());
16 | put("projectTexture", new ExportProjectTexture());
17 | put("textureMap", new ExportTextureMap());
18 | }};
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/ExportHandInfo.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types;
2 |
3 | import com.google.common.base.Splitter;
4 | import me.ichun.mods.ichunutil.api.client.hand.HandInfo;
5 | import me.ichun.mods.ichunutil.client.gui.bns.Workspace;
6 | import me.ichun.mods.ichunutil.common.head.HeadHandler;
7 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
8 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
9 | import me.ichun.mods.tabula.client.core.ResourceHelper;
10 | import me.ichun.mods.tabula.client.export.types.handInfo.WindowExportHandInfo;
11 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
12 | import me.ichun.mods.tabula.client.tabula.Mainframe;
13 | import net.minecraft.client.Minecraft;
14 | import net.minecraft.client.resources.I18n;
15 | import org.apache.commons.io.FileUtils;
16 |
17 | import java.io.File;
18 | import java.util.List;
19 |
20 | public class ExportHandInfo extends Exporter
21 | {
22 | public ExportHandInfo()
23 | {
24 | super(I18n.format("tabula.export.handInfo.name"));
25 | }
26 |
27 | @Override
28 | public String getId()
29 | {
30 | return "handInfo";
31 | }
32 |
33 | @Override
34 | public boolean override(Workspace workspace, Project project)
35 | {
36 | Mainframe.ProjectInfo activeProject = ((WorkspaceTabula)workspace).mainframe.getActiveProject();
37 | if(activeProject != null)
38 | {
39 | WindowExportHandInfo.open((WorkspaceTabula)workspace, activeProject);
40 | }
41 |
42 | return true;
43 | }
44 |
45 | @Override
46 | public boolean export(Project project, Object... params)
47 | {
48 | HandInfo info = (HandInfo)params[0];
49 |
50 | if(!Minecraft.getInstance().getSession().getUsername().equals("Dev"))
51 | {
52 | info.author = Minecraft.getInstance().getSession().getUsername();
53 | }
54 |
55 | List strings = Splitter.on(".").trimResults().omitEmptyStrings().splitToList(info.forClass);
56 |
57 | if(strings.isEmpty())
58 | {
59 | strings.add("NO_CLASS_DEFINED");
60 | }
61 |
62 | File file = new File(ResourceHelper.getExportsDir().toFile(), strings.get(strings.size() - 1) + ".json");
63 | try
64 | {
65 | String json = HeadHandler.GSON.toJson(info, HandInfo.class);
66 | FileUtils.writeStringToFile(file, json, "UTF-8");
67 | return true;
68 | }
69 | catch(Throwable e1)
70 | {
71 | e1.printStackTrace();
72 | }
73 |
74 | return false; //Export is done by the window. We forget about it here.
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/ExportHeadInfo.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types;
2 |
3 | import com.google.common.base.Splitter;
4 | import me.ichun.mods.ichunutil.api.common.head.HeadInfo;
5 | import me.ichun.mods.ichunutil.client.gui.bns.Workspace;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
7 | import me.ichun.mods.ichunutil.common.head.HeadHandler;
8 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
9 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
10 | import me.ichun.mods.tabula.client.core.ResourceHelper;
11 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
12 | import me.ichun.mods.tabula.client.gui.window.popup.WindowExportHeadInfo;
13 | import me.ichun.mods.tabula.client.tabula.Mainframe;
14 | import net.minecraft.client.Minecraft;
15 | import net.minecraft.client.resources.I18n;
16 | import org.apache.commons.io.FileUtils;
17 |
18 | import java.io.File;
19 | import java.util.List;
20 |
21 | public class ExportHeadInfo extends Exporter
22 | {
23 | public ExportHeadInfo()
24 | {
25 | super(I18n.format("tabula.export.headInfo.name"));
26 | }
27 |
28 | @Override
29 | public String getId()
30 | {
31 | return "headInfo";
32 | }
33 |
34 | @Override
35 | public boolean override(Workspace workspace, Project project)
36 | {
37 | Mainframe.ProjectInfo activeProject = ((WorkspaceTabula)workspace).mainframe.getActiveProject();
38 | if(activeProject != null)
39 | {
40 | Project.Part selectedPart = activeProject.getSelectedPart();
41 | if(selectedPart != null)
42 | {
43 | if(!HeadHandler.hasInit())
44 | {
45 | HeadHandler.init();
46 | }
47 |
48 | WindowExportHeadInfo.open((WorkspaceTabula)workspace, project, null, false);
49 | }
50 | else
51 | {
52 | WindowPopup.popup(workspace, 0.5D, 0.5D, w ->{}, I18n.format("tabula.export.headInfo.selectPart"));
53 | }
54 | }
55 |
56 | return true;
57 | }
58 |
59 | @Override
60 | public boolean export(Project project, Object... params)
61 | {
62 | HeadInfo info = (HeadInfo)params[0];
63 |
64 | if(!Minecraft.getInstance().getSession().getUsername().equals("Dev"))
65 | {
66 | info.author = Minecraft.getInstance().getSession().getUsername();
67 | }
68 |
69 | List strings = Splitter.on(".").trimResults().omitEmptyStrings().splitToList(info.forClass);
70 |
71 | if(strings.isEmpty())
72 | {
73 | strings.add("NO_CLASS_DEFINED");
74 | }
75 |
76 | File file = new File(ResourceHelper.getExportsDir().toFile(), strings.get(strings.size() - 1) + ".json");
77 | try
78 | {
79 | String json = HeadHandler.GSON.toJson(info, HeadInfo.class);
80 | FileUtils.writeStringToFile(file, json, "UTF-8");
81 | return true;
82 | }
83 | catch(Throwable e1)
84 | {
85 | e1.printStackTrace();
86 | }
87 |
88 | return false; //Export is done by the window. We forget about it here.
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/ExportJava.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.Workspace;
4 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
5 | import me.ichun.mods.ichunutil.common.module.tabula.project.Identifiable;
6 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
7 | import me.ichun.mods.tabula.client.core.ResourceHelper;
8 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
9 | import me.ichun.mods.tabula.client.gui.window.popup.WindowExportJava;
10 | import me.ichun.mods.tabula.common.Tabula;
11 | import net.minecraft.client.resources.I18n;
12 | import org.apache.commons.io.FileUtils;
13 |
14 | import java.io.File;
15 | import java.io.IOException;
16 | import java.nio.charset.StandardCharsets;
17 | import java.util.ArrayList;
18 | import java.util.HashMap;
19 | import java.util.Map;
20 |
21 | public class ExportJava extends Exporter
22 | {
23 | public ExportJava()
24 | {
25 | super(I18n.format("export.javaClass.name"));
26 | }
27 |
28 | @Override
29 | public String getId()
30 | {
31 | return "javaClass";
32 | }
33 |
34 | @Override
35 | public boolean override(Workspace workspace, Project project)
36 | {
37 | workspace.openWindowInCenter(new WindowExportJava(((WorkspaceTabula)workspace), project), 0.6D, 0.6D);
38 | return true;
39 | }
40 |
41 | @Override
42 | public boolean export(Project project, Object... params)
43 | {
44 | File file = new File(ResourceHelper.getExportsDir().toFile(), params[1] + ".java");
45 |
46 | StringBuilder sb = new StringBuilder();
47 |
48 | ArrayList allCubes = project.getAllParts();
49 |
50 | HashMap cubeFieldMap = new HashMap<>();
51 |
52 | sb.append("package " + params[0] + ";\n\n");
53 | sb.append("import com.google.common.collect.ImmutableList;\n");
54 | sb.append("import com.mojang.blaze3d.matrix.MatrixStack;\n");
55 | sb.append("import com.mojang.blaze3d.vertex.IVertexBuilder;\n");
56 | sb.append("import net.minecraft.client.renderer.entity.model.EntityModel;\n");
57 | sb.append("import net.minecraft.client.renderer.model.ModelRenderer;\n");
58 | sb.append("import net.minecraft.entity.Entity;\n");
59 | sb.append("import net.minecraftforge.api.distmarker.Dist;\n");
60 | sb.append("import net.minecraftforge.api.distmarker.OnlyIn;\n");
61 |
62 |
63 | sb.append("\n");
64 | sb.append("/**\n");
65 | sb.append(" * " + project.name + " - " + project.author + "\n");
66 | sb.append(" * Created using Tabula " + Tabula.VERSION + "\n");
67 | sb.append(" */\n");
68 | sb.append("@OnlyIn(Dist.CLIENT)\n");
69 | sb.append("public class " + params[1] + " extends EntityModel {\n");
70 | boolean hasProjectScale = !(project.scaleX == 1F && project.scaleY == 1F && project.scaleZ == 1F);
71 | if(hasProjectScale)
72 | {
73 | sb.append(" public float[] modelScale = new float[] { " + project.scaleX + "F, " + project.scaleY + "F, " + project.scaleZ + "F };\n");
74 | }
75 | for(Project.Part cube : allCubes)
76 | {
77 | int count = 0;
78 | while(count == 0 && cubeFieldMap.containsValue(getFieldName(cube)) || count != 0 && cubeFieldMap.containsValue(getFieldName(cube) + "_" + count))
79 | {
80 | count++;
81 | }
82 | String fieldName = getFieldName(cube);
83 | if(count != 0)
84 | {
85 | fieldName = fieldName + "_" + count;
86 | }
87 | cubeFieldMap.put(cube, fieldName);
88 | sb.append(" public ModelRenderer " + fieldName + ";\n");
89 | }
90 | sb.append("\n");
91 | sb.append(" public " + params[1] + "() {\n");
92 | sb.append(" this.textureWidth = " + project.texWidth + ";\n");
93 | sb.append(" this.textureHeight = " + project.texHeight + ";\n");
94 | HashMap parentMap = new HashMap<>();
95 | StringBuilder childSb = new StringBuilder();
96 | for(Map.Entry e : cubeFieldMap.entrySet())
97 | {
98 | Project.Part cube = e.getKey();
99 | for(Project.Part child : cube.children)
100 | {
101 | parentMap.put(child, cube);
102 | }
103 | }
104 | for(Map.Entry e : cubeFieldMap.entrySet())
105 | {
106 | Project.Part cube = e.getKey();
107 | String field = e.getValue();
108 | sb.append(" this." + field + " = new ModelRenderer(this, " + cube.texOffX + ", " + cube.texOffY + ");\n");
109 | if(cube.mirror)
110 | {
111 | sb.append(" this." + field + ".mirror = true;\n");
112 | }
113 | sb.append(" this." + field + ".setRotationPoint(" + cube.rotPX + "F, " + cube.rotPY + "F, " + cube.rotPZ + "F);\n");
114 | for(Project.Part.Box box : cube.boxes)
115 | {
116 | sb.append(" this." + field);
117 | if(!(box.texOffX == 0 && box.texOffY == 0))
118 | {
119 | sb.append(".setTextureOffset(" + box.texOffX + ", " + box.texOffY + ")");
120 | }
121 | sb.append(".addBox(" + box.posX + "F, " + box.posY + "F, " + box.posZ + "F, " + box.dimX + "F, " + box.dimY + "F, " + box.dimZ + "F, " + box.expandX + "F, " + box.expandY + "F, " + box.expandZ + "F);\n");
122 | }
123 | if(!(cube.rotAX == 0.0D && cube.rotAY == 0.0D && cube.rotAZ == 0.0D))
124 | {
125 | sb.append(" this.setRotateAngle(" + field + ", " + Math.toRadians(cube.rotAX) + "F, " + Math.toRadians(cube.rotAY) + "F, " + Math.toRadians(cube.rotAZ) + "F);\n");
126 | }
127 | for(Project.Part child : cube.children)
128 | {
129 | parentMap.put(child, cube);
130 | }
131 | if(parentMap.get(cube) != null)
132 | {
133 | childSb.append(" this." + cubeFieldMap.get(parentMap.get(cube)) + ".addChild(this." + field + ");\n");
134 | }
135 | }
136 | sb.append(childSb.toString());
137 | for(Map.Entry e : parentMap.entrySet())
138 | {
139 | cubeFieldMap.remove(e.getKey());//removing it so children don't get called to render later on.
140 | }
141 | sb.append(" }\n\n");
142 | sb.append(" @Override\n");
143 | sb.append(" public void render(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) { \n");
144 |
145 | if(hasProjectScale)
146 | {
147 | sb.append(" matrixStackIn.push();\n");
148 | sb.append(" matrixStackIn.scale(modelScale[0], modelScale[1], modelScale[2]);\n");
149 | }
150 | sb.append(" ImmutableList.of(");
151 | int i = 0;
152 | for(Map.Entry e : cubeFieldMap.entrySet())
153 | {
154 | Project.Part cube = e.getKey();
155 | String field = e.getValue();
156 | sb.append("this." + field);
157 | if(i < cubeFieldMap.size() - 1)
158 | {
159 | sb.append(", ");
160 | }
161 | i++;
162 | }
163 | sb.append(").forEach((modelRenderer) -> { \n");
164 | sb.append(" modelRenderer.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);\n");
165 | sb.append(" });\n");
166 | if(hasProjectScale)
167 | {
168 | sb.append(" matrixStackIn.pop();\n");
169 | }
170 |
171 | sb.append(" }\n\n");
172 | sb.append(" @Override\n");
173 | sb.append(" public void setRotationAngles(T entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {}\n\n");
174 | sb.append(" /**\n");
175 | sb.append(" * This is a helper function from Tabula to set the rotation of model parts\n");
176 | sb.append(" */\n");
177 | sb.append(" public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) {\n");
178 | sb.append(" modelRenderer.rotateAngleX = x;\n");
179 | sb.append(" modelRenderer.rotateAngleY = y;\n");
180 | sb.append(" modelRenderer.rotateAngleZ = z;\n");
181 | sb.append(" }\n");
182 | sb.append("}\n");
183 |
184 | try
185 | {
186 | FileUtils.writeStringToFile(file, sb.toString(), StandardCharsets.UTF_8);
187 | return true;
188 | }
189 | catch(IOException e)
190 | {
191 | e.printStackTrace();
192 | return false;
193 | }
194 | }
195 |
196 | public String getFieldName(Identifiable> cube)
197 | {
198 | String name = cube.name.replaceAll("[^A-Za-z0-9_$]", "");
199 | return name;
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/ExportProjectTexture.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
4 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
5 | import me.ichun.mods.tabula.client.core.ResourceHelper;
6 | import net.minecraft.client.resources.I18n;
7 |
8 | import java.io.File;
9 | import java.io.FileOutputStream;
10 | import java.io.IOException;
11 |
12 | public class ExportProjectTexture extends Exporter
13 | {
14 | public ExportProjectTexture()
15 | {
16 | super(I18n.format("export.projTexture.name"));
17 | }
18 |
19 | @Override
20 | public String getId()
21 | {
22 | return "projectTexture";
23 | }
24 |
25 | @Override
26 | public boolean export(Project project, Object... params)
27 | {
28 | if(project.getTextureBytes() == null)
29 | {
30 | return false;
31 | }
32 |
33 | File file = new File(ResourceHelper.getExportsDir().toFile(), project.name + "-texture.png");
34 |
35 | try
36 | {
37 | FileOutputStream stream = new FileOutputStream(file);
38 | stream.write(project.getTextureBytes());
39 | stream.close();
40 | return true;
41 | }
42 | catch (IOException ioexception)
43 | {
44 | ioexception.printStackTrace();
45 | return false;
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/ExportTextureMap.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
4 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
5 | import me.ichun.mods.tabula.client.core.ResourceHelper;
6 | import net.minecraft.client.renderer.texture.NativeImage;
7 | import net.minecraft.client.resources.I18n;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 | import java.util.ArrayList;
12 |
13 | public class ExportTextureMap extends Exporter
14 | {
15 | public ExportTextureMap()
16 | {
17 | super(I18n.format("export.textureMap.name"));
18 | }
19 |
20 | @Override
21 | public String getId()
22 | {
23 | return "textureMap";
24 | }
25 |
26 | @Override
27 | public boolean export(Project project, Object... params)
28 | {
29 | File file = new File(ResourceHelper.getExportsDir().toFile(), project.name + "-texturemap.png");
30 |
31 | NativeImage tmp = new NativeImage(project.texWidth, project.texHeight, true);
32 |
33 | ArrayList cubes = project.getAllBoxes();
34 |
35 | for(Project.Part.Box cube : cubes)
36 | {
37 | for(int i = 0; i < (int)Math.ceil(cube.dimX) || i == 0 && (int)Math.ceil(cube.dimX) == 0; i++)
38 | {
39 | for(int j = 0; j < (int)Math.ceil(cube.dimY) || j == 0 && (int)Math.ceil(cube.dimY) == 0; j++)
40 | {
41 | for(int k = 0; k < (int)Math.ceil(cube.dimZ) || k == 0 && (int)Math.ceil(cube.dimZ) == 0; k++)
42 | {
43 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + k, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j) && (int)Math.ceil(cube.dimZ) > 0 && (int)Math.ceil(cube.dimY) > 0)
44 | {
45 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + k, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j, 0xffff0000); //red
46 | }
47 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j) && (int)Math.ceil(cube.dimX) > 0 && (int)Math.ceil(cube.dimY) > 0)
48 | {
49 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j, 0xff0000ff); //blue
50 | }
51 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + k, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j) && (int)Math.ceil(cube.dimZ) > 0 && (int)Math.ceil(cube.dimY) > 0)
52 | {
53 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + k, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j, 0xffaa0000); //dark red
54 | }
55 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j) && (int)Math.ceil(cube.dimX) > 0 && (int)Math.ceil(cube.dimY) > 0)
56 | {
57 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + (int)Math.ceil(cube.dimZ) + j, 0xff0000aa); //dark blue
58 | }
59 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + k) && (int)Math.ceil(cube.dimX) > 0 && (int)Math.ceil(cube.dimZ) > 0)
60 | {
61 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + k, 0xff00ff00); //green
62 | }
63 | if(withinBounds(tmp, (cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + k) && (int)Math.ceil(cube.dimX) > 0 && (int)Math.ceil(cube.dimZ) > 0)
64 | {
65 | tmp.setPixelRGBA((cube.texOffX + ((Project.Part)cube.parent).texOffX) + (int)Math.ceil(cube.dimZ) + (int)Math.ceil(cube.dimX) + i, (cube.texOffY + ((Project.Part)cube.parent).texOffY) + k, 0xff00aa00); //dark green
66 | }
67 | }
68 | }
69 | }
70 | }
71 |
72 | try
73 | {
74 | tmp.write(file);
75 | return true;
76 | }
77 | catch (IOException ioexception)
78 | {
79 | ioexception.printStackTrace();
80 | return false;
81 | }
82 | finally
83 | {
84 | tmp.close();
85 | }
86 | }
87 |
88 | public boolean withinBounds(NativeImage img, int x, int y)
89 | {
90 | return x >= 0 && x < img.getWidth() && y >= 0 && y < img.getHeight();
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/headInfo/ModelGooglyEye.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types.headInfo;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import com.mojang.blaze3d.vertex.IVertexBuilder;
5 | import net.minecraft.client.renderer.RenderType;
6 | import net.minecraft.client.renderer.model.Model;
7 | import net.minecraft.client.renderer.model.ModelRenderer;
8 |
9 | /**
10 | * Googly Eyes - iChun
11 | * Created using Tabula 5.1.0
12 | * Taken from Googly Eyes 10.0.0
13 | */
14 | public class ModelGooglyEye extends Model
15 | {
16 | public ModelRenderer cornea1;
17 | public ModelRenderer cornea2;
18 | public ModelRenderer cornea3;
19 | public ModelRenderer cornea4;
20 | public ModelRenderer cornea5;
21 | public ModelRenderer cornea6;
22 | public ModelRenderer[] iris = new ModelRenderer[3];
23 |
24 | public ModelGooglyEye()
25 | {
26 | super(RenderType::getEntityCutout);
27 |
28 | this.textureWidth = 64;
29 | this.textureHeight = 32;
30 |
31 | this.cornea1 = new ModelRenderer(this, 0, 0);
32 | this.cornea1.setRotationPoint(0.0F, 0.0F, 0.0F);
33 | this.cornea1.addBox(-0.5F, -1.865F, -1.03F, 1, 3.73F, 1, 0.0F);
34 |
35 | this.cornea2 = new ModelRenderer(this, 0, 0);
36 | this.cornea2.setRotationPoint(0.0F, 0.0F, 0.0F);
37 | this.cornea2.addBox(-0.5F, -1.865F, -1.0F, 1, 3.73F, 1, 0.0F);
38 | this.setRotateAngle(cornea2, 0.0F, -0.0F, 0.5235987755982988F);
39 |
40 | this.cornea3 = new ModelRenderer(this, 0, 0);
41 | this.cornea3.setRotationPoint(0.0F, 0.0F, 0.0F);
42 | this.cornea3.addBox(-0.5F, -1.865F, -1.02F, 1, 3.73F, 1, 0.0F);
43 | this.setRotateAngle(cornea3, 0.0F, 0.0F, 1.0471975511965976F);
44 |
45 | this.cornea4 = new ModelRenderer(this, 0, 0);
46 | this.cornea4.setRotationPoint(0.0F, 0.0F, 0.0F);
47 | this.cornea4.addBox(-0.5F, -1.865F, -0.99F, 1, 3.73F, 1, 0.0F);
48 | this.setRotateAngle(cornea4, 0.0F, -0.0F, 1.5707963267948966F);
49 |
50 | this.cornea5 = new ModelRenderer(this, 0, 0);
51 | this.cornea5.setRotationPoint(0.0F, 0.0F, 0.0F);
52 | this.cornea5.addBox(-0.5F, -1.865F, -1.01F, 1, 3.73F, 1, 0.0F);
53 | this.setRotateAngle(cornea5, 0.0F, -0.0F, 2.0943951023931953F);
54 |
55 | this.cornea6 = new ModelRenderer(this, 0, 0);
56 | this.cornea6.setRotationPoint(0.0F, 0.0F, 0.0F);
57 | this.cornea6.addBox(-0.5F, -1.865F, -0.98F, 1, 3.73F, 1, 0.0F);
58 | this.setRotateAngle(cornea6, 0.0F, -0.0F, 2.6179938779914944F);
59 |
60 | iris[0] = new ModelRenderer(this, 0, 0);
61 | iris[0].setRotationPoint(0.0F, 0.0F, 0.0F);
62 | iris[0].addBox(-0.5F, -0.8665F, -1.51F, 1, 1.733F, 1, 0.0F);
63 | this.setRotateAngle(iris[0], 0.0F, -0.0F, 2.0943951023931953F);
64 |
65 | iris[1] = new ModelRenderer(this, 0, 0);
66 | iris[1].setRotationPoint(0.0F, 0.0F, 0.0F);
67 | iris[1].addBox(-0.5F, -0.8665F, -1.5F, 1, 1.733F, 1, 0.0F);
68 | this.setRotateAngle(iris[1], 0.0F, -0.0F, 1.0471975511965976F);
69 |
70 | iris[2] = new ModelRenderer(this, 0, 0);
71 | iris[2].setRotationPoint(0.0F, 0.0F, 0.0F);
72 | iris[2].addBox(-0.5F, -0.8665F, -1.49F, 1, 1.733F, 1, 0.0F);
73 | }
74 |
75 | @Override
76 | public void render(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha){}
77 |
78 | public void renderCornea(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha)
79 | {
80 | this.cornea1.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
81 | this.cornea2.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
82 | this.cornea3.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
83 | this.cornea4.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
84 | this.cornea5.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
85 | this.cornea6.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
86 | }
87 |
88 | public void renderIris(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha)
89 | {
90 | for(int i = 0; i < iris.length; i++)
91 | {
92 | iris[i].render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
93 | }
94 | }
95 |
96 | public void moveIris(float x, float y, float pupilSize)
97 | {
98 | //pupilSize is not for scaling.
99 | float shiftFactor = (1.45F - pupilSize * 0.525F) / pupilSize;
100 | float rotX = -x * shiftFactor;// * (float)Math.cos(Math.toRadians((y / 1F) * 90F));
101 | float rotY = -y * shiftFactor * (float)Math.cos(Math.toRadians(x * 90F));
102 |
103 | for(int i = 0; i < iris.length; i++)
104 | {
105 | iris[i].rotationPointX = rotX;
106 | iris[i].rotationPointY = rotY;
107 | }
108 | }
109 |
110 | /**
111 | * This is a helper function from Tabula to set the rotation of model parts
112 | */
113 | public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) {
114 | modelRenderer.rotateAngleX = x;
115 | modelRenderer.rotateAngleY = y;
116 | modelRenderer.rotateAngleZ = z;
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/export/types/headInfo/PreviewRenderHandler.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.export.types.headInfo;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import com.mojang.blaze3d.vertex.IVertexBuilder;
5 | import me.ichun.mods.ichunutil.api.common.head.HeadInfo;
6 | import me.ichun.mods.ichunutil.client.model.tabula.ModelTabula;
7 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
8 | import net.minecraft.block.Block;
9 | import net.minecraft.block.Blocks;
10 | import net.minecraft.client.Minecraft;
11 | import net.minecraft.client.renderer.IRenderTypeBuffer;
12 | import net.minecraft.client.renderer.RenderType;
13 | import net.minecraft.client.renderer.model.ModelRenderer;
14 | import net.minecraft.client.renderer.texture.OverlayTexture;
15 | import net.minecraft.entity.LivingEntity;
16 | import net.minecraft.item.ItemStack;
17 | import net.minecraft.util.ResourceLocation;
18 | import net.minecraft.util.math.vector.Vector3f;
19 |
20 | import javax.annotation.Nonnull;
21 | import java.util.ArrayList;
22 | import java.util.List;
23 | import java.util.Map;
24 |
25 | public class PreviewRenderHandler
26 | {
27 | private static final ResourceLocation TEX_GOOGLY_EYE = new ResourceLocation("tabula","textures/model/modelgooglyeye.png");
28 | private static final RenderType RENDER_TYPE = RenderType.getEntityCutout(TEX_GOOGLY_EYE);
29 | private static final RenderType RENDER_TYPE_EYES = RenderType.getEyes(TEX_GOOGLY_EYE);
30 |
31 | private static final ModelGooglyEye MODEL_GOOGLY_EYE = new ModelGooglyEye();
32 | private static final ItemStack ITEMSTACK_SLAB = new ItemStack(Blocks.SPRUCE_SLAB);
33 |
34 | public static void renderHeadInfoPreview(@Nonnull MatrixStack stack, @Nonnull HeadInfo helper, @Nonnull ModelTabula model, @Nonnull Project.Part selectedPart)
35 | {
36 | if(helper.noFaceInfo && helper.noTopInfo) //but why tho
37 | {
38 | return;
39 | }
40 |
41 | List names = HeadInfo.DOT_SPLITTER.splitToList(helper.modelFieldName);
42 | ModelRenderer head = null;
43 | ArrayList childs = new ArrayList<>();
44 |
45 | if(!names.isEmpty())
46 | {
47 | for(int i = 0; i < names.size(); i++)
48 | {
49 | String name = names.get(i);
50 |
51 | for(Map.Entry entry : model.partMap.entrySet())
52 | {
53 | if(entry.getKey().name.equals(name))
54 | {
55 | //we found it;
56 | if(i == 0)
57 | {
58 | head = entry.getValue();
59 | }
60 | else
61 | {
62 | childs.add(entry.getValue());
63 | }
64 | }
65 | }
66 | }
67 | }
68 | else
69 | {
70 | return;
71 | }
72 |
73 | if(!(head != null && childs.size() + 1 == names.size())) //we didn't find it all.
74 | {
75 | return;
76 | }
77 |
78 | helper.headModel = head;
79 | helper.childTranslates = childs.toArray(new ModelRenderer[0]);
80 |
81 | stack.push();
82 |
83 | LivingEntity living = null;
84 | float partialTicks = 1F;
85 | int packedLightIn = 0xf000f0;
86 | IRenderTypeBuffer.Impl bufferIn = Minecraft.getInstance().getRenderTypeBuffers().getBufferSource();
87 |
88 | if(!helper.noFaceInfo)
89 | {
90 | int eyeCount = Math.min(helper.getEyeCount(living), 2);
91 |
92 | for(int i = 0; i < eyeCount; i++)
93 | {
94 | float eyeScale = helper.getEyeScale(living, stack, partialTicks, i);
95 |
96 | if(eyeScale <= 0F)
97 | {
98 | continue;
99 | }
100 |
101 | stack.push();
102 |
103 | float[] joint = helper.getHeadJointOffset(living, stack, partialTicks, -1);
104 | stack.translate(-joint[0], -joint[1], -joint[2]);
105 |
106 | stack.rotate(Vector3f.ZP.rotationDegrees(helper.getHeadRoll(living, stack, partialTicks, -1, i)));
107 | stack.rotate(Vector3f.YP.rotationDegrees(helper.getHeadYaw(living, stack, partialTicks, -1, i)));
108 | stack.rotate(Vector3f.XP.rotationDegrees(helper.getHeadPitch(living, stack, partialTicks, -1, i)));
109 |
110 | helper.postHeadTranslation(living, stack, partialTicks);
111 |
112 | float[] eyes = helper.getEyeOffsetFromJoint(living, stack, partialTicks, i);
113 | stack.translate(-(eyes[0] + helper.getEyeSideOffset(living, stack, partialTicks, i)), -eyes[1], -eyes[2]);
114 |
115 | stack.rotate(Vector3f.YP.rotationDegrees(helper.getEyeRotation(living, stack, partialTicks, i)));
116 | stack.rotate(Vector3f.XP.rotationDegrees(helper.getEyeTopRotation(living, stack, partialTicks, i)));
117 |
118 | stack.scale(eyeScale, eyeScale, eyeScale * 0.4F);
119 |
120 | //rendering the eyes
121 | IVertexBuilder buffer = bufferIn.getBuffer(RENDER_TYPE);
122 |
123 | int overlay = OverlayTexture.NO_OVERLAY;
124 |
125 | float[] irisColours = helper.getCorneaColours(living, stack, partialTicks, i);
126 | MODEL_GOOGLY_EYE.renderCornea(stack, buffer, packedLightIn, overlay, irisColours[0], irisColours[1], irisColours[2], 1F);
127 |
128 | float[] pupilColours = helper.getIrisColours(living, stack, partialTicks, i);
129 |
130 | float pupilScale = 1F;
131 | stack.push();
132 | stack.scale(pupilScale, pupilScale, 1F);
133 | MODEL_GOOGLY_EYE.renderIris(stack, buffer, packedLightIn, overlay, pupilColours[0], pupilColours[1], pupilColours[2], 1F);
134 | stack.pop();
135 |
136 | if(helper.doesEyeGlow(living, i))
137 | {
138 | buffer = bufferIn.getBuffer(RENDER_TYPE_EYES);
139 | MODEL_GOOGLY_EYE.renderCornea(stack, buffer, packedLightIn, overlay, irisColours[0], irisColours[1], irisColours[2], 1F);
140 |
141 | stack.push();
142 | stack.scale(pupilScale, pupilScale, 1F);
143 | MODEL_GOOGLY_EYE.renderIris(stack, buffer, packedLightIn, overlay, pupilColours[0], pupilColours[1], pupilColours[2], 1F);
144 | stack.pop();
145 | }
146 | //end rendering the eyes
147 |
148 | bufferIn.finish();
149 |
150 | stack.pop();
151 | }
152 | }
153 |
154 | if(!helper.noTopInfo)
155 | {
156 | int headCount = 1;
157 |
158 | for(int i = 0; i < headCount; i++)
159 | {
160 | float hatScale = helper.getHatScale(living, stack, partialTicks, i);
161 |
162 | if(hatScale <= 0F)
163 | {
164 | continue;
165 | }
166 | hatScale *= 1.005F; //to reduce Z-fighting
167 |
168 | stack.push();
169 |
170 | float[] joint = helper.getHeadJointOffset(living, stack, partialTicks, i);
171 | stack.translate(-joint[0], -joint[1], -joint[2]); //to fight Z-fighting
172 |
173 | stack.rotate(Vector3f.ZP.rotationDegrees(helper.getHeadRoll(living, stack, partialTicks, i, -1)));
174 | stack.rotate(Vector3f.YP.rotationDegrees(helper.getHeadYaw(living, stack, partialTicks, i, -1)));
175 | stack.rotate(Vector3f.XP.rotationDegrees(helper.getHeadPitch(living, stack, partialTicks, i, -1)));
176 |
177 | helper.postHeadTranslation(living, stack, partialTicks);
178 |
179 | float[] headPoint = helper.getHatOffsetFromJoint(living, stack, partialTicks, i);
180 | stack.translate(-headPoint[0], -headPoint[1] - 0.00225F, -headPoint[2]);
181 |
182 | stack.rotate(Vector3f.YP.rotationDegrees(helper.getHatYaw(living, stack, partialTicks, i)));
183 | stack.rotate(Vector3f.XP.rotationDegrees(helper.getHatPitch(living, stack, partialTicks, i)));
184 |
185 | stack.scale(hatScale, hatScale, hatScale);
186 |
187 | stack.translate(-0.25D, -0.25D, -0.25D);
188 | stack.scale(0.5F, 0.5F, 0.5F);
189 |
190 | Block block = Blocks.SPRUCE_SLAB;
191 | Minecraft.getInstance().getItemRenderer().renderModel(Minecraft.getInstance().getBlockRendererDispatcher().getBlockModelShapes().getModel(block.getDefaultState()), ITEMSTACK_SLAB, packedLightIn, OverlayTexture.NO_OVERLAY, stack, bufferIn.getBuffer(RenderType.getSolid()));
192 |
193 | bufferIn.finish();
194 |
195 | stack.pop();
196 | }
197 | }
198 |
199 | stack.pop();
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/IProjectInfo.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui;
2 |
3 | import me.ichun.mods.tabula.client.tabula.Mainframe;
4 | import net.minecraft.client.gui.INestedGuiEventHandler;
5 |
6 | import javax.annotation.Nullable;
7 |
8 | public interface IProjectInfo extends INestedGuiEventHandler
9 | {
10 | /**
11 | * Called before projectChanged(PROJECT) (ideally)
12 | * @param info
13 | */
14 | default void setCurrentProject(@Nullable Mainframe.ProjectInfo info)
15 | {
16 | getEventListeners().stream().filter(child -> child instanceof IProjectInfo).forEach(child -> ((IProjectInfo)child).setCurrentProject(info));
17 | }
18 |
19 | default void projectChanged(ChangeType type)
20 | {
21 | getEventListeners().stream().filter(child -> child instanceof IProjectInfo).forEach(child -> ((IProjectInfo)child).projectChanged(type));
22 | }
23 |
24 | public enum ChangeType
25 | {
26 | PROJECTS, // When the number of opened projects change
27 | PROJECT, // When the current project changes
28 | PARTS,
29 | TEXTURE
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/WindowInputReceiver.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.screen.Screen;
9 | import org.lwjgl.glfw.GLFW;
10 |
11 | public class WindowInputReceiver extends Window
12 | {
13 | public WindowInputReceiver(WorkspaceTabula parent)
14 | {
15 | super(parent);
16 | size(parent.getWidth(), parent.getHeight());
17 | setConstraint(Constraint.matchParent(this, parent, 0));
18 | borderSize = () -> 0;
19 | titleSize = () -> 0;
20 |
21 | disableBringToFront();
22 | disableDocking();
23 | disableDockStacking();
24 | disableUndocking();
25 | disableDrag();
26 | disableDragResize();
27 | disableTitle();
28 | }
29 |
30 | @Override
31 | public void init()
32 | {
33 | constraint.apply();
34 | }
35 |
36 | @Override
37 | public void resize(Minecraft mc, int width, int height)
38 | {
39 | constraint.apply();
40 | }
41 |
42 | @Override
43 | public void render(MatrixStack stack, int mouseX, int mouseY, float partialTick)
44 | {
45 | }
46 |
47 | @Override
48 | public boolean mouseClicked(double mouseX, double mouseY, int button)
49 | {
50 | if(isMouseOver(mouseX, mouseY))
51 | {
52 | if(button == GLFW.GLFW_MOUSE_BUTTON_LEFT)
53 | {
54 | parent.selecting = true;
55 | }
56 | parent.setDragging(true);
57 | return true;
58 | }
59 | return false;
60 | }
61 |
62 | @Override
63 | public boolean mouseReleased(double mouseX, double mouseY, int button)
64 | {
65 | super.mouseReleased(mouseX, mouseY, button);
66 | return true;
67 | }
68 |
69 | @Override
70 | public boolean mouseDragged(double mouseX, double mouseY, int button, double distX, double distY)
71 | {
72 | if(button == GLFW.GLFW_MOUSE_BUTTON_RIGHT || button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE)
73 | {
74 | if(button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE || Screen.hasShiftDown()) // if middle mouse or holding shift
75 | {
76 | float mag = 0.0125F;
77 | parent.mainframe.getCamera().x -= distX * mag;
78 | parent.mainframe.getCamera().y += distY * mag;
79 | }
80 | else if(Screen.hasControlDown())
81 | {
82 | parent.mainframe.getCamera().zoom += (distX - distY) * 0.05D;
83 | }
84 | else
85 | {
86 | float mag = 0.5F;
87 | parent.mainframe.getCamera().yaw += distX * mag;
88 | parent.mainframe.getCamera().pitch -= distY * mag;
89 | }
90 | }
91 | return true;
92 | }
93 |
94 | @Override
95 | public boolean mouseScrolled(double mouseX, double mouseY, double amount)
96 | {
97 | if(isMouseOver(mouseX, mouseY))
98 | {
99 | if(Screen.hasShiftDown())
100 | {
101 | parent.mainframe.getCamera().fov -= amount * 1D;
102 | }
103 | else
104 | {
105 | parent.mainframe.getCamera().zoom += amount * 0.05D;
106 | }
107 | return true;
108 | }
109 | return false;
110 | }
111 |
112 | @Override
113 | public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_)
114 | {
115 | return false;
116 | }
117 |
118 | @Override
119 | public boolean keyReleased(int keyCode, int scanCode, int modifiers)
120 | {
121 | return false;
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/WindowProjectNavigator.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.IConstrainable;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.Element;
9 | import me.ichun.mods.ichunutil.client.render.RenderHelper;
10 | import me.ichun.mods.tabula.client.gui.IProjectInfo;
11 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
12 | import me.ichun.mods.tabula.client.gui.window.element.ElementProjectButton;
13 | import me.ichun.mods.tabula.client.tabula.Mainframe;
14 |
15 | import javax.annotation.Nonnull;
16 |
17 | public class WindowProjectNavigator extends Window
18 | implements IProjectInfo
19 | {
20 | public WindowProjectNavigator(WorkspaceTabula parent)
21 | {
22 | super(parent);
23 | borderSize = () -> 0;
24 | disableDocking();
25 | disableDockStacking();
26 | disableUndocking();
27 | disableBringToFront();
28 | disableDrag();
29 | disableDragResize();
30 | disableTitle();
31 |
32 | setView(new ViewProjectNavigator(this));
33 | setId("windowNav");
34 |
35 | setHeight(10);
36 | }
37 |
38 | @Override
39 | public int getMaxHeight()
40 | {
41 | return 10;
42 | }
43 |
44 | @Override
45 | public int getMinHeight()
46 | {
47 | return 10;
48 | }
49 |
50 | public static class ViewProjectNavigator extends View
51 | implements IProjectInfo
52 | {
53 | public Mainframe.ProjectInfo currentInfo = null;
54 |
55 | public ViewProjectNavigator(@Nonnull WindowProjectNavigator parent)
56 | {
57 | super(parent, "");
58 |
59 | populate();
60 | }
61 |
62 | @Override
63 | public void setCurrentProject(Mainframe.ProjectInfo info)
64 | {
65 | currentInfo = info;
66 | }
67 |
68 | @Override
69 | public void projectChanged(ChangeType type)
70 | {
71 | if(type == ChangeType.PROJECTS || type == ChangeType.PROJECT)
72 | {
73 | populate();
74 | }
75 | }
76 |
77 | public void populate()
78 | {
79 | elements.clear();
80 |
81 | Mainframe mainframe = parentFragment.parent.mainframe;
82 | IConstrainable last = null;
83 | for(int i = 0; i < mainframe.projects.size(); i++)
84 | {
85 | Mainframe.ProjectInfo projectInfo = mainframe.projects.get(i);
86 | ElementProjectButton> btn = new ElementProjectButton<>(this, projectInfo, button -> {});
87 | btn.setConstraint(new Constraint(btn).left(last == null ? this : last, last == null ? Constraint.Property.Type.LEFT : Constraint.Property.Type.RIGHT, 0));
88 | btn.setWidth(getFontRenderer().getStringWidth(projectInfo.project.name) + 16);
89 | elements.add(btn);
90 | last = btn;
91 | }
92 |
93 | init();
94 | }
95 |
96 | @Override
97 | public void render(MatrixStack stack, int mouseX, int mouseY, float partialTick)
98 | {
99 | setScissor();
100 | //render our background
101 | if(renderMinecraftStyle() == 0)
102 | {
103 | fill(stack, getTheme().windowBackground, 0);
104 |
105 | int[] clr = getTheme().elementTreeBorder;
106 | RenderHelper.drawColour(stack, clr[0], clr[1], clr[2], 255, getLeft(), getTop(), getWidth(), 1, 0);
107 | }
108 |
109 | //render attached elements
110 | for(Element> element : elements)
111 | {
112 | element.render(stack, mouseX, mouseY, partialTick);
113 | }
114 |
115 | resetScissorToParent();
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/element/ElementProjectButton.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.element;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import me.ichun.mods.ichunutil.client.gui.bns.Theme;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.Fragment;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementClickable;
7 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
8 | import me.ichun.mods.tabula.client.tabula.Mainframe;
9 | import org.lwjgl.glfw.GLFW;
10 |
11 | import javax.annotation.Nonnull;
12 | import javax.annotation.Nullable;
13 | import java.util.function.Consumer;
14 |
15 | public class ElementProjectButton extends ElementClickable
16 | {
17 | @Nonnull
18 | public final Mainframe.ProjectInfo projectInfo;
19 |
20 | public ElementProjectButton(@Nonnull Fragment parent, @Nonnull Mainframe.ProjectInfo projectInfo, Consumer callback)
21 | {
22 | super(parent, callback);
23 | this.projectInfo = projectInfo;
24 | }
25 |
26 | @Override
27 | public void render(MatrixStack stack, int mouseX, int mouseY, float partialTick)
28 | {
29 | hover = isMouseOver(mouseX, mouseY) || parentFragment.getListener() == this;
30 |
31 | if(renderMinecraftStyle() > 0)
32 | {
33 | renderMinecraftStyleButton(stack, getLeft(), getTop(), width, height, parentFragment.isDragging() && parentFragment.getListener() == this ? ButtonState.CLICK : hover ? ButtonState.HOVER : ButtonState.IDLE, renderMinecraftStyle());
34 | }
35 | else
36 | {
37 | int[] colour = parentFragment.isDragging() && parentFragment.getListener() == this ? getTheme().elementButtonClick : hover ? getTheme().elementProjectTabHover : getTheme().elementTreeItemBg;
38 | fill(stack, colour, 0);
39 | }
40 | int[] fontClr = getTheme().fontDim;
41 | Mainframe.ProjectInfo info = ((WorkspaceTabula)getWorkspace()).mainframe.getActiveProject();
42 | if(info != null)
43 | {
44 | if(info == projectInfo) //this is active
45 | {
46 | fontClr = getTheme().font;
47 | }
48 | else if(projectInfo.project.isDirty)
49 | {
50 | fontClr = getTheme().fontChat;
51 | }
52 | }
53 | if(!projectInfo.project.name.isEmpty())
54 | {
55 | String s = reString(projectInfo.project.name, width - 14);
56 | if(projectInfo.project.isDirty)
57 | {
58 | s = s + "*";
59 | }
60 |
61 | drawString(stack, s, getLeft() + 2, getTop() + (height - getFontRenderer().FONT_HEIGHT) / 2F + 1, Theme.getAsHex(fontClr));
62 | }
63 | drawString(stack, "X", getRight() - 7, getTop() + (height - getFontRenderer().FONT_HEIGHT) / 2F + 1, Theme.getAsHex(isOverX(mouseX, mouseY) ? getTheme().font : getTheme().fontDim));
64 | }
65 |
66 | @Override
67 | public boolean mouseReleased(double mouseX, double mouseY, int button)
68 | {
69 | boolean flag = super.mouseReleased(mouseX, mouseY, button); // unsets dragging;
70 | parentFragment.setListener(null); //we're a one time click, stop focusing on us
71 | if(isMouseOver(mouseX, mouseY)) //lmb
72 | {
73 | trigger(); //Switch to this project anyway
74 |
75 | if(isOverX(mouseX, mouseY) || button == GLFW.GLFW_MOUSE_BUTTON_MIDDLE)
76 | {
77 | ((WorkspaceTabula)getWorkspace()).closeProject(projectInfo);
78 | }
79 | }
80 | return flag;
81 | }
82 |
83 | public boolean isOverX(double mouseX, double mouseY)
84 | {
85 | return parentFragment.isMouseOver(mouseX, mouseY) && isMouseBetween(mouseX, getLeft() + width - 10, getLeft() + width) && isMouseBetween(mouseY, getTop(), getTop() + height);
86 | }
87 |
88 | @Nullable
89 | @Override
90 | public String tooltip(double mouseX, double mouseY)
91 | {
92 | return projectInfo.project.name + " - " + projectInfo.project.author;
93 | }
94 |
95 | @Override
96 | public void onClickRelease()
97 | {
98 | if(projectInfo != ((WorkspaceTabula)getWorkspace()).mainframe.getActiveProject())
99 | {
100 | ((WorkspaceTabula)getWorkspace()).mainframe.setActiveProject(projectInfo);
101 | }
102 | }
103 |
104 | @Override
105 | public int getMinWidth()
106 | {
107 | return 15;
108 | }
109 |
110 | @Override
111 | public int getMinHeight()
112 | {
113 | return 10;
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExport.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButtonTextured;
9 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementList;
10 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementScrollBar;
11 | import me.ichun.mods.ichunutil.common.module.tabula.formats.types.Exporter;
12 | import me.ichun.mods.tabula.client.core.ResourceHelper;
13 | import me.ichun.mods.tabula.client.export.ExportList;
14 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
15 | import me.ichun.mods.tabula.client.tabula.Mainframe;
16 | import net.minecraft.client.resources.I18n;
17 | import net.minecraft.util.ResourceLocation;
18 | import net.minecraft.util.Util;
19 |
20 | import javax.annotation.Nonnull;
21 |
22 | public class WindowExport extends Window
23 | {
24 | public WindowExport(WorkspaceTabula parent, Mainframe.ProjectInfo info)
25 | {
26 | super(parent);
27 |
28 | setView(new ViewExport(this, info));
29 | disableDockingEntirely();
30 | }
31 |
32 | public static class ViewExport extends View
33 | {
34 | public ViewExport(@Nonnull WindowExport parent, Mainframe.ProjectInfo info)
35 | {
36 | super(parent, "export.title");
37 |
38 | ElementScrollBar> sv = new ElementScrollBar<>(this, ElementScrollBar.Orientation.VERTICAL, 0.6F);
39 | sv.setConstraint(new Constraint(sv).top(this, Constraint.Property.Type.TOP, 0)
40 | .bottom(this, Constraint.Property.Type.BOTTOM, 40) // 10 + 20 + 10, bottom + button height + padding
41 | .right(this, Constraint.Property.Type.RIGHT, 0)
42 | );
43 | elements.add(sv);
44 |
45 | ElementList> list = new ElementList<>(this).setScrollVertical(sv);
46 | list.setConstraint(new Constraint(list).bottom(this, Constraint.Property.Type.BOTTOM, 40)
47 | .left(this, Constraint.Property.Type.LEFT, 0).right(sv, Constraint.Property.Type.LEFT, 0)
48 | .top(this, Constraint.Property.Type.TOP, 0));
49 | elements.add(list);
50 |
51 | ExportList.EXPORTERS.forEach((s, e) -> {
52 | list.addItem(e).addTextWrapper(e.name).setDoubleClickHandler(item -> {
53 | if(item.selected)
54 | {
55 | loadFile(item.getObject(), info);
56 | }
57 | });
58 | });
59 |
60 | ElementButtonTextured> openDir = new ElementButtonTextured<>(this, new ResourceLocation("tabula", "textures/icon/info.png"), btn -> {
61 | Util.getOSType().openFile(ResourceHelper.getExportsDir().toFile());
62 | });
63 | openDir.setTooltip(I18n.format("topdock.openWorkingDir")).setSize(20, 20);
64 | openDir.setConstraint(new Constraint(openDir).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(this, Constraint.Property.Type.LEFT, 10));
65 | elements.add(openDir);
66 |
67 | ElementButton> button = new ElementButton<>(this, "gui.cancel", btn ->
68 | {
69 | getWorkspace().removeWindow(parent);
70 | });
71 | button.setSize(60, 20);
72 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
73 | elements.add(button);
74 |
75 | ElementButton> button1 = new ElementButton<>(this, "gui.ok", btn ->
76 | {
77 | for(ElementList.Item> item : list.items)
78 | {
79 | if(item.selected)
80 | {
81 | loadFile((Exporter)item.getObject(), info);
82 | return;
83 | }
84 | }
85 | });
86 | button1.setSize(60, 20);
87 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
88 | elements.add(button1);
89 | }
90 |
91 | public void loadFile(Exporter exporter, Mainframe.ProjectInfo info)
92 | {
93 | parentFragment.parent.removeWindow(parentFragment);
94 |
95 | if(info != null && !exporter.override(parentFragment.parent, info.project) && !exporter.export(info.project))
96 | {
97 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, w -> {}, I18n.format("export.failed"));
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowExportJava.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextField;
9 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextWrapper;
10 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
11 | import me.ichun.mods.tabula.client.export.ExportList;
12 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
13 | import net.minecraft.client.resources.I18n;
14 |
15 | import javax.annotation.Nonnull;
16 | import java.util.function.Consumer;
17 |
18 | public class WindowExportJava extends Window
19 | {
20 | public WindowExportJava(WorkspaceTabula parent, Project project)
21 | {
22 | super(parent);
23 |
24 | setView(new ViewExportJava(this, project));
25 | disableDockingEntirely();
26 | }
27 |
28 | public static class ViewExportJava extends View
29 | {
30 | public ViewExportJava(@Nonnull WindowExportJava parent, Project project)
31 | {
32 | super(parent, "export.javaClass.title");
33 |
34 | Consumer enterResponder = s -> {
35 | if(!s.isEmpty())
36 | {
37 | submit(project);
38 | }
39 | };
40 |
41 | ElementTextWrapper text = new ElementTextWrapper(this);
42 | text.setNoWrap().setText(I18n.format("export.javaClass.package"));
43 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(this, Constraint.Property.Type.TOP, 20));
44 | elements.add(text);
45 |
46 | ElementTextField textField = new ElementTextField(this);
47 | textField.setId("packageName");
48 | textField.setDefaultText("my.first.mod.model").setEnterResponder(enterResponder);
49 | textField.setConstraint(new Constraint(textField).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
50 | elements.add(textField);
51 |
52 | text = new ElementTextWrapper(this);
53 | text.setNoWrap().setText(I18n.format("export.javaClass.className"));
54 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(textField, Constraint.Property.Type.BOTTOM, 20));
55 | elements.add(text);
56 |
57 | textField = new ElementTextField(this);
58 | textField.setId("className");
59 | textField.setDefaultText(project.name).setValidator(ElementTextField.FILE_SAFE.and(s-> !s.contains(" "))).setEnterResponder(enterResponder);
60 | textField.setConstraint(new Constraint(textField).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
61 | elements.add(textField);
62 |
63 | ElementButton> button = new ElementButton<>(this, "gui.cancel", elementClickable ->
64 | {
65 | getWorkspace().removeWindow(parent);
66 | });
67 | button.setSize(60, 20);
68 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
69 | elements.add(button);
70 |
71 | ElementButton> button1 = new ElementButton<>(this, "gui.ok", elementClickable -> submit(project));
72 | button1.setSize(60, 20);
73 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
74 | elements.add(button1);
75 | }
76 |
77 | public void submit(Project project)
78 | {
79 | getWorkspace().removeWindow(parentFragment);
80 |
81 | String packageName;
82 | String className;
83 | packageName = ((ElementTextField)getById("packageName")).getText();
84 | if(packageName.isEmpty())
85 | {
86 | packageName = "there.was.supposed.to.be.a.package";
87 | }
88 | className = ((ElementTextField)getById("className")).getText();
89 | if(className.isEmpty())
90 | {
91 | className = "ThereWasSupposedToBeAClassName";
92 | }
93 |
94 | if(!ExportList.EXPORTERS.get("javaClass").export(project, packageName, className))
95 | {
96 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("export.failed"));
97 | }
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowGhostProject.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import com.google.common.collect.Ordering;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.*;
9 | import me.ichun.mods.ichunutil.common.module.tabula.formats.ImportList;
10 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
11 | import me.ichun.mods.tabula.client.core.ResourceHelper;
12 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
13 | import me.ichun.mods.tabula.client.tabula.Mainframe;
14 | import net.minecraft.client.resources.I18n;
15 | import net.minecraft.entity.LivingEntity;
16 |
17 | import javax.annotation.Nonnull;
18 | import java.io.File;
19 | import java.util.TreeSet;
20 |
21 | public class WindowGhostProject extends Window
22 | {
23 | public WindowGhostProject(WorkspaceTabula parent)
24 | {
25 | super(parent);
26 |
27 | setView(new ViewGhostProject(this));
28 | disableDockingEntirely();
29 | }
30 |
31 | public static class ViewGhostProject extends View
32 | {
33 | public ViewGhostProject(@Nonnull WindowGhostProject parent)
34 | {
35 | super(parent, "window.ghostModel.title");
36 |
37 | ElementScrollBar> sv = new ElementScrollBar<>(this, ElementScrollBar.Orientation.VERTICAL, 0.6F);
38 | sv.setConstraint(new Constraint(sv).top(this, Constraint.Property.Type.TOP, 0)
39 | .bottom(this, Constraint.Property.Type.BOTTOM, 40) // 10 + 20 + 10, bottom + button height + padding
40 | .right(this, Constraint.Property.Type.RIGHT, 0)
41 | );
42 | elements.add(sv);
43 |
44 | ElementList> list = new ElementList<>(this).setScrollVertical(sv);
45 | list.setConstraint(new Constraint(list).bottom(this, Constraint.Property.Type.BOTTOM, 40)
46 | .left(this, Constraint.Property.Type.LEFT, 0).right(sv, Constraint.Property.Type.LEFT, 0)
47 | .top(this, Constraint.Property.Type.TOP, 0));
48 | elements.add(list);
49 |
50 | TreeSet files = new TreeSet<>(Ordering.natural());
51 | File[] textures = ResourceHelper.getSavesDir().toFile().listFiles();
52 | if(textures != null)
53 | {
54 | for(File file : textures)
55 | {
56 | if(!file.isDirectory() && ImportList.isFileSupported(file))
57 | {
58 | files.add(file);
59 | }
60 | }
61 | }
62 |
63 | for(File file : files)
64 | {
65 | list.addItem(file).setDefaultAppearance().setDoubleClickHandler(item -> {
66 | if(item.selected)
67 | {
68 | getWorkspace().removeWindow(parent);
69 |
70 | loadFile(item.getObject());
71 | }
72 | });
73 | }
74 |
75 | ElementToggle> toggle = new ElementToggle<>(this, "window.import.texture", btn -> {});
76 | toggle.setToggled(true).setTooltip(I18n.format("window.import.textureFull")).setSize(60, 20).setId("buttonTexture");
77 | toggle.setConstraint(new Constraint(toggle).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(this, Constraint.Property.Type.LEFT, 10));
78 | elements.add(toggle);
79 |
80 | ElementNumberInput input = new ElementNumberInput(this, false);
81 | String defText = "20";
82 | Mainframe.ProjectInfo info1 = parent.parent.mainframe.getActiveProject();
83 | if(info1 != null && info1.ghostProject != null)
84 | {
85 | defText = Integer.toString((int)(info1.ghostOpacity * 100F));
86 | }
87 | input.setMin(0).setMax(100).setDefaultText(defText).setTooltip(I18n.format("window.controls.opacity")).setSize(60, 20).setId("inputOpacity");
88 | input.setConstraint(new Constraint(input).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(toggle, Constraint.Property.Type.RIGHT, 10));
89 | elements.add(input);
90 |
91 | ElementButton> button = new ElementButton<>(this, "element.button.clear", btn ->
92 | {
93 | Mainframe.ProjectInfo info = parent.parent.mainframe.getActiveProject();
94 | if(info != null)
95 | {
96 | info.setGhostProject(null, 0F);
97 | }
98 | });
99 | button.setSize(60, 20);
100 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
101 | elements.add(button);
102 |
103 | ElementButton> button1 = new ElementButton<>(this, "gui.ok", btn ->
104 | {
105 | getWorkspace().removeWindow(parent);
106 |
107 | for(ElementList.Item> item : list.items)
108 | {
109 | if(item.selected)
110 | {
111 | loadFile((File)item.getObject());
112 | return;
113 | }
114 | }
115 |
116 | Mainframe.ProjectInfo info = parentFragment.parent.mainframe.getActiveProject();
117 | if(info != null)
118 | {
119 | info.setGhostProject(info.ghostProject, ((ElementNumberInput)getById("inputOpacity")).getInt() / 100F);
120 | }
121 | });
122 | button1.setSize(60, 20);
123 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
124 | elements.add(button1);
125 | }
126 |
127 | public void loadFile(File file)
128 | {
129 | Project project = ImportList.createProjectFromFile(file);
130 | if(project == null)
131 | {
132 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("window.open.failed"));
133 | }
134 | else
135 | {
136 | Mainframe.ProjectInfo info = parentFragment.parent.mainframe.getActiveProject();
137 | if(info != null)
138 | {
139 | if(!((ElementToggle)getById("buttonTexture")).toggleState && project.getTextureBytes() != null)
140 | {
141 | project.setImageBytes(null);
142 | }
143 | info.setGhostProject(project, ((ElementNumberInput)getById("inputOpacity")).getInt() / 100F);
144 | }
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowImportProject.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import com.google.common.collect.Ordering;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.*;
9 | import me.ichun.mods.ichunutil.common.module.tabula.formats.ImportList;
10 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
11 | import me.ichun.mods.tabula.client.core.ResourceHelper;
12 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
13 | import net.minecraft.client.resources.I18n;
14 | import net.minecraft.util.ResourceLocation;
15 | import net.minecraft.util.Util;
16 |
17 | import javax.annotation.Nonnull;
18 | import java.io.File;
19 | import java.util.TreeSet;
20 |
21 | public class WindowImportProject extends Window
22 | {
23 | public WindowImportProject(WorkspaceTabula parent)
24 | {
25 | super(parent);
26 |
27 | setView(new ViewImportProject(this));
28 | disableDockingEntirely();
29 | }
30 |
31 | public static class ViewImportProject extends View
32 | {
33 | public ViewImportProject(@Nonnull WindowImportProject parent)
34 | {
35 | super(parent, "window.import.title");
36 |
37 | ElementScrollBar> sv = new ElementScrollBar<>(this, ElementScrollBar.Orientation.VERTICAL, 0.6F);
38 | sv.setConstraint(new Constraint(sv).top(this, Constraint.Property.Type.TOP, 0)
39 | .bottom(this, Constraint.Property.Type.BOTTOM, 40) // 10 + 20 + 10, bottom + button height + padding
40 | .right(this, Constraint.Property.Type.RIGHT, 0)
41 | );
42 | elements.add(sv);
43 |
44 | ElementList> list = new ElementList<>(this).setScrollVertical(sv);
45 | list.setConstraint(new Constraint(list).bottom(this, Constraint.Property.Type.BOTTOM, 40)
46 | .left(this, Constraint.Property.Type.LEFT, 0).right(sv, Constraint.Property.Type.LEFT, 0)
47 | .top(this, Constraint.Property.Type.TOP, 0));
48 | elements.add(list);
49 |
50 | TreeSet files = new TreeSet<>(Ordering.natural());
51 | File[] textures = ResourceHelper.getSavesDir().toFile().listFiles();
52 | if(textures != null)
53 | {
54 | for(File file : textures)
55 | {
56 | if(!file.isDirectory() && ImportList.isFileSupported(file))
57 | {
58 | files.add(file);
59 | }
60 | }
61 | }
62 |
63 | for(File file : files)
64 | {
65 | list.addItem(file).setDefaultAppearance().setDoubleClickHandler(item -> {
66 | if(item.selected)
67 | {
68 | loadFile(item.getObject());
69 | }
70 | });
71 | }
72 |
73 | ElementButtonTextured> openDir = new ElementButtonTextured<>(this, new ResourceLocation("tabula", "textures/icon/info.png"), btn -> {
74 | Util.getOSType().openFile(ResourceHelper.getSavesDir().toFile());
75 | });
76 | openDir.setTooltip(I18n.format("topdock.openWorkingDir")).setSize(20, 20);
77 | openDir.setConstraint(new Constraint(openDir).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(this, Constraint.Property.Type.LEFT, 10));
78 | elements.add(openDir);
79 |
80 | ElementToggle> toggle = new ElementToggle<>(this, "window.import.texture", btn -> {});
81 | toggle.setToggled(true).setTooltip(I18n.format("window.import.textureFull")).setSize(60, 20).setId("buttonTexture");
82 | toggle.setConstraint(new Constraint(toggle).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(openDir, Constraint.Property.Type.RIGHT, 10));
83 | elements.add(toggle);
84 |
85 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), btn ->
86 | {
87 | getWorkspace().removeWindow(parent);
88 | });
89 | button.setSize(60, 20);
90 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
91 | elements.add(button);
92 |
93 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), btn ->
94 | {
95 | for(ElementList.Item> item : list.items)
96 | {
97 | if(item.selected)
98 | {
99 | loadFile((File)item.getObject());
100 | return;
101 | }
102 | }
103 | });
104 | button1.setSize(60, 20);
105 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
106 | elements.add(button1);
107 | }
108 |
109 | public void loadFile(File file)
110 | {
111 | parentFragment.parent.removeWindow(parentFragment);
112 |
113 | Project project = ImportList.createProjectFromFile(file);
114 | if(project == null)
115 | {
116 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("window.open.failed"));
117 | }
118 | else
119 | {
120 | parentFragment.parent.mainframe.importProject(project, ((ElementToggle)getById("buttonTexture")).toggleState, true);
121 | }
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowNewProject.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementNumberInput;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextField;
9 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextWrapper;
10 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
11 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
12 | import me.ichun.mods.tabula.common.Tabula;
13 | import net.minecraft.client.Minecraft;
14 | import net.minecraft.client.resources.I18n;
15 |
16 | import javax.annotation.Nonnull;
17 | import java.util.function.Consumer;
18 |
19 | public class WindowNewProject extends Window
20 | {
21 | public WindowNewProject(WorkspaceTabula parent)
22 | {
23 | super(parent);
24 |
25 | setView(new ViewNewProject(this));
26 | disableDockingEntirely();
27 | }
28 |
29 | public static class ViewNewProject extends View
30 | {
31 | public ViewNewProject(@Nonnull WindowNewProject parent)
32 | {
33 | super(parent, "window.newProject.title");
34 |
35 | Consumer enterResponder = s -> {
36 | if(!s.isEmpty())
37 | {
38 | submit();
39 | }
40 | };
41 |
42 | ElementTextWrapper text = new ElementTextWrapper(this);
43 | text.setNoWrap().setText(I18n.format("window.newProject.projIdent"));
44 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(this, Constraint.Property.Type.TOP, 20));
45 | elements.add(text);
46 |
47 | ElementTextField textField = new ElementTextField(this);
48 | textField.setId("modelName");
49 | textField.setDefaultText("MyFirstModel").setEnterResponder(enterResponder);
50 | textField.setConstraint(new Constraint(textField).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
51 | elements.add(textField);
52 |
53 | text = new ElementTextWrapper(this);
54 | text.setNoWrap().setText(I18n.format("window.newProject.animName"));
55 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(textField, Constraint.Property.Type.BOTTOM, 20));
56 | elements.add(text);
57 |
58 | textField = new ElementTextField(this);
59 | textField.setId("author");
60 | textField.setDefaultText(Minecraft.getInstance().getSession().getUsername()).setEnterResponder(enterResponder);
61 | textField.setConstraint(new Constraint(textField).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
62 | elements.add(textField);
63 |
64 | text = new ElementTextWrapper(this);
65 | text.setNoWrap().setText(I18n.format("window.controls.scale"));
66 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(textField, Constraint.Property.Type.BOTTOM, 20));
67 | elements.add(text);
68 |
69 | ElementNumberInput numberInput = new ElementNumberInput(this, true);
70 | numberInput.setId("scaleX");
71 | numberInput.setMin(0).setMaxDec(Tabula.configClient.guiMaxDecimals).setDefaultText("1");
72 | numberInput.setWidth(80);
73 | numberInput.setConstraint(new Constraint(numberInput).left(this, Constraint.Property.Type.LEFT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
74 | elements.add(numberInput);
75 |
76 | ElementNumberInput numberInput1 = new ElementNumberInput(this, true);
77 | numberInput1.setId("scaleY");
78 | numberInput1.setMin(0).setMaxDec(Tabula.configClient.guiMaxDecimals).setDefaultText("1");
79 | numberInput1.setWidth(80);
80 | numberInput1.setConstraint(new Constraint(numberInput1).left(numberInput, Constraint.Property.Type.RIGHT, 3));
81 | elements.add(numberInput1);
82 |
83 | ElementNumberInput numberInput2 = new ElementNumberInput(this, true);
84 | numberInput2.setId("scaleZ");
85 | numberInput2.setMin(0).setMaxDec(Tabula.configClient.guiMaxDecimals).setDefaultText("1");
86 | numberInput2.setWidth(80);
87 | numberInput2.setConstraint(new Constraint(numberInput2).left(numberInput1, Constraint.Property.Type.RIGHT, 3));
88 | elements.add(numberInput2);
89 |
90 | text = new ElementTextWrapper(this);
91 | text.setNoWrap().setText(I18n.format("window.newProject.txDimensions"));
92 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(numberInput, Constraint.Property.Type.BOTTOM, 20));
93 | elements.add(text);
94 |
95 | numberInput = new ElementNumberInput(this, false);
96 | numberInput.setTooltip(I18n.format("tabula.project.width")).setId("texWidth");
97 | numberInput.setMin(1).setDefaultText("64");
98 | numberInput.setWidth(80);
99 | numberInput.setConstraint(new Constraint(numberInput).left(this, Constraint.Property.Type.LEFT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
100 | elements.add(numberInput);
101 |
102 | numberInput1 = new ElementNumberInput(this, false);
103 | numberInput1.setTooltip(I18n.format("tabula.project.height")).setId("texHeight");
104 | numberInput1.setMin(1).setDefaultText("32");
105 | numberInput1.setWidth(80);
106 | numberInput1.setConstraint(new Constraint(numberInput1).left(numberInput, Constraint.Property.Type.RIGHT, 3));
107 | elements.add(numberInput1);
108 |
109 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), elementClickable ->
110 | {
111 | getWorkspace().removeWindow(parent);
112 | });
113 | button.setSize(60, 20);
114 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
115 | elements.add(button);
116 |
117 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), elementClickable -> submit());
118 | button1.setSize(60, 20);
119 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
120 | elements.add(button1);
121 | }
122 |
123 | public void submit()
124 | {
125 | Project project = new Project();
126 | project.name = ((ElementTextField)getById("modelName")).getText();
127 | if(project.name.isEmpty())
128 | {
129 | project.name = "NewProject";
130 | }
131 | project.author = ((ElementTextField)getById("author")).getText();
132 | if(project.author.isEmpty())
133 | {
134 | project.author = "Undefined";
135 | }
136 | project.scaleX = (float)((ElementNumberInput)getById("scaleX")).getDouble();
137 | project.scaleY = (float)((ElementNumberInput)getById("scaleY")).getDouble();
138 | project.scaleZ = (float)((ElementNumberInput)getById("scaleZ")).getDouble();
139 |
140 | project.texWidth = ((ElementNumberInput)getById("texWidth")).getInt();
141 | project.texHeight = ((ElementNumberInput)getById("texHeight")).getInt();
142 | project.markDirty();
143 | parentFragment.parent.mainframe.openProject(project, true);
144 | getWorkspace().removeWindow(parentFragment);
145 | }
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowNewTexture.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import com.google.common.collect.Ordering;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.*;
8 | import me.ichun.mods.ichunutil.common.util.IOUtil;
9 | import me.ichun.mods.tabula.client.core.ResourceHelper;
10 | import me.ichun.mods.tabula.client.gui.IProjectInfo;
11 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
12 | import me.ichun.mods.tabula.client.tabula.Mainframe;
13 | import net.minecraft.client.renderer.texture.NativeImage;
14 | import net.minecraft.client.resources.I18n;
15 | import net.minecraft.util.ResourceLocation;
16 | import net.minecraft.util.Util;
17 |
18 | import javax.annotation.Nonnull;
19 | import java.io.File;
20 | import java.io.FileInputStream;
21 | import java.io.IOException;
22 | import java.util.TreeSet;
23 |
24 | public class WindowNewTexture extends Window
25 | {
26 | public Mainframe.ProjectInfo projectInfo;
27 |
28 | public WindowNewTexture(WorkspaceTabula parent, Mainframe.ProjectInfo projectInfo)
29 | {
30 | super(parent);
31 | this.projectInfo = projectInfo;
32 |
33 | setView(new ViewNewTexture(this));
34 | disableDockingEntirely();
35 | }
36 |
37 | public static class ViewNewTexture extends View
38 | {
39 | public ViewNewTexture(@Nonnull WindowNewTexture parent)
40 | {
41 | super(parent, "window.loadTexture.title");
42 |
43 | ElementScrollBar> sv = new ElementScrollBar<>(this, ElementScrollBar.Orientation.VERTICAL, 0.6F);
44 | sv.setConstraint(new Constraint(sv).top(this, Constraint.Property.Type.TOP, 0)
45 | .bottom(this, Constraint.Property.Type.BOTTOM, 40) // 10 + 20 + 10, bottom + button height + padding
46 | .right(this, Constraint.Property.Type.RIGHT, 0)
47 | );
48 | elements.add(sv);
49 |
50 | ElementList> list = new ElementList<>(this).setScrollVertical(sv);
51 | list.setConstraint(new Constraint(list).bottom(this, Constraint.Property.Type.BOTTOM, 40)
52 | .left(this, Constraint.Property.Type.LEFT, 0).right(sv, Constraint.Property.Type.LEFT, 0)
53 | .top(this, Constraint.Property.Type.TOP, 0));
54 | elements.add(list);
55 |
56 | TreeSet files = new TreeSet<>(Ordering.natural());
57 | File[] textures = ResourceHelper.getTexturesDir().toFile().listFiles();
58 | if(textures != null)
59 | {
60 | for(File file : textures)
61 | {
62 | if(!file.isDirectory() && file.getName().endsWith(".png"))
63 | {
64 | files.add(file);
65 | }
66 | }
67 | }
68 |
69 | for(File file : files)
70 | {
71 | list.addItem(file).setDefaultAppearance().setDoubleClickHandler(item -> {
72 | if(item.selected)
73 | {
74 | loadFile(item.getObject());
75 | }
76 | });
77 | }
78 | list.init();
79 |
80 | ElementButtonTextured> openDir = new ElementButtonTextured<>(this, new ResourceLocation("tabula", "textures/icon/info.png"), btn -> {
81 | Util.getOSType().openFile(ResourceHelper.getTexturesDir().toFile());
82 | });
83 | openDir.setTooltip(I18n.format("topdock.openWorkingDir")).setSize(20, 20);
84 | openDir.setConstraint(new Constraint(openDir).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(this, Constraint.Property.Type.LEFT, 10));
85 | elements.add(openDir);
86 |
87 | ElementToggle> toggle = new ElementToggle<>(this, "window.loadTexture.updateTextureDimensions", btn -> {});
88 | toggle.setToggled(true).setTooltip(I18n.format("window.loadTexture.updateTextureDimensionsFull")).setSize(60, 20).setId("buttonTexture");
89 | toggle.setConstraint(new Constraint(toggle).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(openDir, Constraint.Property.Type.RIGHT, 10));
90 | elements.add(toggle);
91 |
92 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), btn ->
93 | {
94 | getWorkspace().removeWindow(parent);
95 | });
96 | button.setSize(60, 20);
97 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
98 | elements.add(button);
99 |
100 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), btn ->
101 | {
102 | for(ElementList.Item> item : list.items)
103 | {
104 | if(item.selected)
105 | {
106 | loadFile((File)item.getObject());
107 | return;
108 | }
109 | }
110 | });
111 | button1.setSize(60, 20);
112 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
113 | elements.add(button1);
114 | }
115 |
116 | public void loadFile(File file)
117 | {
118 | parentFragment.parent.removeWindow(parentFragment);
119 |
120 | Mainframe.ProjectInfo info = parentFragment.parent.mainframe.getActiveProject();
121 | if(info != null)
122 | {
123 | parentFragment.projectInfo.textureFile = file;
124 | parentFragment.projectInfo.project.textureFile = file.getName();
125 | parentFragment.projectInfo.project.textureFileMd5 = IOUtil.getMD5Checksum(file);
126 |
127 | byte[] image = null;
128 | try (NativeImage img = NativeImage.read(new FileInputStream(file)))
129 | {
130 | image = img.getBytes();
131 |
132 | if(!(parentFragment.projectInfo.project.texWidth == img.getWidth() && parentFragment.projectInfo.project.texHeight == img.getHeight()) && ((ElementToggle)getById("buttonTexture")).toggleState)
133 | {
134 | parentFragment.projectInfo.project.texWidth = img.getWidth();
135 | parentFragment.projectInfo.project.texHeight = img.getHeight();
136 | parentFragment.parent.projectChanged(IProjectInfo.ChangeType.PROJECT);
137 | }
138 | }
139 | catch(IOException ignored){}
140 |
141 | parentFragment.parent.mainframe.setImage(info, image, true);
142 | }
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowOpenProject.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import com.google.common.collect.Ordering;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
9 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButtonTextured;
10 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementList;
11 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementScrollBar;
12 | import me.ichun.mods.ichunutil.common.module.tabula.formats.ImportList;
13 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
14 | import me.ichun.mods.tabula.client.core.ResourceHelper;
15 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
16 | import me.ichun.mods.tabula.common.Tabula;
17 | import net.minecraft.client.resources.I18n;
18 | import net.minecraft.util.ResourceLocation;
19 | import net.minecraft.util.Util;
20 |
21 | import javax.annotation.Nonnull;
22 | import java.io.File;
23 | import java.util.TreeSet;
24 |
25 | public class WindowOpenProject extends Window
26 | {
27 | public WindowOpenProject(WorkspaceTabula parent)
28 | {
29 | super(parent);
30 |
31 | setView(new ViewOpenProject(this));
32 | disableDockingEntirely();
33 | }
34 |
35 | public static class ViewOpenProject extends View
36 | {
37 | public ViewOpenProject(@Nonnull WindowOpenProject parent)
38 | {
39 | super(parent, "window.open.title");
40 |
41 | ElementScrollBar> sv = new ElementScrollBar<>(this, ElementScrollBar.Orientation.VERTICAL, 0.6F);
42 | sv.setConstraint(new Constraint(sv).top(this, Constraint.Property.Type.TOP, 0)
43 | .bottom(this, Constraint.Property.Type.BOTTOM, 40) // 10 + 20 + 10, bottom + button height + padding
44 | .right(this, Constraint.Property.Type.RIGHT, 0)
45 | );
46 | elements.add(sv);
47 |
48 | ElementList> list = new ElementList<>(this).setScrollVertical(sv);
49 | list.setConstraint(new Constraint(list).bottom(this, Constraint.Property.Type.BOTTOM, 40)
50 | .left(this, Constraint.Property.Type.LEFT, 0).right(sv, Constraint.Property.Type.LEFT, 0)
51 | .top(this, Constraint.Property.Type.TOP, 0));
52 | elements.add(list);
53 |
54 | TreeSet files = new TreeSet<>(Ordering.natural());
55 | File[] textures = ResourceHelper.getSavesDir().toFile().listFiles();
56 | if(textures != null)
57 | {
58 | for(File file : textures)
59 | {
60 | if(!file.isDirectory() && ImportList.isFileSupported(file))
61 | {
62 | files.add(file);
63 | }
64 | }
65 | }
66 |
67 | for(File file : files)
68 | {
69 | list.addItem(file).setDefaultAppearance().setDoubleClickHandler(item -> {
70 | if(item.selected)
71 | {
72 | loadFile(item.getObject());
73 | }
74 | });
75 | }
76 |
77 | ElementButtonTextured> openDir = new ElementButtonTextured<>(this, new ResourceLocation("tabula", "textures/icon/info.png"), btn -> {
78 | Util.getOSType().openFile(ResourceHelper.getSavesDir().toFile());
79 | });
80 | openDir.setTooltip(I18n.format("topdock.openWorkingDir")).setSize(20, 20);
81 | openDir.setConstraint(new Constraint(openDir).bottom(this, Constraint.Property.Type.BOTTOM, 10).left(this, Constraint.Property.Type.LEFT, 10));
82 | elements.add(openDir);
83 |
84 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), btn ->
85 | {
86 | getWorkspace().removeWindow(parent);
87 | });
88 | button.setSize(60, 20);
89 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
90 | elements.add(button);
91 |
92 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), btn ->
93 | {
94 | for(ElementList.Item> item : list.items)
95 | {
96 | if(item.selected)
97 | {
98 | loadFile((File)item.getObject());
99 | return;
100 | }
101 | }
102 | });
103 | button1.setSize(60, 20);
104 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
105 | elements.add(button1);
106 | }
107 |
108 | public void loadFile(File file)
109 | {
110 | parentFragment.parent.removeWindow(parentFragment);
111 |
112 | Project project = ImportList.createProjectFromFile(file);
113 | if(project == null)
114 | {
115 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("window.open.failed"));
116 | }
117 | else
118 | {
119 | if(project.tampered)
120 | {
121 | WindowPopup.popup(parentFragment.parent, 0.5D, 160, null, I18n.format("window.open.tampered"));
122 | }
123 |
124 | if(project.isOldTabula && !Tabula.configClient.ignoreOldTabulaWarning)
125 | {
126 | WindowPopup.popup(parentFragment.parent, 0.5D, 300, null, I18n.format("window.open.oldTabula1"), I18n.format("window.open.oldTabula2"), I18n.format("window.open.oldTabula3"), I18n.format("window.open.oldTabula4"));
127 | }
128 |
129 | parentFragment.parent.mainframe.openProject(project, true);
130 | }
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowSaveAs.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextField;
9 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextWrapper;
10 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
11 | import me.ichun.mods.tabula.client.core.ResourceHelper;
12 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
13 | import net.minecraft.client.resources.I18n;
14 |
15 | import javax.annotation.Nonnull;
16 | import java.io.File;
17 |
18 | public class WindowSaveAs extends Window
19 | {
20 | public WindowSaveAs(WorkspaceTabula parent, Project project)
21 | {
22 | super(parent);
23 |
24 | setView(new ViewSaveAs(this, project));
25 | disableDockingEntirely();
26 | }
27 |
28 | public static class ViewSaveAs extends View
29 | {
30 | @Nonnull
31 | public final Project project;
32 |
33 | public ViewSaveAs(@Nonnull WindowSaveAs parent, Project project)
34 | {
35 | super(parent, "window.saveAs.title");
36 | this.project = project;
37 |
38 | ElementTextWrapper text = new ElementTextWrapper(this);
39 | text.setNoWrap().setText(I18n.format("window.saveAs.fileName"));
40 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(this, Constraint.Property.Type.TOP, 20));
41 | elements.add(text);
42 |
43 | ElementTextField textField = new ElementTextField(this);
44 | textField.setId("fileName");
45 | textField.setValidator(ElementTextField.FILE_SAFE).setEnterResponder(s -> {
46 | submit();
47 | });
48 | textField.setDefaultText(project.name).setHeight(14);
49 | textField.setConstraint(new Constraint(textField).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(text, Constraint.Property.Type.BOTTOM, 3));
50 | elements.add(textField);
51 |
52 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), elementClickable ->
53 | {
54 | parent.parent.removeWindow(parent);
55 | });
56 | button.setSize(60, 20);
57 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
58 | elements.add(button);
59 |
60 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), button2 ->
61 | {
62 | submit();
63 | });
64 | button1.setSize(60, 20);
65 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
66 | elements.add(button1);
67 | }
68 |
69 | public void submit()
70 | {
71 | String fileName = ((ElementTextField)getById("fileName")).getText();
72 | if(!fileName.isEmpty())
73 | {
74 | if(!fileName.endsWith(".tbl"))
75 | {
76 | fileName = fileName + ".tbl";
77 | }
78 |
79 | File file = new File(ResourceHelper.getSavesDir().toFile(), fileName);
80 |
81 | if(file.exists())
82 | {
83 | getWorkspace().openWindowInCenter(new WindowSaveOverwrite(getWorkspace(), project, file), 0.6D, 0.8D);
84 | }
85 | else
86 | {
87 | parentFragment.parent.removeWindow(parentFragment);
88 |
89 | if(!project.save(file))
90 | {
91 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("window.saveAs.failed"));
92 | }
93 | }
94 | }
95 | }
96 | }
97 |
98 | @Override
99 | public void onClose()
100 | {
101 | super.onClose();
102 | WindowSaveOverwrite window = parent.getByWindowType(WindowSaveOverwrite.class);
103 | if(window != null)
104 | {
105 | getWorkspace().removeWindow(window);
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/gui/window/popup/WindowSaveOverwrite.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.gui.window.popup;
2 |
3 | import me.ichun.mods.ichunutil.client.gui.bns.window.Window;
4 | import me.ichun.mods.ichunutil.client.gui.bns.window.WindowPopup;
5 | import me.ichun.mods.ichunutil.client.gui.bns.window.constraint.Constraint;
6 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.View;
7 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementButton;
8 | import me.ichun.mods.ichunutil.client.gui.bns.window.view.element.ElementTextWrapper;
9 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
10 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
11 | import net.minecraft.client.resources.I18n;
12 |
13 | import javax.annotation.Nonnull;
14 | import java.io.File;
15 |
16 | public class WindowSaveOverwrite extends Window
17 | {
18 | public WindowSaveOverwrite(WorkspaceTabula parent, Project project, File saveFile)
19 | {
20 | super(parent);
21 |
22 | setView(new ViewSaveAs(this, project, saveFile));
23 | disableDockingEntirely();
24 | }
25 |
26 | public static class ViewSaveAs extends View
27 | {
28 | @Nonnull
29 | public final Project project;
30 | public final File saveFile;
31 |
32 | public ViewSaveAs(@Nonnull WindowSaveOverwrite parent, Project project, File file)
33 | {
34 | super(parent, "window.saveAs.overwrite");
35 | this.project = project;
36 | this.saveFile = file;
37 |
38 | ElementTextWrapper text = new ElementTextWrapper(this);
39 | text.setNoWrap().setText(I18n.format("window.saveAs.confirmOverwrite"));
40 | text.setConstraint(new Constraint(text).left(this, Constraint.Property.Type.LEFT, 20).right(this, Constraint.Property.Type.RIGHT, 20).top(this, Constraint.Property.Type.TOP, 20));
41 | elements.add(text);
42 |
43 | ElementButton> button = new ElementButton<>(this, I18n.format("gui.cancel"), elementClickable ->
44 | {
45 | parent.parent.removeWindow(parent);
46 | });
47 | button.setSize(60, 20);
48 | button.setConstraint(new Constraint(button).bottom(this, Constraint.Property.Type.BOTTOM, 10).right(this, Constraint.Property.Type.RIGHT, 10));
49 | elements.add(button);
50 |
51 | ElementButton> button1 = new ElementButton<>(this, I18n.format("gui.ok"), button2 ->
52 | {
53 | parent.parent.removeWindow(parent);
54 |
55 | WindowSaveAs window = parent.parent.getByWindowType(WindowSaveAs.class);
56 | if(window != null)
57 | {
58 | getWorkspace().removeWindow(window);
59 | }
60 |
61 | if(!project.save(file))
62 | {
63 | WindowPopup.popup(parentFragment.parent, 0.4D, 140, null, I18n.format("window.saveAs.failed"));
64 | }
65 | });
66 | button1.setSize(60, 20);
67 | button1.setConstraint(new Constraint(button1).right(button, Constraint.Property.Type.LEFT, 10));
68 | elements.add(button1);
69 | }
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/model/ModelVoxel.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.model;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import com.mojang.blaze3d.vertex.IVertexBuilder;
5 | import me.ichun.mods.ichunutil.client.model.tabula.ModelTabula;
6 | import net.minecraft.client.renderer.model.Model;
7 | import net.minecraft.client.renderer.model.ModelRenderer;
8 |
9 | /**
10 | * Created using Tabula 5.0.0
11 | */
12 | public class ModelVoxel extends Model
13 | {
14 | public ModelRenderer shape1;
15 |
16 | public ModelVoxel()
17 | {
18 | super(rl -> ModelTabula.RENDER_MODEL_COMPASS_FLAT);
19 | this.textureWidth = 4;
20 | this.textureHeight = 2;
21 | this.shape1 = new ModelRenderer(this, 0, 0);
22 | this.shape1.setRotationPoint(0.0F, 0.0F, 0.0F);
23 | this.shape1.addBox(-0.5F, -0.5F, -0.5F, 1, 1, 1, 0.0F);
24 | }
25 |
26 | @Override
27 | public void render(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha)
28 | {
29 | shape1.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/model/ModelWaxTablet.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.model;
2 |
3 | import com.google.common.collect.ImmutableList;
4 | import com.mojang.blaze3d.matrix.MatrixStack;
5 | import com.mojang.blaze3d.vertex.IVertexBuilder;
6 | import net.minecraft.client.renderer.RenderType;
7 | import net.minecraft.client.renderer.model.Model;
8 | import net.minecraft.client.renderer.model.ModelRenderer;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Wax Tablet - iChun
14 | * Created using Tabula 4.1.0
15 | * Updated whilst writing Tabula 8.0.0 :)
16 | */
17 | public class ModelWaxTablet extends Model
18 | {
19 | public float[] modelScale = new float[] { 2.0F, 2.0F, 2.0F };
20 | public ModelRenderer bBindTop;
21 | public ModelRenderer bBindLeft;
22 | public ModelRenderer bBindRight;
23 | public ModelRenderer bBindBottom;
24 | public ModelRenderer fBindTop;
25 | public ModelRenderer fBindLeft;
26 | public ModelRenderer fBindRight;
27 | public ModelRenderer fBindBottom;
28 | public ModelRenderer lBorderL;
29 | public ModelRenderer lBorderR;
30 | public ModelRenderer lBorderFront;
31 | public ModelRenderer lBorderBack;
32 | public ModelRenderer lPage;
33 | public ModelRenderer rBorderL;
34 | public ModelRenderer rBorderR;
35 | public ModelRenderer rBorderFront;
36 | public ModelRenderer rBorderBack;
37 | public ModelRenderer rPage;
38 | public List modelRenderers;
39 |
40 | public ModelWaxTablet() {
41 | super(RenderType::getEntityCutoutNoCull);
42 | this.textureWidth = 64;
43 | this.textureHeight = 32;
44 | this.bBindBottom = new ModelRenderer(this, 0, 0);
45 | this.bBindBottom.setRotationPoint(-1.0F, 0.8999999999999986F, 3.0F);
46 | this.bBindBottom.addBox(0.0F, 0.0F, 0.0F, 2, 1, 1, 0.0F);
47 | this.lBorderBack = new ModelRenderer(this, 0, 15);
48 | this.lBorderBack.setRotationPoint(-9.5F, 0.0F, 7.0F);
49 | this.lBorderBack.addBox(0.0F, 0.0F, 0.0F, 7, 2, 2, 0.0F);
50 | this.bBindRight = new ModelRenderer(this, 0, 2);
51 | this.bBindRight.setRotationPoint(1.0F, -1.2000000000000028F, 3.0F);
52 | this.bBindRight.addBox(0.0F, 0.0F, 0.0F, 1, 2, 1, 0.0F);
53 | this.fBindLeft = new ModelRenderer(this, 0, 2);
54 | this.fBindLeft.setRotationPoint(-2.0F, -1.2000000000000028F, -4.0F);
55 | this.fBindLeft.addBox(0.0F, 0.0F, 0.0F, 1, 2, 1, 0.0F);
56 | this.fBindTop = new ModelRenderer(this, 0, 0);
57 | this.fBindTop.setRotationPoint(-1.0F, -1.2000000000000028F, -4.0F);
58 | this.fBindTop.addBox(0.0F, 0.0F, 0.0F, 2, 1, 1, 0.0F);
59 | this.lBorderFront = new ModelRenderer(this, 0, 15);
60 | this.lBorderFront.setRotationPoint(-9.5F, 0.0F, -9.0F);
61 | this.lBorderFront.addBox(0.0F, 0.0F, 0.0F, 7, 2, 2, 0.0F);
62 | this.rBorderR = new ModelRenderer(this, 24, 0);
63 | this.rBorderR.setRotationPoint(9.5F, 0.0F, -9.0F);
64 | this.rBorderR.addBox(0.0F, 0.0F, 0.0F, 2, 2, 18, 0.0F);
65 | this.bBindLeft = new ModelRenderer(this, 0, 2);
66 | this.bBindLeft.setRotationPoint(-2.0F, -1.2000000000000028F, 3.0F);
67 | this.bBindLeft.addBox(0.0F, 0.0F, 0.0F, 1, 2, 1, 0.0F);
68 | this.lBorderL = new ModelRenderer(this, 24, 0);
69 | this.lBorderL.setRotationPoint(-11.5F, 0.0F, -9.0F);
70 | this.lBorderL.addBox(0.0F, 0.0F, 0.0F, 2, 2, 18, 0.0F);
71 | this.rPage = new ModelRenderer(this, -8, 0);
72 | this.rPage.setRotationPoint(2.5F, 1.0F, -7.0F);
73 | this.rPage.addBox(0.0F, 0.0F, 0.0F, 7, 1, 14, 0.0F);
74 | this.rBorderBack = new ModelRenderer(this, 0, 15);
75 | this.rBorderBack.setRotationPoint(2.5F, 0.0F, 7.0F);
76 | this.rBorderBack.addBox(0.0F, 0.0F, 0.0F, 7, 2, 2, 0.0F);
77 | this.fBindBottom = new ModelRenderer(this, 0, 0);
78 | this.fBindBottom.setRotationPoint(-1.0F, 0.8999999999999986F, -4.0F);
79 | this.fBindBottom.addBox(0.0F, 0.0F, 0.0F, 2, 1, 1, 0.0F);
80 | this.bBindTop = new ModelRenderer(this, 0, 0);
81 | this.bBindTop.setRotationPoint(-1.0F, -1.2000000000000028F, 3.0F);
82 | this.bBindTop.addBox(0.0F, 0.0F, 0.0F, 2, 1, 1, 0.0F);
83 | this.fBindRight = new ModelRenderer(this, 0, 2);
84 | this.fBindRight.setRotationPoint(1.0F, -1.2000000000000028F, -4.0F);
85 | this.fBindRight.addBox(0.0F, 0.0F, 0.0F, 1, 2, 1, 0.0F);
86 | this.lPage = new ModelRenderer(this, -8, 0);
87 | this.lPage.setRotationPoint(-9.5F, 1.0F, -7.0F);
88 | this.lPage.addBox(0.0F, 0.0F, 0.0F, 7, 1, 14, 0.0F);
89 | this.rBorderFront = new ModelRenderer(this, 0, 15);
90 | this.rBorderFront.setRotationPoint(2.5F, 0.0F, -9.0F);
91 | this.rBorderFront.addBox(0.0F, 0.0F, 0.0F, 7, 2, 2, 0.0F);
92 | this.lBorderR = new ModelRenderer(this, 2, 2);
93 | this.lBorderR.setRotationPoint(-2.5F, 0.0F, -9.0F);
94 | this.lBorderR.addBox(0.0F, 0.0F, 0.0F, 2, 2, 18, 0.0F);
95 | this.rBorderL = new ModelRenderer(this, 2, 2);
96 | this.rBorderL.setRotationPoint(0.5F, 0.0F, -9.0F);
97 | this.rBorderL.addBox(0.0F, 0.0F, 0.0F, 2, 2, 18, 0.0F);
98 |
99 | modelRenderers = ImmutableList.of(
100 | this.bBindBottom,
101 | this.lBorderBack,
102 | this.bBindRight,
103 | this.fBindLeft,
104 | this.fBindTop,
105 | this.lBorderFront,
106 | this.rBorderR,
107 | this.bBindLeft,
108 | this.lBorderL,
109 | this.rPage,
110 | this.rBorderBack,
111 | this.fBindBottom,
112 | this.bBindTop,
113 | this.fBindRight,
114 | this.lPage,
115 | this.rBorderFront,
116 | this.lBorderR,
117 | this.rBorderL);
118 | }
119 |
120 | @Override
121 | public void render(MatrixStack matrixStackIn, IVertexBuilder bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha)
122 | {
123 | matrixStackIn.scale(1F / modelScale[0], 1F / modelScale[1], 1F / modelScale[2]);
124 | modelRenderers.forEach(modelRenderer -> {
125 | modelRenderer.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
126 | });
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/client/render/TileRendererTabulaRasa.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.client.render;
2 |
3 | import com.mojang.blaze3d.matrix.MatrixStack;
4 | import com.mojang.blaze3d.systems.RenderSystem;
5 | import me.ichun.mods.tabula.client.model.ModelWaxTablet;
6 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.renderer.IRenderTypeBuffer;
9 | import net.minecraft.client.renderer.RenderType;
10 | import net.minecraft.client.renderer.model.RenderMaterial;
11 | import net.minecraft.client.renderer.texture.AtlasTexture;
12 | import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
13 | import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
14 | import net.minecraft.util.ResourceLocation;
15 | import net.minecraft.util.math.vector.Vector3f;
16 |
17 | public class TileRendererTabulaRasa extends TileEntityRenderer
18 | {
19 | public static final RenderMaterial MATERIAL_MODEL = new RenderMaterial(AtlasTexture.LOCATION_BLOCKS_TEXTURE, new ResourceLocation("tabula", "model/tabularasa"));
20 | public ModelWaxTablet model;
21 |
22 | public TileRendererTabulaRasa(TileEntityRendererDispatcher dispatcher)
23 | {
24 | super(dispatcher);
25 | model = new ModelWaxTablet();
26 | }
27 |
28 | @Override
29 | public void render(TileEntityTabulaRasa tr, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int combinedLightIn, int combinedOverlayIn)
30 | {
31 | matrixStackIn.push();
32 | matrixStackIn.translate(0.5D, 0.0625D, 0.5D);
33 | matrixStackIn.scale(-1F, -1F, 1F);
34 |
35 | matrixStackIn.rotate(Vector3f.YP.rotationDegrees((tr.facing.getHorizontalIndex() * 90F)));
36 |
37 | model.render(matrixStackIn, MATERIAL_MODEL.getBuffer(bufferIn, RenderType::getEntityCutoutNoCull), combinedLightIn, combinedOverlayIn, 1F, 1F, 1F, 1F);
38 |
39 | if(!tr.host.isEmpty())
40 | {
41 | if(tr.projectReq <= 0)
42 | {
43 | tr.projectReq = 100;
44 | tr.requestProject();
45 | }
46 |
47 | if(tr.project != null)
48 | {
49 | RenderSystem.enableBlend();
50 | RenderSystem.defaultBlendFunc();
51 |
52 | matrixStackIn.push();
53 |
54 | matrixStackIn.scale(0.2F, 0.2F, 0.2F);
55 | matrixStackIn.translate(0F, -2.6005F, 0F);
56 |
57 | float ticks = Minecraft.getInstance().player.ticksExisted + partialTicks;
58 | matrixStackIn.translate(0F, 0.5F * Math.sin(Math.toRadians(ticks * 2)), 0F);
59 | matrixStackIn.rotate(Vector3f.YP.rotationDegrees(1F * ticks));
60 |
61 | tr.project.getModel().render(matrixStackIn, null, null, false, 1F);
62 |
63 | matrixStackIn.pop();
64 | }
65 | }
66 |
67 | matrixStackIn.pop();
68 |
69 | // if(!tr.host.isEmpty() && !tr.currentProj.isEmpty())
70 | // {
71 | // ProjectInfo info = ProjectHelper.projects.get(tr.currentProj);
72 | // if(info != null && !info.destroyed)
73 | // {
74 | // if(info.model == null)
75 | // {
76 | // info.initClient();
77 | // }
78 | //
79 | // ArrayList hidden = new ArrayList<>();
80 | // for(CubeGroup group1 : info.cubeGroups)
81 | // {
82 | // GuiWorkspace.addElementsForHiding(group1, hidden);
83 | // }
84 | //
85 | // GlStateManager.pushMatrix();
86 | //
87 | // GlStateManager.enableBlend();
88 | // GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
89 | //
90 | // GlStateManager.disableCull();
91 | //
92 | // GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
93 | //
94 | // float scale = 0.3F;
95 | //
96 | // float size = info.getMaximumSize();
97 | // if(size != 0)
98 | // {
99 | // scale = 0.3F * 16F / size;
100 | // }
101 | //
102 | // GlStateManager.rotate((tr.age + f) / 2F, 0.0F, 1.0F, 0.0F);
103 | //
104 | // GlStateManager.translate(0.0F, -0.6F + (-0.075F * (float)Math.sin((tr.age + f) / 10F)), 0.0F);
105 | //
106 | // GlStateManager.scale(scale, scale, scale);
107 | //
108 | // GlStateManager.scale(1D / info.scale[0], 1D / info.scale[1], 1D / info.scale[2]);
109 | //
110 | // if(info.bufferedTexture != null)
111 | // {
112 | // Integer id = ProjectHelper.projectTextureIDs.computeIfAbsent(info.bufferedTexture, k -> TextureUtil.uploadTextureImage(TextureUtil.glGenTextures(), info.bufferedTexture));
113 | //
114 | // GlStateManager.bindTexture(id);
115 | //
116 | // info.model.render(0.0625F, new ArrayList<>(), hidden, 1.0F, true, 1, false, true);
117 | // }
118 | // else
119 | // {
120 | // GlStateManager.disableTexture2D();
121 | // GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
122 | //
123 | // info.model.render(0.0625F, new ArrayList<>(), hidden, 1.0F, false, 1, false, true);
124 | //
125 | // GlStateManager.enableTexture2D();
126 | // }
127 | //
128 | // GlStateManager.enableCull();
129 | // GlStateManager.popMatrix();
130 | // }
131 | // }
132 |
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/Tabula.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.TabulaPlugin;
4 | import me.ichun.mods.ichunutil.common.network.PacketChannel;
5 | import me.ichun.mods.tabula.client.core.ConfigClient;
6 | import me.ichun.mods.tabula.client.core.EventHandlerClient;
7 | import me.ichun.mods.tabula.client.core.ResourceHelper;
8 | import me.ichun.mods.tabula.client.render.TileRendererTabulaRasa;
9 | import me.ichun.mods.tabula.common.block.BlockTabulaRasa;
10 | import me.ichun.mods.tabula.common.packet.*;
11 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
12 | import net.minecraft.block.Block;
13 | import net.minecraft.client.renderer.model.Model;
14 | import net.minecraft.client.renderer.texture.AtlasTexture;
15 | import net.minecraft.item.BlockItem;
16 | import net.minecraft.item.Item;
17 | import net.minecraft.item.ItemGroup;
18 | import net.minecraft.tileentity.TileEntityType;
19 | import net.minecraft.util.ResourceLocation;
20 | import net.minecraftforge.api.distmarker.Dist;
21 | import net.minecraftforge.api.distmarker.OnlyIn;
22 | import net.minecraftforge.client.event.TextureStitchEvent;
23 | import net.minecraftforge.common.MinecraftForge;
24 | import net.minecraftforge.eventbus.api.IEventBus;
25 | import net.minecraftforge.fml.*;
26 | import net.minecraftforge.fml.client.registry.ClientRegistry;
27 | import net.minecraftforge.fml.common.Mod;
28 | import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
29 | import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
30 | import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
31 | import net.minecraftforge.fml.loading.FMLEnvironment;
32 | import net.minecraftforge.registries.DeferredRegister;
33 | import net.minecraftforge.registries.ForgeRegistries;
34 | import org.apache.logging.log4j.LogManager;
35 | import org.apache.logging.log4j.Logger;
36 |
37 | import java.util.HashSet;
38 |
39 | @Mod(Tabula.MOD_ID)
40 | public class Tabula
41 | {
42 | public static final String MOD_ID = "tabula";
43 | public static final String MOD_NAME = "Tabula";
44 | public static final String VERSION = "8.0.0";
45 | public static final String PROTOCOL = "1";
46 |
47 | public static final Logger LOGGER = LogManager.getLogger();
48 |
49 | public static ConfigClient configClient;
50 |
51 | public static EventHandlerClient eventHandlerClient;
52 |
53 | public static PacketChannel channel;
54 |
55 | public static HashSet> modelBlacklist = new HashSet<>();
56 |
57 | public Tabula()
58 | {
59 | IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
60 |
61 | DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
62 | configClient = new ConfigClient().init();
63 | MinecraftForge.EVENT_BUS.register(eventHandlerClient = new EventHandlerClient());
64 | ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> me.ichun.mods.ichunutil.client.core.EventHandlerClient::getConfigGui);
65 | ResourceHelper.init();
66 | bus.addListener(this::processIMC);
67 | bus.addListener(this::onTextureStitchEvent);
68 | });
69 |
70 | Blocks.REGISTRY.register(bus);
71 | Items.REGISTRY.register(bus);
72 | TileEntityTypes.REGISTRY.register(bus);
73 | bus.addListener(this::onClientSetup);
74 |
75 | channel = new PacketChannel(new ResourceLocation(MOD_ID, "channel"), PROTOCOL,
76 | PacketRequestSession.class, PacketPing.class, PacketKillSession.class, PacketListenerChange.class, PacketChat.class, PacketEditorStatus.class, PacketProjectFragment.class, PacketRequestProject.class
77 | );
78 | }
79 |
80 | private void onClientSetup(FMLClientSetupEvent event)
81 | {
82 | ClientRegistry.bindTileEntityRenderer(TileEntityTypes.TABULA_RASA.get(), TileRendererTabulaRasa::new);
83 | }
84 |
85 | private void onTextureStitchEvent(TextureStitchEvent.Pre event)
86 | {
87 | if(event.getMap().getTextureLocation() == AtlasTexture.LOCATION_BLOCKS_TEXTURE)
88 | {
89 | event.addSprite(new ResourceLocation("tabula", "model/tabularasa"));
90 | }
91 | }
92 |
93 | private void processIMC(InterModProcessEvent event)
94 | {
95 | event.getIMCStream(m -> m.equalsIgnoreCase("blacklist")).forEach(msg -> {
96 | Object o = msg.getMessageSupplier().get();
97 | Class extends Model> modelClz = null;
98 | if(o instanceof Class>)
99 | {
100 | if(Model.class.isAssignableFrom((Class>)o) && o != Model.class) //is an instance
101 | {
102 | modelClz = (Class extends Model>)o;
103 | }
104 | }
105 | else if(o instanceof String)
106 | {
107 | try
108 | {
109 | Class clz = Class.forName(o.toString());
110 | if(Model.class.isAssignableFrom(clz)) //is an instance
111 | {
112 | modelClz = (Class extends Model>)o;
113 | }
114 | }
115 | catch(ClassNotFoundException ignored){}
116 | }
117 |
118 | if(modelClz != null)
119 | {
120 | modelBlacklist.add(modelClz);
121 | LOGGER.info("Blacklisting {} as requested by {}", modelClz.getName(), msg.getSenderModId());
122 | }
123 | });
124 | event.getIMCStream(m -> m.equalsIgnoreCase("plugin")).forEach(msg -> {
125 | if(FMLEnvironment.dist.isClient())
126 | {
127 | handleClientIMC(msg);
128 | }
129 | else
130 | {
131 | LOGGER.warn("Received plugin IMC when we're not on a client: {}", msg.getSenderModId());
132 | }
133 | });
134 | }
135 |
136 | @OnlyIn(Dist.CLIENT)
137 | private void handleClientIMC(InterModComms.IMCMessage msg)
138 | {
139 | Object o = msg.getMessageSupplier().get();
140 | if(o instanceof TabulaPlugin)
141 | {
142 | eventHandlerClient.loadPlugin(msg.getSenderModId(), (TabulaPlugin)o);
143 | }
144 | else if(o instanceof Class>)
145 | {
146 | if(TabulaPlugin.class.isAssignableFrom((Class>)o))
147 | {
148 | try
149 | {
150 | eventHandlerClient.loadPlugin(msg.getSenderModId(), ((Class)o).newInstance());
151 | }
152 | catch(InstantiationException | IllegalAccessException e)
153 | {
154 | Tabula.LOGGER.error("Error creating instance for {} from {}", ((Class)o).getName(), msg.getSenderModId());
155 | e.printStackTrace();
156 | }
157 | }
158 | else
159 | {
160 | LOGGER.error("Found invalid plugin class from {}: {}", msg.getSenderModId(), ((Class>)o).getName());
161 | }
162 | }
163 | else if(o instanceof String)
164 | {
165 | try
166 | {
167 | Class clz = Class.forName(o.toString());
168 | if(TabulaPlugin.class.isAssignableFrom((Class>)o))
169 | {
170 | try
171 | {
172 | eventHandlerClient.loadPlugin(msg.getSenderModId(), ((Class)clz).newInstance());
173 | }
174 | catch(InstantiationException | IllegalAccessException e)
175 | {
176 | Tabula.LOGGER.error("Error creating instance for {} from {}", ((Class)clz).getName(), msg.getSenderModId());
177 | e.printStackTrace();
178 | }
179 | }
180 | }
181 | catch(ClassNotFoundException ignored)
182 | {
183 | LOGGER.error("Found invalid plugin class from {}: {}", msg.getSenderModId(), o.toString());
184 | }
185 | }
186 | }
187 |
188 | public static class Blocks
189 | {
190 | private static final DeferredRegister REGISTRY = DeferredRegister.create(ForgeRegistries.BLOCKS, MOD_ID);
191 |
192 | public static final RegistryObject TABULA_RASA = REGISTRY.register("tabularasa", BlockTabulaRasa::new);
193 | }
194 |
195 | public static class Items
196 | {
197 | private static final DeferredRegister- REGISTRY = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
198 |
199 | public static final RegistryObject TABULA_RASA = REGISTRY.register("tabularasa", () -> new BlockItem(Blocks.TABULA_RASA.get(), (new Item.Properties()).group(ItemGroup.DECORATIONS)));
200 | }
201 |
202 | public static class TileEntityTypes
203 | {
204 | private static final DeferredRegister> REGISTRY = DeferredRegister.create(ForgeRegistries.TILE_ENTITIES, MOD_ID);
205 |
206 | public static final RegistryObject> TABULA_RASA = REGISTRY.register("tabularasa", () -> TileEntityType.Builder.create(TileEntityTabulaRasa::new, Blocks.TABULA_RASA.get()).build(null));
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/block/BlockTabulaRasa.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.block;
2 |
3 | import me.ichun.mods.tabula.common.Tabula;
4 | import me.ichun.mods.tabula.common.packet.PacketRequestSession;
5 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
6 | import net.minecraft.block.Block;
7 | import net.minecraft.block.BlockRenderType;
8 | import net.minecraft.block.BlockState;
9 | import net.minecraft.block.SoundType;
10 | import net.minecraft.block.material.Material;
11 | import net.minecraft.entity.LivingEntity;
12 | import net.minecraft.entity.player.PlayerEntity;
13 | import net.minecraft.item.ItemStack;
14 | import net.minecraft.tileentity.TileEntity;
15 | import net.minecraft.util.ActionResultType;
16 | import net.minecraft.util.Direction;
17 | import net.minecraft.util.Hand;
18 | import net.minecraft.util.math.BlockPos;
19 | import net.minecraft.util.math.BlockRayTraceResult;
20 | import net.minecraft.util.math.shapes.ISelectionContext;
21 | import net.minecraft.util.math.shapes.VoxelShape;
22 | import net.minecraft.world.IBlockReader;
23 | import net.minecraft.world.IWorldReader;
24 | import net.minecraft.world.World;
25 |
26 | import javax.annotation.Nullable;
27 |
28 | public class BlockTabulaRasa extends Block
29 | {
30 | public static final VoxelShape SHAPE = Block.makeCuboidShape(2.0D, 0.0D, 2.0D, 14.0D, 2.0D, 14.0D);
31 |
32 | public BlockTabulaRasa()
33 | {
34 | super(Block.Properties.create(Material.MISCELLANEOUS)
35 | // .doesNotBlockMovement()
36 | .hardnessAndResistance(0.0F)
37 | .sound(SoundType.WOOD)
38 | );
39 | }
40 |
41 | @Override
42 | public boolean hasTileEntity(BlockState state)
43 | {
44 | return true;
45 | }
46 |
47 | @Nullable
48 | @Override
49 | public TileEntity createTileEntity(BlockState state, IBlockReader world)
50 | {
51 | return new TileEntityTabulaRasa();
52 | }
53 |
54 | @Override
55 | public boolean canSpawnInBlock() {
56 | return true;
57 | }
58 |
59 | @Override
60 | public BlockRenderType getRenderType(BlockState state) {
61 | return BlockRenderType.ENTITYBLOCK_ANIMATED;
62 | }
63 |
64 | @Override
65 | public void onBlockPlacedBy(World world, BlockPos pos, BlockState state, @Nullable LivingEntity living, ItemStack stack)
66 | {
67 | super.onBlockPlacedBy(world, pos, state, living, stack);
68 | TileEntity te = world.getTileEntity(pos);
69 | if(te instanceof TileEntityTabulaRasa && living != null)
70 | {
71 | TileEntityTabulaRasa tr = (TileEntityTabulaRasa)te;
72 | tr.facing = Direction.fromAngle(living.rotationYaw);
73 | }
74 | }
75 |
76 | @Override
77 | public ActionResultType onBlockActivated(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand handIn, BlockRayTraceResult hit)
78 | {
79 | if(world.isRemote)
80 | {
81 | Tabula.channel.sendToServer(new PacketRequestSession(pos, ""));
82 | }
83 | return ActionResultType.SUCCESS;
84 | }
85 |
86 | @Override
87 | public float getPlayerRelativeBlockHardness(BlockState state, PlayerEntity player, IBlockReader world, BlockPos pos)
88 | {
89 | TileEntity te = world.getTileEntity(pos);
90 | if(te instanceof TileEntityTabulaRasa)
91 | {
92 | TileEntityTabulaRasa tr = (TileEntityTabulaRasa)te;
93 | if(!tr.host.isEmpty())
94 | {
95 | return 0.0F; //super returns 0 if hardness is -1
96 | }
97 | }
98 | return super.getPlayerRelativeBlockHardness(state, player, world, pos);
99 | }
100 |
101 | @Override
102 | public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
103 | return SHAPE;
104 | }
105 |
106 | @Override
107 | public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
108 | return hasSolidSideOnTop(worldIn, pos.down());
109 | }
110 |
111 | @Override
112 | public void neighborChanged(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving)
113 | {
114 | if (!world.isRemote)
115 | {
116 | TileEntity te = world.getTileEntity(pos);
117 | if(te instanceof TileEntityTabulaRasa)
118 | {
119 | TileEntityTabulaRasa tr = (TileEntityTabulaRasa)te;
120 | if(!tr.host.isEmpty())
121 | {
122 | return;
123 | }
124 | }
125 | if(!state.isValidPosition(world, pos))
126 | {
127 | world.removeBlock(pos, false);
128 | spawnDrops(state, world, pos);
129 | }
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketChat.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.screen.Screen;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.network.PacketBuffer;
11 | import net.minecraft.tileentity.TileEntity;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.world.World;
14 | import net.minecraftforge.api.distmarker.Dist;
15 | import net.minecraftforge.api.distmarker.OnlyIn;
16 | import net.minecraftforge.fml.network.NetworkEvent;
17 |
18 | public class PacketChat extends AbstractPacket
19 | {
20 | public BlockPos pos;
21 | public String chat;
22 |
23 | public PacketChat(){}
24 |
25 | public PacketChat(BlockPos pos, String chat)
26 | {
27 | this.pos = pos;
28 | this.chat = chat;
29 | }
30 |
31 | @Override
32 | public void writeTo(PacketBuffer buf)
33 | {
34 | buf.writeBlockPos(pos);
35 | buf.writeString(chat);
36 | }
37 |
38 | @Override
39 | public void readFrom(PacketBuffer buf)
40 | {
41 | pos = buf.readBlockPos();
42 | chat = readString(buf);
43 | }
44 |
45 | @Override
46 | public void process(NetworkEvent.Context context)
47 | {
48 | context.enqueueWork(() -> {
49 | if(context.getDirection().getReceptionSide().isServer()) // server
50 | {
51 | ServerPlayerEntity player = context.getSender();
52 | World world = player.world;
53 | TileEntity tileEntity = world.getTileEntity(pos);
54 | if(tileEntity instanceof TileEntityTabulaRasa)
55 | {
56 | TileEntityTabulaRasa tabulaRasa = (TileEntityTabulaRasa)tileEntity;
57 | world.getPlayers().stream().filter(player1 -> tabulaRasa.listeners.contains(player1.getName().getUnformattedComponentText())).forEach(player1 -> Tabula.channel.sendTo(new PacketChat(this.pos, this.chat), (ServerPlayerEntity)player1));
58 | }
59 | }
60 | else
61 | {
62 | chat();
63 | }
64 | });
65 | }
66 |
67 | @OnlyIn(Dist.CLIENT)
68 | public void chat()
69 | {
70 | Screen screen = Minecraft.getInstance().currentScreen;
71 | if(screen instanceof WorkspaceTabula)
72 | {
73 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
74 | workspace.mainframe.receiveChat(chat, false);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketEditorStatus.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import net.minecraft.client.Minecraft;
7 | import net.minecraft.client.gui.screen.Screen;
8 | import net.minecraft.entity.player.PlayerEntity;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.network.PacketBuffer;
11 | import net.minecraft.world.World;
12 | import net.minecraftforge.api.distmarker.Dist;
13 | import net.minecraftforge.api.distmarker.OnlyIn;
14 | import net.minecraftforge.fml.network.NetworkEvent;
15 |
16 | import java.util.List;
17 |
18 | public class PacketEditorStatus extends AbstractPacket
19 | {
20 | public String editor;
21 | public boolean status;
22 |
23 | public PacketEditorStatus(){}
24 |
25 | public PacketEditorStatus(String editor, boolean status)
26 | {
27 | this.editor = editor;
28 | this.status = status;
29 | }
30 |
31 | @Override
32 | public void writeTo(PacketBuffer buf)
33 | {
34 | buf.writeString(editor);
35 | buf.writeBoolean(status);
36 | }
37 |
38 | @Override
39 | public void readFrom(PacketBuffer buf)
40 | {
41 | editor = readString(buf);
42 | status = buf.readBoolean();
43 | }
44 |
45 | @Override
46 | public void process(NetworkEvent.Context context)
47 | {
48 | context.enqueueWork(() -> {
49 | if(context.getDirection().getReceptionSide().isServer()) // server
50 | {
51 | ServerPlayerEntity player = context.getSender();
52 | World world = player.world;
53 | List extends PlayerEntity> players = world.getPlayers();
54 | for(PlayerEntity playerEntity : players)
55 | {
56 | if(playerEntity.getName().getUnformattedComponentText().equalsIgnoreCase(editor))
57 | {
58 | Tabula.channel.sendTo(new PacketEditorStatus(editor, status), (ServerPlayerEntity)playerEntity);
59 | break;
60 | }
61 | }
62 | }
63 | else
64 | {
65 | handleClient();
66 | }
67 | });
68 | }
69 |
70 | @OnlyIn(Dist.CLIENT)
71 | public void handleClient()
72 | {
73 | Screen screen = Minecraft.getInstance().currentScreen;
74 | if(screen instanceof WorkspaceTabula)
75 | {
76 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
77 |
78 | workspace.mainframe.setCanEdit(status);
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketKillSession.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.screen.Screen;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.network.PacketBuffer;
11 | import net.minecraft.tileentity.TileEntity;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.world.World;
14 | import net.minecraftforge.api.distmarker.Dist;
15 | import net.minecraftforge.api.distmarker.OnlyIn;
16 | import net.minecraftforge.fml.network.NetworkEvent;
17 |
18 | public class PacketKillSession extends AbstractPacket
19 | {
20 | public BlockPos pos;
21 |
22 | public PacketKillSession(){}
23 |
24 | public PacketKillSession(BlockPos pos)
25 | {
26 | this.pos = pos;
27 | }
28 |
29 | @Override
30 | public void writeTo(PacketBuffer buf)
31 | {
32 | buf.writeBlockPos(pos);
33 | }
34 |
35 | @Override
36 | public void readFrom(PacketBuffer buf)
37 | {
38 | pos = buf.readBlockPos();
39 | }
40 |
41 | @Override
42 | public void process(NetworkEvent.Context context)
43 | {
44 | context.enqueueWork(() -> {
45 | if(context.getDirection().getReceptionSide().isServer()) // server
46 | {
47 | ServerPlayerEntity player = context.getSender();
48 | World world = player.world;
49 | TileEntity tileEntity = world.getTileEntity(pos);
50 | if(tileEntity instanceof TileEntityTabulaRasa)
51 | {
52 | TileEntityTabulaRasa tabulaRasa = (TileEntityTabulaRasa)tileEntity;
53 | if(tabulaRasa.host.equals(player.getName().getUnformattedComponentText())) //we got a kill session order from the host.
54 | {
55 | tabulaRasa.listeners.remove(player.getName().getUnformattedComponentText()); // remove from listeners first
56 | tabulaRasa.killSession();
57 | }
58 | else
59 | {
60 | ServerPlayerEntity host = tabulaRasa.getHost();
61 | if(host != null)
62 | {
63 | Tabula.channel.sendTo(new PacketListenerChange(player.getName().getUnformattedComponentText(), false), host);
64 | }
65 | }
66 | }
67 | }
68 | else
69 | {
70 | killSession();
71 | }
72 | });
73 | }
74 |
75 | @OnlyIn(Dist.CLIENT)
76 | public void killSession()
77 | {
78 | Screen screen = Minecraft.getInstance().currentScreen;
79 | if(screen instanceof WorkspaceTabula)
80 | {
81 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
82 | workspace.mainframe.sessionEnded = true;
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketListenerChange.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import net.minecraft.client.Minecraft;
6 | import net.minecraft.client.gui.screen.Screen;
7 | import net.minecraft.network.PacketBuffer;
8 | import net.minecraftforge.api.distmarker.Dist;
9 | import net.minecraftforge.api.distmarker.OnlyIn;
10 | import net.minecraftforge.fml.network.NetworkEvent;
11 |
12 | public class PacketListenerChange extends AbstractPacket
13 | {
14 | public String listener;
15 | public boolean add;
16 |
17 | public PacketListenerChange(){}
18 |
19 | public PacketListenerChange(String listener, boolean add)
20 | {
21 | this.listener = listener;
22 | this.add = add;
23 | }
24 |
25 | @Override
26 | public void writeTo(PacketBuffer buf)
27 | {
28 | buf.writeString(listener);
29 | buf.writeBoolean(add);
30 | }
31 |
32 | @Override
33 | public void readFrom(PacketBuffer buf)
34 | {
35 | listener = readString(buf);
36 | add = buf.readBoolean();
37 | }
38 |
39 | @Override
40 | public void process(NetworkEvent.Context context)
41 | {
42 | context.enqueueWork(this::handleClient);
43 | }
44 |
45 | @OnlyIn(Dist.CLIENT)
46 | public void handleClient()
47 | {
48 | Screen screen = Minecraft.getInstance().currentScreen;
49 | if(screen instanceof WorkspaceTabula)
50 | {
51 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
52 |
53 | workspace.mainframe.listenerChange(listener, add);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketPing.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
7 | import net.minecraft.client.Minecraft;
8 | import net.minecraft.client.gui.screen.Screen;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.network.PacketBuffer;
11 | import net.minecraft.tileentity.TileEntity;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.world.World;
14 | import net.minecraftforge.api.distmarker.Dist;
15 | import net.minecraftforge.api.distmarker.OnlyIn;
16 | import net.minecraftforge.fml.network.NetworkEvent;
17 |
18 | public class PacketPing extends AbstractPacket
19 | {
20 | public BlockPos pos;
21 |
22 | public PacketPing(){}
23 |
24 | public PacketPing(BlockPos pos)
25 | {
26 | this.pos = pos;
27 | }
28 |
29 | @Override
30 | public void writeTo(PacketBuffer buf)
31 | {
32 | buf.writeBlockPos(pos);
33 | }
34 |
35 | @Override
36 | public void readFrom(PacketBuffer buf)
37 | {
38 | pos = buf.readBlockPos();
39 | }
40 |
41 | @Override
42 | public void process(NetworkEvent.Context context)
43 | {
44 | context.enqueueWork(() -> {
45 | if(context.getDirection().getReceptionSide().isServer()) // server getting a pong from the host
46 | {
47 | ServerPlayerEntity player = context.getSender();
48 | World world = player.world;
49 | TileEntity tileEntity = world.getTileEntity(pos);
50 | if(tileEntity instanceof TileEntityTabulaRasa)
51 | {
52 | TileEntityTabulaRasa tabulaRasa = (TileEntityTabulaRasa)tileEntity;
53 | tabulaRasa.lastPing = 0;
54 | }
55 | }
56 | else
57 | {
58 | pong();
59 | }
60 | });
61 | }
62 |
63 | @OnlyIn(Dist.CLIENT)
64 | public void pong()
65 | {
66 | Screen screen = Minecraft.getInstance().currentScreen;
67 | if(screen instanceof WorkspaceTabula)
68 | {
69 | WorkspaceTabula workspace = (WorkspaceTabula)screen;
70 | workspace.mainframe.lastPing = 0;
71 |
72 | if(workspace.mainframe.getIsMaster()) // we are the master. pong.
73 | {
74 | Tabula.channel.sendToServer(new PacketPing(pos));
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketRequestProject.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
4 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
5 | import me.ichun.mods.ichunutil.common.util.IOUtil;
6 | import me.ichun.mods.tabula.common.Tabula;
7 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
8 | import net.minecraft.entity.player.ServerPlayerEntity;
9 | import net.minecraft.network.PacketBuffer;
10 | import net.minecraft.tileentity.TileEntity;
11 | import net.minecraft.util.math.BlockPos;
12 | import net.minecraft.world.World;
13 | import net.minecraftforge.fml.network.NetworkEvent;
14 | import org.apache.commons.lang3.RandomStringUtils;
15 |
16 | import java.io.IOException;
17 |
18 | public class PacketRequestProject extends AbstractPacket
19 | {
20 | public BlockPos pos;
21 |
22 | public PacketRequestProject(){}
23 |
24 | public PacketRequestProject(BlockPos pos)
25 | {
26 | this.pos = pos;
27 | }
28 |
29 | @Override
30 | public void writeTo(PacketBuffer buf)
31 | {
32 | buf.writeBlockPos(pos);
33 | }
34 |
35 | @Override
36 | public void readFrom(PacketBuffer buf)
37 | {
38 | pos = buf.readBlockPos();
39 | }
40 |
41 | @Override
42 | public void process(NetworkEvent.Context context)
43 | {
44 | context.enqueueWork(() -> {
45 | ServerPlayerEntity player = context.getSender();
46 | World world = player.world;
47 | TileEntity tileEntity = world.getTileEntity(pos);
48 | if(tileEntity instanceof TileEntityTabulaRasa)
49 | {
50 | TileEntityTabulaRasa tabulaRasa = (TileEntityTabulaRasa)tileEntity;
51 | if(tabulaRasa.projectString != null)
52 | {
53 | sendContent("project", tabulaRasa.projectString, player);
54 | if(tabulaRasa.projectImage != null)
55 | {
56 | sendContent("image", tabulaRasa.projectImage, player);
57 | }
58 | }
59 | }
60 | });
61 | }
62 |
63 | public void sendContent(String projIdent, Object o, ServerPlayerEntity requester) //empty string for directed to send to all
64 | {
65 | byte[] data;
66 | if(projIdent.equals("image")) //sending out an image
67 | {
68 | data = (byte[])o;
69 | }
70 | else
71 | {
72 | try
73 | {
74 | data = IOUtil.compress(o.toString());
75 | }
76 | catch(IOException e){return;}
77 | }
78 |
79 | final int maxFile = 31000; //smaller packet cause I'm worried about too much info carried over from the bloat vs hat info.
80 |
81 | String fileName = RandomStringUtils.randomAscii(Project.IDENTIFIER_LENGTH);
82 | int fileSize = data.length;
83 |
84 | int packetsToSend = (int)Math.ceil((float)fileSize / (float)maxFile);
85 |
86 | int packetCount = 0;
87 | int offset = 0;
88 | while(fileSize > 0)
89 | {
90 | byte[] fileBytes = new byte[Math.min(fileSize, maxFile)];
91 | int index = 0;
92 | while(index < fileBytes.length) //from index 0 to 31999
93 | {
94 | fileBytes[index] = data[index + offset];
95 | index++;
96 | }
97 |
98 | Tabula.channel.sendTo(new PacketProjectFragment(fileName, packetsToSend, packetCount, fileBytes, pos, "", projIdent, "", (byte)0, (byte)-1), requester);
99 |
100 | packetCount++;
101 | fileSize -= 32000;
102 | offset += index;
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/packet/PacketRequestSession.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.packet;
2 |
3 | import me.ichun.mods.ichunutil.common.network.AbstractPacket;
4 | import me.ichun.mods.tabula.client.gui.WorkspaceTabula;
5 | import me.ichun.mods.tabula.common.Tabula;
6 | import me.ichun.mods.tabula.common.tileentity.TileEntityTabulaRasa;
7 | import net.minecraft.block.BlockState;
8 | import net.minecraft.client.Minecraft;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.network.PacketBuffer;
11 | import net.minecraft.tileentity.TileEntity;
12 | import net.minecraft.util.math.BlockPos;
13 | import net.minecraft.world.World;
14 | import net.minecraftforge.api.distmarker.Dist;
15 | import net.minecraftforge.api.distmarker.OnlyIn;
16 | import net.minecraftforge.fml.network.NetworkEvent;
17 |
18 | public class PacketRequestSession extends AbstractPacket
19 | {
20 | public BlockPos pos;
21 | public String host;
22 |
23 | public PacketRequestSession(){}
24 |
25 | public PacketRequestSession(BlockPos pos, String host)
26 | {
27 | this.pos = pos;
28 | this.host = host;
29 | }
30 |
31 | @Override
32 | public void writeTo(PacketBuffer buf)
33 | {
34 | buf.writeBlockPos(pos);
35 | buf.writeString(host);
36 | }
37 |
38 | @Override
39 | public void readFrom(PacketBuffer buf)
40 | {
41 | pos = buf.readBlockPos();
42 | host = readString(buf);
43 | }
44 |
45 | @Override
46 | public void process(NetworkEvent.Context context)
47 | {
48 | context.enqueueWork(() -> {
49 | if(context.getDirection().getReceptionSide().isServer()) // server getting a request
50 | {
51 | ServerPlayerEntity player = context.getSender();
52 | World world = player.world;
53 | TileEntity tileEntity = world.getTileEntity(pos);
54 | if(tileEntity instanceof TileEntityTabulaRasa)
55 | {
56 | TileEntityTabulaRasa tabulaRasa = (TileEntityTabulaRasa)tileEntity;
57 | tabulaRasa.listeners.add(player.getName().getUnformattedComponentText());
58 | if(tabulaRasa.host.isEmpty())
59 | {
60 | tabulaRasa.host = player.getName().getUnformattedComponentText(); //you are now the host!
61 | tabulaRasa.projectString = null;
62 | tabulaRasa.projectImage = null;
63 |
64 | BlockState state = world.getBlockState(pos);
65 | world.notifyBlockUpdate(pos, state, state, 3);
66 | }
67 | else
68 | {
69 | ServerPlayerEntity host = tabulaRasa.getHost();
70 | if(host != null)
71 | {
72 | Tabula.channel.sendTo(new PacketListenerChange(player.getName().getUnformattedComponentText(), true), host);
73 | }
74 | }
75 |
76 | Tabula.channel.sendTo(new PacketRequestSession(pos, tabulaRasa.host), context.getSender());
77 | }
78 | }
79 | else //client receiving a reply
80 | {
81 | beginClientSession();
82 | }
83 | });
84 | }
85 |
86 | @OnlyIn(Dist.CLIENT)
87 | public void beginClientSession()
88 | {
89 | WorkspaceTabula workspace = WorkspaceTabula.create(host);
90 | workspace.mainframe.setOrigin(pos);
91 | Minecraft.getInstance().displayGuiScreen(workspace);
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/me/ichun/mods/tabula/common/tileentity/TileEntityTabulaRasa.java:
--------------------------------------------------------------------------------
1 | package me.ichun.mods.tabula.common.tileentity;
2 |
3 | import me.ichun.mods.ichunutil.common.module.tabula.project.Project;
4 | import me.ichun.mods.tabula.common.Tabula;
5 | import me.ichun.mods.tabula.common.packet.PacketKillSession;
6 | import me.ichun.mods.tabula.common.packet.PacketPing;
7 | import me.ichun.mods.tabula.common.packet.PacketRequestProject;
8 | import net.minecraft.block.BlockState;
9 | import net.minecraft.entity.player.ServerPlayerEntity;
10 | import net.minecraft.nbt.CompoundNBT;
11 | import net.minecraft.network.NetworkManager;
12 | import net.minecraft.network.play.server.SUpdateTileEntityPacket;
13 | import net.minecraft.tileentity.ITickableTileEntity;
14 | import net.minecraft.tileentity.TileEntity;
15 | import net.minecraft.util.Direction;
16 | import net.minecraftforge.api.distmarker.Dist;
17 | import net.minecraftforge.api.distmarker.OnlyIn;
18 |
19 | import java.util.HashSet;
20 |
21 | public class TileEntityTabulaRasa extends TileEntity
22 | implements ITickableTileEntity
23 | {
24 | public Direction facing;
25 | public String host;
26 |
27 | public HashSet listeners = new HashSet<>();
28 |
29 | public int lastPing;
30 |
31 | public String projectString;
32 | public byte[] projectImage;
33 |
34 | @OnlyIn(Dist.CLIENT)
35 | public Project project;
36 | public int projectReq;
37 |
38 | public TileEntityTabulaRasa()
39 | {
40 | super(Tabula.TileEntityTypes.TABULA_RASA.get());
41 | facing = Direction.UP; //invalid
42 | host = "";
43 | }
44 |
45 | @Override
46 | public void tick()
47 | {
48 | if(!world.isRemote)
49 | {
50 | if(!host.isEmpty())
51 | {
52 | lastPing++;
53 | if(lastPing == 300) //15 seconds
54 | {
55 | world.getPlayers().stream().filter(player -> listeners.contains(player.getName().getUnformattedComponentText())).forEach(player -> Tabula.channel.sendTo(new PacketPing(this.pos), (ServerPlayerEntity)player));
56 | }
57 | else if(lastPing == 600) //30 seconds
58 | {
59 | killSession();
60 | }
61 | }
62 | }
63 | else
64 | {
65 | if(host != null && !host.isEmpty())
66 | {
67 | projectReq--;
68 | }
69 | else
70 | {
71 | if(project != null)
72 | {
73 | project.destroy();
74 | }
75 | project = null;
76 | projectReq = 0;
77 | }
78 | }
79 | }
80 |
81 | public void requestProject()
82 | {
83 | Tabula.channel.sendToServer(new PacketRequestProject(pos));
84 | }
85 |
86 | public void killSession()
87 | {
88 | world.getPlayers().stream().filter(player -> listeners.contains(player.getName().getUnformattedComponentText())).forEach(player -> Tabula.channel.sendTo(new PacketKillSession(this.pos), (ServerPlayerEntity)player));
89 |
90 | host = "";
91 | listeners.clear();
92 | lastPing = 0;
93 | projectString = null;
94 | projectImage = null;
95 |
96 | BlockState state = world.getBlockState(pos);
97 | world.notifyBlockUpdate(pos, state, state, 3);
98 | }
99 |
100 | public ServerPlayerEntity getHost()
101 | {
102 | if(!host.isEmpty() && !world.isRemote)
103 | {
104 | return (ServerPlayerEntity)world.getPlayers().stream().filter(player -> player.getName().getUnformattedComponentText().equals(host)).findAny().get();
105 | }
106 | return null;
107 | }
108 |
109 | @Override
110 | public void onDataPacket(NetworkManager net, SUpdateTileEntityPacket pkt)
111 | {
112 | BlockState state = world.getBlockState(getPos());
113 |
114 | read(state, pkt.getNbtCompound());
115 |
116 | world.notifyBlockUpdate(getPos(), state, state, 3);
117 | }
118 |
119 | @Override
120 | public CompoundNBT getUpdateTag()
121 | {
122 | return this.write(new CompoundNBT());
123 | }
124 |
125 | @Override
126 | public SUpdateTileEntityPacket getUpdatePacket()
127 | {
128 | return new SUpdateTileEntityPacket(getPos(), 0, getUpdateTag());
129 | }
130 |
131 | @Override
132 | public CompoundNBT write(CompoundNBT tag)
133 | {
134 | super.write(tag);
135 | tag.putByte("facing", (byte)facing.getHorizontalIndex());
136 | tag.putString("host", host);
137 | return tag;
138 | }
139 |
140 | @Override
141 | public void read(BlockState state, CompoundNBT tag)
142 | {
143 | super.read(state, tag);
144 | facing = Direction.byHorizontalIndex(tag.getByte("facing"));
145 | host = tag.getString("host");
146 | }
147 | }
148 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/mods.toml:
--------------------------------------------------------------------------------
1 | modLoader="javafml"
2 | loaderVersion="[34,)" #forge version dep
3 | license="GNU Lesser General Public License v3.0"
4 | issueTrackerURL="https://github.com/iChun/Tabula/issues"
5 |
6 | [[mods]]
7 | modId="tabula"
8 | version="${file.jarVersion}" #mandatory
9 | displayName="Tabula"
10 | displayURL="http://ichun.me/mods/tabula-minecraft-modeler/"
11 | authors="iChun"
12 | description='''
13 | A successor to the modeler Techne, an in-game modeler with SMP support.
14 | '''
15 |
16 | [[dependencies.tabula]]
17 | modId="ichunutil"
18 | mandatory=true
19 | versionRange="[10.5.1,11)"
20 | ordering="NONE"
21 | side="BOTH"
22 |
--------------------------------------------------------------------------------
/src/main/resources/PlayerGhost.tbl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/PlayerGhost.tbl
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/blockstates/tabularasa.json:
--------------------------------------------------------------------------------
1 | {
2 | "variants": {
3 | "": { "model": "tabula:block/tabularasa" }
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/lang/de_de.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabula.name": "Tabula",
3 |
4 | "window.controls.title": "Steuerung",
5 | "window.controls.cubeName": "Gewählter Würfelname",
6 | "window.controls.dimensions": "Dimensionen",
7 | "window.controls.position": "Position",
8 | "window.controls.offset": "Offset",
9 | "window.controls.rotation": "Rotation",
10 | "window.controls.mcScale": "MC Skalierung",
11 | "window.controls.scale": "Eigene Skalierung",
12 | "window.controls.txOffset": "Textur Offset",
13 | "window.controls.txMirror": "Spiegeln",
14 | "window.controls.txMirrorFull": "Textur spiegeln",
15 |
16 | "window.newProject.title": "Neues Projekt",
17 | "window.newProject.projIdent": "Projektname",
18 | "window.newProject.animName": "Autorenname",
19 | "window.newProject.txDimensions": "Texturen-Breite und -Höhe",
20 |
21 | "window.editProject.title": "Projekt bearbeiten",
22 |
23 | "window.modelTree.title": "Modell-Baum",
24 | "window.modelTree.newCube": "Neuer Würfel",
25 | "window.modelTree.newGroup": "Neue Gruppe",
26 | "window.modelTree.delete": "Löschen",
27 |
28 | "window.texture.title": "Textur",
29 | "window.texture.loadTexture": "Textur laden",
30 | "window.texture.clearTexture": "Textur leeren",
31 | "window.texture.listenTexture": "Auf Änderungen achten",
32 | "window.texture.listenTextureFull": "Achte auf Textur-Änderungen (Wenn die Textur dir gehört)",
33 | "window.texture.remoteTexture": "Remote Textur",
34 | "window.texture.noTexture": "Keine Textur",
35 |
36 | "window.import.title": "Modell in aktuelles Projekt importieren",
37 | "window.import.texture": "Textur",
38 | "window.import.textureFull": "Auch die Textur (falls verfügbar) importieren?",
39 |
40 | "window.importMC.title": "Minecraft Modell importieren",
41 | "window.importMC.newProject": "Neu?",
42 | "window.importMC.newProjectFull": "Das Modell in ein neues Projekt importieren?",
43 |
44 | "window.loadTexture.title": "Textur laden",
45 | "window.loadTexture.updateTextureDimensions": "Aktualisieren?",
46 | "window.loadTexture.updateTextureDimensionsFull": "Die Textur-Dimensionen des Projekts aktualisieren?",
47 |
48 | "window.chat.title": "Chat",
49 | "window.chat.textbox": "Drücke ENTER zum Senden",
50 |
51 | "window.notSaved.title": "Projekt nicht gespeichert!",
52 | "window.notSaved.unsaved": "Das Projekt ist nicht gespeichert!",
53 | "window.notSaved.save": "Möchtest du vor dem Schließen speichern?",
54 |
55 | "window.open.title": "Projekt öffnen",
56 | "window.open.opening": "Öffne...",
57 | "window.open.failed": "Öffnen der Datei fehlgeschlagen.",
58 |
59 | "window.about.title": "Über",
60 | "window.about.line0": "Mod Version: ",
61 | "window.about.line1": "Entwickler: ",
62 | "window.about.line2": "Texturen: ",
63 | "window.about.line3": "Beiträge: ",
64 | "window.about.line4": "Tester: ",
65 | "window.about.line5": "Aktuelle Lokalisierung: NPException",
66 | "window.about.line6": "Funktion und User Interface basieren auf dem ursprünglichen Techne von ZeuX und r4wk",
67 | "window.about.os1": "Wenn du irgendwelche Probleme oder Vorschläge hast, gehe zu folgendem Link",
68 | "window.about.os2": "Das Projekt ist Open Source und kann hier gefunden werden:",
69 |
70 | "export.title": "Projekt exportieren",
71 | "export.failed": "Export fehlgeschlagen!",
72 | "export.textureMap.name": "Textur Map",
73 | "export.javaClass.title": "Als Java-Klasse exportieren",
74 | "export.javaClass.package": "Paket für die Klasse",
75 | "export.javaClass.name": "Java-Klasse",
76 | "export.javaClass.className": "Klassenname",
77 | "export.projTexture.name": "Projekt Textur",
78 | "export.blockjson.name": "Block JSON",
79 | "export.blockjson.title": "Export Block JSON",
80 | "export.blockjson.filename": "Dateiname",
81 | "export.blockjson.corner": "Blockecke ist um (0, 0) (zum Ändern klicken)",
82 | "export.blockjson.centre": "Die Mitte des Blocks befindet sich um (0, 0) (zum Ändern klicken)",
83 | "export.blockjson.relative": "Blockmodell ist relativ zum Holzblock (zum Ändern klicken)",
84 | "export.blockjson.absolute": "Blockmodell ist relativ zu y = 0 (zum Ändern klicken)",
85 |
86 | "topdock.new": "Neues Projekt",
87 | "topdock.edit": "Projekt bearbeiten",
88 | "topdock.open": "Projekt öffnen",
89 | "topdock.save": "Speichern",
90 | "topdock.saveAs": "Speichern unter",
91 | "topdock.import": "Projekt Importieren",
92 | "topdock.importMC": "Von Minecraft importieren",
93 | "topdock.export": "Projekt exportieren",
94 | "topdock.cut": "Ausschneiden",
95 | "topdock.copy": "Kopieren",
96 | "topdock.paste": "Einfügen",
97 | "topdock.pasteInPlace": "An Position einfügen",
98 | "topdock.undo": "Rückgängig",
99 | "topdock.redo": "Wiederholen",
100 | "topdock.chat": "Chat Fenster an-/ausschalten",
101 | "topdock.info": "Über diese Mod",
102 | "topdock.exitTabula": "Tabula verlassen",
103 | "topdock.wood": "Holz",
104 | "topdock.woodFull": "Anzeige der Planken an-/ausschalten",
105 |
106 | "system.joinedSession": "%s ist der Sitzung beigetreten.",
107 | "system.addEditor": "%1$s hat %2$s als Bearbeiter hinzugefügt.",
108 | "system.removeEditor": "%1$s hat %2$s als Bearbeiter entfernt.",
109 | "system.cannotRemoveHost": "%s ist der Host und kann nicht als Bearbeiter entfernt werden.",
110 | "system.cannotReachHost": "Der Host ist nicht erreichbar. Er ist möglicherweise gecrasht oder hat die Verbindung getrennt. Ziehe vor dem Verlassen ein Speichern der Modelle für ihn in Erwägung.",
111 | "system.sessionEnded": "Der Host hat die Sitzung beendet."
112 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/lang/it_it.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabula.name": "Tabula",
3 |
4 | "element.minimize": "Minimizza",
5 | "element.expand": "Espandi",
6 |
7 | "element.button.ok": "OK",
8 | "element.button.cancel": "Annulla",
9 |
10 | "window.controls.title": "Controlli",
11 | "window.controls.cubeName": "Nome Cubo selezionato",
12 | "window.controls.dimensions": "Dimensioni",
13 | "window.controls.position": "Posizione",
14 | "window.controls.offset": "Offset",
15 | "window.controls.rotation": "Rotazione",
16 | "window.controls.mcScale": "Scala MC",
17 | "window.controls.scale": "Scala",
18 | "window.controls.txOffset": "Offset della Texture",
19 | "window.controls.txMirror": "Specchio",
20 | "window.controls.txMirrorFull": "Texture a specchio",
21 |
22 | "window.newProject.title": "Nuovo progetto",
23 | "window.newProject.projIdent": "Nome del progetto",
24 | "window.newProject.animName": "Nome dell'autore",
25 | "window.newProject.txDimensions": "Altezza e larghezza delle texture",
26 |
27 | "window.editProject.title": "Edit Project",
28 |
29 | "window.modelTree.title": "Albero del modello",
30 | "window.modelTree.newCube": "Nuovo cubo",
31 | "window.modelTree.newGroup": "Nuovo gruppo",
32 | "window.modelTree.delete": "Cancella",
33 |
34 | "window.texture.title": "Texture",
35 | "window.texture.loadTexture": "Carica Texture",
36 | "window.texture.clearTexture": "Rimuovi Texture",
37 | "window.texture.listenTexture": "Attendi",
38 | "window.texture.listenTextureFull": "Aspetta cambiamenti di texture (se le texture sono tue)",
39 | "window.texture.remoteTexture": "Texture remote",
40 | "window.texture.noTexture": "Senza Texture",
41 |
42 | "window.import.title": "Importa il modello nel progetto corrente",
43 | "window.import.texture": "Texture",
44 | "window.import.textureFull": "Importa comunque la texture (se presente)?",
45 |
46 | "window.importMC.title": "Importa il modello di Minecraft",
47 | "window.importMC.newProject": "Nuovo?",
48 | "window.importMC.newProjectFull": "Importa il modello in un nuovo progetto?",
49 |
50 | "window.loadTexture.title": "Carica Texture",
51 | "window.loadTexture.updateTextureDimensions": "Aggiorna?",
52 | "window.loadTexture.updateTextureDimensionsFull": "Aggiorna la misura delle texture del progetto?",
53 |
54 | "window.chat.title": "Chat",
55 | "window.chat.textbox": "Premi ENTER per inviare",
56 |
57 | "window.saveAs.title": "Salva come",
58 | "window.saveAs.fileName": "Nome del file",
59 | "window.saveAs.overwrite": "Sovrascrivi?",
60 | "window.saveAs.confirmOverwrite": "Il file esiste già. Vuoi sovrascrivere?",
61 | "window.saveAs.failed": "Fallito il salvataggio.",
62 |
63 | "window.notSaved.title": "Progetto non salvato!",
64 | "window.notSaved.unsaved": "Il progetto non è salvato!",
65 | "window.notSaved.save": "Vuoi salvare prima di chiudere?",
66 |
67 | "window.open.title": "Apri il progetto",
68 | "window.open.opening": "Apertura in corso...",
69 | "window.open.failed": "Errore nell'apertura del file",
70 |
71 | "window.popup.title": "Attenzione!",
72 |
73 | "window.about.title": "Info",
74 | "window.about.line0": "Versione della mod: ",
75 | "window.about.line1": "Sviluppatori: ",
76 | "window.about.line2": "Texture: ",
77 | "window.about.line3": "Contributi: ",
78 | "window.about.line4": "Testers: ",
79 | "window.about.line5": "Localizzazione corrente: Fundor333",
80 | "window.about.line6": "Funzioni e GUI sono basate su Techne di ZeuX e r4wk",
81 | "window.about.os1": "Se hai qualche problema da segnalare o suggerimento segui questo link",
82 | "window.about.os2": "Il progetto è open source e può essere trovato qui:",
83 |
84 | "export.title": "Esporta il progetto",
85 | "export.failed": "Fallito l'esportazione!",
86 | "export.textureMap.name": "Mappa delle texture",
87 | "export.javaClass.title": "Esportato come classe Java",
88 | "export.javaClass.package": "Package per classe",
89 | "export.javaClass.name": "Classe Java",
90 | "export.javaClass.className": "Nome della classe",
91 | "export.projTexture.name": "Texture del progetto",
92 | "export.blockjson.name": "Blocco JSON",
93 | "export.blockjson.title": "Esporta Blocco JSON",
94 | "export.blockjson.filename": "Nome del file",
95 | "export.blockjson.corner": "Angolo del blocco è a (0, 0) (clicca per cambiare)",
96 | "export.blockjson.centre": "Il centro del blocco è a (0, 0) (clicca per cambiare)",
97 | "export.blockjson.relative": "Il modello a blocchi è relativo al blocco di legno (clicca per cambiare)",
98 | "export.blockjson.absolute": "Il modello a blocchi è relativo a y = 0 (clicca per cambiare)",
99 |
100 | "topdock.new": "Nuovo progetto",
101 | "topdock.edit": "Modifica progetto",
102 | "topdock.open": "Apri progetto",
103 | "topdock.save": "Salva",
104 | "topdock.saveAs": "Salva come",
105 | "topdock.import": "Importa il progetto",
106 | "topdock.importMC": "Importa da Minecraft",
107 | "topdock.export": "Esporta il progetto",
108 | "topdock.cut": "Taglia",
109 | "topdock.copy": "Copia",
110 | "topdock.paste": "Incolla",
111 | "topdock.pasteInPlace": "Incolla sul posto",
112 | "topdock.undo": "Annulla",
113 | "topdock.redo": "Avanti",
114 | "topdock.chat": "Riduci la finestra della chat",
115 | "topdock.info": "Info sulla mod",
116 | "topdock.exitTabula": "Esci da Tabula",
117 | "topdock.wood": "Legno",
118 | "topdock.woodFull": "Abilita la visione degli assi",
119 |
120 | "system.joinedSession": "%s si è unito a te.",
121 | "system.addEditor": "%1$s ha aggiunto %2$s come editor.",
122 | "system.removeEditor": "%1$s ha rimosso %2$s come editor.",
123 | "system.cannotRemoveHost": "%s è l'host e non può essere rimosso come editor.",
124 | "system.cannotReachHost": "L'host è irraggiungibile. O ha crashato o si è disconnesso. Salva i modelli prima di uscire.",
125 | "system.sessionEnded": "L'host ha terminato la sessione."
126 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/lang/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabula.name": "Tabula",
3 |
4 | "window.controls.title": "控制",
5 | "window.controls.cubeName": "选定方块名称",
6 | "window.controls.dimensions": "尺寸",
7 | "window.controls.position": "位置",
8 | "window.controls.offset": "偏移",
9 | "window.controls.rotation": "旋转",
10 | "window.controls.opacity": "不透明度",
11 | "window.controls.mcScale": "MC比例",
12 | "window.controls.scale": "自定义比例",
13 | "window.controls.txOffset": "材质偏移",
14 | "window.controls.txMirror": "镜像",
15 | "window.controls.txMirrorFull": "镜像材质",
16 |
17 | "window.newProject.title": "新建项目",
18 | "window.newProject.projIdent": "项目名称",
19 | "window.newProject.animName": "作者名称",
20 | "window.newProject.txDimensions": "材质宽度与高度",
21 | "window.newProject.projectScale": "项目比例",
22 |
23 | "window.editProject.title": "编辑项目",
24 |
25 | "window.modelTree.title": "模型树",
26 | "window.modelTree.newCube": "新建方块",
27 | "window.modelTree.newGroup": "新建组",
28 | "window.modelTree.delete": "删除",
29 | "window.modelTree.editMeta": "编辑元数据",
30 |
31 | "window.texture.title": "材质",
32 | "window.texture.loadTexture": "加载材质",
33 | "window.texture.clearTexture": "清除材质",
34 | "window.texture.listenTexture": "监听",
35 | "window.texture.listenTextureFull": "监听材质变化(如果材质是你的)",
36 | "window.texture.remoteTexture": "材质预览",
37 | "window.texture.noTexture": "无材质",
38 |
39 | "window.import.title": "向当前项目导入模型",
40 | "window.import.texture": "材质",
41 | "window.import.textureFull": "同步导入材质?(如果可用的话)",
42 |
43 | "window.importMC.title": "导入Minecraft模型",
44 | "window.importMC.newProject": "导入新项目?",
45 | "window.importMC.newProjectFull": "是否将模型导入一个新项目?",
46 |
47 | "window.loadTexture.title": "载入材质",
48 | "window.loadTexture.updateTextureDimensions": "更新?",
49 | "window.loadTexture.updateTextureDimensionsFull": "是否更新项目的材质尺寸?",
50 |
51 | "window.chat.title": "聊天",
52 | "window.chat.textbox": "按ENTER键发送",
53 |
54 | "window.notSaved.title": "项目未保存!",
55 | "window.notSaved.unsaved": "项目还未保存!",
56 | "window.notSaved.save": "你想要在关闭前保存吗?",
57 |
58 | "window.open.title": "打开项目",
59 | "window.open.opening": "打开中...",
60 | "window.open.failed": "打开文件失败.",
61 |
62 | "window.about.title": "关于",
63 | "window.about.line0": "Mod版本: ",
64 | "window.about.line1": "开发: ",
65 | "window.about.line2": "材质: ",
66 | "window.about.line3": "贡献: ",
67 | "window.about.line4": "测试: ",
68 | "window.about.line5": "当前语言翻译: Mrkwtkr",
69 | "window.about.line6": "功能与UI基于原始的Techne(制作者: ZeuX, r4wk)",
70 | "window.about.os1": "如果你有任何问题或建议,可访问下方链接",
71 | "window.about.os2": "项目开源详见:",
72 |
73 | "window.animate.title": "动画",
74 | "window.animate.newAnim": "新建动画",
75 | "window.animate.editAnim": "编辑动画",
76 | "window.animate.delAnim": "删除动画",
77 | "window.animate.playAnim": "播放动画",
78 | "window.animate.stopAnim": "暂停动画",
79 | "window.animate.newComponent": "新建组件",
80 | "window.animate.editComponent": "编辑组件",
81 | "window.animate.delComponent": "删除组件",
82 | "window.animate.splitComponent": "分离组件. 这会重置组件曲线",
83 | "window.animate.editProgComponent": "编辑组件曲线",
84 | "window.animate.selectCube": "请先选择需要动画的方块!",
85 | "window.animate.selectAnim": "请先选择一个动画!",
86 |
87 | "window.newAnim.title": "新建动画",
88 | "window.newAnim.animName": "动画名称",
89 | "window.newAnim.animLoop": "动画是否循环?",
90 | "window.editAnim.title": "编辑动画",
91 |
92 | "window.newAnimComp.title": "新建动画组件",
93 | "window.newAnimComp.name": "组件名称",
94 | "window.newAnimComp.length": "组件时长(以tick计)",
95 | "window.editAnimComp.title": "编辑动画组件",
96 | "window.editAnimComp.startPos": "组件起始Tick",
97 |
98 | "window.editAnimCompProg.title": "编辑动画组件曲线",
99 | "window.editAnimCompProg.prog": "动画曲线",
100 | "window.editAnimCompProg.reset": "重置",
101 | "window.editAnimCompProg.play": "播放动画",
102 | "window.editAnimCompProg.playDesc": "是否在编辑曲线时播放动画?",
103 | "window.editAnimCompProg.invalid": "无效的曲线!",
104 | "window.editAnimCompProg.animInfo": "动画关键帧信息: ",
105 |
106 | "window.selectTheme.title": "选择主题",
107 |
108 | "window.settings.title": "设置",
109 | "window.settings.renderRotationPoint": "渲染模型旋转点",
110 |
111 | "window.autoLayout.failed": "布置材质失败.",
112 |
113 | "window.metadata.title": "项目元数据",
114 | "window.metadata.titleShort": "元数据",
115 |
116 | "window.ghostModel.title": "设置幽灵模型",
117 |
118 | "export.title": "导出项目",
119 | "export.failed": "导出失败!",
120 | "export.textureMap.name": "材质映射",
121 | "export.javaClass.title": "导出为Java类",
122 | "export.javaClass.package": "类所在包",
123 | "export.javaClass.name": "Java类",
124 | "export.javaClass.className": "类名",
125 | "export.projTexture.name": "项目材质",
126 |
127 | "topdock.new": "新建项目",
128 | "topdock.edit": "编辑项目",
129 | "topdock.open": "打开项目",
130 | "topdock.save": "保存",
131 | "topdock.saveAs": "另存为",
132 | "topdock.import": "导入项目",
133 | "topdock.importMC": "从Minecraft导入",
134 | "topdock.export": "导出项目",
135 | "topdock.cut": "剪贴",
136 | "topdock.copy": "复制",
137 | "topdock.paste": "粘贴",
138 | "topdock.pasteInPlace": "原位粘贴",
139 | "topdock.pasteWithoutChildren": "忽视子集粘贴",
140 | "topdock.undo": "撤销",
141 | "topdock.redo": "重做",
142 | "topdock.chat": "开关聊天窗口",
143 | "topdock.addEditor": "添加编辑者",
144 | "topdock.removeEditor": "移除编辑者",
145 | "topdock.themes": "选择主题",
146 | "topdock.settings": "设置",
147 | "topdock.info": "关于此Mod",
148 | "topdock.exitTabula": "退出Tabula",
149 | "topdock.wood": "基座方块",
150 | "topdock.woodFull": "切换方块的显示",
151 | "topdock.autoLayout": "自动布置材质",
152 | "topdock.ghostModel": "设置幽灵模型",
153 |
154 | "system.playersInSession": "会话中的用户",
155 | "system.editor": "编辑者",
156 | "system.host": "主机",
157 | "system.joinedSession": "%s 加入了会话.",
158 | "system.leftSession": "%s 离开了会话.",
159 | "system.timeout": "%s 连接超时.",
160 | "system.openProject": "%1$s 打开了 %2$s.",
161 | "system.isEditor": "%s 被赋予了编辑权限.",
162 | "system.addEditor": "%1$s 将 %2$s 加入了编辑者.",
163 | "system.removeEditor": "%1$s 将 %2$s 从编辑者中移除.",
164 | "system.alreadyEditor": "%s 已经是编辑者了.",
165 | "system.notEditor": "%s 不是一个编辑者.",
166 | "system.cannotRemoveHost": "%s 是主机且不能被取消编辑权限.",
167 | "system.hosting": "你是该Tabula会话的主机.",
168 | "system.hostingOther": "%s 成为该Tabula会话的主机.",
169 | "system.cannotReachHost": "%s (主机)无法访问. 可能出现了崩溃或断线问题, 在退出前最好为其保存模型.",
170 | "system.sessionEnded": "%s (主机)结束了会话.",
171 |
172 | "config.tabula.cat.multiplayer.name": "多人",
173 | "config.tabula.cat.others.name": "其他",
174 |
175 | "config.tabula.cat.multiplayer.desc": "Tabula会话的多人设置",
176 | "config.tabula.cat.others.desc": "其他配置, 你大概不需要修改这些.",
177 |
178 | "config.tabula.prop.favTheme.name": "收藏主题",
179 | "config.tabula.prop.renderRotationPoint.name": "渲染模型旋转点",
180 | "config.tabula.prop.renderWorkspaceBlock.name": "渲染工作区方块",
181 | "config.tabula.prop.renderGrid.name": "渲染网格",
182 | "config.tabula.prop.renderModelControls.name": "渲染模型控件",
183 | "config.tabula.prop.swapPositionOffset.name": "位置/偏移互换",
184 | "config.tabula.prop.chatSound.name": "聊天音效",
185 | "config.tabula.prop.allowEveryoneToEdit.name": "允许所有人编辑",
186 | "config.tabula.prop.editors.name": "授权编辑者",
187 | "config.tabula.prop.animateImports.name": "动画导入",
188 | "config.tabula.prop.chatWindow.name": "聊天窗口设置",
189 | "config.tabula.prop.tooltipTime.name": "提示框时间",
190 |
191 | "config.tabula.prop.favTheme.desc": "收藏的Tabula界面颜色主题",
192 | "config.tabula.prop.renderRotationPoint.desc": "是否渲染选定模型部件的旋转点",
193 | "config.tabula.prop.renderWorkspaceBlock.desc": "是否渲染工作区的基座方块",
194 | "config.tabula.prop.renderGrid.desc": "是否渲染工作区的网格",
195 | "config.tabula.prop.renderModelControls.desc": "是否渲染模型上的控件",
196 | "config.tabula.prop.swapPositionOffset.desc": "是否在修改位置或偏移时互换两者?",
197 | "config.tabula.prop.chatSound.desc": "是否启用聊天音效?",
198 | "config.tabula.prop.allowEveryoneToEdit.desc": "允许任何连入Tabula会话的人编辑模型",
199 | "config.tabula.prop.editors.desc": "在你的Tabula多人会话中被允许编辑模型的人.\\n使用逗号和空格分隔用户名(\", \" - 不需要引号)",
200 | "config.tabula.prop.animateImports.desc": "是否尝试为可能的导入模型附加动画以修复其旋转?",
201 | "config.tabula.prop.chatWindow.desc": "请勿使用.",
202 | "config.tabula.prop.tooltipTime.desc": "提示框存在的时间(以tick计).",
203 |
204 | "block.tabula.block.tabularasa": "书写蜡板"
205 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/models/block/tabularasa.json:
--------------------------------------------------------------------------------
1 | {
2 | "textures": {
3 | "particle": "tabula:blocks/tabularasa",
4 | "texture": "tabula:blocks/tabularasa"
5 | },
6 | "elements": [
7 | { "from": [ 0, 0, 0 ],
8 | "to": [ 0, 0, 0 ],
9 | "shade": false,
10 | "faces": {
11 | "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#texture" }
12 | }
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/models/item/tabularasa.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "builtin/generated",
3 | "textures": {
4 | "layer0": "tabula:blocks/tabularasa"
5 | },
6 | "display": {
7 | "thirdperson": {
8 | "rotation": [ -90, 0, 0 ],
9 | "translation": [ 0, 1, -2.5 ],
10 | "scale": [ 0.55, 0.55, 0.55 ]
11 | },
12 | "firstperson": {
13 | "rotation": [ 0, -135, 25 ],
14 | "translation": [ 0, 4, 2 ],
15 | "scale": [ 1.7, 1.7, 1.7 ]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/blocks/tabularasa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/blocks/tabularasa.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/addeditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/addeditor.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/autolayout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/autolayout.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/chat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/chat.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/cleartexture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/cleartexture.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/copy.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/cut.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/delete.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/edit.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/editmeta.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/editmeta.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/exittabula.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/exittabula.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/export.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/ghostmodel.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/ghostmodel.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/group.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/hidetexture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/hidetexture.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/import.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/importmc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/importmc.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/info.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/model.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/model.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/new.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/newcube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/newcube.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/newgroup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/newgroup.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/newtexture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/newtexture.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/open.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/paste.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/pasteinplace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/pasteinplace.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/pastewithoutchildren.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/pastewithoutchildren.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/redo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/redo.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/removeeditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/removeeditor.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/save.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/saveas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/saveas.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/settings.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/icon/undo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/icon/undo.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/model/cube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/model/cube.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/model/modelgooglyeye.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/model/modelgooglyeye.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/model/tabularasa.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/model/tabularasa.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/workspace/grid16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/workspace/grid16.png
--------------------------------------------------------------------------------
/src/main/resources/assets/tabula/textures/workspace/orientationbase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iChun/Tabula/59f397a8d595c2919a80422a0354d798a292fe82/src/main/resources/assets/tabula/textures/workspace/orientationbase.png
--------------------------------------------------------------------------------
/src/main/resources/data/tabula/loot_tables/blocks/tabularasa.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:block",
3 | "pools": [
4 | {
5 | "rolls": 1,
6 | "entries": [
7 | {
8 | "type": "minecraft:item",
9 | "name": "tabula:tabularasa"
10 | }
11 | ],
12 | "conditions": [
13 | {
14 | "condition": "minecraft:survives_explosion"
15 | }
16 | ]
17 | }
18 | ]
19 | }
--------------------------------------------------------------------------------
/src/main/resources/data/tabula/recipes/tabularasa.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:crafting_shaped",
3 | "pattern": [
4 | "#",
5 | "S"
6 | ],
7 | "key": {
8 | "#": {
9 | "item": "minecraft:ghast_tear"
10 | },
11 | "S": {
12 | "item": "minecraft:oak_pressure_plate"
13 | }
14 | },
15 | "result": {
16 | "item": "tabula:tabularasa"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/resources/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack":{
3 | "pack_format":6,
4 | "description":"Tabula"
5 | }
6 | }
--------------------------------------------------------------------------------