mirror of
https://github.com/GTNewHorizons/ForgeRelocation.git
synced 2026-10-25 20:22:27 +00:00
Rewrite of library and movement engine
This commit is contained in:
1 parent
ff3e4183d3
commit
d6731ef60b
62 files changed
+2265
-2197
No files matched your search
Regular → Executable
+2
@@ -64,3 +64,5 @@ white-list.txt.converted
|
||||
whitelist.json
|
||||
world-20140811-075700.zip
|
||||
.cache
|
||||
|
||||
gradle.properties
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,29 +1,33 @@
|
||||
Forge Relocation
|
||||
ForgeRelocation
|
||||
==========
|
||||
Forge Relocation is a mod created to handle the movement of blocks. The aim is to allow developers to use the API toimplement ways to move their own blocks instead of having one mod handle them all in a very hacky and non-reliable manner.
|
||||
An API for handling the movement of blocks.
|
||||
- [](https://travis-ci.org/MrTJP/ForgeRelocation)
|
||||
- [Minecraft Forum Thread](http://www.minecraftforum.net/topic/1885652-)
|
||||
- [Website](http://projectredwiki.com)
|
||||
|
||||
Note:
|
||||
----------
|
||||
Forge Relocation is currently in alpha stages of development. Although it is fairly stable, the safety of your world is not guaranteed.
|
||||
|
||||
*This mod is not affiliated with Minecraft Forge.*
|
||||
Info
|
||||
-
|
||||
The ForgeRelocation API contains utility classes that can easily help move blocks. Operation
|
||||
of the API is very simple. Just specify the blocks, the direction, and the speed. The
|
||||
rest will be taken care of.
|
||||
|
||||
|
||||
Developing:
|
||||
----------
|
||||
Setup is slightly different depending on what system and IDE you use.
|
||||
This assumes you know how to run gradle commands on your system.
|
||||
The base command, `./gradlew` being used below is for Linux or Unix based systems. For windows, this would simply change to `gradlew`.
|
||||
Of course, if you dont need to use the wrapper (as in, you have gradle installed on your system), you can simply go right to `gradle`.
|
||||
The MCFrames mod (included) contains a robust and highly configurable implementation of
|
||||
frames. It also contains an API that can quickly resolve frame sticks.
|
||||
An example implementation of a motor block is included as well.
|
||||
|
||||
Usage
|
||||
-
|
||||
The best way to use the API is to simply link the dev jar as a dependency in your IDE.
|
||||
|
||||
However, both ForgeRelocation and MCFrames contains a self-contained API package. If needed, they can be used,
|
||||
but it is recommended that they are not included. They should be used as a soft dependency.
|
||||
|
||||
|
||||
1. Clone repository to empty folder.
|
||||
2. Cd to the repository (folder where `src` and `resources` are located).
|
||||
3. Run `./gradlew setupDecompWorkspace` to set up an environment.
|
||||
4. Run `./gradlew eclipse` or `./gradlew idea` appropriately.
|
||||
5. Open your IDE using the generated files (i.e., for IDEA, a ProjectRed.ipr is generated in `./`)
|
||||
6. Edit, run, and debug your new code.
|
||||
7. Once its bug free and working, you may submit it as a PR to the main repo.
|
||||
Development
|
||||
-
|
||||
If you would like to contribute to the API, a simple `./gradlew setupDecompWorkspace` followed by a `./gradlew idea` or
|
||||
`./gradlew eclipse` should set up the entire dev environment.
|
||||
|
||||
|
||||
*This mod is not affiliated with Minecraft Forge.*
|
||||
+19
-2
@@ -34,6 +34,7 @@ repositories {
|
||||
|
||||
apply plugin: 'scala'
|
||||
apply plugin: 'forge'
|
||||
apply plugin: 'curseforge'
|
||||
|
||||
group = "mrtjp"
|
||||
archivesBaseName = "ForgeRelocation"
|
||||
@@ -58,7 +59,7 @@ dependencies {
|
||||
|
||||
def build_number = project.hasProperty("manualbuildnum") ? project.manualbuildnum : (System.getenv("BUILD_NUMBER") ?: "1")
|
||||
version = "${project.config.mod.version}."+build_number
|
||||
println config.mc.version+"-"+config.forge.version
|
||||
println "Starting build for $archivesBaseName $version for MC $config.mc.version-$config.forge.version"
|
||||
|
||||
minecraft {
|
||||
version = config.mc.version+"-"+config.forge.version
|
||||
@@ -133,6 +134,7 @@ task sourceJar(type: Jar) {
|
||||
task apiJar(type: Jar) {
|
||||
from(sourceSets.main.allSource) {
|
||||
include "**/relocation/api/**"
|
||||
include "**/mcframes/api/**"
|
||||
}
|
||||
classifier = 'api'
|
||||
}
|
||||
@@ -227,7 +229,7 @@ uploadArchives {
|
||||
licenses {
|
||||
license {
|
||||
name 'Restricted Public Software License (RPSL) v1.3.1'
|
||||
url 'https://raw.githubusercontent.com/MrTJP/ProjectRed/master/LICENSE.md'
|
||||
url 'https://raw.githubusercontent.com/MrTJP/'+project.archivesBaseName+'/master/LICENSE'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
@@ -244,4 +246,19 @@ uploadArchives {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (project.hasProperty('curseapi'))
|
||||
{
|
||||
curse {
|
||||
projectId = '232075'
|
||||
apiKey = project.curseapi
|
||||
releaseType = 'release'
|
||||
|
||||
relatedProject 'mrtjpcore': 'requiredLibrary'
|
||||
|
||||
additionalArtifact deobfJar
|
||||
additionalArtifact sourceJar
|
||||
additionalArtifact apiJar
|
||||
}
|
||||
}
|
||||
Regular → Executable
+4
-4
@@ -1,7 +1,7 @@
|
||||
mod.version=0.0.1a
|
||||
mod.version=0.0.1
|
||||
|
||||
mc.version=1.7.10
|
||||
forge.version=10.13.2.1277
|
||||
forge.version=10.13.3.1399-1.7.10
|
||||
|
||||
mrtjp.version=1.0.5.11
|
||||
ccl.version=1.1.1.110
|
||||
mrtjp.version=1.0.10.23
|
||||
ccl.version=1.1.3.136
|
||||
File mode changed.
Binary file not shown.
|
After Width: | Height: | Size: 274 KiB |
Regular → Executable
+2
-2
@@ -1,2 +1,2 @@
|
||||
v0.0.1a
|
||||
- Initial alpha release
|
||||
v0.0.1.2
|
||||
- Initial release
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
tile.mcframes.frame.name=Frame
|
||||
tile.mcframes.motor|0.name=Debug Frame Motor
|
||||
Regular → Executable
BIN
Binary file not shown.
Executable
+111
@@ -0,0 +1,111 @@
|
||||
# Blender v2.71 (sub 5) OBJ File: 'frame.blend'
|
||||
# www.blender.org
|
||||
g frame_frame_Cube.001
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v -0.500000 -0.375000 -0.375000
|
||||
v -0.500000 0.375000 -0.375000
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v -0.500000 -0.375000 0.375000
|
||||
v -0.375000 -0.375000 0.500000
|
||||
v -0.375000 0.375000 0.500000
|
||||
v -0.500000 0.500000 0.500000
|
||||
v -0.375000 0.500000 -0.375000
|
||||
v 0.375000 0.500000 -0.375000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
v -0.375000 0.375000 -0.500000
|
||||
v -0.375000 -0.375000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.375000 -0.500000 -0.375000
|
||||
v -0.375000 -0.500000 -0.375000
|
||||
v 0.375000 0.375000 0.500000
|
||||
v -0.375000 0.375000 0.375000
|
||||
v 0.375000 0.375000 0.375000
|
||||
v 0.375000 -0.375000 0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v 0.375000 0.500000 0.375000
|
||||
v -0.375000 0.500000 0.375000
|
||||
v 0.375000 -0.375000 -0.500000
|
||||
v 0.375000 0.375000 -0.500000
|
||||
v 0.375000 -0.500000 0.375000
|
||||
v 0.500000 -0.375000 -0.375000
|
||||
v 0.500000 -0.375000 0.375000
|
||||
v 0.500000 0.375000 -0.375000
|
||||
v 0.375000 -0.375000 -0.375000
|
||||
v 0.375000 -0.375000 0.375000
|
||||
v 0.375000 -0.375000 -0.000000
|
||||
v -0.375000 0.375000 0.000000
|
||||
v -0.375000 0.375000 -0.375000
|
||||
v 0.375000 0.375000 -0.375000
|
||||
v -0.375000 -0.375000 -0.375000
|
||||
v -0.375000 -0.375000 0.375000
|
||||
v -0.375000 -0.500000 0.375000
|
||||
v 0.500000 0.375000 0.375000
|
||||
v 0.375000 0.375000 0.000000
|
||||
v -0.500000 0.375000 0.375000
|
||||
v -0.375000 -0.375000 -0.000000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.125000 0.125000
|
||||
vt 0.125000 0.875000
|
||||
vt 1.000000 0.000000
|
||||
vt 0.875000 0.125000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.875000 0.875000
|
||||
vt 0.750000 0.125000
|
||||
vt 0.750000 0.875000
|
||||
vt 0.250000 0.875000
|
||||
vt 0.250000 0.125000
|
||||
vt 0.875000 0.500000
|
||||
vt 0.250000 0.500000
|
||||
vt 0.750000 0.500000
|
||||
s 1
|
||||
f 1/1 2/2 3/3 4/4
|
||||
f 5/5 6/6 3/3 2/2
|
||||
f 7/3 8/4 9/1 5/2
|
||||
f 1/2 10/3 11/4 12/1
|
||||
f 2/5 1/7 13/8 14/6
|
||||
f 2/1 15/2 16/3 17/4
|
||||
f 18/8 8/6 19/9 20/10
|
||||
f 21/6 22/5 23/7 18/8
|
||||
f 9/5 23/7 24/8 25/6
|
||||
f 26/3 27/4 12/1 15/2
|
||||
f 22/5 28/6 16/3 15/2
|
||||
f 22/2 15/5 29/6 30/3
|
||||
f 12/7 31/8 29/6 15/5
|
||||
f 36/11 37/12 11/3 10/4
|
||||
f 36/12 13/3 27/4 37/11
|
||||
f 38/12 14/3 13/4 36/11
|
||||
f 17/8 16/6 32/9 38/10
|
||||
f 7/8 21/6 33/9 39/10
|
||||
f 33/12 21/3 18/4 20/11
|
||||
f 20/8 19/6 25/9 24/10
|
||||
f 27/8 26/6 32/9 37/10
|
||||
f 32/6 26/9 14/10 38/8
|
||||
f 28/8 40/6 39/9 33/10
|
||||
f 29/8 31/6 37/9 32/10
|
||||
f 41/8 30/6 33/9 20/10
|
||||
f 38/11 36/12 4/3 3/4
|
||||
f 19/11 39/12 6/3 43/4
|
||||
f 8/8 7/6 39/9 19/10
|
||||
f 23/1 41/4 31/8 12/7
|
||||
f 23/1 22/2 30/3 41/4
|
||||
f 7/3 5/2 22/5 21/6
|
||||
f 8/4 18/8 23/7 9/1
|
||||
f 9/7 43/8 6/6 5/5
|
||||
f 9/7 1/1 4/4 43/8
|
||||
f 1/7 12/1 27/4 13/8
|
||||
f 14/6 26/3 15/2 2/5
|
||||
f 23/7 12/1 11/4 24/8
|
||||
f 10/3 1/2 9/5 25/6
|
||||
f 5/7 2/1 17/4 40/8
|
||||
f 5/7 40/8 28/6 22/5
|
||||
f 43/9 4/10 36/8 35/13 19/6
|
||||
f 33/11 34/14 32/12 16/3 28/4
|
||||
f 44/15 38/10 3/8 6/6 39/9
|
||||
f 35/14 36/12 10/3 25/4 19/11
|
||||
f 42/15 37/10 31/8 41/6 20/9
|
||||
f 34/14 33/12 30/3 29/4 32/11
|
||||
f 40/8 17/6 38/9 44/15 39/10
|
||||
f 42/15 20/10 24/8 11/6 37/9
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Regular → Executable
File renamed without changes.
Regular → Executable
File renamed without changes.
Regular → Executable
File renamed without changes.
Regular → Executable
File renamed without changes.
Regular → Executable
File renamed without changes.
@@ -1,2 +0,0 @@
|
||||
tile.relocation.blockframe|0=Frame
|
||||
tile.relocation.blockmotor|0=Frame Motor
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.7 KiB |
Binary file not shown.
Binary file not shown.
@@ -1,267 +0,0 @@
|
||||
# Blender v2.71 (sub 5) OBJ File: 'frame.blend'
|
||||
# www.blender.org
|
||||
g support_Cube.010
|
||||
v 0.375030 0.380070 0.468458
|
||||
v 0.437530 0.380070 0.468458
|
||||
v 0.437530 0.468458 0.380070
|
||||
v 0.375030 0.468458 0.380070
|
||||
v 0.375030 -0.468458 -0.380070
|
||||
v 0.437530 -0.468458 -0.380070
|
||||
v 0.437530 -0.380070 -0.468458
|
||||
v 0.375030 -0.380070 -0.468458
|
||||
v 0.375020 0.468458 -0.380070
|
||||
v 0.437520 0.468458 -0.380070
|
||||
v 0.437520 0.380070 -0.468458
|
||||
v 0.375020 0.380070 -0.468458
|
||||
v 0.375020 -0.380070 0.468458
|
||||
v 0.437520 -0.380070 0.468458
|
||||
v 0.437520 -0.468458 0.380070
|
||||
v 0.375020 -0.468458 0.380070
|
||||
v -0.380070 -0.437510 0.468458
|
||||
v -0.380070 -0.375010 0.468458
|
||||
v -0.468458 -0.375010 0.380070
|
||||
v -0.468458 -0.437510 0.380070
|
||||
v 0.468458 -0.437510 -0.380070
|
||||
v 0.468458 -0.375010 -0.380070
|
||||
v 0.380070 -0.375010 -0.468458
|
||||
v 0.380070 -0.437510 -0.468458
|
||||
v -0.468458 -0.437520 -0.380070
|
||||
v -0.468458 -0.375020 -0.380070
|
||||
v -0.380070 -0.375020 -0.468458
|
||||
v -0.380070 -0.437520 -0.468458
|
||||
v 0.380070 -0.437520 0.468458
|
||||
v 0.380070 -0.375020 0.468458
|
||||
v 0.468458 -0.375020 0.380070
|
||||
v 0.468458 -0.437520 0.380070
|
||||
v -0.380070 0.375030 0.468458
|
||||
v -0.380070 0.437530 0.468458
|
||||
v -0.468458 0.437530 0.380070
|
||||
v -0.468458 0.375030 0.380070
|
||||
v 0.468458 0.375030 -0.380070
|
||||
v 0.468458 0.437530 -0.380070
|
||||
v 0.380070 0.437530 -0.468458
|
||||
v 0.380070 0.375030 -0.468458
|
||||
v -0.468458 0.375020 -0.380070
|
||||
v -0.468458 0.437520 -0.380070
|
||||
v -0.380070 0.437520 -0.468458
|
||||
v -0.380070 0.375020 -0.468458
|
||||
v 0.380070 0.375020 0.468458
|
||||
v 0.380070 0.437520 0.468458
|
||||
v 0.468458 0.437520 0.380070
|
||||
v 0.468458 0.375020 0.380070
|
||||
v -0.380070 0.468458 0.437510
|
||||
v -0.380070 0.468458 0.375010
|
||||
v -0.468458 0.380070 0.375010
|
||||
v -0.468458 0.380070 0.437510
|
||||
v 0.468458 -0.380070 0.437510
|
||||
v 0.468458 -0.380070 0.375010
|
||||
v 0.380070 -0.468458 0.375010
|
||||
v 0.380070 -0.468458 0.437510
|
||||
v -0.468458 -0.380070 0.437520
|
||||
v -0.468458 -0.380070 0.375020
|
||||
v -0.380070 -0.468458 0.375020
|
||||
v -0.380070 -0.468458 0.437520
|
||||
v 0.380070 0.468458 0.437520
|
||||
v 0.380070 0.468458 0.375020
|
||||
v 0.468458 0.380070 0.375020
|
||||
v 0.468458 0.380070 0.437520
|
||||
v -0.380070 0.468458 -0.375030
|
||||
v -0.380070 0.468458 -0.437530
|
||||
v -0.468458 0.380070 -0.437530
|
||||
v -0.468458 0.380070 -0.375030
|
||||
v 0.468458 -0.380070 -0.375030
|
||||
v 0.468458 -0.380070 -0.437530
|
||||
v 0.380070 -0.468458 -0.437530
|
||||
v 0.380070 -0.468458 -0.375030
|
||||
v -0.468458 -0.380070 -0.375020
|
||||
v -0.468458 -0.380070 -0.437520
|
||||
v -0.380070 -0.468458 -0.437520
|
||||
v -0.380070 -0.468458 -0.375020
|
||||
v 0.380070 0.468458 -0.375020
|
||||
v 0.380070 0.468458 -0.437520
|
||||
v 0.468458 0.380070 -0.437520
|
||||
v 0.468458 0.380070 -0.375020
|
||||
v -0.437510 0.380070 0.468458
|
||||
v -0.375010 0.380070 0.468458
|
||||
v -0.375010 0.468458 0.380070
|
||||
v -0.437510 0.468458 0.380070
|
||||
v -0.437510 -0.468458 -0.380070
|
||||
v -0.375010 -0.468458 -0.380070
|
||||
v -0.375010 -0.380070 -0.468458
|
||||
v -0.437510 -0.380070 -0.468458
|
||||
v -0.437520 0.468458 -0.380070
|
||||
v -0.375020 0.468458 -0.380070
|
||||
v -0.375020 0.380070 -0.468458
|
||||
v -0.437520 0.380070 -0.468458
|
||||
v -0.437520 -0.380070 0.468458
|
||||
v -0.375020 -0.380070 0.468458
|
||||
v -0.375020 -0.468458 0.380070
|
||||
v -0.437520 -0.468458 0.380070
|
||||
vt 0.312500 0.000000
|
||||
vt 0.375000 0.000000
|
||||
vt 0.375000 1.000000
|
||||
vt 0.312500 1.000000
|
||||
vt 0.500000 0.000000
|
||||
vt 0.500000 1.000000
|
||||
vt 0.562500 0.000000
|
||||
vt 0.562500 1.000000
|
||||
vt 0.687500 1.000000
|
||||
vt 0.687500 0.000000
|
||||
s 1
|
||||
f 5/1 6/2 2/3 1/4
|
||||
f 6/2 7/5 3/6 2/3
|
||||
f 7/5 8/7 4/8 3/6
|
||||
f 8/9 5/8 1/7 4/10
|
||||
f 13/1 14/2 10/3 9/4
|
||||
f 14/2 15/5 11/6 10/3
|
||||
f 15/5 16/7 12/8 11/6
|
||||
f 16/9 13/8 9/7 12/10
|
||||
f 21/1 22/2 18/3 17/4
|
||||
f 22/2 23/5 19/6 18/3
|
||||
f 23/5 24/7 20/8 19/6
|
||||
f 24/9 21/8 17/7 20/10
|
||||
f 29/1 30/2 26/3 25/4
|
||||
f 30/2 31/5 27/6 26/3
|
||||
f 31/5 32/7 28/8 27/6
|
||||
f 32/9 29/8 25/7 28/10
|
||||
f 37/1 38/2 34/3 33/4
|
||||
f 38/2 39/5 35/6 34/3
|
||||
f 39/5 40/7 36/8 35/6
|
||||
f 40/9 37/8 33/7 36/10
|
||||
f 45/1 46/2 42/3 41/4
|
||||
f 46/2 47/5 43/6 42/3
|
||||
f 47/5 48/7 44/8 43/6
|
||||
f 48/9 45/8 41/7 44/10
|
||||
f 53/1 54/2 50/3 49/4
|
||||
f 54/2 55/5 51/6 50/3
|
||||
f 55/5 56/7 52/8 51/6
|
||||
f 56/9 53/8 49/7 52/10
|
||||
f 61/1 62/2 58/3 57/4
|
||||
f 62/2 63/5 59/6 58/3
|
||||
f 63/5 64/7 60/8 59/6
|
||||
f 64/9 61/8 57/7 60/10
|
||||
f 69/1 70/2 66/3 65/4
|
||||
f 70/2 71/5 67/6 66/3
|
||||
f 71/5 72/7 68/8 67/6
|
||||
f 72/9 69/8 65/7 68/10
|
||||
f 77/1 78/2 74/3 73/4
|
||||
f 78/2 79/5 75/6 74/3
|
||||
f 79/5 80/7 76/8 75/6
|
||||
f 80/9 77/8 73/7 76/10
|
||||
f 85/1 86/2 82/3 81/4
|
||||
f 86/2 87/5 83/6 82/3
|
||||
f 87/5 88/7 84/8 83/6
|
||||
f 88/9 85/8 81/7 84/10
|
||||
f 93/1 94/2 90/3 89/4
|
||||
f 94/2 95/5 91/6 90/3
|
||||
f 95/5 96/7 92/8 91/6
|
||||
f 96/9 93/8 89/7 92/10
|
||||
g frame_Cube.001
|
||||
v -0.500000 0.500000 0.500000
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v -0.500000 -0.375000 -0.375000
|
||||
v -0.500000 0.375000 -0.375000
|
||||
v -0.500000 0.375000 0.375000
|
||||
v -0.500000 -0.375000 0.375000
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v -0.375000 0.375000 0.500000
|
||||
v 0.375000 0.375000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v -0.375000 -0.375000 0.500000
|
||||
v -0.375000 0.500000 0.375000
|
||||
v -0.375000 0.500000 -0.375000
|
||||
v 0.375000 0.500000 -0.375000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
v -0.375000 0.375000 -0.500000
|
||||
v -0.375000 -0.375000 -0.500000
|
||||
v 0.375000 0.375000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.375000 -0.500000 -0.375000
|
||||
v -0.375000 -0.500000 -0.375000
|
||||
v -0.375000 -0.500000 0.375000
|
||||
v -0.375000 -0.375000 0.375000
|
||||
v -0.375000 0.375000 0.375000
|
||||
v 0.375000 0.375000 0.375000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v 0.375000 -0.375000 0.500000
|
||||
v 0.375000 0.500000 0.375000
|
||||
v -0.375000 0.375000 0.000000
|
||||
v -0.375000 0.375000 -0.375000
|
||||
v 0.375000 -0.375000 -0.500000
|
||||
v 0.375000 -0.500000 0.375000
|
||||
v 0.375000 -0.375000 -0.375000
|
||||
v -0.375000 -0.375000 -0.375000
|
||||
v -0.375000 -0.375000 0.000000
|
||||
v 0.375000 -0.375000 0.375000
|
||||
v 0.500000 -0.375000 -0.375000
|
||||
v 0.500000 -0.375000 0.375000
|
||||
v 0.500000 0.375000 0.375000
|
||||
v 0.500000 0.375000 -0.375000
|
||||
v 0.375000 0.375000 -0.000000
|
||||
v 0.375000 0.375000 -0.375000
|
||||
v 0.375000 -0.375000 -0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.875000 0.875000
|
||||
vt 0.875000 0.125000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.125000 0.875000
|
||||
vt 0.125000 0.125000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.250000 0.875000
|
||||
vt 0.250000 0.125000
|
||||
vt 0.750000 0.875000
|
||||
vt 0.750000 0.125000
|
||||
vt 0.750000 0.500000
|
||||
vt 0.250000 0.500000
|
||||
vt 0.125000 0.500000
|
||||
s 1
|
||||
f 98/11 99/12 100/13 101/14
|
||||
f 104/15 103/16 100/13 99/12
|
||||
f 108/13 105/14 97/11 104/12
|
||||
f 98/12 110/13 111/14 112/11
|
||||
f 113/17 114/16 99/15 98/18
|
||||
f 99/11 116/12 117/13 118/14
|
||||
f 106/17 105/16 121/19 122/20
|
||||
f 124/16 123/15 107/18 106/17
|
||||
f 97/15 107/18 125/17 109/16
|
||||
f 128/13 115/14 112/11 116/12
|
||||
f 123/15 129/16 117/13 116/12
|
||||
f 123/12 116/15 134/16 135/13
|
||||
f 112/18 137/17 134/16 116/15
|
||||
f 130/21 117/13 129/14 133/22 140/23
|
||||
f 126/23 127/21 110/13 109/14 121/22
|
||||
f 127/22 139/21 111/13 110/14
|
||||
f 127/21 113/13 115/14 139/22
|
||||
f 131/21 114/13 113/14 127/22
|
||||
f 118/17 117/16 130/19 131/20
|
||||
f 108/17 124/16 133/19 120/20
|
||||
f 133/21 124/13 106/14 122/22
|
||||
f 122/17 121/16 109/19 125/20
|
||||
f 115/17 128/16 130/19 139/20
|
||||
f 130/16 128/19 114/20 131/17
|
||||
f 129/17 119/16 120/19 133/20
|
||||
f 137/17 136/16 122/19 138/24 139/20
|
||||
f 134/17 137/16 139/19 130/20
|
||||
f 136/17 135/16 133/19 122/20
|
||||
f 130/22 140/23 133/21 135/13 134/14
|
||||
f 127/17 126/25 121/16 102/19 101/20
|
||||
f 131/22 127/21 101/13 100/14
|
||||
f 121/22 120/21 103/13 102/14
|
||||
f 100/17 103/16 120/19 132/24 131/20
|
||||
f 105/17 108/16 120/19 121/20
|
||||
f 119/17 118/16 131/19 132/24 120/20
|
||||
f 125/17 111/16 139/19 138/24 122/20
|
||||
f 107/11 136/14 137/17 112/18
|
||||
f 107/11 123/12 135/13 136/14
|
||||
f 108/13 104/12 123/15 124/16
|
||||
f 105/14 106/17 107/18 97/11
|
||||
f 97/18 102/17 103/16 104/15
|
||||
f 97/18 98/11 101/14 102/17
|
||||
f 115/14 113/17 98/18 112/11
|
||||
f 114/16 128/13 116/12 99/15
|
||||
f 107/18 112/11 111/14 125/17
|
||||
f 97/15 109/16 110/13 98/12
|
||||
f 104/18 99/11 118/14 119/17
|
||||
f 104/18 119/17 129/16 123/15
|
||||
Binary file not shown.
@@ -1,237 +0,0 @@
|
||||
# Blender v2.71 (sub 5) OBJ File: 'frame_simple.blend'
|
||||
# www.blender.org
|
||||
g frame_frame_Cube.001
|
||||
v -0.500000 0.500000 -0.500000
|
||||
v -0.500000 -0.500000 -0.500000
|
||||
v -0.500000 -0.375000 -0.375000
|
||||
v -0.500000 0.375000 -0.375000
|
||||
v -0.500000 -0.500000 0.500000
|
||||
v -0.500000 -0.375000 0.375000
|
||||
v -0.375000 -0.375000 0.500000
|
||||
v -0.375000 0.375000 0.500000
|
||||
v -0.500000 0.500000 0.500000
|
||||
v -0.375000 0.500000 -0.375000
|
||||
v 0.375000 0.500000 -0.375000
|
||||
v 0.500000 0.500000 -0.500000
|
||||
v -0.375000 0.375000 -0.500000
|
||||
v -0.375000 -0.375000 -0.500000
|
||||
v 0.500000 -0.500000 -0.500000
|
||||
v 0.375000 -0.500000 -0.375000
|
||||
v -0.375000 -0.500000 -0.375000
|
||||
v 0.375000 0.375000 0.500000
|
||||
v -0.375000 0.375000 0.375000
|
||||
v 0.375000 0.375000 0.375000
|
||||
v 0.375000 -0.375000 0.500000
|
||||
v 0.500000 -0.500000 0.500000
|
||||
v 0.500000 0.500000 0.500000
|
||||
v 0.375000 0.500000 0.375000
|
||||
v -0.375000 0.500000 0.375000
|
||||
v 0.375000 -0.375000 -0.500000
|
||||
v 0.375000 0.375000 -0.500000
|
||||
v 0.375000 -0.500000 0.375000
|
||||
v 0.500000 -0.375000 -0.375000
|
||||
v 0.500000 -0.375000 0.375000
|
||||
v 0.500000 0.375000 -0.375000
|
||||
v 0.375000 -0.375000 -0.375000
|
||||
v 0.375000 -0.375000 0.375000
|
||||
v 0.375000 -0.375000 -0.000000
|
||||
v -0.375000 0.375000 0.000000
|
||||
v -0.375000 0.375000 -0.375000
|
||||
v 0.375000 0.375000 -0.375000
|
||||
v -0.375000 -0.375000 -0.375000
|
||||
v -0.375000 -0.375000 0.375000
|
||||
v -0.375000 -0.500000 0.375000
|
||||
v 0.500000 0.375000 0.375000
|
||||
v 0.375000 0.375000 0.000000
|
||||
v -0.500000 0.375000 0.375000
|
||||
v -0.375000 -0.375000 -0.000000
|
||||
vt 1.000000 0.000000
|
||||
vt 1.000000 1.000000
|
||||
vt 0.875000 0.875000
|
||||
vt 0.875000 0.125000
|
||||
vt 0.000000 1.000000
|
||||
vt 0.125000 0.875000
|
||||
vt 0.000000 0.000000
|
||||
vt 0.125000 0.125000
|
||||
vt 0.250000 0.875000
|
||||
vt 0.250000 0.125000
|
||||
vt 0.750000 0.125000
|
||||
vt 0.750000 0.875000
|
||||
vt 0.125000 0.500000
|
||||
vt 0.750000 0.500000
|
||||
vt 0.250000 0.500000
|
||||
s 1
|
||||
f 1/1 2/2 3/3 4/4
|
||||
f 5/5 6/6 3/3 2/2
|
||||
f 7/3 8/4 9/1 5/2
|
||||
f 1/2 10/3 11/4 12/1
|
||||
f 2/5 1/7 13/8 14/6
|
||||
f 2/1 15/2 16/3 17/4
|
||||
f 18/8 8/6 19/9 20/10
|
||||
f 21/6 22/5 23/7 18/8
|
||||
f 9/5 23/7 24/8 25/6
|
||||
f 26/3 27/4 12/1 15/2
|
||||
f 22/5 28/6 16/3 15/2
|
||||
f 22/2 15/5 29/6 30/3
|
||||
f 12/7 31/8 29/6 15/5
|
||||
f 36/11 37/12 11/3 10/4
|
||||
f 36/12 13/3 27/4 37/11
|
||||
f 38/12 14/3 13/4 36/11
|
||||
f 17/8 16/6 32/9 38/10
|
||||
f 7/8 21/6 33/9 39/10
|
||||
f 33/12 21/3 18/4 20/11
|
||||
f 20/8 19/6 25/9 24/10
|
||||
f 27/8 26/6 32/9 37/10
|
||||
f 32/6 26/9 14/10 38/8
|
||||
f 28/8 40/6 39/9 33/10
|
||||
f 29/8 31/6 37/9 32/10
|
||||
f 41/8 30/6 33/9 20/10
|
||||
f 38/11 36/12 4/3 3/4
|
||||
f 19/11 39/12 6/3 43/4
|
||||
f 8/8 7/6 39/9 19/10
|
||||
f 23/1 41/4 31/8 12/7
|
||||
f 23/1 22/2 30/3 41/4
|
||||
f 7/3 5/2 22/5 21/6
|
||||
f 8/4 18/8 23/7 9/1
|
||||
f 9/7 43/8 6/6 5/5
|
||||
f 9/7 1/1 4/4 43/8
|
||||
f 1/7 12/1 27/4 13/8
|
||||
f 14/6 26/3 15/2 2/5
|
||||
f 23/7 12/1 11/4 24/8
|
||||
f 10/3 1/2 9/5 25/6
|
||||
f 5/7 2/1 17/4 40/8
|
||||
f 5/7 40/8 28/6 22/5
|
||||
f 43/9 4/10 36/8 35/13 19/6
|
||||
f 33/11 34/14 32/12 16/3 28/4
|
||||
f 44/15 38/10 3/8 6/6 39/9
|
||||
f 35/14 36/12 10/3 25/4 19/11
|
||||
f 42/15 37/10 31/8 41/6 20/9
|
||||
f 34/14 33/12 30/3 29/4 32/11
|
||||
f 40/8 17/6 38/9 44/15 39/10
|
||||
f 42/15 20/10 24/8 11/6 37/9
|
||||
g support_Cube.004
|
||||
v -0.437495 0.380070 0.468458
|
||||
v -0.437495 0.468458 0.380070
|
||||
v -0.437495 -0.468458 -0.380070
|
||||
v -0.437495 -0.380070 -0.468458
|
||||
v -0.437505 0.468458 -0.380070
|
||||
v -0.437505 0.380070 -0.468458
|
||||
v -0.437505 -0.380070 0.468458
|
||||
v -0.437505 -0.468458 0.380070
|
||||
v -0.437495 0.380070 0.468458
|
||||
v -0.437495 0.468458 0.380070
|
||||
v -0.437495 -0.468458 -0.380070
|
||||
v -0.437495 -0.380070 -0.468458
|
||||
v -0.437505 0.468458 -0.380070
|
||||
v -0.437505 0.380070 -0.468458
|
||||
v -0.437505 -0.380070 0.468458
|
||||
v -0.437505 -0.468458 0.380070
|
||||
v 0.437505 0.380070 0.468458
|
||||
v 0.437505 0.468458 0.380070
|
||||
v 0.437505 -0.468458 -0.380070
|
||||
v 0.437505 -0.380070 -0.468458
|
||||
v 0.437495 0.468458 -0.380070
|
||||
v 0.437495 0.380070 -0.468458
|
||||
v 0.437495 -0.380070 0.468458
|
||||
v 0.437495 -0.468458 0.380070
|
||||
v 0.437505 0.380070 0.468458
|
||||
v 0.437505 0.468458 0.380070
|
||||
v 0.437505 -0.468458 -0.380070
|
||||
v 0.437505 -0.380070 -0.468458
|
||||
v 0.437495 0.468458 -0.380070
|
||||
v 0.437495 0.380070 -0.468458
|
||||
v 0.437495 -0.380070 0.468458
|
||||
v 0.437495 -0.468458 0.380070
|
||||
v -0.380070 -0.437495 0.468458
|
||||
v -0.468458 -0.437495 0.380070
|
||||
v 0.468458 -0.437495 -0.380070
|
||||
v 0.380070 -0.437495 -0.468458
|
||||
v -0.468458 -0.437505 -0.380070
|
||||
v -0.380070 -0.437505 -0.468458
|
||||
v 0.380070 -0.437505 0.468458
|
||||
v 0.468458 -0.437505 0.380070
|
||||
v -0.380070 -0.437495 0.468458
|
||||
v -0.468458 -0.437495 0.380070
|
||||
v 0.468458 -0.437495 -0.380070
|
||||
v 0.380070 -0.437495 -0.468458
|
||||
v -0.468458 -0.437505 -0.380070
|
||||
v -0.380070 -0.437505 -0.468458
|
||||
v 0.380070 -0.437505 0.468458
|
||||
v 0.468458 -0.437505 0.380070
|
||||
v -0.380070 0.437505 0.468458
|
||||
v -0.468458 0.437505 0.380070
|
||||
v 0.468458 0.437505 -0.380070
|
||||
v 0.380070 0.437505 -0.468458
|
||||
v -0.468458 0.437495 -0.380070
|
||||
v -0.380070 0.437495 -0.468458
|
||||
v 0.380070 0.437495 0.468458
|
||||
v 0.468458 0.437495 0.380070
|
||||
v -0.380070 0.437505 0.468458
|
||||
v -0.468458 0.437505 0.380070
|
||||
v 0.468458 0.437505 -0.380070
|
||||
v 0.380070 0.437505 -0.468458
|
||||
v -0.468458 0.437495 -0.380070
|
||||
v -0.380070 0.437495 -0.468458
|
||||
v 0.380070 0.437495 0.468458
|
||||
v 0.468458 0.437495 0.380070
|
||||
v -0.380070 0.468458 0.437495
|
||||
v -0.468458 0.380070 0.437495
|
||||
v 0.468458 -0.380070 0.437495
|
||||
v 0.380070 -0.468458 0.437495
|
||||
v -0.468458 -0.380070 0.437505
|
||||
v -0.380070 -0.468458 0.437505
|
||||
v 0.380070 0.468458 0.437505
|
||||
v 0.468458 0.380070 0.437505
|
||||
v -0.380070 0.468458 0.437495
|
||||
v -0.468458 0.380070 0.437495
|
||||
v 0.468458 -0.380070 0.437495
|
||||
v 0.380070 -0.468458 0.437495
|
||||
v -0.468458 -0.380070 0.437505
|
||||
v -0.380070 -0.468458 0.437505
|
||||
v 0.380070 0.468458 0.437505
|
||||
v 0.468458 0.380070 0.437505
|
||||
v -0.380070 0.468458 -0.437505
|
||||
v -0.468458 0.380070 -0.437505
|
||||
v 0.468458 -0.380070 -0.437505
|
||||
v 0.380070 -0.468458 -0.437505
|
||||
v -0.468458 -0.380070 -0.437495
|
||||
v -0.380070 -0.468458 -0.437495
|
||||
v 0.380070 0.468458 -0.437495
|
||||
v 0.468458 0.380070 -0.437495
|
||||
v -0.380070 0.468458 -0.437505
|
||||
v -0.468458 0.380070 -0.437505
|
||||
v 0.468458 -0.380070 -0.437505
|
||||
v 0.380070 -0.468458 -0.437505
|
||||
v -0.468458 -0.380070 -0.437495
|
||||
v -0.380070 -0.468458 -0.437495
|
||||
v 0.380070 0.468458 -0.437495
|
||||
v 0.468458 0.380070 -0.437495
|
||||
vt 0.687500 1.000000
|
||||
vt 0.562500 1.000000
|
||||
vt 0.562500 0.000000
|
||||
vt 0.687500 0.000000
|
||||
s off
|
||||
f 48/16 47/17 45/18 46/19
|
||||
f 52/16 51/17 49/18 50/19
|
||||
f 56/16 54/19 53/18 55/17
|
||||
f 60/16 58/19 57/18 59/17
|
||||
f 64/16 63/17 61/18 62/19
|
||||
f 68/16 67/17 65/18 66/19
|
||||
f 72/16 70/19 69/18 71/17
|
||||
f 76/16 74/19 73/18 75/17
|
||||
f 80/16 79/17 77/18 78/19
|
||||
f 84/16 83/17 81/18 82/19
|
||||
f 88/16 86/19 85/18 87/17
|
||||
f 92/16 90/19 89/18 91/17
|
||||
f 96/16 95/17 93/18 94/19
|
||||
f 100/16 99/17 97/18 98/19
|
||||
f 104/16 102/19 101/18 103/17
|
||||
f 108/16 106/19 105/18 107/17
|
||||
f 112/16 111/17 109/18 110/19
|
||||
f 116/16 115/17 113/18 114/19
|
||||
f 120/16 118/19 117/18 119/17
|
||||
f 124/16 122/19 121/18 123/17
|
||||
f 128/16 127/17 125/18 126/19
|
||||
f 132/16 131/17 129/18 130/19
|
||||
f 136/16 134/19 133/18 135/17
|
||||
f 140/16 138/19 137/18 139/17
|
||||
Binary file not shown.
Regular → Executable
+4
-4
@@ -1,6 +1,6 @@
|
||||
[{
|
||||
"repo": "http://files.minecraftforge.net/maven/codechicken/CodeChickenLib/@MC_VERSION@-@CCL_VERSION@/",
|
||||
"file": "CodeChickenLib-@MC_VERSION@-@CCL_VERSION@-universal.jar",
|
||||
"dev": "CodeChickenLib-@MC_VERSION@-@CCL_VERSION@-dev.jar",
|
||||
"class": "codechicken.lib.asm.ASMHelper"
|
||||
"repo": "http://projectredwiki.com/maven/mrtjp/MrTJPCore/@MC_VERSION@-@MRTJP_VERSION@/",
|
||||
"file": "MrTJPCore-@MC_VERSION@-@MRTJP_VERSION@-universal.jar",
|
||||
"dev": "MrTJPCore-@MC_VERSION@-@MRTJP_VERSION@-dev.jar",
|
||||
"class": "mrtjp.core.handler.MrTJPCoreMod"
|
||||
}]
|
||||
Regular → Executable
+3
-3
@@ -10,9 +10,9 @@
|
||||
"credits": "",
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"requiredMods": [ "Forge", "MrTJPCoreMod" ],
|
||||
"dependencies": [ "MrTJPCoreMod" ],
|
||||
"dependants" : [ "RelocationFMP" ],
|
||||
"requiredMods": ["MrTJPCoreMod"],
|
||||
"dependencies": [],
|
||||
"dependants" : ["RelocationFMP"],
|
||||
"useDependencyInformation": true
|
||||
}
|
||||
]
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.api;
|
||||
|
||||
import mrtjp.relocation.api.Relocator;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Interface that can be implemented on Tile Entities or Blocks that wish to
|
||||
* act as frames, which are the blocks that stick together and form a
|
||||
* moving structure when moved through the {@link Relocator}. No other action besides
|
||||
* implementation of this interface is needed for the block to function.
|
||||
*/
|
||||
public interface IFrame
|
||||
{
|
||||
/**
|
||||
* Used to check if this frame block is allowed to grab
|
||||
* a block on the given side.
|
||||
*
|
||||
* Convention requires that this method yields the same result
|
||||
* on both client and server.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param side The side of the block, as a ForgeDirection
|
||||
* @return True if the side can stick on to another block.
|
||||
*/
|
||||
boolean stickOut(World w, int x, int y, int z, int side);
|
||||
|
||||
/**
|
||||
* Used to check if this frame block can be grabbed on the
|
||||
* given side from another frame.
|
||||
*
|
||||
* Convention requires that this method yields the same result
|
||||
* on both client and server.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param side The side of the block, as a ForgeDirection
|
||||
* @return True if the side can be stuck onto by a frame block.
|
||||
*/
|
||||
boolean stickIn(World w, int x, int y, int z, int side);
|
||||
}
|
||||
Regular → Executable
+5
-4
@@ -3,8 +3,9 @@
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
package mrtjp.mcframes.api;
|
||||
|
||||
import mrtjp.relocation.api.RelocationAPI;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
@@ -13,7 +14,7 @@ import net.minecraft.world.World;
|
||||
* implement the IFrame interface. This class must be registered in
|
||||
* the {@link RelocationAPI}.
|
||||
*/
|
||||
public abstract class IFrameInteraction implements IFrame
|
||||
public interface IFrameInteraction extends IFrame
|
||||
{
|
||||
/**
|
||||
* Check to see if this interaction can be executed at the given
|
||||
@@ -26,5 +27,5 @@ public abstract class IFrameInteraction implements IFrame
|
||||
* @return True if this interaction is valid for the given
|
||||
* location.
|
||||
*/
|
||||
public abstract boolean canInteract(World w, int x, int y, int z);
|
||||
}
|
||||
boolean canInteract(World w, int x, int y, int z);
|
||||
}
|
||||
Regular → Executable
+11
-10
@@ -3,9 +3,10 @@
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
package mrtjp.mcframes.api;
|
||||
|
||||
import codechicken.lib.vec.Vector3;
|
||||
import mrtjp.relocation.api.RelocationAPI;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.world.World;
|
||||
@@ -21,15 +22,15 @@ public interface IFramePlacement
|
||||
/**
|
||||
* Called sequentially on all registered IFrameBlockPlacements on
|
||||
* the frame item block's onItemUse function, until one returns true.
|
||||
* @param item
|
||||
* @param player
|
||||
* @param world
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @param side
|
||||
* @param hit
|
||||
* @return
|
||||
* @param item The itemstack of the frame block.
|
||||
* @param player The player who is placing the block.
|
||||
* @param world The world the block is being placed in.
|
||||
* @param x The x coordinate that the block is being placed in.
|
||||
* @param y The y coordinate that the block is being placed in.
|
||||
* @param z The z coordinate that the block is being placed in.
|
||||
* @param side The side the player clicked on
|
||||
* @param hit The exact hit position of the click.
|
||||
* @return True if something happened. This will subsequently block the actual placement of the block.
|
||||
*/
|
||||
public boolean onItemUse(ItemStack item, EntityPlayer player, World world, int x, int y, int z, int side, Vector3 hit);
|
||||
}
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.api;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.util.Vec3;
|
||||
|
||||
/**
|
||||
* API class for MCFrames.
|
||||
* <br><br>
|
||||
* It is recommended that mods access this class within a soft dependency class.
|
||||
*/
|
||||
public abstract class MCFramesAPI
|
||||
{
|
||||
/**
|
||||
* This field will contain an implementor of this API if Relocation is installed.
|
||||
*/
|
||||
public static MCFramesAPI instance;
|
||||
|
||||
/**
|
||||
* Used to register a custom placment that can define how a frame is placed.
|
||||
* This is useful for cases such as if the frame is placed on a Multipart from
|
||||
* the Forge Multipart API, this placement property can perform special actions
|
||||
* that would add the frame to the multipart tile.
|
||||
*
|
||||
* @param placement The custom frame placement to register.
|
||||
*/
|
||||
public abstract void registerFramePlacement(IFramePlacement placement);
|
||||
|
||||
/**
|
||||
* Used to register a {@link IFrameInteraction}, which is a class that
|
||||
* can be used to add frame-like properties to any block.
|
||||
*
|
||||
* @param interaction The interaction to register.
|
||||
*/
|
||||
public abstract void registerFrameInteraction(IFrameInteraction interaction);
|
||||
|
||||
/**
|
||||
* Getter for the optional StickResolver object which can be used to quicky
|
||||
* resolve a structure based on default Relocation frame blocks and stick
|
||||
* rules.
|
||||
*
|
||||
* @return The StickResolver object
|
||||
*/
|
||||
public abstract StickResolver getStickResolver();
|
||||
|
||||
/**
|
||||
* Getter for the instance variable of the Frame block. Used if external
|
||||
* implementations need the block. (i.e. registration purposes)
|
||||
*
|
||||
* @return The frame block.
|
||||
*/
|
||||
public abstract Block getFrameBlock();
|
||||
|
||||
/**
|
||||
* Tessellates the frame model at the given coordinates. Useful for making
|
||||
* your block look like the default frame block.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param mask The mask of sides not to render.
|
||||
*/
|
||||
public abstract void renderFrame(double x, double y, double z, int mask);
|
||||
|
||||
/**
|
||||
* Raytrace a frame block at the given world coords with start and end
|
||||
* points of a ray.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param mask The side mask for the model.
|
||||
* @param start The start point of the ray.
|
||||
* @param end The end point of the ray.
|
||||
* @return The object position if anything from the frame model was hit.
|
||||
*/
|
||||
public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, int mask, Vec3 start, Vec3 end);
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.api;
|
||||
|
||||
import mrtjp.relocation.api.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper class used to resolve frame structures.
|
||||
*/
|
||||
public abstract class StickResolver
|
||||
{
|
||||
/**
|
||||
* Method used to obtain the block coordinates of every block that is part of the same
|
||||
* framed structure as the one that was given as an argument.
|
||||
*
|
||||
* @param world The world
|
||||
* @param x The x coordinate of any block in the structure.
|
||||
* @param y The y coordinate of any block in the structure.
|
||||
* @param z The z coordinate of any block in the structure.
|
||||
* @param exclusions All coordinates to not include in the structure.
|
||||
* generally, one of these is the motor block that moved the structure.
|
||||
* @return A set of all block coordinates that are part of the structure that the input block was in.
|
||||
*/
|
||||
public abstract Set<BlockPos> getStructure(World world, int x, int y, int z, BlockPos... exclusions);
|
||||
}
|
||||
Executable
+240
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes
|
||||
|
||||
import codechicken.lib.lighting.LightModel
|
||||
import codechicken.lib.render.CCModel._
|
||||
import codechicken.lib.render.uv.IconTransformation
|
||||
import codechicken.lib.render.{CCModel, CCRenderState, TextureUtils, Vertex5}
|
||||
import codechicken.lib.vec._
|
||||
import cpw.mods.fml.client.registry.ISimpleBlockRenderingHandler
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.block.BlockCore
|
||||
import mrtjp.core.resource.SoundLib
|
||||
import mrtjp.core.vec.InvertX
|
||||
import mrtjp.mcframes.api.{IFrame, IFramePlacement, MCFramesAPI}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.RenderBlocks
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.{ItemBlock, ItemStack}
|
||||
import net.minecraft.util.{IIcon, Vec3}
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
class BlockFrame extends BlockCore("mcframes.frame", Material.wood) with IFrame
|
||||
{
|
||||
setResistance(5.0F)
|
||||
setHardness(2.0F)
|
||||
setStepSound(Block.soundTypeWood)
|
||||
setCreativeTab(CreativeTabs.tabTransport)
|
||||
|
||||
override def getItemBlockClass = classOf[ItemBlockFrame]
|
||||
|
||||
override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = true
|
||||
override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = true
|
||||
|
||||
override def isSideSolid(w:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = false
|
||||
|
||||
override def isOpaqueCube = false
|
||||
|
||||
override def renderAsNormalBlock = false
|
||||
|
||||
override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3) =
|
||||
MCFramesAPI.instance.raytraceFrame(x, y, z, 0, start, end)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getSelectedBoundingBoxFromPool(w:World, x:Int, y:Int, z:Int) =
|
||||
Cuboid6.full.copy.add(new Vector3(x, y, z)).toAABB
|
||||
|
||||
override def getRenderType = RenderFrame.renderID
|
||||
|
||||
override def getIcon(side:Int, meta:Int) = RenderFrame.icon
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def registerBlockIcons(reg:IIconRegister)
|
||||
{
|
||||
RenderFrame.registerIcons(reg)
|
||||
}
|
||||
}
|
||||
|
||||
object ItemBlockFrame
|
||||
{
|
||||
var placements = Seq[IFramePlacement]()
|
||||
}
|
||||
|
||||
class ItemBlockFrame(b:Block) extends ItemBlock(b)
|
||||
{
|
||||
override def getMetadata(meta:Int) = meta
|
||||
|
||||
override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean =
|
||||
{
|
||||
if (ItemBlockFrame.placements.exists(_.onItemUse(item, player, world, x, y, z,
|
||||
side, new Vector3(hitX, hitY, hitZ))))
|
||||
{
|
||||
SoundLib.playBlockPlacement(world, x, y, z, field_150939_a)
|
||||
true
|
||||
}
|
||||
else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
}
|
||||
|
||||
override def func_150936_a(world:World, x:Int, y:Int, z:Int, side:Int, player:EntityPlayer, stack:ItemStack) = true
|
||||
}
|
||||
|
||||
object RenderFrame extends ISimpleBlockRenderingHandler
|
||||
{
|
||||
var renderID = -1
|
||||
var icon:IIcon = _
|
||||
|
||||
private val model = parseModel("frame")
|
||||
private val models = new Array[CCModel](64)
|
||||
|
||||
private def parseModel(name:String) =
|
||||
{
|
||||
val m = combine(parseObjModels(this.getClass.getResource(
|
||||
"/assets/mcframes/obj/"+name+".obj").openStream(),
|
||||
7, InvertX).values())
|
||||
|
||||
m.shrinkUVs(0.0005)
|
||||
m.apply(new Scale(1.00075, 1.00075, 1.00075))
|
||||
m.apply(new Translation(Vector3.center))
|
||||
m.computeNormals
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
m
|
||||
}
|
||||
|
||||
override def getRenderId = renderID
|
||||
|
||||
override def shouldRender3DInInventory(modelId:Int) = true
|
||||
|
||||
override def renderInventoryBlock(b:Block, meta:Int, id:Int, rb:RenderBlocks)
|
||||
{
|
||||
renderInvBlock(rb, meta)
|
||||
}
|
||||
|
||||
override def renderWorldBlock(world:IBlockAccess, x:Int, y:Int, z:Int, b:Block, id:Int, rb:RenderBlocks) =
|
||||
{
|
||||
renderWorldBlock(rb, world, x, y, z, world.getBlockMetadata(x, y, z))
|
||||
true
|
||||
}
|
||||
|
||||
def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int)
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.lightMatrix.locate(w, x, y, z)
|
||||
CCRenderState.setBrightness(w, x, y, z)
|
||||
|
||||
if (r.hasOverrideBlockTexture)
|
||||
{
|
||||
getOrGenerateModel(0).render(new Translation(x, y, z), new IconTransformation(r.overrideBlockTexture))
|
||||
}
|
||||
else RenderFrame.render(new Vector3(x, y, z), 0)
|
||||
}
|
||||
|
||||
def renderInvBlock(r:RenderBlocks, meta:Int)
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.setDynamic()
|
||||
CCRenderState.pullLightmap()
|
||||
|
||||
CCRenderState.startDrawing()
|
||||
RenderFrame.render(new Vector3(-0.5, -0.5, -0.5), 0)
|
||||
|
||||
CCRenderState.render()
|
||||
CCRenderState.draw()
|
||||
}
|
||||
|
||||
def registerIcons(reg:IIconRegister)
|
||||
{
|
||||
icon = reg.registerIcon("mcframes:frame")
|
||||
}
|
||||
|
||||
def render(pos:Vector3, mask:Int)
|
||||
{
|
||||
getOrGenerateModel(mask).render(pos.translation, new IconTransformation(icon))
|
||||
}
|
||||
|
||||
def getOrGenerateModel(mask:Int) =
|
||||
{
|
||||
var m = models(mask&0x3F)
|
||||
if (m == null)
|
||||
{
|
||||
m = combine(Seq(model, FrameModelGen.generate(mask)))
|
||||
models(mask&0x3F) = m
|
||||
}
|
||||
m
|
||||
}
|
||||
}
|
||||
|
||||
object FrameModelGen
|
||||
{
|
||||
val w = 2.0/16.0
|
||||
val l = 16.0/16.0
|
||||
val i = 1.0/16.0
|
||||
val u = 0.5
|
||||
val v = 0.5
|
||||
|
||||
def generate(mask:Int) =
|
||||
{
|
||||
var m = generateSinglePeg
|
||||
m = generateQuartRotated(m)
|
||||
m = generateEightRotated(m)
|
||||
m = generateBackface(m)
|
||||
|
||||
var b = Seq.newBuilder[CCModel]
|
||||
for (s <- 0 until 6) if ((mask&1<<s) == 0)
|
||||
b += generateSided(m.copy, s)
|
||||
|
||||
finishModel(combine(b.result()))
|
||||
}
|
||||
|
||||
def generateSinglePeg =
|
||||
{
|
||||
val dw = w/2.0
|
||||
val dl = l/2.0
|
||||
|
||||
val m = quadModel(4)
|
||||
m.verts(0) = new Vertex5( dw, i, -dl, u+dw, v-dl)
|
||||
m.verts(1) = new Vertex5( dw, i, dl, u+dw, v+dl)
|
||||
m.verts(2) = new Vertex5(-dw, i, dl, u-dw, v+dl)
|
||||
m.verts(3) = new Vertex5(-dw, i, -dl, u-dw, v-dl)
|
||||
m.apply(new Translation(u, 0, v))
|
||||
}
|
||||
|
||||
def generateQuartRotated(m:CCModel) =
|
||||
{
|
||||
combine(Seq(m, m.copy.apply(Rotation.quarterRotations(1)
|
||||
.at(Vector3.center) `with` new Translation(0, 0.01, 0))))
|
||||
}
|
||||
|
||||
def generateEightRotated(m:CCModel) =
|
||||
{
|
||||
m.apply(new Rotation(math.Pi/4, 0, 1, 0).at(Vector3.center))
|
||||
}
|
||||
|
||||
def generateBackface(m:CCModel) =
|
||||
{
|
||||
combine(Seq(m, m.backfacedCopy()))
|
||||
}
|
||||
|
||||
def generateSided(m:CCModel, side:Int) =
|
||||
{
|
||||
m.apply(Rotation.sideRotations(side).at(Vector3.center.copy))
|
||||
}
|
||||
|
||||
def finishModel(m:CCModel) =
|
||||
{
|
||||
m.shrinkUVs(0.0005)
|
||||
m.computeNormals()
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.handler
|
||||
|
||||
import java.util.{Set => JSet}
|
||||
|
||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||
import mrtjp.core.vec.ModelRayTracer
|
||||
import mrtjp.core.world.WorldLib
|
||||
import mrtjp.mcframes.api.{IFrameInteraction, IFramePlacement, MCFramesAPI, StickResolver}
|
||||
import mrtjp.mcframes.{ItemBlockFrame, RenderFrame, StickRegistry}
|
||||
import mrtjp.relocation.api.{BlockPos, RelocationAPI}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraft.world.World
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.collection.immutable.Queue
|
||||
|
||||
object MCFramesAPI_Impl extends MCFramesAPI
|
||||
{
|
||||
override def registerFramePlacement(placement:IFramePlacement)
|
||||
{
|
||||
ItemBlockFrame.placements :+= placement
|
||||
}
|
||||
|
||||
override def getFrameBlock = MCFramesMod.blockFrame
|
||||
|
||||
override def registerFrameInteraction(interaction:IFrameInteraction)
|
||||
{
|
||||
StickRegistry.interactionList :+= interaction
|
||||
}
|
||||
|
||||
override def getStickResolver = StickResolver_Impl
|
||||
|
||||
override def renderFrame(x:Double, y:Double, z:Double, mask:Int)
|
||||
{
|
||||
RenderFrame.render(new Vector3(x, y, z), mask)
|
||||
}
|
||||
|
||||
override def raytraceFrame(x:Double, y:Double, z:Double, mask:Int, start:Vec3, end:Vec3) =
|
||||
ModelRayTracer.raytraceModel(x, y, z, start, end, RenderFrame.getOrGenerateModel(mask))
|
||||
}
|
||||
|
||||
object StickResolver_Impl extends StickResolver
|
||||
{
|
||||
private var world:World = null
|
||||
private var start:BlockCoord = null
|
||||
private var excl:Set[BlockCoord] = null
|
||||
|
||||
override def getStructure(w:World, x:Int, y:Int, z:Int, ex:BlockPos*):JSet[BlockPos] =
|
||||
{
|
||||
world = w
|
||||
start = new BlockCoord(x, y, z)
|
||||
excl = ex.map(b => new BlockCoord(b.x, b.y, b.z)).toSet
|
||||
val result = iterate(Queue(start))
|
||||
world = null
|
||||
start = null
|
||||
excl = null
|
||||
result.map(b => new BlockPos(b.x, b.y, b.z))
|
||||
}
|
||||
|
||||
@tailrec
|
||||
private def iterate(open:Seq[BlockCoord], closed:Set[BlockCoord] = Set.empty):Set[BlockCoord] = open match
|
||||
{
|
||||
case Seq() => closed
|
||||
case Seq(next, rest@_*) => WorldLib.getBlock(world, next) match
|
||||
{
|
||||
case block:Block =>
|
||||
val toCheck = Vector.newBuilder[BlockCoord]
|
||||
for (s <- 0 until 6)
|
||||
{
|
||||
if (StickRegistry.resolveStick(world, next, s))
|
||||
{
|
||||
val to = next.copy.offset(s)
|
||||
if (!excl(to) && !closed(to) && !open.contains(to))
|
||||
if (!world.isAirBlock(to.x, to.y, to.z) && !RelocationAPI.instance.isMoving(world, to.x, to.y, to.z)
|
||||
/**&& MovingTileRegistry.canMove(world, to.x, to.y, to.z)**/)//Dont ignore non-movables, have them halt movement.
|
||||
toCheck += to
|
||||
}
|
||||
}
|
||||
iterate(rest++toCheck.result(), closed+next)
|
||||
case _ => iterate(rest, closed+next)
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.handler
|
||||
|
||||
import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent}
|
||||
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
||||
import mrtjp.mcframes.api.MCFramesAPI
|
||||
import mrtjp.mcframes.{BlockFrame, BlockMotor, StickRegistry}
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
|
||||
@Mod(modid = MCFramesMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.mcframes.handler.GuiConfigFactory")
|
||||
object MCFramesMod
|
||||
{
|
||||
MCFramesAPI.instance = MCFramesAPI_Impl
|
||||
|
||||
final val modID = "MCFrames"
|
||||
final val modName = "MCFrames"
|
||||
final val version = "@VERSION@"
|
||||
final val buildnumber = "@BUILD_NUMBER@"
|
||||
|
||||
var blockFrame:BlockFrame = _
|
||||
var blockMotor:BlockMotor = _
|
||||
|
||||
@Mod.EventHandler
|
||||
def preInit(event:FMLPreInitializationEvent)
|
||||
{
|
||||
MCFramesProxy.preinit()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def init(event:FMLInitializationEvent)
|
||||
{
|
||||
MCFramesConfig.loadConfig()
|
||||
MCFramesProxy.init()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def postInit(event:FMLPostInitializationEvent)
|
||||
{
|
||||
MCFramesProxy.postinit()
|
||||
}
|
||||
}
|
||||
|
||||
class MCFramesConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "MCFrames", MCFramesConfig.config)
|
||||
class GuiConfigFactory extends TModGuiFactory
|
||||
{
|
||||
override def mainConfigGuiClass() = classOf[MCFramesConfigGui]
|
||||
}
|
||||
|
||||
object MCFramesConfig extends ModConfig("MCFrames")
|
||||
{
|
||||
var setMap = Array(
|
||||
"minecraft:bed -> minecraft:bed",
|
||||
"minecraft:wooden_door -> minecraft:wooden_door",
|
||||
"minecraft:iron_door -> minecraft:iron_door"
|
||||
)
|
||||
|
||||
override protected def initValues()
|
||||
{
|
||||
val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc)
|
||||
setMap = sets.put("latch registry", setMap)
|
||||
setMap = sets.put("latch registry", StickRegistry.parseAndAddLatchSets(setMap), true)
|
||||
}
|
||||
|
||||
def buildLatchSetsDesc:String =
|
||||
{
|
||||
var s = "Used to define which pairs of blocks will be stuck together. \n"
|
||||
s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n"
|
||||
s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n"
|
||||
s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n"
|
||||
s += "Sets are defined using the syntax of key -> value. \n"
|
||||
s += "Possible keys and values:\n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||
s
|
||||
}
|
||||
}
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes.handler
|
||||
|
||||
import java.lang.{Character => JC}
|
||||
|
||||
import cpw.mods.fml.client.registry.RenderingRegistry
|
||||
import cpw.mods.fml.common.registry.GameRegistry
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.block.TileRenderRegistry
|
||||
import mrtjp.mcframes._
|
||||
import mrtjp.mcframes.handler.MCFramesMod._
|
||||
import net.minecraft.init.Items
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraftforge.oredict.ShapedOreRecipe
|
||||
|
||||
class MCFramesProxy_server
|
||||
{
|
||||
def preinit()
|
||||
{
|
||||
blockMotor = new BlockMotor
|
||||
blockFrame = new BlockFrame
|
||||
}
|
||||
|
||||
def init()
|
||||
{
|
||||
MCFramesRecipes.initRecipes()
|
||||
}
|
||||
|
||||
def postinit(){}
|
||||
}
|
||||
|
||||
class MCFramesProxy_client extends MCFramesProxy_server
|
||||
{
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def preinit()
|
||||
{
|
||||
super.preinit()
|
||||
|
||||
TileRenderRegistry.setRenderer(MCFramesMod.blockMotor, 0, RenderMotor)
|
||||
|
||||
RenderFrame.renderID = RenderingRegistry.getNextAvailableRenderId
|
||||
RenderingRegistry.registerBlockHandler(RenderFrame)
|
||||
}
|
||||
}
|
||||
|
||||
object MCFramesProxy extends MCFramesProxy_client
|
||||
|
||||
object MCFramesRecipes
|
||||
{
|
||||
def initRecipes()
|
||||
{
|
||||
//Frame
|
||||
GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(blockFrame, 8),
|
||||
"sls","lsl","sls",
|
||||
's':JC, Items.stick,
|
||||
'l':JC, "logWood"
|
||||
))
|
||||
}
|
||||
}
|
||||
Executable
+178
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes
|
||||
|
||||
import codechicken.lib.data.{MCDataInput, MCDataOutput}
|
||||
import codechicken.lib.render.uv.MultiIconTransformation
|
||||
import codechicken.lib.vec.{Rotation, Vector3}
|
||||
import mrtjp.core.block.{InstancedBlock, InstancedBlockTile, TTileOrient}
|
||||
import mrtjp.core.render.TCubeMapRender
|
||||
import mrtjp.core.world.WorldLib
|
||||
import mrtjp.mcframes.api.{IFrame, MCFramesAPI}
|
||||
import mrtjp.mcframes.handler.MCFramesMod
|
||||
import mrtjp.relocation.api.{BlockPos, RelocationAPI}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class BlockMotor extends InstancedBlock("mcframes.motor", Material.iron)
|
||||
{
|
||||
setHardness(5f)
|
||||
setResistance(10f)
|
||||
setStepSound(Block.soundTypeMetal)
|
||||
setCreativeTab(CreativeTabs.tabTransport)
|
||||
addSingleTile(classOf[TileMotor])
|
||||
|
||||
override def isSideSolid(world:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = true
|
||||
|
||||
override def renderAsNormalBlock = true
|
||||
}
|
||||
|
||||
class TileMotor extends InstancedBlockTile with TTileOrient with IFrame
|
||||
{
|
||||
override def save(tag:NBTTagCompound)
|
||||
{
|
||||
super.save(tag)
|
||||
tag.setByte("orient", orientation)
|
||||
}
|
||||
|
||||
override def load(tag:NBTTagCompound)
|
||||
{
|
||||
super.load(tag)
|
||||
orientation = tag.getByte("orient")
|
||||
}
|
||||
|
||||
override def readDesc(in:MCDataInput)
|
||||
{
|
||||
super.readDesc(in)
|
||||
orientation = in.readByte()
|
||||
}
|
||||
|
||||
override def writeDesc(out:MCDataOutput)
|
||||
{
|
||||
super.writeDesc(out)
|
||||
out.writeByte(orientation)
|
||||
}
|
||||
|
||||
override def read(in:MCDataInput, key:Int) = key match
|
||||
{
|
||||
case 2 =>
|
||||
orientation = in.readByte()
|
||||
markRender()
|
||||
case _ => super.read(in, key)
|
||||
}
|
||||
|
||||
def sendOrientUpdate()
|
||||
{
|
||||
if (!world.isRemote)
|
||||
writeStream(2).writeByte(orientation).sendToChunk()
|
||||
}
|
||||
|
||||
override def onBlockPlaced(side:Int, meta:Int, player:EntityPlayer, stack:ItemStack, hit:Vector3)
|
||||
{
|
||||
super.onBlockPlaced(side, meta, player, stack, hit)
|
||||
setSide(side^1)
|
||||
setRotation(Rotation.getSidedRotation(player, side^1))
|
||||
}
|
||||
|
||||
override def onBlockActivated(player:EntityPlayer, s:Int):Boolean =
|
||||
{
|
||||
if (super.onBlockActivated(player, s)) return true
|
||||
|
||||
if (player.isSneaking) setRotation((rotation+1)%4)
|
||||
else setSide((side+1)%6)
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
override def onOrientChanged(oldOrient:Int)
|
||||
{
|
||||
super.onOrientChanged(oldOrient)
|
||||
sendOrientUpdate()
|
||||
}
|
||||
|
||||
override def getBlock = MCFramesMod.blockMotor
|
||||
|
||||
def getMoveDir = absoluteDir((rotation+2)%4)
|
||||
|
||||
override def stickOut(w:World, x:Int, y:Int, z:Int, side:Int) = side == (this.side^1)
|
||||
override def stickIn(w:World, x:Int, y:Int, z:Int, side:Int) = side != (this.side^1)
|
||||
|
||||
override def update()
|
||||
{
|
||||
if (!world.isRemote && world.getBlockPowerInput(x, y, z) > 0)
|
||||
{
|
||||
val pos = position.offset(side^1)
|
||||
if (world.isAirBlock(pos.x, pos.y, pos.z)) return
|
||||
|
||||
if (!RelocationAPI.instance.isMoving(world, pos.x, pos.y, pos.z) &&
|
||||
!RelocationAPI.instance.isMoving(world, x, y, z))
|
||||
{
|
||||
val blocks = MCFramesAPI.instance.getStickResolver
|
||||
.getStructure(world, pos.x, pos.y, pos.z, new BlockPos(x, y, z))
|
||||
|
||||
val r = RelocationAPI.instance.getRelocator
|
||||
r.push()
|
||||
r.setWorld(world)
|
||||
r.setDirection(getMoveDir)
|
||||
r.addBlocks(blocks)
|
||||
r.execute()
|
||||
r.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object RenderMotor extends TCubeMapRender
|
||||
{
|
||||
var bottom:IIcon = _
|
||||
var side:IIcon = _
|
||||
var sidew:IIcon = _
|
||||
var sidee:IIcon = _
|
||||
var top:IIcon = _
|
||||
|
||||
override def getData(w:IBlockAccess, x:Int, y:Int, z:Int) =
|
||||
{
|
||||
val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor])
|
||||
var s = 0
|
||||
var r = 0
|
||||
if (te != null)
|
||||
{
|
||||
s = te.side
|
||||
r = te.rotation
|
||||
}
|
||||
(s, r, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
||||
}
|
||||
|
||||
override def getInvData =
|
||||
(0, 0, new MultiIconTransformation(bottom, top, side, side, sidew, sidee))
|
||||
|
||||
override def getIcon(s:Int, meta:Int) = s match
|
||||
{
|
||||
case 0 => bottom
|
||||
case 1 => top
|
||||
case 2 => side
|
||||
case 3 => side
|
||||
case 4 => sidew
|
||||
case 5 => sidee
|
||||
}
|
||||
|
||||
override def registerIcons(reg:IIconRegister)
|
||||
{
|
||||
bottom = reg.registerIcon("mcframes:motor/bottom")
|
||||
top = reg.registerIcon("mcframes:motor/top")
|
||||
side = reg.registerIcon("mcframes:motor/side")
|
||||
sidew = reg.registerIcon("mcframes:motor/sidew")
|
||||
sidee = reg.registerIcon("mcframes:motor/sidee")
|
||||
}
|
||||
}
|
||||
Executable
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.mcframes
|
||||
|
||||
import codechicken.lib.vec.BlockCoord
|
||||
import mrtjp.core.world.WorldLib._
|
||||
import mrtjp.mcframes.api.{IFrame, IFrameInteraction}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.world.World
|
||||
|
||||
object StickRegistry
|
||||
{
|
||||
val rKeyVal = raw"([\w:]+)\s*->\s*(.+)".r
|
||||
val rName = raw"(.+)".r
|
||||
val rNameMetaM = raw"(.+)m(\d+)".r
|
||||
val rMod = raw"mod:(\w+)".r
|
||||
|
||||
var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set())
|
||||
var interactionList = Seq[IFrameInteraction]()
|
||||
|
||||
def parseKV(kv:Seq[String]) = kv.map { case rKeyVal(k, v) => (k, v); case s => throw new MatchError(s"Illegal [k -> v] pair: $s") }
|
||||
def parseBlockMeta(b:String) = b match
|
||||
{
|
||||
case rNameMetaM(name, meta) => Block.getBlockFromName(fixName(name)) -> meta.toInt
|
||||
case rName(name) => Block.getBlockFromName(fixName(name)) -> -1
|
||||
case _ => throw new MatchError(s"Illegal set part: $b")
|
||||
}
|
||||
def fixName(name:String) = name.indexOf(':') match
|
||||
{
|
||||
case -1 => "minecraft:"+name
|
||||
case i => name
|
||||
}
|
||||
|
||||
def parseAndAddLatchSets(kv:Seq[String]):Array[String] =
|
||||
{
|
||||
parseKV(kv).foreach(b => addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2)))
|
||||
latchMap.map{kv =>
|
||||
val (b, i) = kv._1
|
||||
val e1 = Block.blockRegistry.getNameForObject(b)+(if (i != -1) s"m$i" else "")
|
||||
kv._2.map { k =>
|
||||
val (b2, i2) = k
|
||||
val e2 = Block.blockRegistry.getNameForObject(b2)+(if (i2 != -1) s"m$i2" else "")
|
||||
e1+" -> "+e2
|
||||
}
|
||||
}.flatten.toArray
|
||||
}
|
||||
|
||||
def addLatchSet(b1:(Block, Int), b2:(Block, Int))
|
||||
{
|
||||
latchMap += b1 -> (latchMap(b1)+b2)
|
||||
}
|
||||
|
||||
def resolveStick(w:World, pos:BlockCoord, side:Int):Boolean =
|
||||
{
|
||||
def getFrame(pos:BlockCoord):IFrame =
|
||||
{
|
||||
val b = getBlock(w, pos)
|
||||
if (b.isInstanceOf[IFrame]) return b.asInstanceOf[IFrame]
|
||||
val te = getTileEntity(w, pos, classOf[IFrame])
|
||||
if (te != null) return te
|
||||
interactionList.find(_.canInteract(w, pos.x, pos.y, pos.z)).orNull
|
||||
}
|
||||
|
||||
val f1 = getFrame(pos)
|
||||
if (f1 != null && f1.stickOut(w, pos.x, pos.y, pos.z, side))
|
||||
{
|
||||
val p2 = pos.copy.offset(side)
|
||||
val f2 = getFrame(p2)
|
||||
return f2 == null || f2.stickIn(w, p2.x, p2.y, p2.z, side^1)
|
||||
}
|
||||
|
||||
if (latchSet(w, pos.x, pos.y, pos.z, side)) return true
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
def latchSet(w:World, x:Int, y:Int, z:Int, side:Int) =
|
||||
{
|
||||
val pos = new BlockCoord(x, y, z).offset(side)
|
||||
val b1 = getBlockMetaPair(w, x, y, z)
|
||||
val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z)
|
||||
|
||||
val set = latchMap.getOrElse(b1, latchMap((b1._1, -1)))
|
||||
set.contains(b2) || set.contains((b2._1, -1))
|
||||
}
|
||||
}
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
|
||||
/**
|
||||
* Lightweight block position object used to keep dependencies confined
|
||||
* to the api package, used by some of the API's methods.
|
||||
*/
|
||||
public class BlockPos
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
|
||||
public BlockPos(int x, int y, int z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if(!(obj instanceof BlockPos)) return false;
|
||||
else
|
||||
{
|
||||
BlockPos o2 = (BlockPos) obj;
|
||||
return this.x == o2.x && this.y == o2.y && this.z == o2.z;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode()
|
||||
{
|
||||
return (this.x^this.z)*31+this.y;
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Interface that can be implemented on Tile Entities or Blocks that wish to
|
||||
* act as frames, which are the blocks that stick together and form a
|
||||
* moving structure when moved with a motor. No other action besides
|
||||
* implementation of this interface is needed for the block to function.
|
||||
*/
|
||||
public interface IFrame
|
||||
{
|
||||
/**
|
||||
* Used to check if the given side on this frame block is sticky.
|
||||
* Sticky sides will allow other frames to stick to this one,
|
||||
* as well as other blocks.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param side The side of the block, as a ForgeDirection
|
||||
* @return True if the side can latch on to another block.
|
||||
*/
|
||||
public boolean latchSide(World w, int x, int y, int z, int side);
|
||||
}
|
||||
Regular → Executable
+14
-7
@@ -8,7 +8,7 @@ package mrtjp.relocation.api;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* Interface which when implemented manages the movement of blocks and tiles that are
|
||||
* Interface for an object that manages the movement of blocks and tiles that are
|
||||
* registered to it. This class should be registered through the {@link RelocationAPI}.
|
||||
*/
|
||||
public interface ITileMover
|
||||
@@ -20,37 +20,44 @@ public interface ITileMover
|
||||
* for this handler. This is called before actually moving. If
|
||||
* everything is able to move, an animation will start.
|
||||
*
|
||||
* Called server-side only when determining what to move.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @return True if the block at the given position is able to move.
|
||||
*/
|
||||
public boolean canMove(World w, int x, int y, int z);
|
||||
boolean canMove(World w, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Method used to actually move the tile. Called after the animation
|
||||
* has run. This is where you should tell the tile that it is time
|
||||
* to move, and peform any extra checks or calls. This is called
|
||||
* on every block in the moved structure sequentially.
|
||||
* to move, and peform any extra checks or calls. This should also
|
||||
* move the block and tile as well. This is called
|
||||
* on every block in the moving structure sequentially.
|
||||
*
|
||||
* Called on both server and client.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param side The ForgeDirection side the structure is moving in.
|
||||
* @param dir The ForgeDirection the structure is moving in.
|
||||
*/
|
||||
public void move(World w, int x, int y, int z, int side);
|
||||
void move(World w, int x, int y, int z, int dir);
|
||||
|
||||
/**
|
||||
* Called after all blocks in the group have moved to their
|
||||
* new locations. This is where you would reload your tile,
|
||||
* tell it to refresh or reacknowledge its new position.
|
||||
*
|
||||
* Callod on both server and client.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
*/
|
||||
public void postMove(World w, int x, int y, int z);
|
||||
void postMove(World w, int x, int y, int z);
|
||||
}
|
||||
Regular → Executable
+15
-107
@@ -5,10 +5,6 @@
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.MovingObjectPosition;
|
||||
import net.minecraft.util.Vec3;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
@@ -47,7 +43,7 @@ public abstract class RelocationAPI
|
||||
* default - to assign default mover
|
||||
* mod:<modID> - to assign every block from a mod
|
||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
||||
<modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
||||
* <modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
||||
*
|
||||
* @param value The name of the mover to assign this block. A list of all available
|
||||
* movers will show up in the configs.
|
||||
@@ -67,7 +63,7 @@ public abstract class RelocationAPI
|
||||
* default - to assign default mover
|
||||
* mod:<modID> - to assign every block from a mod
|
||||
* <modID>:<blockname> - to assign block from a mod for every meta
|
||||
<modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
||||
* <modID>:<blockname>m<meta> - to assign block from mod for specific meta
|
||||
*
|
||||
* @param value The name of the mover to assign this block. A list of all available
|
||||
* movers will show up in the configs.
|
||||
@@ -75,111 +71,23 @@ public abstract class RelocationAPI
|
||||
public abstract void registerMandatoryMover(String key, String value);
|
||||
|
||||
/**
|
||||
* Used to register a custom placment that can define how a frame is placed.
|
||||
* This is useful for cases such as if the frame is placed on a Multipart from
|
||||
* the Forge Multipart API, this placement property can perform special actions
|
||||
* that would add the frame to the multipart tile.
|
||||
* Getter for the global Relocator object which is what is used
|
||||
* to actually initiate movements.
|
||||
*
|
||||
* @param placement The custom frame placement to register.
|
||||
* @return The Relocator object
|
||||
*/
|
||||
public abstract void registerFramePlacement(IFramePlacement placement);
|
||||
public abstract Relocator getRelocator();
|
||||
|
||||
/**
|
||||
* Used to register a {@link IFrameInteraction}, which is a class that
|
||||
* can be used to add frame-like properties to any block.
|
||||
* Used to check if the given block is currently moving. This method is
|
||||
* client and server safe.
|
||||
*
|
||||
* @param interaction The interaction to register.
|
||||
*/
|
||||
public abstract void registerFrameInteraction(IFrameInteraction interaction);
|
||||
|
||||
/**
|
||||
* Getter for the instance variable of the Frame block. Used if external
|
||||
* implementations need the block. (i.e. registration purposes)
|
||||
* @param world The world the block is in.
|
||||
* @param x The x coordinate of the block.
|
||||
* @param y The y coordinate of the block.
|
||||
* @param z The z coordinate of the block.
|
||||
*
|
||||
* @return The frame block.
|
||||
* @return True if the block is currently moving.
|
||||
*/
|
||||
public abstract Block getFrameBlock();
|
||||
|
||||
/**
|
||||
* Getter for the instance variable of the Motor block. Used if external
|
||||
* implementations need the block. (i.e. registration purposes)
|
||||
*
|
||||
* @return The motor block.
|
||||
*/
|
||||
public abstract Block getMotorBlock();
|
||||
|
||||
|
||||
/** Utilities - used for silent block manipulation. Caution: May be removed.. **/
|
||||
|
||||
/**
|
||||
* Used to set a block in the world to the given block without
|
||||
* alerting the world of the change.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param b The block.
|
||||
* @param meta Block metadata
|
||||
*/
|
||||
public abstract void uncheckedSetBlock(World w, int x, int y, int z, Block b, int meta);
|
||||
|
||||
/**
|
||||
* Used to set a tile entity in the world without alerting the
|
||||
* world of the change.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param te The TileEntity.
|
||||
*/
|
||||
public abstract void uncheckedSetTileEntity(World w, int x, int y, int z, TileEntity te);
|
||||
|
||||
/**
|
||||
* Used to remove a tile entity in the world without alerting the
|
||||
* world of the change.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
*/
|
||||
public abstract void uncheckedRemoveTileEntity(World w, int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Used to retreive a tile from a world without alerting the world
|
||||
* that the tile was fetched from memory.
|
||||
*
|
||||
* @param w The world.
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @return The TileEnity at the given coordinates
|
||||
*/
|
||||
public abstract TileEntity uncheckedGetTileEntity(World w, int x, int y, int z);
|
||||
|
||||
|
||||
/**
|
||||
* Tessellates the frame model at the given coordinates. Useful for making
|
||||
* your block look like the default frame block.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
*/
|
||||
public abstract void renderFrame(double x, double y, double z);
|
||||
|
||||
/**
|
||||
* Raytrace a frame block at the given world coords with start and end
|
||||
* points of a ray.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
* @param z The z coordinate.
|
||||
* @param start The start point of the ray
|
||||
* @param end The end point of the ray
|
||||
* @return The object position if anything from the frame model was hit.
|
||||
*/
|
||||
public abstract MovingObjectPosition raytraceFrame(double x, double y, double z, Vec3 start, Vec3 end);
|
||||
}
|
||||
public abstract boolean isMoving(World world, int x, int y, int z);
|
||||
}
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.api;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper class used to queue and execute the movement of a set of blocks.
|
||||
* See {@link mrtjp.mcframes.TileMotor} for usage.
|
||||
*/
|
||||
public abstract class Relocator
|
||||
{
|
||||
/**
|
||||
* Pushes the instance of the Relocator onto the stack.
|
||||
* Must be called before using any methods.
|
||||
*
|
||||
* @throws IllegalStateException If the Relocator is already on the stack.
|
||||
*/
|
||||
public abstract void push();
|
||||
|
||||
/**
|
||||
* Pops the instance of the Relocator off the stack.
|
||||
* Must be called after you are done using this.
|
||||
*
|
||||
* @throws IllegalStateException If the Relocator is not on the stack.
|
||||
*/
|
||||
public abstract void pop();
|
||||
|
||||
/**
|
||||
* Sets the world for the movement.
|
||||
*
|
||||
* @param world The world in which the movement will occure.
|
||||
*/
|
||||
public abstract void setWorld(World world);
|
||||
|
||||
/**
|
||||
* Sets the direction towards which all the queued blocks will move.
|
||||
* This is a ForgeDirection index, from 0 to 5
|
||||
*
|
||||
* @param dir The direction to move the blocks.
|
||||
*
|
||||
* @throws IllegalStateException If the Relocator is not on the stack.
|
||||
*/
|
||||
public abstract void setDirection(int dir);
|
||||
|
||||
/**
|
||||
* Following methods are used to add blocks to the queue.
|
||||
*
|
||||
* @throws IllegalStateException If the Relocator is not on the stack.
|
||||
*/
|
||||
public abstract void addBlock(int x, int y, int z);
|
||||
public abstract void addBlock(BlockPos bc);
|
||||
public abstract void addBlocks(Set<BlockPos> blocks);
|
||||
|
||||
/**
|
||||
* Used to execute the queued movement. Before calling, the world, direction,
|
||||
* and queue of blocks must be set.
|
||||
*
|
||||
* @return True if the movement was successfully started.
|
||||
*
|
||||
* @throws IllegalStateException If the Relocator is not on the stack.
|
||||
*/
|
||||
public abstract boolean execute();
|
||||
}
|
||||
Regular → Executable
File mode changed.
Regular → Executable
+1
-1
@@ -9,7 +9,7 @@ import java.util.{Map => JMap}
|
||||
|
||||
import cpw.mods.fml.common.asm.transformers.deobf.FMLDeobfuscatingRemapper.{INSTANCE => mapper}
|
||||
import cpw.mods.fml.relauncher.{IFMLCallHook, IFMLLoadingPlugin}
|
||||
import mrtjp.relocation.RelocationMod
|
||||
import mrtjp.relocation.handler.RelocationMod
|
||||
import net.minecraft.launchwrapper.{IClassTransformer, Launch}
|
||||
import org.objectweb.asm.Opcodes._
|
||||
import org.objectweb.asm.tree._
|
||||
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import java.util.{List => JList}
|
||||
|
||||
import codechicken.lib.vec.{BlockCoord, Cuboid6, Vector3}
|
||||
import mrtjp.core.block.{InstancedBlock, InstancedBlockTile}
|
||||
import mrtjp.relocation.handler.RelocationMod
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraft.world.World
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
|
||||
class BlockMovingRow extends InstancedBlock("relocation.BlockMovingRow", Material.iron)
|
||||
{
|
||||
setHardness(-1F)
|
||||
setStepSound(Block.soundTypeGravel)
|
||||
setCreativeTab(null)
|
||||
addSingleTile(classOf[TileMovingRow])
|
||||
}
|
||||
|
||||
object TileMovingRow
|
||||
{
|
||||
def setBlockForRow(w:World, r:BlockRow)
|
||||
{
|
||||
w.setBlock(r.pos.x, r.pos.y, r.pos.z, RelocationMod.blockMovingRow, 0, 3)
|
||||
}
|
||||
|
||||
def getBoxFor(w:World, r:BlockRow, progress:Double) =
|
||||
{
|
||||
val p = r.pos.copy.offset(r.moveDir^1)
|
||||
w.getBlock(p.x, p.y, p.z).getCollisionBoundingBoxFromPool(w, p.x, p.y, p.z) match
|
||||
{
|
||||
case aabb:AxisAlignedBB => new Cuboid6(aabb).sub(new Vector3(r.pos))
|
||||
.add(new Vector3(BlockCoord.sideOffsets(r.moveDir))*progress)
|
||||
case _ => Cuboid6.full.copy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TileMovingRow extends InstancedBlockTile
|
||||
{
|
||||
override def update()
|
||||
{
|
||||
if (!MovementManager2.isMoving(world, x, y, z)) world.setBlockToAir(x, y, z)
|
||||
else pushEntities()
|
||||
}
|
||||
|
||||
override def getBlock = RelocationMod.blockMovingRow
|
||||
|
||||
override def getBlockBounds =
|
||||
{
|
||||
val s = MovementManager2.getEnclosedStructure(world, x, y, z)
|
||||
if (s != null)
|
||||
{
|
||||
val r = s.rows.find(_.contains(x, y, z)).get
|
||||
TileMovingRow.getBoxFor(world, r, s.progress)
|
||||
}
|
||||
else Cuboid6.full
|
||||
}
|
||||
|
||||
override def getCollisionBounds = getBlockBounds
|
||||
|
||||
def pushEntities()
|
||||
{
|
||||
val s = MovementManager2.getEnclosedStructure(world, x, y, z)
|
||||
if (s != null)
|
||||
{
|
||||
val r = s.rows.find(_.contains(x, y, z)).get
|
||||
val box = TileMovingRow.getBoxFor(world, r, s.progress).add(new Vector3(r.pos))
|
||||
val d = new Vector3(BlockCoord.sideOffsets(r.moveDir))*s.speed
|
||||
world.getEntitiesWithinAABBExcludingEntity(null, box.toAABB) match
|
||||
{
|
||||
case list:JList[_] => for (e <- list.asInstanceOf[JList[Entity]])
|
||||
{
|
||||
e.moveEntity(0, d.y max 0, 0)
|
||||
e.addVelocity(d.x, d.y, d.z)
|
||||
e.velocityChanged = true
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import cpw.mods.fml.common.gameevent.TickEvent
|
||||
import mrtjp.relocation.handler.RelocationSPH
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent
|
||||
import net.minecraftforge.event.world.{ChunkWatchEvent, WorldEvent}
|
||||
|
||||
object RelocationEventHandler
|
||||
{
|
||||
@SubscribeEvent
|
||||
def worldUnload(event:WorldEvent.Unload)
|
||||
{
|
||||
RelocationSPH.onWorldUnload(event.world)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def chunkWatch(event:ChunkWatchEvent.Watch)
|
||||
{
|
||||
RelocationSPH.onChunkWatch(event.player, event.chunk)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def chunkUnwatch(event:ChunkWatchEvent.UnWatch)
|
||||
{
|
||||
RelocationSPH.onChunkUnWatch(event.player, event.chunk)
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def serverTick(event:TickEvent.ServerTickEvent)
|
||||
{
|
||||
if (event.phase == TickEvent.Phase.END)
|
||||
{
|
||||
RelocationSPH.onTickEnd()
|
||||
MovementManager2.onTick(false)
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def clientTick(event:TickEvent.ClientTickEvent)
|
||||
{
|
||||
if (event.phase == TickEvent.Phase.END)
|
||||
MovementManager2.onTick(true)
|
||||
}
|
||||
}
|
||||
|
||||
object RelocationClientEventHandler
|
||||
{
|
||||
@SubscribeEvent
|
||||
def onRenderTick(e:TickEvent.RenderTickEvent)
|
||||
{
|
||||
if (e.phase == TickEvent.Phase.START)
|
||||
MovingRenderer.onPreRenderTick(e.renderTickTime)
|
||||
else MovingRenderer.onPostRenderTick()
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def onRenderWorld(e:RenderWorldLastEvent)
|
||||
{
|
||||
MovingRenderer.onRenderWorldEvent()
|
||||
}
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.data.{MCDataInput, MCDataOutput}
|
||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||
import mrtjp.core.block.{InstancedBlockTile, InstancedBlock}
|
||||
import mrtjp.core.world.WorldLib
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
|
||||
import scala.collection.mutable.{Set => MSet}
|
||||
|
||||
class BlockMovingRow extends InstancedBlock("relocation.BlockMovingRow", Material.iron)
|
||||
{
|
||||
setHardness(-1F)
|
||||
setStepSound(Block.soundTypeGravel)
|
||||
setCreativeTab(null)
|
||||
addSingleTile(classOf[TileMovingRow])
|
||||
|
||||
override def createTileEntity(world:World, meta:Int) = new TileMovingRow(None)
|
||||
|
||||
override def setBlockBoundsBasedOnState(world:IBlockAccess, x:Int, y:Int, z:Int)
|
||||
{
|
||||
Option(world.getTileEntity(x, y, z)).collect
|
||||
{
|
||||
case te:TileMovingRow if te.parentPos.isDefined =>
|
||||
Option(WorldLib.getTileEntity(te.getWorldObj, te.parentPos.get)).map(p => (te, p))
|
||||
}.flatten.collect
|
||||
{
|
||||
case (te, parent:TileMotor) =>
|
||||
val pos = new BlockCoord(te).offset(parent.getMoveDir^1)
|
||||
val block = world.getBlock(pos.x, pos.y, pos.z)
|
||||
if (parent.offset == 0 || block == null) setBlockBounds(.5F, .5F, .5F, .5F, .5F, .5F)
|
||||
else
|
||||
{
|
||||
val shift = (16-parent.offset).toFloat/16F
|
||||
val sh = new Vector3(new BlockCoord().offset(parent.getMoveDir))*shift
|
||||
setBlockBounds(
|
||||
(block.getBlockBoundsMinX-sh.x).toFloat,
|
||||
(block.getBlockBoundsMinY-sh.y).toFloat,
|
||||
(block.getBlockBoundsMinZ-sh.z).toFloat,
|
||||
(block.getBlockBoundsMaxX-sh.x).toFloat,
|
||||
(block.getBlockBoundsMaxY-sh.y).toFloat,
|
||||
(block.getBlockBoundsMaxZ-sh.z).toFloat)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def getCollisionBoundingBoxFromPool(world:World, x:Int, y:Int, z:Int) =
|
||||
{
|
||||
setBlockBoundsBasedOnState(world, x, y, z)
|
||||
Option(world.getTileEntity(x, y, z)).collect
|
||||
{
|
||||
case te:TileMovingRow if te.parentPos.isDefined =>
|
||||
Option(WorldLib.getTileEntity(te.getWorldObj, te.parentPos.get))
|
||||
}.flatten.collect
|
||||
{
|
||||
case te:TileMotor => te.getAabb(new BlockCoord(x, y, z))
|
||||
}.orNull
|
||||
}
|
||||
}
|
||||
|
||||
class TileMovingRow(var parentPos:Option[BlockCoord] = None) extends InstancedBlockTile
|
||||
{
|
||||
override def update(){super.update(); checkLocation()}
|
||||
override def updateClient(){super.updateClient(); checkLocation()}
|
||||
|
||||
def checkLocation()
|
||||
{
|
||||
def voidBlock(){world.setBlock(xCoord, yCoord, zCoord, Blocks.air, 0, 3)}
|
||||
parentPos match
|
||||
{
|
||||
case Some(e) => WorldLib.getTileEntity(world, e) match
|
||||
{
|
||||
case te:TileMotor =>
|
||||
case _ => voidBlock()
|
||||
}
|
||||
case None => voidBlock()
|
||||
}
|
||||
}
|
||||
|
||||
override def getBlock = RelocationMod.blockMovingRow
|
||||
|
||||
override def save(tag:NBTTagCompound)
|
||||
{
|
||||
super.save(tag)
|
||||
val (x, y, z) = parentPos match
|
||||
{
|
||||
case Some(bc) => (bc.x, bc.y, bc.z)
|
||||
case None => (0, -1, 0)
|
||||
}
|
||||
tag.setIntArray("pos", Array(x, y, z))
|
||||
}
|
||||
|
||||
override def load(tag:NBTTagCompound)
|
||||
{
|
||||
super.load(tag)
|
||||
parentPos = Option(new BlockCoord(tag.getIntArray("pos")))
|
||||
}
|
||||
|
||||
override def readDesc(in:MCDataInput)
|
||||
{
|
||||
super.readDesc(in)
|
||||
parentPos = Option(in.readCoord())
|
||||
}
|
||||
|
||||
override def writeDesc(out:MCDataOutput)
|
||||
{
|
||||
super.writeDesc(out)
|
||||
val (x, y, z) = parentPos match
|
||||
{
|
||||
case Some(bc) => (bc.x, bc.y, bc.z)
|
||||
case None => (0, -1, 0)
|
||||
}
|
||||
out.writeCoord(x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
case class BlockRow(pos:BlockCoord, moveDir:Int, size:Int)
|
||||
{
|
||||
def preMove(w:World, offset:RenderPos)
|
||||
{
|
||||
for (i <- 1 to size)
|
||||
{
|
||||
val bc = pos.copy.offset(moveDir^1, i)
|
||||
MovementManager.addMoving(w, bc, offset)
|
||||
}
|
||||
}
|
||||
|
||||
def doMove(w:World)
|
||||
{
|
||||
if (pos.y < 0 || pos.y >= 256) return
|
||||
|
||||
w.removeTileEntity(pos.x, pos.y, pos.z)
|
||||
WorldLib.uncheckedSetBlock(w, pos.x, pos.y, pos.z, Blocks.air, 0) //Remove movement block
|
||||
|
||||
for (i <- 1 to size)
|
||||
{
|
||||
val c = pos.copy.offset(moveDir^1, i)
|
||||
MovingTileRegistry.move(w, c.x, c.y, c.z, moveDir)
|
||||
}
|
||||
}
|
||||
|
||||
def postMove(w:World)
|
||||
{
|
||||
for (i <- 0 until size)
|
||||
{
|
||||
val c = pos.copy.offset(moveDir^1, i)
|
||||
MovingTileRegistry.postMove(w, c.x, c.y, c.z)
|
||||
}
|
||||
}
|
||||
|
||||
def endMove(w:World)
|
||||
{
|
||||
for (i <- 0 to size)
|
||||
MovementManager.removeMoving(w, pos.copy.offset(moveDir^1, i))
|
||||
}
|
||||
|
||||
def cacheChanges(w:World, changes:MSet[BlockCoord])
|
||||
{
|
||||
for (i <- 0 to size)
|
||||
{
|
||||
val c = pos.copy.offset(moveDir^1, i)
|
||||
changes += c
|
||||
for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s^1))
|
||||
changes += c.copy.offset(s).offset(s1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.vec.{Cuboid6, Vector3}
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.block.{InstancedBlock, ItemBlockCore}
|
||||
import mrtjp.core.resource.SoundLib
|
||||
import mrtjp.relocation.api.{IFrame, IFramePlacement}
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
class BlockFrame extends InstancedBlock("relocation.blockframe", Material.wood) with IFrame
|
||||
{
|
||||
setResistance(5.0F)
|
||||
setHardness(2.0F)
|
||||
setStepSound(Block.soundTypeWood)
|
||||
setCreativeTab(CreativeTabs.tabTransport)
|
||||
|
||||
override def getItemBlockClass = classOf[ItemBlockFrame]
|
||||
|
||||
override def latchSide(w:World, x:Int, y:Int, z:Int, side:Int) = true
|
||||
|
||||
override def isSideSolid(w:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = false
|
||||
|
||||
override def collisionRayTrace(world:World, x:Int, y:Int, z:Int, start:Vec3, end:Vec3) =
|
||||
Utils.raytraceFrame(x, y, z, start, end)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getSelectedBoundingBoxFromPool(w:World, x:Int, y:Int, z:Int) =
|
||||
Cuboid6.full.copy.expand(0.002).add(new Vector3(x, y, z)).toAABB
|
||||
}
|
||||
|
||||
object ItemBlockFrame
|
||||
{
|
||||
var placements = Seq[IFramePlacement]()
|
||||
}
|
||||
|
||||
class ItemBlockFrame(b:Block) extends ItemBlockCore(b)
|
||||
{
|
||||
override def onItemUse(item:ItemStack, player:EntityPlayer, world:World, x:Int, y:Int, z:Int, side:Int, hitX:Float, hitY:Float, hitZ:Float):Boolean =
|
||||
{
|
||||
if (ItemBlockFrame.placements.exists(_.onItemUse(item, player, world, x, y, z,
|
||||
side, new Vector3(hitX, hitY, hitZ))))
|
||||
{
|
||||
SoundLib.playBlockPlacement(world, x, y, z, field_150939_a)
|
||||
true
|
||||
}
|
||||
else super.onItemUse(item, player, world, x, y, z, side, hitX, hitY, hitZ)
|
||||
}
|
||||
|
||||
override def func_150936_a(world:World, x:Int, y:Int, z:Int, side:Int, player:EntityPlayer, stack:ItemStack) = true
|
||||
}
|
||||
Regular → Executable
+5
-5
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.math.MathLib
|
||||
import net.minecraft.block.Block
|
||||
@@ -18,10 +17,11 @@ object ASMHacks
|
||||
@SideOnly(Side.CLIENT)
|
||||
def renderTileEntityAt(te:TileEntity, x:Double, y:Double, z:Double, tick:Float):Unit =
|
||||
{
|
||||
if (MovementManager.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord))
|
||||
if (MovementManager2.isMoving(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord))
|
||||
{
|
||||
val o = MovementManager.getData(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)
|
||||
val vec = o.vec.copy+new Vector3(new BlockCoord().offset(o.moveDir))*tick/16F
|
||||
val s = MovementManager2.getEnclosedStructure(te.getWorldObj, te.xCoord, te.yCoord, te.zCoord)
|
||||
val vec = MovingRenderer.renderPos(s, tick)
|
||||
|
||||
TileEntityRendererDispatcher.instance.renderTileEntityAt(te,
|
||||
x+MathLib.clamp(-1F, 1F, vec.x.toFloat),
|
||||
y+MathLib.clamp(-1F, 1F, vec.y.toFloat),
|
||||
@@ -33,7 +33,7 @@ object ASMHacks
|
||||
@SideOnly(Side.CLIENT)
|
||||
def getRenderType(block:Block, x:Int, y:Int, z:Int):Int =
|
||||
{
|
||||
if (MovingRenderer.renderHack && MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) -1
|
||||
if (MovingRenderer.renderHack && MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z)) -1
|
||||
else block.getRenderType
|
||||
}
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.handler
|
||||
|
||||
import java.util.{Set => JSet}
|
||||
|
||||
import codechicken.lib.vec.BlockCoord
|
||||
import mrtjp.relocation.api.{BlockPos, ITileMover, RelocationAPI, Relocator}
|
||||
import mrtjp.relocation.{MovementManager2, MovingTileRegistry}
|
||||
import net.minecraft.world.World
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.collection.mutable.{Set => MSet}
|
||||
|
||||
object RelocationAPI_Impl extends RelocationAPI
|
||||
{
|
||||
var isPreInit = true
|
||||
|
||||
override def registerTileMover(name:String, desc:String, handler:ITileMover) =
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.registerTileMover(name, desc, handler)
|
||||
}
|
||||
|
||||
override def registerPreferredMover(key:String, value:String)
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.preferredMovers :+= (key, value)
|
||||
}
|
||||
|
||||
override def registerMandatoryMover(key:String, value:String)
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.mandatoryMovers :+= (key, value)
|
||||
}
|
||||
|
||||
override def getRelocator = Relocator_Impl
|
||||
|
||||
override def isMoving(world:World, x:Int, y:Int, z:Int) =
|
||||
MovementManager2.isMoving(world, x, y, z)
|
||||
}
|
||||
|
||||
object Relocator_Impl extends Relocator
|
||||
{
|
||||
private var enabled = false
|
||||
|
||||
private var world:World = null
|
||||
private var dir = -1
|
||||
private val blocks = MSet[BlockCoord]()
|
||||
|
||||
private def assertState()
|
||||
{
|
||||
if (!enabled) throw new IllegalStateException("Relocator must be on the stack before use.")
|
||||
}
|
||||
|
||||
override def push()
|
||||
{
|
||||
if (enabled) throw new IllegalStateException("Relocator is already on the stack.")
|
||||
enabled = true
|
||||
}
|
||||
|
||||
override def pop()
|
||||
{
|
||||
if (!enabled) throw new IllegalStateException("Relocator is not on the stack.")
|
||||
enabled = false
|
||||
world = null
|
||||
dir = -1
|
||||
blocks.clear()
|
||||
}
|
||||
|
||||
override def setWorld(w:World)
|
||||
{
|
||||
assertState()
|
||||
if (world != null) throw new IllegalStateException("World already set.")
|
||||
world = w
|
||||
}
|
||||
|
||||
override def setDirection(d:Int)
|
||||
{
|
||||
assertState()
|
||||
if (dir != -1) throw new IllegalStateException("Direction already set.")
|
||||
dir = d
|
||||
}
|
||||
|
||||
override def addBlock(x:Int, y:Int, z:Int)
|
||||
{
|
||||
assertState()
|
||||
blocks += new BlockCoord(x, y, z)
|
||||
}
|
||||
|
||||
override def addBlock(bc:BlockPos)
|
||||
{
|
||||
addBlock(bc.x, bc.y, bc.z)
|
||||
}
|
||||
|
||||
override def addBlocks(blocks:JSet[BlockPos])
|
||||
{
|
||||
for (b <- blocks) addBlock(b)
|
||||
}
|
||||
|
||||
override def execute() =
|
||||
{
|
||||
assertState()
|
||||
if (world == null) throw new IllegalStateException("World must be set before move.")
|
||||
if (world.isRemote) throw new IllegalStateException("Movements cannot be executed client-side.")
|
||||
if (dir == -1) throw new IllegalStateException("Direction must be set before move.")
|
||||
if (blocks.isEmpty) throw new IllegalStateException("At least 1 block is required for move.")
|
||||
MovementManager2.tryStartMove(world, blocks.toSet, dir)
|
||||
}
|
||||
}
|
||||
Executable
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.handler
|
||||
|
||||
import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent}
|
||||
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
||||
import mrtjp.relocation.api._
|
||||
import mrtjp.relocation.{BlockMovingRow, MovingTileRegistry}
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import org.apache.logging.log4j.LogManager
|
||||
|
||||
@Mod(modid = RelocationMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.relocation.handler.GuiConfigFactory")
|
||||
object RelocationMod
|
||||
{
|
||||
RelocationAPI.instance = RelocationAPI_Impl
|
||||
|
||||
final val modID = "ForgeRelocation"
|
||||
final val modName = "ForgeRelocation"
|
||||
final val version = "@VERSION@"
|
||||
final val buildnumber = "@BUILD_NUMBER@"
|
||||
|
||||
val log = LogManager.getFormatterLogger(modID)
|
||||
|
||||
var blockMovingRow:BlockMovingRow = _
|
||||
|
||||
@Mod.EventHandler
|
||||
def preInit(event:FMLPreInitializationEvent)
|
||||
{
|
||||
RelocationProxy.preinit()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def init(event:FMLInitializationEvent)
|
||||
{
|
||||
RelocationAPI_Impl.isPreInit = false
|
||||
RelocationConfig.loadConfig()
|
||||
RelocationProxy.init()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def postInit(event:FMLPostInitializationEvent)
|
||||
{
|
||||
RelocationProxy.postinit()
|
||||
}
|
||||
}
|
||||
|
||||
class RelocationConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "ForgeRelocation", RelocationConfig.config)
|
||||
class GuiConfigFactory extends TModGuiFactory
|
||||
{
|
||||
override def mainConfigGuiClass() = classOf[RelocationConfigGui]
|
||||
}
|
||||
|
||||
object RelocationConfig extends ModConfig("ForgeRelocation")
|
||||
{
|
||||
var moveLimit = 2048
|
||||
|
||||
var moverMap = Array(
|
||||
"default -> saveload"
|
||||
)
|
||||
|
||||
override protected def initValues()
|
||||
{
|
||||
val general = new BaseCategory("General", "Basic settings")
|
||||
moveLimit = general.put("moveLimit", moveLimit, "Maximum amount of blocks that can be moved at once.")
|
||||
|
||||
val movers = new BaseCategory("Tile Movers", buildMoverDesc)
|
||||
moverMap = movers.put("mover registry", moverMap)
|
||||
moverMap = movers.put("mover registry", MovingTileRegistry.parseAndSetMovers(moverMap), true)
|
||||
}
|
||||
|
||||
def buildMoverDesc:String =
|
||||
{
|
||||
var s = "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" +
|
||||
"the syntax key -> value. \n"
|
||||
s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" +
|
||||
"blocks.\n"
|
||||
s += "Possible keys: \n"
|
||||
s += " 'default' - to assign default handler. \n"
|
||||
s += " 'mod:<modID>' - to assign every block from a mod. \n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||
|
||||
s += "\nAvailable tile movers:\n"
|
||||
for ((k, v) <- MovingTileRegistry.moverDescMap)
|
||||
s += " '"+k+"' - "+v+"\n"
|
||||
|
||||
if (MovingTileRegistry.mandatoryMovers.nonEmpty)
|
||||
{
|
||||
s += "\nMovers locked via API:\n"
|
||||
for ((k, v) <- MovingTileRegistry.mandatoryMovers)
|
||||
s += " "+k+" -> "+v+"\n"
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
Executable
+175
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation.handler
|
||||
|
||||
import java.io.{ByteArrayOutputStream, DataOutputStream}
|
||||
import java.util.{LinkedList => JLinkedList, List => JList}
|
||||
|
||||
import codechicken.lib.data.MCDataOutputWrapper
|
||||
import codechicken.lib.packet.PacketCustom
|
||||
import codechicken.lib.packet.PacketCustom.{IClientPacketHandler, IServerPacketHandler}
|
||||
import mrtjp.relocation.MovementManager2
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.entity.player.{EntityPlayer, EntityPlayerMP}
|
||||
import net.minecraft.network.play.server.S40PacketDisconnect
|
||||
import net.minecraft.network.play.{INetHandlerPlayClient, INetHandlerPlayServer}
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.util.ChatComponentText
|
||||
import net.minecraft.world.{ChunkCoordIntPair, World}
|
||||
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.collection.mutable.{HashMap => MHashMap, Map => MMap, MultiMap => MMultiMap, Set => MSet}
|
||||
|
||||
/**
|
||||
* Tweaked version of Chickenbones' compressed end-of-tick tile data stream.
|
||||
*/
|
||||
class RelocationPH
|
||||
{
|
||||
val channel = RelocationMod
|
||||
}
|
||||
|
||||
object RelocationCPH extends RelocationPH with IClientPacketHandler
|
||||
{
|
||||
def handlePacket(packet: PacketCustom, mc: Minecraft, netHandler:INetHandlerPlayClient) {
|
||||
try {
|
||||
packet.getType match {
|
||||
case 1 => handleChunkDesc(packet, mc.theWorld)
|
||||
case 2 => handleChunkData(packet, mc.theWorld)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
case e:RuntimeException if e.getMessage.startsWith("DC: ") =>
|
||||
netHandler.handleDisconnect(new S40PacketDisconnect(new ChatComponentText(e.getMessage.substring(4))))
|
||||
}
|
||||
}
|
||||
|
||||
def handleChunkData(packet:PacketCustom, world:World)
|
||||
{
|
||||
var i = packet.readUByte()
|
||||
while (i != 255) {
|
||||
MovementManager2.read(world, packet, i)
|
||||
i = packet.readUByte()
|
||||
}
|
||||
}
|
||||
|
||||
def handleChunkDesc(packet:PacketCustom, world:World)
|
||||
{
|
||||
MovementManager2.readDesc(world, packet)
|
||||
}
|
||||
}
|
||||
|
||||
object RelocationSPH extends RelocationPH with IServerPacketHandler
|
||||
{
|
||||
class MCByteStream(bout:ByteArrayOutputStream) extends MCDataOutputWrapper(new DataOutputStream(bout))
|
||||
{
|
||||
def getBytes = bout.toByteArray
|
||||
}
|
||||
|
||||
override def handlePacket(packetCustom:PacketCustom, entityPlayerMP:EntityPlayerMP, iNetHandlerPlayServer:INetHandlerPlayServer){}
|
||||
|
||||
private val updateMap = MMap[World, MMap[Set[ChunkCoordIntPair], MCByteStream]]()
|
||||
private val chunkWatchers = new MHashMap[Int, MSet[ChunkCoordIntPair]] with MMultiMap[Int, ChunkCoordIntPair]
|
||||
private val newWatchers = MMap[Int, JLinkedList[ChunkCoordIntPair]]()
|
||||
|
||||
def onTickEnd()
|
||||
{
|
||||
val players = getServerPlayers
|
||||
sendData(players)
|
||||
sendDesc(players)
|
||||
}
|
||||
|
||||
def onWorldUnload(world:World)
|
||||
{
|
||||
if(!world.isRemote)
|
||||
updateMap.remove(world)
|
||||
}
|
||||
|
||||
def onChunkWatch(p:EntityPlayer, c:ChunkCoordIntPair)
|
||||
{
|
||||
newWatchers.getOrElseUpdate(p.getEntityId, new JLinkedList).add(c)
|
||||
}
|
||||
|
||||
def onChunkUnWatch(p:EntityPlayer, c:ChunkCoordIntPair)
|
||||
{
|
||||
newWatchers.get(p.getEntityId) match
|
||||
{
|
||||
case Some(chunks) => chunks.remove(c)
|
||||
case _ =>
|
||||
}
|
||||
chunkWatchers.removeBinding(p.getEntityId, c)
|
||||
}
|
||||
|
||||
private def getServerPlayers:Seq[EntityPlayerMP] =
|
||||
MinecraftServer.getServer.getConfigurationManager.playerEntityList
|
||||
.asInstanceOf[JList[EntityPlayerMP]]
|
||||
|
||||
private def sendData(players:Seq[EntityPlayerMP])
|
||||
{
|
||||
for(p <- players if chunkWatchers.containsKey(p.getEntityId))
|
||||
{
|
||||
updateMap.get(p.worldObj) match
|
||||
{
|
||||
case Some(m) if m.nonEmpty =>
|
||||
val chunks = chunkWatchers(p.getEntityId)
|
||||
val packet = new PacketCustom(channel, 2).compress()
|
||||
var send = false
|
||||
for((uchunks, stream) <- m if uchunks.exists(chunks.contains))
|
||||
{
|
||||
send = true
|
||||
packet.writeByteArray(stream.getBytes)
|
||||
packet.writeByte(255) //terminator
|
||||
}
|
||||
if(send) packet.sendToPlayer(p)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
updateMap.foreach(_._2.clear())
|
||||
}
|
||||
|
||||
private def sendDesc(players:Seq[EntityPlayerMP])
|
||||
{
|
||||
for(p <- players if newWatchers.containsKey(p.getEntityId))
|
||||
{
|
||||
val watched = newWatchers(p.getEntityId)
|
||||
val pkt = getDescPacket(p.worldObj, watched.toSet)
|
||||
if(pkt != null) pkt.sendToPlayer(p)
|
||||
for(c <- watched)
|
||||
chunkWatchers.addBinding(p.getEntityId, c)
|
||||
}
|
||||
newWatchers.clear()
|
||||
}
|
||||
|
||||
private def getDescPacket(world:World, chunks:Set[ChunkCoordIntPair]):PacketCustom =
|
||||
{
|
||||
val packet = new PacketCustom(channel, 1)
|
||||
if(MovementManager2.writeDesc(world, chunks, packet)) packet else null
|
||||
}
|
||||
|
||||
def forceSendData()
|
||||
{
|
||||
sendData(getServerPlayers)
|
||||
}
|
||||
|
||||
def forceSendDesc()
|
||||
{
|
||||
sendDesc(getServerPlayers)
|
||||
}
|
||||
|
||||
def getStream(world:World, chunks:Set[ChunkCoordIntPair], key:Int) =
|
||||
{
|
||||
updateMap.getOrElseUpdate(world,
|
||||
{
|
||||
if(world.isRemote)
|
||||
throw new IllegalArgumentException("Cannot use RelocationSPH on a client world")
|
||||
MMap()
|
||||
}).getOrElseUpdate(chunks,
|
||||
{
|
||||
val s = new MCByteStream(new ByteArrayOutputStream)
|
||||
s.writeByte(key)
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
Regular → Executable
+19
-20
@@ -3,11 +3,12 @@
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
package mrtjp.relocation.handler
|
||||
|
||||
import codechicken.lib.packet.PacketCustom
|
||||
import cpw.mods.fml.common.FMLCommonHandler
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.block.TileRenderRegistry
|
||||
import mrtjp.relocation._
|
||||
import mrtjp.relocation.api.RelocationAPI.{instance => API}
|
||||
import net.minecraftforge.common.MinecraftForge
|
||||
|
||||
@@ -15,19 +16,18 @@ class RelocationProxy_server
|
||||
{
|
||||
def preinit()
|
||||
{
|
||||
RelocationMod.blockMotor = new BlockMotor
|
||||
RelocationMod.blockFrame = new BlockFrame
|
||||
RelocationMod.blockMovingRow = new BlockMovingRow
|
||||
|
||||
API.registerTileMover("saveload",
|
||||
"Saves the tile and then reloads it in the next position. Reliable but CPU intensive.",
|
||||
new SaveLoadTileHandler)
|
||||
new SaveLoadTileMover)
|
||||
|
||||
API.registerTileMover("coordpush",
|
||||
"Physically changes the location of tiles. Works if tiles do not cache their position.",
|
||||
new CoordPushTileHandler)
|
||||
new CoordPushTileMover)
|
||||
|
||||
API.registerTileMover("static", "Setting this disables movement for the specified block.", new StaticTileHandler)
|
||||
API.registerTileMover("static", "Setting this disables movement for the specified block.",
|
||||
new StaticTileMover)
|
||||
|
||||
API.registerPreferredMover("default", "saveload")
|
||||
API.registerPreferredMover("mod:minecraft", "coordpush")
|
||||
@@ -40,29 +40,28 @@ class RelocationProxy_server
|
||||
|
||||
def init()
|
||||
{
|
||||
RelocationConfig.loadConfig()
|
||||
}
|
||||
|
||||
def postinit(){}
|
||||
def postinit()
|
||||
{
|
||||
PacketCustom.assignHandler(RelocationSPH.channel, RelocationSPH)
|
||||
|
||||
FMLCommonHandler.instance.bus.register(RelocationEventHandler)
|
||||
MinecraftForge.EVENT_BUS.register(RelocationEventHandler)
|
||||
}
|
||||
}
|
||||
|
||||
class RelocationProxy_client extends RelocationProxy_server
|
||||
{
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def preinit()
|
||||
{
|
||||
super.preinit()
|
||||
FMLCommonHandler.instance.bus.register(RenderTicker)
|
||||
MinecraftForge.EVENT_BUS.register(MovingRenderer)
|
||||
|
||||
TileRenderRegistry.setRenderer(RelocationMod.blockMotor, 0, MotorRenderer)
|
||||
TileRenderRegistry.setRenderer(RelocationMod.blockFrame, 0, FrameRenderer)
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def postinit()
|
||||
{
|
||||
super.postinit()
|
||||
PacketCustom.assignHandler(RelocationCPH.channel, RelocationCPH)
|
||||
|
||||
FMLCommonHandler.instance.bus.register(RelocationClientEventHandler)
|
||||
MinecraftForge.EVENT_BUS.register(RelocationClientEventHandler)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||
import cpw.mods.fml.common.eventhandler.SubscribeEvent
|
||||
import cpw.mods.fml.common.gameevent.TickEvent
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.math.MathLib
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.texture.TextureMap
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
||||
import net.minecraft.client.renderer.{OpenGlHelper, RenderBlocks, RenderHelper, Tessellator}
|
||||
import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World}
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import org.lwjgl.opengl.GL11._
|
||||
|
||||
object MovingRenderer
|
||||
{
|
||||
var partialTickTime = 0.0f
|
||||
var isRendering = false
|
||||
var renderHack = true
|
||||
|
||||
def mc = Minecraft.getMinecraft
|
||||
def world = mc.theWorld
|
||||
def tes = Tessellator.instance
|
||||
|
||||
var oldWorld:World = null
|
||||
var renderBlocks:RenderBlocks = null
|
||||
|
||||
def render(x:Int, y:Int, z:Int, d:RenderPos, tick:Float)
|
||||
{
|
||||
val oldOcclusion = mc.gameSettings.ambientOcclusion
|
||||
mc.gameSettings.ambientOcclusion = 0
|
||||
|
||||
val block = world.getBlock(x, y, z)
|
||||
if (block == null) return
|
||||
|
||||
val engine = TileEntityRendererDispatcher.instance.field_147553_e
|
||||
if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture)
|
||||
mc.entityRenderer.enableLightmap(partialTickTime)
|
||||
|
||||
val light = world.getLightBrightnessForSkyBlocks(x, y, z, block.getLightValue(world, x, y, z))
|
||||
val l1 = light%65536
|
||||
val l2 = light/65536
|
||||
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
||||
glColor4f(0, 0, 0, 0)
|
||||
RenderHelper.disableStandardItemLighting()
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
glEnable(GL_BLEND)
|
||||
glDisable(GL_CULL_FACE)
|
||||
glShadeModel(if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT)
|
||||
|
||||
val vec = d.vec.copy+new Vector3(new BlockCoord().offset(d.moveDir))*tick/16F
|
||||
for (pass <- 0 to 1)
|
||||
{
|
||||
tes.startDrawingQuads()
|
||||
tes.setTranslation(
|
||||
-TileEntityRendererDispatcher.staticPlayerX+MathLib.clamp(-1F, 1F, vec.x.toFloat),
|
||||
-TileEntityRendererDispatcher.staticPlayerY+MathLib.clamp(-1F, 1F, vec.y.toFloat),
|
||||
-TileEntityRendererDispatcher.staticPlayerZ+MathLib.clamp(-1F, 1F, vec.z.toFloat))
|
||||
tes.setColorOpaque(1, 1, 1)
|
||||
|
||||
block.getRenderBlockPass
|
||||
if (block.canRenderInPass(pass))
|
||||
{
|
||||
renderHack = false
|
||||
renderBlocks.renderBlockByRenderType(block, x, y, z)
|
||||
renderHack = true
|
||||
}
|
||||
|
||||
tes.setTranslation(0, 0, 0)
|
||||
tes.draw()
|
||||
}
|
||||
RenderHelper.enableStandardItemLighting()
|
||||
mc.entityRenderer.disableLightmap(partialTickTime)
|
||||
mc.gameSettings.ambientOcclusion = oldOcclusion
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
def onRenderWorld(e:RenderWorldLastEvent)
|
||||
{
|
||||
if (oldWorld != world)
|
||||
{
|
||||
oldWorld = world
|
||||
renderBlocks = new MovingRenderBlocks(new MovingWorld(world))
|
||||
renderBlocks.renderAllFaces = true
|
||||
MovementManager.clientMap.clear()
|
||||
}
|
||||
MovementManager.clientMap.synchronized
|
||||
{
|
||||
val it = MovementManager.clientMap.iterator
|
||||
while (it.hasNext)
|
||||
{
|
||||
it.advance()
|
||||
val k = it.key()
|
||||
val v = it.value()
|
||||
import mrtjp.core.world.WorldLib.{unpackX, unpackY, unpackZ}
|
||||
render(unpackX(k), unpackY(k), unpackZ(k), v, partialTickTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def onPreRenderTick(time:Float)
|
||||
{
|
||||
isRendering = true
|
||||
partialTickTime = time
|
||||
}
|
||||
|
||||
def onPostRenderTick()
|
||||
{
|
||||
isRendering = false
|
||||
}
|
||||
}
|
||||
|
||||
object RenderTicker
|
||||
{
|
||||
@SubscribeEvent
|
||||
def onRenderTick(e:TickEvent.RenderTickEvent)
|
||||
{
|
||||
if (e.phase == TickEvent.Phase.START)
|
||||
MovingRenderer.onPreRenderTick(e.renderTickTime)
|
||||
else MovingRenderer.onPostRenderTick()
|
||||
}
|
||||
}
|
||||
|
||||
class RenderPos(val vec:Vector3, var moveDir:Int)
|
||||
{
|
||||
def this(x:Float, y:Float, z:Float, moveDir:Int) = this(new Vector3(x, y, z), moveDir)
|
||||
|
||||
def x = vec.x.toFloat
|
||||
def y = vec.y.toFloat
|
||||
def z = vec.z.toFloat
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
class MovingRenderBlocks(w:IBlockAccess) extends RenderBlocks(w)
|
||||
{
|
||||
override def renderStandardBlock(block:Block, x:Int, y:Int, z:Int) =
|
||||
{
|
||||
import mrtjp.relocation.MovementManager.eps
|
||||
if (MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z))
|
||||
{
|
||||
if (renderMinX == 0.0D) renderMinX += eps
|
||||
if (renderMinY == 0.0D) renderMinY += eps
|
||||
if (renderMinZ == 0.0D) renderMinZ += eps
|
||||
if (renderMaxX == 1.0D) renderMaxX -= eps
|
||||
if (renderMaxY == 1.0D) renderMaxY -= eps
|
||||
if (renderMaxZ == 1.0D) renderMaxZ -= eps
|
||||
}
|
||||
super.renderStandardBlock(block, x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
class MovingWorld(val world:World) extends IBlockAccess
|
||||
{
|
||||
override def getBlock(x:Int, y:Int, z:Int) = world.getBlock(x, y, z)
|
||||
|
||||
override def getTileEntity(x:Int, y:Int, z:Int) = world.getTileEntity(x, y, z)
|
||||
|
||||
def computeLightValue(x:Int, y:Int, z:Int, tpe:EnumSkyBlock) =
|
||||
{
|
||||
(for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s))
|
||||
yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getLightBrightnessForSkyBlocks(x:Int, y:Int, z:Int, light:Int) =
|
||||
MovementManager.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match
|
||||
{
|
||||
case true =>
|
||||
val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky)
|
||||
val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block)
|
||||
l1<<20|Seq(l2, light).max<<4
|
||||
case false => world.getLightBrightnessForSkyBlocks(x, y, z, light)
|
||||
}
|
||||
|
||||
override def getBlockMetadata(x:Int, y:Int, z:Int) = world.getBlockMetadata(x, y, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def isAirBlock(x:Int, y:Int, z:Int) = world.isAirBlock(x, y, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getBiomeGenForCoords(x:Int, z:Int) = world.getBiomeGenForCoords(x, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getHeight = world.getHeight
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache()
|
||||
|
||||
override def isBlockProvidingPowerTo(x:Int, y:Int, z:Int, side:Int) =
|
||||
world.isBlockProvidingPowerTo(x, y, z, side)
|
||||
|
||||
override def isSideSolid(x:Int, y:Int, z:Int, side:ForgeDirection, _default:Boolean) =
|
||||
world.isSideSolid(x, y, z, side, _default)
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.vec.Vector3
|
||||
import cpw.mods.fml.common.Mod
|
||||
import cpw.mods.fml.common.event.{FMLInitializationEvent, FMLPostInitializationEvent, FMLPreInitializationEvent}
|
||||
import mrtjp.core.data.{ModConfig, SpecialConfigGui, TModGuiFactory}
|
||||
import mrtjp.core.world.WorldLib
|
||||
import mrtjp.relocation.MovingTileRegistry._
|
||||
import mrtjp.relocation.api._
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.gui.GuiScreen
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.Vec3
|
||||
import net.minecraft.world.World
|
||||
import org.apache.logging.log4j.LogManager
|
||||
|
||||
@Mod(modid = RelocationMod.modID, useMetadata = true, modLanguage = "scala", guiFactory = "mrtjp.relocation.GuiConfigFactory")
|
||||
object RelocationMod
|
||||
{
|
||||
RelocationAPI.instance = RelocationAPI_Impl
|
||||
|
||||
final val modID = "ForgeRelocation"
|
||||
final val modName = "ForgeRelocation"
|
||||
final val version = "@VERSION@"
|
||||
final val buildnumber = "@BUILD_NUMBER@"
|
||||
|
||||
val log = LogManager.getFormatterLogger(modID)
|
||||
|
||||
var blockMovingRow:BlockMovingRow = _
|
||||
var blockMotor:BlockMotor = _
|
||||
var blockFrame:Block with IFrame = _
|
||||
|
||||
@Mod.EventHandler
|
||||
def preInit(event:FMLPreInitializationEvent)
|
||||
{
|
||||
RelocationProxy.preinit()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def init(event:FMLInitializationEvent)
|
||||
{
|
||||
RelocationAPI_Impl.isPreInit = false
|
||||
RelocationProxy.init()
|
||||
}
|
||||
|
||||
@Mod.EventHandler
|
||||
def postInit(event:FMLPostInitializationEvent)
|
||||
{
|
||||
RelocationProxy.postinit()
|
||||
}
|
||||
}
|
||||
|
||||
object RelocationConfig extends ModConfig("ForgeRelocation")
|
||||
{
|
||||
var moveLimit = 2048
|
||||
var mCap = 1000.0D
|
||||
var mInitial = 40.0D
|
||||
var mLoad = 10.0D
|
||||
|
||||
var simpleModel = true
|
||||
|
||||
var moverMap = Array(
|
||||
"default -> saveload"
|
||||
)
|
||||
|
||||
var setMap = Array(
|
||||
"bed -> bed",
|
||||
"wooden_door -> wooden_door",
|
||||
"iron_door -> iron_door"
|
||||
)
|
||||
|
||||
override protected def initValues()
|
||||
{
|
||||
val general = new BaseCategory("General", "Basic settings")
|
||||
moveLimit = general.put("moveLimit", moveLimit, "Maxumum amount of blocks that can be moved at once.")
|
||||
|
||||
val renders = new BaseCategory("Rendering", "Settings related to block rendering")
|
||||
simpleModel = renders.put("Simple frame model", simpleModel, "Set to false to use a more complex version of the frame model. Looks better but requires more resources.")
|
||||
|
||||
val movers = new BaseCategory("Tile Movers", buildMoverDesc)
|
||||
moverMap = movers.put("mover registry", moverMap)
|
||||
moverMap = movers.put("mover registry", parseAndSetMovers(moverMap), true)
|
||||
|
||||
val sets = new BaseCategory("Latched Sets", buildLatchSetsDesc)
|
||||
setMap = sets.put("latch registry", setMap)
|
||||
parseAndAddLatchSets(setMap)
|
||||
|
||||
val power = new BaseCategory("Power", "Settings that manage the power use of motors. The cost of moving n blocks is initial + n * load")
|
||||
mCap = power.put("capacity", mCap, "The total power capacity for a motor.")
|
||||
mInitial = power.put("initial", mInitial)
|
||||
mLoad = power.put("load", mLoad)
|
||||
}
|
||||
|
||||
def buildMoverDesc:String =
|
||||
{
|
||||
var s = "Used to configure which registered Tile Mover is used for a block. Key-Value pairs are defined using \n" +
|
||||
"the syntax key -> value. \n"
|
||||
s += "Most blocks are configurable, but some mods may have opted to lock which handlers can be used for its \n" +
|
||||
"blocks.\n"
|
||||
s += "Possible keys: \n"
|
||||
s += " 'default' - to assign default handler. \n"
|
||||
s += " 'mod:<modID>' - to assign every block from a mod. \n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||
|
||||
s += "\nAvailable tile movers:\n"
|
||||
for ((k, v) <- MovingTileRegistry.moverDescMap)
|
||||
s += " '"+k+"' - "+v+"\n"
|
||||
|
||||
if (mandatoryMovers.nonEmpty)
|
||||
{
|
||||
s += "\nMovers locked via API:\n"
|
||||
for ((k, v) <- MovingTileRegistry.mandatoryMovers)
|
||||
s += " "+k+" -> "+v+"\n"
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
def buildLatchSetsDesc:String =
|
||||
{
|
||||
var s = "Used to define which pairs of blocks will be stuck together. \n"
|
||||
s += "Latched sets will always move in pairs, even if only one of them are actually connected to a block. \n"
|
||||
s += "'block1 -> block2' means that if block1 is moved, any block2 connected to it will also move. \n"
|
||||
s += "However, moving block2 does not move block1. To do that, you must also register block2 -> block1. \n"
|
||||
s += "Sets are defined using the syntax of key -> value. \n"
|
||||
s += "Possible keys and values:\n"
|
||||
s += " '<modID>:<blockname>' - to assign block from a mod for every meta. \n"
|
||||
s += " '<modID>:<blockname>m<meta>' - to assign block from mod for specific meta. \n"
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
class RelocationConfigGui(parent:GuiScreen) extends SpecialConfigGui(parent, "RelocationTestConfig", RelocationConfig.config)
|
||||
|
||||
class GuiConfigFactory extends TModGuiFactory
|
||||
{
|
||||
override def mainConfigGuiClass() = classOf[RelocationConfigGui]
|
||||
}
|
||||
|
||||
object RelocationAPI_Impl extends RelocationAPI
|
||||
{
|
||||
var isPreInit = true
|
||||
|
||||
override def registerTileMover(name:String, desc:String, handler:ITileMover) =
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.registerTileMover(name, desc, handler)
|
||||
}
|
||||
|
||||
override def registerPreferredMover(key:String, value:String)
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.preferredMovers :+= (key, value)
|
||||
}
|
||||
|
||||
override def registerMandatoryMover(key:String, value:String)
|
||||
{
|
||||
assert(isPreInit)
|
||||
MovingTileRegistry.mandatoryMovers :+= (key, value)
|
||||
}
|
||||
|
||||
override def registerFramePlacement(placement:IFramePlacement)
|
||||
{
|
||||
ItemBlockFrame.placements :+= placement
|
||||
}
|
||||
|
||||
override def registerFrameInteraction(interaction:IFrameInteraction)
|
||||
{
|
||||
MovingTileRegistry.interactionList :+= interaction
|
||||
}
|
||||
|
||||
override def getFrameBlock = RelocationMod.blockFrame
|
||||
|
||||
override def getMotorBlock = RelocationMod.blockMotor
|
||||
|
||||
override def uncheckedRemoveTileEntity(w:World, x:Int, y:Int, z:Int)
|
||||
{
|
||||
WorldLib.uncheckedRemoveTileEntity(w, x, y, z)
|
||||
}
|
||||
|
||||
override def uncheckedSetBlock(w:World, x:Int, y:Int, z:Int, b:Block, meta:Int)
|
||||
{
|
||||
WorldLib.uncheckedSetBlock(w, x, y, z, b, meta)
|
||||
}
|
||||
|
||||
override def uncheckedGetTileEntity(w:World, x:Int, y:Int, z:Int) =
|
||||
WorldLib.uncheckedGetTileEntity(w, x, y, z)
|
||||
|
||||
override def uncheckedSetTileEntity(w:World, x:Int, y:Int, z:Int, te:TileEntity)
|
||||
{
|
||||
WorldLib.uncheckedSetTileEntity(w, x, y, z, te)
|
||||
}
|
||||
|
||||
override def renderFrame(x:Double, y:Double, z:Double)
|
||||
{
|
||||
RenderFrame.render(new Vector3(x, y, z))
|
||||
}
|
||||
|
||||
override def raytraceFrame(x:Double, y:Double, z:Double, start:Vec3, end:Vec3) =
|
||||
Utils.raytraceFrame(x, y, z, start, end)
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import java.util.{List => JList}
|
||||
|
||||
import codechicken.lib.data.{MCDataInput, MCDataOutput}
|
||||
import codechicken.lib.vec.{BlockCoord, Cuboid6, Rotation, Vector3}
|
||||
import mrtjp.core.block.{InstancedBlock, InstancedBlockTile, TTileOrient}
|
||||
import mrtjp.core.math.MathLib
|
||||
import mrtjp.core.world.WorldLib
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.block.material.Material
|
||||
import net.minecraft.creativetab.CreativeTabs
|
||||
import net.minecraft.entity.Entity
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.util.AxisAlignedBB
|
||||
import net.minecraft.world.{IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import scala.annotation.tailrec
|
||||
import scala.collection.JavaConversions._
|
||||
import scala.collection.immutable.{HashSet, Queue}
|
||||
import scala.collection.mutable.{HashMap => MHashMap, MultiMap => MMultiMap, Set => MSet}
|
||||
|
||||
|
||||
class BlockMotor extends InstancedBlock("relocation.blockmotor", Material.iron)
|
||||
{
|
||||
setHardness(5f)
|
||||
setResistance(10f)
|
||||
setStepSound(Block.soundTypeMetal)
|
||||
setCreativeTab(CreativeTabs.tabTransport)
|
||||
addSingleTile(classOf[TileMotor])
|
||||
|
||||
override def isOpaqueCube = false
|
||||
|
||||
override def isSideSolid(world:IBlockAccess, x:Int, y:Int, z:Int, side:ForgeDirection) = true
|
||||
|
||||
override def renderAsNormalBlock = true
|
||||
}
|
||||
|
||||
class TileMotor extends InstancedBlockTile with TTileOrient with TPowerTile
|
||||
{
|
||||
var rows = HashSet.empty[BlockRow]
|
||||
var isMoving = false
|
||||
var offset = 0
|
||||
var renderOffset = new RenderPos(0, 0, 0, 6)
|
||||
|
||||
override def onBlockPlaced(side:Int, meta:Int, player:EntityPlayer, stack:ItemStack, hit:Vector3)
|
||||
{
|
||||
super.onBlockPlaced(side, meta, player, stack, hit)
|
||||
setSide(side^1)
|
||||
setRotation(Rotation.getSidedRotation(player, side^1))
|
||||
}
|
||||
|
||||
override def onBlockActivated(player:EntityPlayer, s:Int):Boolean =
|
||||
{
|
||||
if (super.onBlockActivated(player, s)) return true
|
||||
|
||||
if (player.isSneaking) setRotation((rotation+1)%4)
|
||||
else setSide((side+1)%6)
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
override def onOrientChanged(oldOrient:Int)
|
||||
{
|
||||
super.onOrientChanged(oldOrient)
|
||||
sendOrientUpdate()
|
||||
}
|
||||
|
||||
override def getBlock = RelocationMod.blockMotor
|
||||
|
||||
override def shouldRefresh(oldB:Block, newB:Block, oldMeta:Int, newMeta:Int, w:World, x:Int, y:Int, z:Int) =
|
||||
!(oldB eq newB)
|
||||
|
||||
def getMoveDir = absoluteDir((rotation+2)%4)
|
||||
|
||||
def canMoveAllRows:Boolean =
|
||||
{
|
||||
if (!world.isBlockIndirectlyGettingPowered(x, y, z)) return false
|
||||
|
||||
val pos = position.offset(side^1)
|
||||
val block = WorldLib.getBlock(world, pos)
|
||||
if (block == Blocks.air || MovementManager.isMoving(world, pos) ||
|
||||
!MovingTileRegistry.canMove(world, pos.x, pos.y, pos.z))
|
||||
return false
|
||||
|
||||
val blocks = iterate(Queue(pos))
|
||||
|
||||
val moveEnergy = RelocationConfig.mInitial+RelocationConfig.mLoad*blocks.size
|
||||
if (getEnergy < moveEnergy-1/4096F) return false
|
||||
|
||||
val map = new MHashMap[(Int, Int), MSet[Int]] with MMultiMap[(Int, Int), Int]
|
||||
for (b <- blocks) map.addBinding(MathLib.normal(b, getMoveDir), MathLib.basis(b, getMoveDir))
|
||||
|
||||
val shift = if ((getMoveDir&1) == 1) 1 else -1
|
||||
val rows =
|
||||
{
|
||||
val builder = Vector.newBuilder[(BlockCoord, Int)]
|
||||
for (normal <- map.keys)
|
||||
{
|
||||
val line = map(normal).toArray
|
||||
val sline = if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse)
|
||||
for ((basis, size) <- MathLib.splitLine(sline, shift))
|
||||
{
|
||||
val c = MathLib.rhrAxis(getMoveDir, normal, basis+shift)
|
||||
builder += ((c, size))
|
||||
}
|
||||
}
|
||||
builder.result()
|
||||
}
|
||||
|
||||
val canMove = (blocks.size <= RelocationConfig.moveLimit) && !rows.exists((pair) =>
|
||||
{
|
||||
val c = pair._1
|
||||
if (c.y < 0 || c.y >= 256) true
|
||||
else
|
||||
{
|
||||
val block = WorldLib.getBlock(world, c)
|
||||
if (block == null) false
|
||||
else !block.isReplaceable(world, c.x, c.y, c.z)
|
||||
}
|
||||
})
|
||||
|
||||
if (canMove)
|
||||
{
|
||||
isMoving = true
|
||||
for ((c, size) <- rows)
|
||||
{
|
||||
world.setBlock(c.x, c.y, c.z, RelocationMod.blockMovingRow, 0, 3)
|
||||
WorldLib.getTileEntity(world, c) match
|
||||
{
|
||||
case te:TileMovingRow => te.parentPos = Some(position)
|
||||
case _ =>
|
||||
}
|
||||
world.markBlockForUpdate(c.x, c.y, c.z)
|
||||
this.rows += BlockRow(c, getMoveDir, size)
|
||||
}
|
||||
markDescUpdate()
|
||||
}
|
||||
|
||||
if (canMove) setEnergy(getEnergy-moveEnergy)
|
||||
canMove
|
||||
}
|
||||
|
||||
@tailrec
|
||||
private def iterate(open:Seq[BlockCoord], closed:Set[BlockCoord] = Set.empty):Set[BlockCoord] = open match
|
||||
{
|
||||
case _ if closed.size > RelocationConfig.moveLimit => closed
|
||||
case Seq() => closed
|
||||
case Seq(next, rest@_*) => WorldLib.getBlock(world, next) match
|
||||
{
|
||||
case block:Block =>
|
||||
val toCheck = Vector.newBuilder[BlockCoord]
|
||||
for (s <- 0 until 6)
|
||||
{
|
||||
val sticks = MovingTileRegistry.resolveStick(world, next, s)
|
||||
val to = next.copy.offset(s)
|
||||
if (sticks && to != position && !closed(to) && !open.contains(to)
|
||||
&& !world.isAirBlock(to.x, to.y, to.z) && !MovementManager.isMoving(world, to)
|
||||
&& MovingTileRegistry.canMove(world, to.x, to.y, to.z))
|
||||
toCheck += to
|
||||
}
|
||||
iterate(rest++toCheck.result(), closed+next)
|
||||
case _ => iterate(rest, closed+next)
|
||||
}
|
||||
}
|
||||
|
||||
def blocks =
|
||||
{
|
||||
val d = getMoveDir
|
||||
for (r <- rows; i <- 1 to r.size) yield r.pos.copy.offset(d^1, i)
|
||||
}
|
||||
|
||||
def allBlocks =
|
||||
{
|
||||
val d = getMoveDir
|
||||
for (r <- rows; i <- 0 to r.size) yield r.pos.copy.offset(d^1, i)
|
||||
}
|
||||
|
||||
def preMove()
|
||||
{
|
||||
if (world != null) for (s <- rows) s.preMove(world, renderOffset)
|
||||
}
|
||||
|
||||
def cycleMove()
|
||||
{
|
||||
if (!world.isRemote) writeStream(1).sendToChunk()
|
||||
|
||||
for (r <- rows) r.doMove(world)
|
||||
for (r <- rows) r.postMove(world)
|
||||
for (r <- rows) r.endMove(world)
|
||||
|
||||
Utils.rescheduleTicks(world, blocks, allBlocks, getMoveDir)
|
||||
|
||||
val changes = MSet[BlockCoord]()
|
||||
for (r <- rows) r.cacheChanges(world, changes)
|
||||
for (bc <- changes) world.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air)
|
||||
|
||||
Utils.rerenderBlocks(world, blocks)
|
||||
|
||||
rows = HashSet.empty
|
||||
renderOffset.vec.set(0, 0, 0)
|
||||
renderOffset.moveDir = 6
|
||||
}
|
||||
|
||||
def clientCycleMove()
|
||||
{
|
||||
cycleMove()
|
||||
isMoving = false
|
||||
offset = 0
|
||||
}
|
||||
|
||||
override def update()
|
||||
{
|
||||
super.update()
|
||||
if (offset >= 16)
|
||||
{
|
||||
pushEntities()
|
||||
cycleMove()
|
||||
isMoving = false
|
||||
offset = 0
|
||||
}
|
||||
if (offset == 0 && canMoveAllRows) preMove()
|
||||
pushBlock()
|
||||
}
|
||||
|
||||
override def updateClient()
|
||||
{
|
||||
super.updateClient()
|
||||
pushBlock()
|
||||
}
|
||||
|
||||
def pushBlock()
|
||||
{
|
||||
if (isMoving && offset <= 16)
|
||||
{
|
||||
val dir = getMoveDir
|
||||
offset += 1
|
||||
val shift = offset.toFloat/16.0F
|
||||
renderOffset.vec.set(new Vector3(new BlockCoord().offset(dir))*shift)
|
||||
renderOffset.moveDir = dir
|
||||
}
|
||||
pushEntities()
|
||||
}
|
||||
|
||||
def pushEntities()
|
||||
{
|
||||
val sh = new Vector3(new BlockCoord().offset(getMoveDir))*1/16D
|
||||
for (s <- rows; aabb = getAabb(s.pos) if aabb != null)
|
||||
world.getEntitiesWithinAABBExcludingEntity(null, aabb) match
|
||||
{
|
||||
case list:JList[_] => for (e <- list.asInstanceOf[JList[Entity]])
|
||||
{
|
||||
e.moveEntity(0, sh.y max 0, 0)
|
||||
e.addVelocity(sh.x, sh.y, sh.z)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
def getAabb(spos:BlockCoord) =
|
||||
{
|
||||
val pos = spos.copy.offset(getMoveDir^1)
|
||||
val block = world.getBlock(pos.x, pos.y, pos.z)
|
||||
|
||||
if (!isMoving || block == null) null
|
||||
else
|
||||
{
|
||||
val shift = offset.toFloat/16F
|
||||
block.getCollisionBoundingBoxFromPool(world, pos.x, pos.y, pos.z) match
|
||||
{
|
||||
case aabb:AxisAlignedBB => new Cuboid6(aabb).add(new Vector3(new BlockCoord()
|
||||
.offset(getMoveDir))*shift).toAABB
|
||||
case _ => null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def sendOrientUpdate()
|
||||
{
|
||||
if (!world.isRemote)
|
||||
writeStream(2).writeByte(orientation).sendToChunk()
|
||||
}
|
||||
|
||||
override def read(in:MCDataInput, key:Int) = key match
|
||||
{
|
||||
case 1 => clientCycleMove()
|
||||
case 2 =>
|
||||
orientation = in.readByte()
|
||||
markRender()
|
||||
case _ => super.read(in, key)
|
||||
}
|
||||
|
||||
override def save(tag:NBTTagCompound)
|
||||
{
|
||||
super.save(tag)
|
||||
tag.setBoolean("move", isMoving)
|
||||
tag.setShort("off", offset.toShort)
|
||||
|
||||
tag.setInteger("length", rows.size)
|
||||
val rowSeq = rows.toSeq
|
||||
for (i <- 0 until rows.size)
|
||||
{
|
||||
val tag2 = new NBTTagCompound
|
||||
val s = rowSeq(i)
|
||||
|
||||
tag.setIntArray("pos", Array(s.pos.x, s.pos.y, s.pos.z))
|
||||
tag.setByte("dir", getMoveDir.toByte)
|
||||
tag.setInteger("size", s.size)
|
||||
|
||||
tag.setTag("tag"+i, tag2)
|
||||
}
|
||||
}
|
||||
|
||||
override def load(tag:NBTTagCompound)
|
||||
{
|
||||
super.load(tag)
|
||||
isMoving = tag.getBoolean("move")
|
||||
offset = tag.getShort("off")
|
||||
|
||||
for (i <- 0 until tag.getInteger("length"))
|
||||
{
|
||||
val tag2 = tag.getCompoundTag("tag"+i)
|
||||
rows += BlockRow(new BlockCoord(tag2.getIntArray("pos")), tag2.getByte("dir"), tag2.getInteger("size"))
|
||||
}
|
||||
|
||||
if (isMoving) preMove()
|
||||
}
|
||||
|
||||
override def writeDesc(out:MCDataOutput)
|
||||
{
|
||||
super.writeDesc(out)
|
||||
out.writeBoolean(isMoving).writeShort(offset)
|
||||
|
||||
out.writeInt(rows.size)
|
||||
val bc = position
|
||||
for (row <- rows)
|
||||
{
|
||||
val delta = row.pos.copy.sub(bc)
|
||||
Seq(delta.x, delta.y, delta.z).foreach(out.writeShort)
|
||||
out.writeByte(row.moveDir)
|
||||
out.writeShort(row.size)
|
||||
}
|
||||
}
|
||||
|
||||
override def readDesc(in:MCDataInput)
|
||||
{
|
||||
super.readDesc(in)
|
||||
isMoving = in.readBoolean()
|
||||
offset = in.readUShort()
|
||||
|
||||
val bc = position
|
||||
for (i <- 0 until in.readInt())
|
||||
{
|
||||
val delta = new BlockCoord(in.readShort(), in.readShort(), in.readShort())
|
||||
rows += BlockRow(delta.add(bc), in.readUByte(), in.readUShort())
|
||||
}
|
||||
|
||||
if (isMoving) preMove()
|
||||
}
|
||||
|
||||
override def compressDesc = true
|
||||
}
|
||||
Executable
+321
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2015.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.data.{MCDataInput, MCDataOutput}
|
||||
import codechicken.lib.packet.PacketCustom
|
||||
import codechicken.lib.vec.BlockCoord
|
||||
import mrtjp.core.math.MathLib
|
||||
import mrtjp.core.world.WorldLib
|
||||
import mrtjp.relocation.handler.{RelocationSPH, RelocationConfig}
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.world.{ChunkCoordIntPair, World}
|
||||
import net.minecraftforge.common.DimensionManager
|
||||
|
||||
import scala.collection.mutable.{HashMap => MHashMap, MultiMap => MMultiMap, Set => MSet}
|
||||
|
||||
object MovementManager2
|
||||
{
|
||||
val serverRelocations = MHashMap[Int, WorldStructs]()
|
||||
val clientRelocations = MHashMap[Int, WorldStructs]()
|
||||
|
||||
def relocationMap(client:Boolean) = if (client) clientRelocations else serverRelocations
|
||||
|
||||
def getWorldStructs(w:World) =
|
||||
relocationMap(w.isRemote).getOrElseUpdate(w.provider.dimensionId, new WorldStructs)
|
||||
|
||||
def writeDesc(w:World, chunks:Set[ChunkCoordIntPair], out:MCDataOutput) =
|
||||
{
|
||||
var send = false
|
||||
for (s <- getWorldStructs(w).structs if s.getChunks.exists(chunks.contains))
|
||||
{
|
||||
send = true
|
||||
out.writeShort(s.id)
|
||||
s.writeDesc(out)
|
||||
}
|
||||
if (send) out.writeShort(Short.MaxValue)
|
||||
send
|
||||
}
|
||||
|
||||
def readDesc(w:World, in:MCDataInput)
|
||||
{
|
||||
var id = in.readUShort()
|
||||
while (id != Short.MaxValue)
|
||||
{
|
||||
val struct = new BlockStruct
|
||||
struct.id = id
|
||||
struct.readDesc(in)
|
||||
id = in.readUShort()
|
||||
}
|
||||
}
|
||||
|
||||
def read(w:World, in:MCDataInput, key:Int) = key match
|
||||
{
|
||||
case 1 =>
|
||||
val struct = new BlockStruct
|
||||
struct.id = in.readUShort()
|
||||
struct.readDesc(in)
|
||||
getWorldStructs(w).addStruct(struct)
|
||||
for (b <- struct.allBlocks)
|
||||
w.func_147479_m(b.x, b.y, b.z)
|
||||
case 2 =>
|
||||
val id = in.readUShort()
|
||||
getWorldStructs(w).structs.find(_.id == id) match
|
||||
{
|
||||
case Some(struct) => clientCycleMove(w, struct)
|
||||
case None => throw new RuntimeException(s"DC: Moving structure with id $id was not found client-side.")
|
||||
}
|
||||
case _ => throw new RuntimeException(s"DC: Packet with ID $key was not handled. " +
|
||||
s"Skipped ${in.asInstanceOf[PacketCustom].getByteBuf.array().length} bytes.")
|
||||
}
|
||||
|
||||
def sendStruct(w:World, struct:BlockStruct)
|
||||
{
|
||||
val out = RelocationSPH.getStream(w, struct.getChunks, 1)
|
||||
out.writeShort(struct.id)
|
||||
struct.writeDesc(out)
|
||||
RelocationSPH.forceSendData()
|
||||
}
|
||||
|
||||
def sendCycle(w:World, struct:BlockStruct)
|
||||
{
|
||||
RelocationSPH.getStream(w, struct.getChunks, 2).writeShort(struct.id)
|
||||
RelocationSPH.forceSendData()
|
||||
}
|
||||
|
||||
def isMoving(w:World, x:Int, y:Int, z:Int) = getWorldStructs(w).contains(x, y, z)
|
||||
|
||||
def getEnclosedStructure(w:World, x:Int, y:Int, z:Int) =
|
||||
getWorldStructs(w).structs.find(_.contains(x, y, z)).orNull
|
||||
|
||||
def tryStartMove(w:World, blocks:Set[BlockCoord], moveDir:Int):Boolean =
|
||||
{
|
||||
if (blocks.size > RelocationConfig.moveLimit) return false
|
||||
|
||||
val map = new MHashMap[(Int, Int), MSet[Int]] with MMultiMap[(Int, Int), Int]
|
||||
for (b <- blocks) map.addBinding(MathLib.normal(b, moveDir), MathLib.basis(b, moveDir))
|
||||
|
||||
val shift = if ((moveDir&1) == 1) 1 else -1
|
||||
val rowB = Set.newBuilder[BlockRow]
|
||||
for (normal <- map.keys)
|
||||
{
|
||||
val line = map(normal).toArray
|
||||
val sline = if (shift == 1) line.sorted else line.sorted(Ordering[Int].reverse)
|
||||
for ((basis, size) <- MathLib.splitLine(sline, shift))
|
||||
{
|
||||
val c = MathLib.rhrAxis(moveDir, normal, basis+shift)
|
||||
rowB += new BlockRow(c, moveDir, size)
|
||||
}
|
||||
}
|
||||
|
||||
val rows = rowB.result()
|
||||
if (rows.exists(row => !MovingTileRegistry.canRunOverBlock(w, row.pos.x, row.pos.y, row.pos.z))) return false
|
||||
for (r <- rows) TileMovingRow.setBlockForRow(w, r)
|
||||
|
||||
val struct = new BlockStruct
|
||||
struct.id = BlockStruct.claimID()
|
||||
struct.rows = rows
|
||||
getWorldStructs(w).addStruct(struct)
|
||||
sendStruct(w, struct)
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
def onTick(client:Boolean)
|
||||
{
|
||||
val map = relocationMap(client)
|
||||
map.values.foreach(_.pushAll())
|
||||
if (!client)
|
||||
{
|
||||
val fin = map.map(pair => (pair._1, pair._2.removeFinished())).filter(_._2.nonEmpty)
|
||||
for ((dim, b) <- fin)
|
||||
{
|
||||
val w = DimensionManager.getWorld(dim)
|
||||
if (w != null) for (s <- b)
|
||||
{
|
||||
cycleMove(w, s)
|
||||
sendCycle(w, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def onWorldUnload(w:World)
|
||||
{
|
||||
getWorldStructs(w).clear()
|
||||
}
|
||||
|
||||
def clientCycleMove(w:World, struct:BlockStruct)
|
||||
{
|
||||
getWorldStructs(w).removeStruct(struct)
|
||||
cycleMove(w, struct)
|
||||
}
|
||||
|
||||
def cycleMove(w:World, struct:BlockStruct)
|
||||
{
|
||||
for (r <- struct.rows) r.doMove(w)
|
||||
for (r <- struct.rows) r.postMove(w)
|
||||
for (r <- struct.rows) r.endMove(w)
|
||||
|
||||
Utils.rescheduleTicks(w, struct.preMoveBlocks, struct.allBlocks, struct.moveDir)
|
||||
|
||||
val changes = MSet[BlockCoord]()
|
||||
for (r <- struct.rows) r.cacheChanges(w, changes)
|
||||
for (bc <- changes) w.notifyBlockOfNeighborChange(bc.x, bc.y, bc.z, Blocks.air)
|
||||
|
||||
Utils.rerenderBlocks(w, struct.preMoveBlocks)
|
||||
}
|
||||
}
|
||||
|
||||
class WorldStructs
|
||||
{
|
||||
var structs:Set[BlockStruct] = Set.empty
|
||||
|
||||
def isEmpty = structs.isEmpty
|
||||
|
||||
def contains(x:Int, y:Int, z:Int) = structs.exists(_.contains(x, y, z))
|
||||
|
||||
def addStruct(b:BlockStruct){ structs += b }
|
||||
|
||||
def pushAll(){ structs.foreach(_.push()) }
|
||||
|
||||
def removeFinished() =
|
||||
{
|
||||
val finished = structs.filter(_.finished)
|
||||
structs = structs.filterNot(_.finished)
|
||||
finished
|
||||
}
|
||||
|
||||
def removeStruct(s:BlockStruct)
|
||||
{
|
||||
structs = structs.filterNot(_ == s)
|
||||
}
|
||||
|
||||
def clear(){structs = Set.empty}
|
||||
|
||||
def getChunks:Set[ChunkCoordIntPair] =
|
||||
{
|
||||
structs.flatMap(_.getChunks)
|
||||
}
|
||||
}
|
||||
|
||||
object BlockStruct
|
||||
{
|
||||
private var maxID = 0
|
||||
def claimID() =
|
||||
{
|
||||
if (maxID < 32765) maxID += 1//little less than Short.MaxValue (reserved for terminator)
|
||||
else maxID = 0
|
||||
maxID
|
||||
}
|
||||
}
|
||||
|
||||
class BlockStruct
|
||||
{
|
||||
var id = -1
|
||||
var progress = 0.0D
|
||||
var speed = 1/16D
|
||||
var rows:Set[BlockRow] = Set.empty
|
||||
|
||||
lazy val allBlocks = rows.flatMap(_.allBlocks)
|
||||
lazy val preMoveBlocks = rows.flatMap(_.preMoveBlocks)
|
||||
lazy val postMoveBlocks = rows.flatMap(_.postMoveBlocks)
|
||||
|
||||
def moveDir = rows.head.moveDir
|
||||
|
||||
def contains(x:Int, y:Int, z:Int) = rows.exists(_.contains(x, y, z))
|
||||
|
||||
def push(){ progress = (progress+speed) min 1.0D }
|
||||
def finished = progress >= 1.0D
|
||||
|
||||
def getChunks:Set[ChunkCoordIntPair] =
|
||||
{
|
||||
val c = Set.newBuilder[ChunkCoordIntPair]
|
||||
for (b <- allBlocks)
|
||||
c += new ChunkCoordIntPair(b.x>>4, b.z>>4)
|
||||
c.result()
|
||||
}
|
||||
|
||||
override def equals(obj:scala.Any) = obj match
|
||||
{
|
||||
case that:BlockStruct => id == that.id
|
||||
case _ => false
|
||||
}
|
||||
|
||||
def writeDesc(out:MCDataOutput)
|
||||
{
|
||||
out.writeFloat(progress.toFloat)
|
||||
out.writeFloat(speed.toFloat)
|
||||
out.writeByte(rows.size)
|
||||
for (r <- rows)
|
||||
{
|
||||
out.writeLong(WorldLib.packCoords(r.pos))
|
||||
out.writeByte(r.moveDir)
|
||||
out.writeShort(r.size)
|
||||
}
|
||||
}
|
||||
|
||||
def readDesc(in:MCDataInput)
|
||||
{
|
||||
progress = in.readFloat()
|
||||
speed = in.readFloat()
|
||||
val rb = Set.newBuilder[BlockRow]
|
||||
for (i <- 0 until in.readUByte())
|
||||
rb += new BlockRow(WorldLib.unpackCoords(in.readLong()), in.readUByte(), in.readUShort())
|
||||
rows = rb.result()
|
||||
}
|
||||
}
|
||||
|
||||
class BlockRow(val pos:BlockCoord, val moveDir:Int, val size:Int)
|
||||
{
|
||||
val allBlocks = 0 to size map {i => pos.copy.offset(moveDir^1, i)}
|
||||
val preMoveBlocks = allBlocks drop 1
|
||||
val postMoveBlocks = allBlocks dropRight 1
|
||||
|
||||
def contains(x:Int, y:Int, z:Int) =
|
||||
{
|
||||
import MathLib.{basis, normal, shift}
|
||||
|
||||
import math.{max, min}
|
||||
if (normal(x, y, z, moveDir) == normal(pos, moveDir))
|
||||
{
|
||||
val b1 = basis(pos, moveDir)
|
||||
val b2 = b1+size*shift(moveDir^1)
|
||||
min(b1, b2) to max(b1, b2) contains basis(x, y, z, moveDir)
|
||||
}
|
||||
else false
|
||||
}
|
||||
|
||||
def doMove(w:World)
|
||||
{
|
||||
if (pos.y < 0 || pos.y >= 256) return
|
||||
|
||||
w.removeTileEntity(pos.x, pos.y, pos.z)
|
||||
WorldLib.uncheckedSetBlock(w, pos.x, pos.y, pos.z, Blocks.air, 0) //Remove movement block
|
||||
|
||||
for (b <- preMoveBlocks)
|
||||
MovingTileRegistry.move(w, b.x, b.y, b.z, moveDir)
|
||||
}
|
||||
|
||||
def postMove(w:World)
|
||||
{
|
||||
for (b <- postMoveBlocks)
|
||||
MovingTileRegistry.postMove(w, b.x, b.y, b.z)
|
||||
}
|
||||
|
||||
def endMove(w:World){}
|
||||
|
||||
def cacheChanges(w:World, changes:MSet[BlockCoord])
|
||||
{
|
||||
for (i <- 0 to size)
|
||||
{
|
||||
val c = pos.copy.offset(moveDir^1, i)
|
||||
changes += c
|
||||
for (s <- 0 until 6; s1 <- 0 until 6 if s1 != (s^1))
|
||||
changes += c.copy.offset(s).offset(s1)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014.
|
||||
* Created by MrTJP.
|
||||
* All rights reserved.
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import mrtjp.core.block.InstancedBlockTile
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
|
||||
trait TPowerTileCommon extends InstancedBlockTile
|
||||
{
|
||||
def getEnergy:Double
|
||||
def setEnergy(en:Double)
|
||||
|
||||
def maxEnergy:Double
|
||||
|
||||
abstract override def load(tag:NBTTagCompound)
|
||||
{
|
||||
super.load(tag)
|
||||
setEnergy(tag.getDouble("energy"))
|
||||
}
|
||||
|
||||
abstract override def save(tag:NBTTagCompound)
|
||||
{
|
||||
super.save(tag)
|
||||
tag.setDouble("energy", getEnergy)
|
||||
}
|
||||
}
|
||||
|
||||
trait TInfinitePower extends TPowerTileCommon
|
||||
{
|
||||
override def getEnergy = Double.MaxValue
|
||||
override def setEnergy(en:Double){}
|
||||
|
||||
override def maxEnergy = Double.MaxValue
|
||||
}
|
||||
|
||||
trait TPowerTile extends TPowerTileCommon with TInfinitePower//TODO mixin with all implementors of TPowerTile
|
||||
Regular → Executable
+12
-134
@@ -5,16 +5,13 @@
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import java.security.InvalidKeyException
|
||||
|
||||
import codechicken.lib.vec.BlockCoord
|
||||
import cpw.mods.fml.common.Loader
|
||||
import gnu.trove.impl.sync.{TSynchronizedIntObjectMap, TSynchronizedLongObjectMap, TSynchronizedLongSet}
|
||||
import gnu.trove.map.hash.{TIntObjectHashMap, TLongObjectHashMap}
|
||||
import gnu.trove.set.hash.TLongHashSet
|
||||
import mrtjp.core.block.BlockLib
|
||||
import mrtjp.core.world.WorldLib
|
||||
import mrtjp.core.world.WorldLib._
|
||||
import mrtjp.relocation.api.{IFrame, IFrameInteraction, ITileMover}
|
||||
import mrtjp.mcframes.api.{IFrame, IFrameInteraction}
|
||||
import mrtjp.relocation.api.ITileMover
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.init.Blocks
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
@@ -30,9 +27,6 @@ object MovingTileRegistry extends ITileMover
|
||||
val rNameMetaM = raw"(.+)m(\d+)".r
|
||||
val rMod = raw"mod:(\w+)".r
|
||||
|
||||
var latchMap = Map[(Block, Int), Set[(Block, Int)]]().withDefaultValue(Set())
|
||||
var interactionList = Seq[IFrameInteraction]()
|
||||
|
||||
var blockMetaMap = Map[(Block, Int), ITileMover]()
|
||||
var modMap = Map[String, ITileMover]()
|
||||
|
||||
@@ -56,11 +50,6 @@ object MovingTileRegistry extends ITileMover
|
||||
case i => name
|
||||
}
|
||||
|
||||
def parseAndAddLatchSets(kv:Seq[String])
|
||||
{
|
||||
parseKV(kv).foreach(b => addLatchSet(parseBlockMeta(b._1), parseBlockMeta(b._2)))
|
||||
}
|
||||
|
||||
def parseAndSetMovers(kv:Seq[String]) =
|
||||
{
|
||||
var moverMap = ListMap(parseKV(kv):_*)
|
||||
@@ -70,14 +59,10 @@ object MovingTileRegistry extends ITileMover
|
||||
moverMap.map(p => p._1+" -> "+p._2).toArray
|
||||
}
|
||||
|
||||
def addLatchSet(b1:(Block, Int), b2:(Block, Int))
|
||||
{
|
||||
latchMap += b1 -> (latchMap(b1)+b2)
|
||||
}
|
||||
|
||||
def setMover(that:String, m:String)
|
||||
{
|
||||
val h = moverNameMap.getOrElse(m, throw new InvalidKeyException("[ForgeRelocation] No tile mover named '"+m+"'"))
|
||||
if (!moverNameMap.contains(m)) return
|
||||
val h = moverNameMap(m)
|
||||
that match
|
||||
{
|
||||
case "default" => defaultMover = h
|
||||
@@ -128,122 +113,15 @@ object MovingTileRegistry extends ITileMover
|
||||
}
|
||||
}
|
||||
|
||||
def resolveStick(w:World, pos:BlockCoord, side:Int):Boolean =
|
||||
def canRunOverBlock(w:World, x:Int, y:Int, z:Int) =
|
||||
{
|
||||
val block = getBlock(w, pos)
|
||||
if (block.isInstanceOf[IFrame] && block.asInstanceOf[IFrame].
|
||||
latchSide(w, pos.x, pos.y, pos.z, side)) return true
|
||||
|
||||
val te = getTileEntity(w, pos)
|
||||
if (te.isInstanceOf[IFrame] && te.asInstanceOf[IFrame].
|
||||
latchSide(w, pos.x, pos.y, pos.z, side)) return true
|
||||
|
||||
if (latchInteraction(w, pos.x, pos.y, pos.z, side)) return true
|
||||
|
||||
if (latchSet(w, pos.x, pos.y, pos.z, side)) return true
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
def latchSet(w:World, x:Int, y:Int, z:Int, side:Int) =
|
||||
{
|
||||
val pos = new BlockCoord(x, y, z).offset(side)
|
||||
val b1 = getBlockMetaPair(w, x, y, z)
|
||||
val b2 = getBlockMetaPair(w, pos.x, pos.y, pos.z)
|
||||
|
||||
val set = latchMap.getOrElse(b1, latchMap((b1._1, -1)))
|
||||
set.contains(b2) || set.contains((b2._1, -1))
|
||||
}
|
||||
|
||||
def latchInteraction(w:World, x:Int, y:Int, z:Int, side:Int) = interactionList.find(_.canInteract(w, x, y, z)) match
|
||||
{
|
||||
case Some(i) => i.latchSide(w, x, y, z, side)
|
||||
case None => false
|
||||
if (w.blockExists(x, y, z))
|
||||
w.isAirBlock(x, y, z) || WorldLib.isBlockSoft(w, x, y, z, w.getBlock(x, y, z))
|
||||
else false
|
||||
}
|
||||
}
|
||||
|
||||
object MovementManager
|
||||
{
|
||||
val eps = 1.0/0x10000
|
||||
|
||||
val clientMap = new TSynchronizedLongObjectMap(new TLongObjectHashMap[RenderPos])
|
||||
val serverMap = new TSynchronizedIntObjectMap(new TIntObjectHashMap[TSynchronizedLongSet])
|
||||
|
||||
def isMoving(w:World, bc:BlockCoord):Boolean =
|
||||
isMoving(w, bc.x, bc.y, bc.z)
|
||||
|
||||
def isMoving(w:World, x:Int, y:Int, z:Int):Boolean =
|
||||
{
|
||||
if (w.isRemote) clientMap.containsKey(packCoords(x, y, z))
|
||||
else
|
||||
{
|
||||
val dim = w.provider.dimensionId
|
||||
if (serverMap.containsKey(dim))
|
||||
{
|
||||
val worldSet = serverMap.get(dim)
|
||||
worldSet.contains(packCoords(x, y, z))
|
||||
}
|
||||
else false
|
||||
}
|
||||
}
|
||||
|
||||
def getData(w:World, bc:BlockCoord):RenderPos =
|
||||
getData(w, bc.x, bc.y, bc.z)
|
||||
|
||||
def getData(w:World, x:Int, y:Int, z:Int):RenderPos =
|
||||
{
|
||||
if (w.isRemote) clientMap.get(packCoords(x, y, z))
|
||||
else null
|
||||
}
|
||||
|
||||
def addMoving(w:World, bc:BlockCoord, offset:RenderPos) = this.synchronized
|
||||
{
|
||||
if (w.isRemote)
|
||||
{
|
||||
clientMap.put(packCoords(bc.x, bc.y, bc.z), offset)
|
||||
w.func_147451_t(bc.x, bc.y, bc.z)
|
||||
for (s <- 0 until 6)
|
||||
{
|
||||
val pos = bc.copy.offset(s)
|
||||
w.func_147479_m(pos.x, pos.y, pos.z)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
val dim = w.provider.dimensionId
|
||||
if (!serverMap.containsKey(dim))
|
||||
serverMap.put(dim, new TSynchronizedLongSet(new TLongHashSet))
|
||||
|
||||
val worldSet = serverMap.get(dim)
|
||||
worldSet.add(packCoords(bc.x, bc.y, bc.z))
|
||||
}
|
||||
}
|
||||
|
||||
def removeMoving(w:World, bc:BlockCoord) = this.synchronized
|
||||
{
|
||||
if (w.isRemote)
|
||||
{
|
||||
clientMap.remove(packCoords(bc.x, bc.y, bc.z))
|
||||
w.func_147451_t(bc.x, bc.y, bc.z)
|
||||
for (s <- 0 until 6)
|
||||
{
|
||||
val pos = bc.copy.offset(s)
|
||||
w.func_147479_m(pos.x, pos.y, pos.z)
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
val dim = w.provider.dimensionId
|
||||
if (serverMap.containsKey(dim))
|
||||
{
|
||||
val worldSet = serverMap.get(dim)
|
||||
worldSet.remove(packCoords(bc.x, bc.y, bc.z))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class CoordPushTileHandler extends ITileMover
|
||||
class CoordPushTileMover extends ITileMover
|
||||
{
|
||||
override def canMove(w:World, x:Int, y:Int, z:Int) = true
|
||||
|
||||
@@ -271,7 +149,7 @@ class CoordPushTileHandler extends ITileMover
|
||||
override def postMove(w:World, x:Int, y:Int, z:Int){}
|
||||
}
|
||||
|
||||
class SaveLoadTileHandler extends ITileMover
|
||||
class SaveLoadTileMover extends ITileMover
|
||||
{
|
||||
override def canMove(w:World, x:Int, y:Int, z:Int) = true
|
||||
|
||||
@@ -307,7 +185,7 @@ class SaveLoadTileHandler extends ITileMover
|
||||
override def postMove(w:World, x:Int, y:Int, z:Int){}
|
||||
}
|
||||
|
||||
class StaticTileHandler extends ITileMover
|
||||
class StaticTileMover extends ITileMover
|
||||
{
|
||||
override def canMove(w:World, x:Int, y:Int, z:Int) = false
|
||||
|
||||
|
||||
Regular → Executable
+131
-111
@@ -5,151 +5,171 @@
|
||||
*/
|
||||
package mrtjp.relocation
|
||||
|
||||
import codechicken.lib.lighting.LightModel
|
||||
import codechicken.lib.render.CCModel._
|
||||
import codechicken.lib.render._
|
||||
import codechicken.lib.render.uv.{IconTransformation, MultiIconTransformation, UVTransformation}
|
||||
import codechicken.lib.vec._
|
||||
import mrtjp.core.block.TInstancedBlockRender
|
||||
import mrtjp.core.vec.InvertX
|
||||
import mrtjp.core.world.WorldLib
|
||||
import net.minecraft.client.renderer.RenderBlocks
|
||||
import net.minecraft.client.renderer.texture.IIconRegister
|
||||
import net.minecraft.util.IIcon
|
||||
import net.minecraft.world.IBlockAccess
|
||||
import codechicken.lib.vec.{BlockCoord, Vector3}
|
||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||
import mrtjp.core.math.MathLib
|
||||
import net.minecraft.block.Block
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.texture.TextureMap
|
||||
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher
|
||||
import net.minecraft.client.renderer.{OpenGlHelper, RenderBlocks, RenderHelper, Tessellator}
|
||||
import net.minecraft.world.{EnumSkyBlock, IBlockAccess, World}
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
import org.lwjgl.opengl.GL11._
|
||||
|
||||
//TODO use cube map renderer
|
||||
object MotorRenderer extends TInstancedBlockRender
|
||||
object MovingRenderer
|
||||
{
|
||||
var bottom:IIcon = _
|
||||
var side:IIcon = _
|
||||
var sidew:IIcon = _
|
||||
var sidee:IIcon = _
|
||||
var top:IIcon = _
|
||||
var iconT:UVTransformation = _
|
||||
var isRendering = false
|
||||
var renderHack = true
|
||||
|
||||
val models = Array.ofDim[CCModel](6, 4)
|
||||
private var oldWorld:World = null
|
||||
private var frame = 0.0f
|
||||
private var renderBlocks:RenderBlocks = null
|
||||
|
||||
private def mc = Minecraft.getMinecraft
|
||||
private def world = mc.theWorld
|
||||
private def tes = Tessellator.instance
|
||||
|
||||
private def render(x:Int, y:Int, z:Int, rpos:Vector3)
|
||||
{
|
||||
val base = CCModel.quadModel(24).generateBlock(0, Cuboid6.full)
|
||||
for (s <- 0 until 6) for (r <- 0 until 4)
|
||||
val oldOcclusion = mc.gameSettings.ambientOcclusion
|
||||
mc.gameSettings.ambientOcclusion = 0
|
||||
|
||||
val block = world.getBlock(x, y, z)
|
||||
if (block == null) return
|
||||
|
||||
val engine = TileEntityRendererDispatcher.instance.field_147553_e
|
||||
if (engine != null) engine.bindTexture(TextureMap.locationBlocksTexture)
|
||||
mc.entityRenderer.enableLightmap(frame)
|
||||
|
||||
val light = world.getLightBrightnessForSkyBlocks(x, y, z, block.getLightValue(world, x, y, z))
|
||||
val l1 = light%65536
|
||||
val l2 = light/65536
|
||||
|
||||
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, l1, l2)
|
||||
glColor4f(0, 0, 0, 0)
|
||||
RenderHelper.disableStandardItemLighting()
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
glEnable(GL_BLEND)
|
||||
glDisable(GL_CULL_FACE)
|
||||
glShadeModel(if (Minecraft.isAmbientOcclusionEnabled) GL_SMOOTH else GL_FLAT)
|
||||
|
||||
for (pass <- 0 to 1)
|
||||
{
|
||||
val m = base.copy.apply(Rotation.sideOrientation(s, r).at(Vector3.center))
|
||||
m.computeNormals()
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
models(s)(r) = m
|
||||
tes.startDrawingQuads()
|
||||
tes.setTranslation(
|
||||
-TileEntityRendererDispatcher.staticPlayerX+MathLib.clamp(-1F, 1F, rpos.x.toFloat),
|
||||
-TileEntityRendererDispatcher.staticPlayerY+MathLib.clamp(-1F, 1F, rpos.y.toFloat),
|
||||
-TileEntityRendererDispatcher.staticPlayerZ+MathLib.clamp(-1F, 1F, rpos.z.toFloat))
|
||||
tes.setColorOpaque(1, 1, 1)
|
||||
|
||||
block.getRenderBlockPass
|
||||
if (block.canRenderInPass(pass))
|
||||
{
|
||||
renderHack = false
|
||||
renderBlocks.renderBlockByRenderType(block, x, y, z)
|
||||
renderHack = true
|
||||
}
|
||||
|
||||
tes.setTranslation(0, 0, 0)
|
||||
tes.draw()
|
||||
}
|
||||
RenderHelper.enableStandardItemLighting()
|
||||
mc.entityRenderer.disableLightmap(frame)
|
||||
mc.gameSettings.ambientOcclusion = oldOcclusion
|
||||
}
|
||||
|
||||
override def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int)
|
||||
def onRenderWorldEvent()
|
||||
{
|
||||
val te = WorldLib.getTileEntity(w, x, y, z, classOf[TileMotor])
|
||||
if (te != null)
|
||||
if (oldWorld != world)
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.lightMatrix.locate(w, x, y, z)
|
||||
CCRenderState.setBrightness(w, x, y, z)
|
||||
models(te.side)(te.rotation).render(new Translation(x, y, z), iconT)
|
||||
oldWorld = world
|
||||
renderBlocks = new MovingRenderBlocks(new MovingWorld(world))
|
||||
renderBlocks.renderAllFaces = true
|
||||
}
|
||||
|
||||
for (s <- MovementManager2.getWorldStructs(world).structs) for (b <- s.preMoveBlocks)
|
||||
render(b.x, b.y, b.z, renderPos(s, frame))
|
||||
}
|
||||
|
||||
override def getIcon(s:Int, meta:Int) = s match
|
||||
def onPreRenderTick(time:Float)
|
||||
{
|
||||
case 0 => bottom
|
||||
case 1 => top
|
||||
case 2 => side
|
||||
case 3 => side
|
||||
case 4 => sidew
|
||||
case 5 => sidee
|
||||
isRendering = true
|
||||
frame = time
|
||||
}
|
||||
|
||||
private val invTranslation = new Translation(0, -0.075, 0)
|
||||
override def renderInvBlock(r:RenderBlocks, meta:Int)
|
||||
def onPostRenderTick()
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.setDynamic()
|
||||
CCRenderState.pullLightmap()
|
||||
CCRenderState.setPipeline(iconT, invTranslation)
|
||||
CCRenderState.startDrawing()
|
||||
BlockRenderer.renderCuboid(Cuboid6.full, 0)
|
||||
CCRenderState.draw()
|
||||
isRendering = false
|
||||
}
|
||||
|
||||
override def registerIcons(reg:IIconRegister)
|
||||
def renderPos(s:BlockStruct, partial:Float) =
|
||||
{
|
||||
bottom = reg.registerIcon("relocation:motor/bottom")
|
||||
top = reg.registerIcon("relocation:motor/top")
|
||||
side = reg.registerIcon("relocation:motor/side")
|
||||
sidew = reg.registerIcon("relocation:motor/sidew")
|
||||
sidee = reg.registerIcon("relocation:motor/sidee")
|
||||
|
||||
iconT = new MultiIconTransformation(bottom, top, side, side, sidew, sidee)
|
||||
new Vector3(BlockCoord.sideOffsets(s.moveDir))
|
||||
.multiply(s.progress+s.speed*partial)
|
||||
}
|
||||
}
|
||||
|
||||
object FrameRenderer extends TInstancedBlockRender
|
||||
@SideOnly(Side.CLIENT)
|
||||
class MovingRenderBlocks(w:IBlockAccess) extends RenderBlocks(w)
|
||||
{
|
||||
var icon:IIcon = _
|
||||
var iconT:UVTransformation = _
|
||||
val eps = 1.0/0x10000
|
||||
|
||||
override def renderWorldBlock(r:RenderBlocks, w:IBlockAccess, x:Int, y:Int, z:Int, meta:Int)
|
||||
override def renderStandardBlock(block:Block, x:Int, y:Int, z:Int) =
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.lightMatrix.locate(w, x, y, z)
|
||||
CCRenderState.setBrightness(w, x, y, z)
|
||||
RenderFrame.render(new Vector3(x, y, z))
|
||||
}
|
||||
|
||||
override def getIcon(side:Int, meta:Int) = icon
|
||||
|
||||
private val invVec = new Vector3(0, -0.075, 0)
|
||||
override def renderInvBlock(r:RenderBlocks, meta:Int)
|
||||
{
|
||||
TextureUtils.bindAtlas(0)
|
||||
CCRenderState.reset()
|
||||
CCRenderState.setDynamic()
|
||||
CCRenderState.pullLightmap()
|
||||
|
||||
CCRenderState.startDrawing()
|
||||
RenderFrame.render(invVec)
|
||||
|
||||
CCRenderState.render()
|
||||
CCRenderState.draw()
|
||||
}
|
||||
|
||||
override def registerIcons(reg:IIconRegister)
|
||||
{
|
||||
icon = reg.registerIcon("relocation:frame")
|
||||
iconT = new IconTransformation(icon)
|
||||
if (MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z))
|
||||
{
|
||||
if (renderMinX == 0.0D) renderMinX += eps
|
||||
if (renderMinY == 0.0D) renderMinY += eps
|
||||
if (renderMinZ == 0.0D) renderMinZ += eps
|
||||
if (renderMaxX == 1.0D) renderMaxX -= eps
|
||||
if (renderMaxY == 1.0D) renderMaxY -= eps
|
||||
if (renderMaxZ == 1.0D) renderMaxZ -= eps
|
||||
}
|
||||
super.renderStandardBlock(block, x, y, z)
|
||||
}
|
||||
}
|
||||
|
||||
object RenderFrame
|
||||
class MovingWorld(val world:World) extends IBlockAccess
|
||||
{
|
||||
val model = parseModel("frame")
|
||||
val model_simple = parseModel("frame_simple")
|
||||
override def getBlock(x:Int, y:Int, z:Int) = world.getBlock(x, y, z)
|
||||
|
||||
def getFrameForRender = if (RelocationConfig.simpleModel) model_simple else model
|
||||
override def getTileEntity(x:Int, y:Int, z:Int) = world.getTileEntity(x, y, z)
|
||||
|
||||
private def parseModel(name:String) =
|
||||
def computeLightValue(x:Int, y:Int, z:Int, tpe:EnumSkyBlock) =
|
||||
{
|
||||
val m = combine(parseObjModels(this.getClass.getResource(
|
||||
"/assets/relocation/textures/obj/"+name+".obj").openStream(),
|
||||
7, InvertX).values())
|
||||
|
||||
m.shrinkUVs(0.0005)
|
||||
m.apply(new Scale(1.00075, 1.00075, 1.00075))
|
||||
m.apply(new Translation(Vector3.center))
|
||||
m.computeNormals
|
||||
m.computeLighting(LightModel.standardLightModel)
|
||||
m
|
||||
(for (s <- 0 until 6; c = new BlockCoord(x, y, z).offset(s))
|
||||
yield world.getSavedLightValue(tpe, c.x, c.y, c.z)).max
|
||||
}
|
||||
|
||||
def render(pos:Vector3)
|
||||
{
|
||||
getFrameForRender.render(new Translation(pos), FrameRenderer.iconT)
|
||||
}
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getLightBrightnessForSkyBlocks(x:Int, y:Int, z:Int, light:Int) =
|
||||
MovementManager2.isMoving(Minecraft.getMinecraft.theWorld, x, y, z) match
|
||||
{
|
||||
case true =>
|
||||
val l1 = computeLightValue(x, y, z, EnumSkyBlock.Sky)
|
||||
val l2 = computeLightValue(x, y, z, EnumSkyBlock.Block)
|
||||
l1<<20|Seq(l2, light).max<<4
|
||||
case false => world.getLightBrightnessForSkyBlocks(x, y, z, light)
|
||||
}
|
||||
|
||||
override def getBlockMetadata(x:Int, y:Int, z:Int) = world.getBlockMetadata(x, y, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def isAirBlock(x:Int, y:Int, z:Int) = world.isAirBlock(x, y, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getBiomeGenForCoords(x:Int, z:Int) = world.getBiomeGenForCoords(x, z)
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def getHeight = world.getHeight
|
||||
|
||||
@SideOnly(Side.CLIENT)
|
||||
override def extendedLevelsInChunkCache() = world.extendedLevelsInChunkCache()
|
||||
|
||||
override def isBlockProvidingPowerTo(x:Int, y:Int, z:Int, side:Int) =
|
||||
world.isBlockProvidingPowerTo(x, y, z, side)
|
||||
|
||||
override def isSideSolid(x:Int, y:Int, z:Int, side:ForgeDirection, _default:Boolean) =
|
||||
world.isSideSolid(x, y, z, side, _default)
|
||||
}
|
||||
Regular → Executable
+1
-3
@@ -10,6 +10,7 @@ import java.util.{ArrayList => JAList, List => JList, Set => JSet, TreeSet => JT
|
||||
import codechicken.lib.vec.BlockCoord
|
||||
import cpw.mods.fml.common.ObfuscationReflectionHelper
|
||||
import mrtjp.core.vec.ModelRayTracer
|
||||
import mrtjp.mcframes.RenderFrame
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.tileentity.TileEntity
|
||||
import net.minecraft.util.Vec3
|
||||
@@ -20,9 +21,6 @@ import scala.collection.immutable.HashSet
|
||||
|
||||
object Utils
|
||||
{
|
||||
def raytraceFrame(x:Double, y:Double, z:Double, start:Vec3, end:Vec3) =
|
||||
ModelRayTracer.raytraceModel(x, y, z, start, end, RenderFrame.getFrameForRender)
|
||||
|
||||
def rescheduleTicks(world:World, blocks:Set[BlockCoord], allBlocks:Set[BlockCoord], dir:Int) = world match
|
||||
{
|
||||
case world:WorldServer =>
|
||||
|
||||
Reference in new issue
Block a user