Rewrite of library and movement engine

This commit is contained in:
MrTJP committed 2015-06-27 18:28:00 -04:00
1 parent ff3e4183d3
commit d6731ef60b
62 files changed
+2265 -2197

No files matched your search

Regular → Executable
+2
View File
@@ -64,3 +64,5 @@ white-list.txt.converted
whitelist.json
world-20140811-075700.zip
.cache
gradle.properties
-165
View File
@@ -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.
Regular → Executable
+24 -20
View File
@@ -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.
- [![Build Status](https://travis-ci.org/MrTJP/ForgeRelocation.svg)](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
View File
@@ -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
View File
@@ -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
Vendored Regular → Executable
View File
File mode changed.
Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

Regular → Executable
+2 -2
View File
@@ -1,2 +1,2 @@
v0.0.1a
- Initial alpha release
v0.0.1.2
- Initial release
+2
View File
@@ -0,0 +1,2 @@
tile.mcframes.frame.name=Frame
tile.mcframes.motor|0.name=Debug Frame Motor
+111
View File
@@ -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
Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@@ -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.
@@ -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
@@ -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
Regular → Executable
+4 -4
View File
@@ -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
View File
@@ -10,9 +10,9 @@
"credits": "",
"logoFile": "",
"screenshots": [],
"requiredMods": [ "Forge", "MrTJPCoreMod" ],
"dependencies": [ "MrTJPCoreMod" ],
"dependants" : [ "RelocationFMP" ],
"requiredMods": ["MrTJPCoreMod"],
"dependencies": [],
"dependants" : ["RelocationFMP"],
"useDependencyInformation": true
}
]
+50
View File
@@ -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);
}
@@ -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);
}
@@ -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);
}
+83
View File
@@ -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);
}
+31
View File
@@ -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);
}
+240
View File
@@ -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
View File
@@ -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)
}
}
}
+81
View File
@@ -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
}
}
+63
View File
@@ -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"
))
}
}
+178
View File
@@ -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")
}
}
+89
View File
@@ -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))
}
}
+39
View File
@@ -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;
}
}
-31
View File
@@ -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);
}
+14 -7
View File
@@ -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);
}
+15 -107
View File
@@ -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);
}
+69
View File
@@ -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();
}
View File
File mode changed.
+1 -1
View File
@@ -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._
+91
View File
@@ -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 _ =>
}
}
}
}
+67
View File
@@ -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()
}
}
-176
View File
@@ -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)
}
}
}
-62
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}
}
+100
View File
@@ -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
}
}
+175
View File
@@ -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
})
}
}
+19 -20
View File
@@ -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)
}
}
-203
View File
@@ -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)
}
-207
View File
@@ -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)
}
-371
View File
@@ -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
}
+321
View File
@@ -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)
}
}
}
-39
View File
@@ -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
+12 -134
View File
@@ -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
+131 -111
View File
@@ -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
View File
@@ -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 =>