Compare commits

..

19 Commits

Author SHA1 Message Date
彼梦Archi 4ebfcec051 feat: Add Chinese handbook translation (by ArchiDreamZ) (#865)
has been used by many people and is guaranteed to be correct.
2025-03-28 22:05:55 +01:00
ArchiDreamZ 0c2da4fb81 Fixed a crash when switching spells (#839)
Switching spells causes ArrayIndexOutOfBoundsException: -1 when the next spell is empty.I made a simple fix
2024-03-27 22:17:46 +01:00
glowredman 2655d5c2ae [1.7.10] Fix incompatibility with unofficial NEI (#823)
* Update buildscript

Gradle update done via `gradlew wrapper --gradle-version=4.4.1`

* Move NEI around GUI
2024-03-27 22:17:01 +01:00
ArchiDreamZ 4cbfafaf6d Add Simplified Chinese translation by ArchiDreamZ (#840)
Add Simplified Chinese translation
I fixed a very common crash in another pull request, hope you can update again
2024-03-27 22:15:33 +01:00
WinDanesz 98997d90ac Fake players don't drop spell books (#818)
Magic shouldn't be automated

Co-authored-by: DrParadox7 <47131096+DrParadox7@users.noreply.github.com>
2022-07-09 23:29:24 +02:00
Electroblob 09f858af20 Replace branch with old 1.7.10 code and assets 2018-06-07 11:58:24 +01:00
Electroblob 78b61cf573 Update README.md 2018-04-09 23:09:22 +01:00
Electroblob bf223ed5ab Update README.md 2018-03-09 10:04:14 +00:00
Electroblob 93b6b41a24 Update README.md 2018-02-26 22:54:03 +00:00
Electroblob 79a5cc4a67 Update ru_RU.lang (credit: VilagVil) 2018-02-25 18:21:30 +00:00
Electroblob f4d7ba6030 Fix inability to upgrade non-elemental wands using tomes of arcana 2018-02-18 23:33:54 +00:00
Electroblob a4695bcce1 Fix curseforge issue #30, where the game would crash when casting mind control on a mob that already had the mind trick status effect 2018-02-18 23:32:54 +00:00
Electroblob 52d12c0c02 Fix curseforge issue #28, where keybinds would be reset on game launch 2018-02-18 23:31:42 +00:00
Electroblob 56861b1ff5 Add coordinate fix from 1.11.2 branch, see 2dd52ce 2018-02-18 23:29:47 +00:00
Electroblob d2129ba256 Update CREDITS.md
Undoes previous commit, was made on the wrong branch
2018-02-13 16:28:32 +00:00
Electroblob 00a6b34310 Update CREDITS.md 2018-02-13 16:26:17 +00:00
Electroblob a2f1463939 Update README.md 2018-02-11 18:27:57 +00:00
Electroblob a9dbf47c4a Fix sparkle particles not being animated (this was accidentally disabled when testing a new feature) 2018-02-10 18:23:25 +00:00
Electroblob 2c8435392e Update version number 2018-02-10 18:22:49 +00:00
1045 changed files with 38177 additions and 38455 deletions
-2
View File
@@ -1,2 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
-1
View File
@@ -21,5 +21,4 @@ build
eclipse
run
misc
libs
Thumbs.db
+2 -10
View File
@@ -1,8 +1,8 @@
# Credits
Electroblob's Wizardry
Version 4.1.4
For Minecraft 1.12.2
Version 2.1.0
For Minecraft 1.10.2
Designed, coded and textured by Electroblob
@@ -12,17 +12,9 @@ Thanks also to the Minecraft modding community, which always has an answer to my
In addition, I'd like to thank the following individuals for their contributions to the mod:
#### Code
- Corail31
- 12foo
- Shadows-of-Fire
- HellFirePvP
#### Translations
- Russian: VilagVil
- Spanish and Mexican Spanish: MadWrist
- Chinese: ZHENGLOC and dragon-evol
Lightning ray sound effect from OhhWowProductions
+2 -4
View File
@@ -1,7 +1,5 @@
Please read the [guide for contributing](https://github.com/Electroblob77/Wizardry/blob/1.12.2/guide_for_contributing.md) before posting.
Minecraft version: 1.12.2 [change as necessary]
Wizardry version: 4.1.4 [change as necessary]
Minecraft version: 1.10.2 [change as necessary]
Wizardry version: 2.1.0 [change as necessary]
Environment: Singleplayer/LAN game/Server [delete as necessary]
Issue details: [describe what you were doing when the issue occurred, what went wrong, what you expected to happen, etc.]
+2 -2
View File
@@ -1,7 +1,7 @@
# License
This repository is copyright © Electroblob 2018. The following license is provided to allow you to creatively contribute to and improve the repository.
This license applies only to the source code, assets and wiki pages present in this repository. The compiled mod (available at https://minecraft.curseforge.com/projects/electroblobs-wizardry) comes under its own separate license, see the aforementioned webpage for details.
This license applies only to the source code and assets present in this repository. The compiled mod (available at https://minecraft.curseforge.com/projects/electroblobs-wizardry) comes under its own separate license, see the aforementioned webpage for details.
TL;DR: Do what you want with this repo on Github, but ask me first if you want to put it anywhere else or publish your version. Don't try and make money off the repo or anything in it. I'm not responsible if the code breaks things, and if you help me out by submitting a PR, I can use and modify the contents of that PR as long as I give you credit. (This brief summary is non-binding and does not override or replace the full license below.)
@@ -17,7 +17,7 @@ TL;DR: Do what you want with this repo on Github, but ask me first if you want t
'Electroblob's Wizardry', 'Wizardry', 'the mod' - The Minecraft modification Electroblob's Wizardry
'Repository' - This repository on Github, containing this license, the wiki, other informational files, configurations, code and assets which are part of Electroblob's Wizardry
'Repository' - This repository on Github, containing this license, other informational files, configurations, code and assets which are part of Electroblob's Wizardry
'Curseforge' - The webpage https://minecraft.curseforge.com/projects/electroblobs-wizardry
+42 -45
View File
@@ -1,60 +1,57 @@
buildscript {
repositories {
jcenter()
maven { url = "http://files.minecraftforge.net/maven" }
mavenCentral()
maven {
name = "forge"
url = "https://maven.minecraftforge.net/"
}
maven {
name = "sonatype"
url = "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT'
}
}
apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'forge'
version = " 4.1.4 - MC 1.12.2"
group= "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
version = " 1.1.5 - MC 1.7.10"
group = "electroblob.wizardry"// http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "Electroblob's Wizardry "
sourceCompatibility = targetCompatibility = "1.8" // Need this here so eclipse task generates correctly.
compileJava {
sourceCompatibility = targetCompatibility = "1.8"
minecraft {
version = "1.7.10-10.13.4.1614-1.7.10"
runDir = "eclipse"
}
minecraft {
version = "1.12.2-14.23.2.2611"
runDir = "run"
// the mappings can be changed at any time, and must be in the following format.
// snapshot_YYYYMMDD snapshot are built nightly.
// stable_# stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work.
// simply re-run your setup task after changing the mappings to update your workspace.
mappings = "stable_39"
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
task deobfJar(type: Jar) { // Generate deobfuscated
from sourceSets.main.output
classifier = 'deobf'
}
task sourceJar(type: Jar) { // Generate sources
from sourceSets.main.allSource
classifier = 'sources'
}
tasks.build.dependsOn('sourceJar', 'deobfJar')
artifacts {
archives deobfJar
archives sourceJar
archives jar
}
repositories {
maven {
name 'ChickenBones maven'
url 'https://chickenbones.net/maven/'
}
}
dependencies {
// you may put jars on which you depend on in ./libs
// or you may define them like so..
//compile "some.group:artifact:version:classifier"
//compile "some.group:artifact:version"
// real examples
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
//compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
// the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
//provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
// except that these dependencies get remapped to your current MCP mappings
//deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
//deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// for more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
compileOnly 'codechicken:NotEnoughItems:1.7.10-1.0.5.120:dev'
}
processResources {
@@ -65,12 +62,12 @@ processResources {
// replace stuff in mcmod.info, nothing else
from(sourceSets.main.resources.srcDirs) {
include 'mcmod.info'
// replace version and mcversion
expand 'version':project.version, 'mcversion':project.minecraft.version
}
// copy everything else except the mcmod.info
// copy everything else, thats not the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
-3
View File
@@ -1,3 +0,0 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G
Binary file not shown.
+1 -2
View File
@@ -1,6 +1,5 @@
#Mon Sep 14 12:28:28 PDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
Vendored
+59 -51
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
@@ -6,47 +6,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -61,9 +20,49 @@ while [ -h "$PRG" ] ; do
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >&-
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -90,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -114,6 +113,7 @@ fi
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
Vendored
+4 -10
View File
@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
+1 -14
View File
@@ -2,20 +2,7 @@
## Submitting an issue
When submitting an issue, I would be grateful if you could follow these few guidelines:
- First and foremost, please check your issue hasn't already been posted. The issue tracker is searchable, so try typing in a few keywords and see if anything comes up.
- Please stick to the issue template, it's there to help you provide the right information so I can fix the problem more easily. If you're not sure what to put for anything, that's ok, just leave it as it is.
- Please give me as much information about the issue as you can, but keep it relevant. "This is really annoying me and my friend" does not help me fix the problem!
- There's no need to put 'tags' in square brackets in the issue title, I'll put proper github issue tags on it which will also help organise it. You can use them to search for issues too!
- Don't close an issue unless it has actually been fixed or is no longer relevant - otherwise I might not end up fixing it at all! Usually I'll take care of closing issues anyway, so you don't have to worry about it.
- Most importantly, use gist or pastebin to post crash reports. Do not paste the entire crash report inline, not even in a code block!
> If you've got a git account (which you do, if you're posting an issue) you can access gist, and pastebin doesn't require an account at all, so there's no excuse!
When submitting an issue, please stick to the issue template. Please give me as much information about the issue as you can, but keep it relevant. "This is really annoying me and my friend" does not help me fix the problem! Most importantly, use gist or pastebin to post crash reports.
## Submitting a PR
Binary file not shown.
Binary file not shown.
@@ -1,213 +1,203 @@
package electroblob.wizardry;
import electroblob.wizardry.item.ItemSpectralBow;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import cpw.mods.fml.common.FMLCommonHandler;
import electroblob.wizardry.packet.PacketCastContinuousSpell;
import electroblob.wizardry.packet.PacketCastSpell;
import electroblob.wizardry.packet.PacketClairvoyance;
import electroblob.wizardry.packet.PacketGlyphData;
import electroblob.wizardry.packet.PacketNPCCastSpell.Message;
import electroblob.wizardry.packet.PacketPlayerSync;
import electroblob.wizardry.packet.PacketTransportation;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.WizardryParticleType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.Block;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.translation.I18n;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.StatCollector;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Property;
/**
* The common proxy for wizardry, serving the usual purpose of dealing with all things that need to be handled
* differently on the client and the server. A lot of the methods here appear to do absolutely nothing; this is because
* they do client-only things which are only handled in the client proxy.
*
* @see {@link electroblob.wizardry.client.ClientProxy}
* @author Electroblob
* @since Wizardry 1.0
*/
@SuppressWarnings("deprecation")
/** The common proxy for wizardry, serving the usual purpose of dealing with all things that need to be handled
* differently on the client and the server. A lot of the methods here appear to do absolutely nothing; this is
* because they do client-only things which are only handled in the client proxy.
* @see {@link electroblob.wizardry.client.ClientProxy} */
public class CommonProxy {
// SECTION Registry
// ===============================================================================================================
public void registerRenderers(){
}
public void initialiseLayers(){
}
public void registerKeyBindings(){
}
/** Used to store IExtendedEntityProperties data temporarily between player death and respawn */
private static final Map<String, NBTTagCompound> extendedEntityData = new HashMap<String, NBTTagCompound>();
public void registerRenderers(){}
public void registerKeyBindings(){}
public void registerSpellHUD(){}
public net.minecraft.client.model.ModelBiped getWizardArmourModel(){
public ModelBiped getWizardArmourModel(){
return null;
}
/**
* Adds an entity's custom data to the map for temporary storage
* @param compound An NBT Tag Compound that stores the IExtendedEntityProperties data only
*/
public static void storeEntityData(String name, NBTTagCompound compound){
extendedEntityData.put(name, compound);
}
public void initGuiBits(){}
/**
* Removes the compound from the map and returns the NBT tag stored for name or null if none exists
*/
public static NBTTagCompound getEntityData(String name){
return extendedEntityData.remove(name);
}
public double getPlayerEyesPos(EntityPlayer player){
return player.posY + player.eyeHeight;
}
/** Gets the absolute coordinates of the tip of the wand belonging to the given entity. If this is a client in
* first person view, the coordinates will instead be the entity's position + 1.2. */
public Vec3 getWandTipPosition(EntityLivingBase entity){
// 0.7 forwards, 0.4 to the right, and 1.35 upwards.
double x = entity.posX - 0.7*Math.sin(Math.toRadians(entity.renderYawOffset)) - 0.4*Math.cos(Math.toRadians(entity.renderYawOffset));
double y = entity.boundingBox.minY + 1.35;
double z = entity.posZ + 0.7*Math.cos(Math.toRadians(entity.renderYawOffset)) - 0.4*Math.sin(Math.toRadians(entity.renderYawOffset));
return Vec3.createVectorHelper(x, y, z);
}
/**
* Spawns a custom particle of the specified type.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
* @param r Red component of particle colour
* @param g Red component of particle colour
* @param b Red component of particle colour
* @param doGravity Whether the particle is affected by gravity (only affects SPARKLE at the moment)
* @param radius The radius of the particle's motion, for cirular motion particles
*/
public void spawnParticle(EnumParticleType type, World world, double x, double y, double z, double velX, double velY, double velZ, int maxAge, float r, float g, float b, boolean doGravity, double radius){
// Does nothing since particles are client-side only
}
/** Spawns a custom particle of the specified type. doGravity defaults to false and radius defaults to 0.
* Note that some of these settings may not affect the particle; some particles are always affected by
* gravity, for instance.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
* @param r Red component of particle colour (unless this is a MAGIC_FIRE particle, in which case this is the scale)
* @param g Red component of particle colour
* @param b Red component of particle colour
*/
public void spawnParticle(EnumParticleType type, World world, double x, double y, double z, double velX, double velY, double velZ, int maxAge, float r, float g, float b){
this.spawnParticle(type, world, x, y, z, velX, velY, velZ, maxAge, r, g, b, false, 0);
}
/** Spawns a custom particle of the specified type. Colour defaults to white, doGravity defaults to false and radius
* defaults to 0. Note that some of these settings may not affect the particle; some particles are always affected by
* gravity, for instance.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
*/
public void spawnParticle(EnumParticleType type, World world, double x, double y, double z, double velX, double velY, double velZ, int maxAge){
this.spawnParticle(type, world, x, y, z, velX, velY, velZ, maxAge, 1, 1, 1, false, 0);
}
public void spawnDigParticle(World world, double x, double y, double z, double velX, double velY, double velZ, Block block){}
// SECTION Particles
// ===============================================================================================================
/**
* Spawns a custom particle of the specified type.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
* @param r Red component of particle colour; will be clamped to between 0 and 1
* @param g Red component of particle colour; will be clamped to between 0 and 1
* @param b Red component of particle colour; will be clamped to between 0 and 1
* @param doGravity Whether the particle is affected by gravity (only affects SPARKLE at the moment)
* @param radius The radius of the particle's motion, for cirular motion particles
*/
public void spawnParticle(WizardryParticleType type, World world, double x, double y, double z, double velX,
double velY, double velZ, int maxAge, float r, float g, float b, boolean doGravity, double radius){
// Does nothing since particles are client-side only
public void spawnTornadoParticle(World world, double x, double y, double z, double velX, double velZ, double radius, int maxAge, Block block, int metadata){}
/** Plays a sound which moves with the given entity.
*
* @param entity The source of the sound
* @param soundName String resource path of the sound
* @param volume Volume relative to 1
* @param pitch Pitch relative to 1
* @param repeat Whether to repeat the sound for as long as the entity is alive (or until stopped manually)
*/
public void playMovingSound(Entity entity, String soundName, float volume, float pitch, boolean repeat){}
public void handleCastSpellPacket(PacketCastSpell.Message message){}
public double getWandDisplayDamage(ItemStack stack){
return 1.0d;
}
public int getConjuredItemDisplayDamage(ItemStack stack){
return 0;
}
/**
* Spawns a custom particle of the specified type. doGravity defaults to false and radius defaults to 0. Note that
* some of these settings may not affect the particle; some particles are always affected by gravity, for instance.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
* @param r Red component of particle colour; will be clamped to between 0 and 1 (unless this is a MAGIC_FIRE
* particle, in which case this is the scale)
* @param g Red component of particle colour; will be clamped to between 0 and 1
* @param b Red component of particle colour; will be clamped to between 0 and 1
*/
public void spawnParticle(WizardryParticleType type, World world, double x, double y, double z, double velX,
double velY, double velZ, int maxAge, float r, float g, float b){
this.spawnParticle(type, world, x, y, z, velX, velY, velZ, maxAge, r, g, b, false, 0);
public void registerEventHandlers(){
MinecraftForge.EVENT_BUS.register(new WizardryEventHandler());
}
/**
* Spawns a custom particle of the specified type. Colour defaults to white, doGravity defaults to false and radius
* defaults to 0. Note that some of these settings may not affect the particle; some particles are always affected
* by gravity, for instance.
*
* @param type EnumParticleType of the particle
* @param world Reference to the World object
* @param x Particle x position
* @param y Particle y position
* @param z Particle z position
* @param velX Particle x velocity
* @param velY Particle y velocity
* @param velZ Particle z velocity
* @param maxAge Lifetime of the particle in ticks
*/
public void spawnParticle(WizardryParticleType type, World world, double x, double y, double z, double velX,
double velY, double velZ, int maxAge){
this.spawnParticle(type, world, x, y, z, velX, velY, velZ, maxAge, 1, 1, 1, false, 0);
}
public void handleTransportationPacket(PacketTransportation.Message message){}
public void spawnTornadoParticle(World world, double x, double y, double z, double velX, double velZ, double radius,
int maxAge, IBlockState block, BlockPos pos){
}
// SECTION Items
// ===============================================================================================================
public net.minecraft.client.gui.FontRenderer getFontRenderer(ItemStack stack){
public FontRenderer getFontRenderer(ItemStack stack) {
return null;
}
/**
* Returns the translated name of the scroll, taking spell discovery into account. If, for some reason, this gets
/** Returns the translated name of the scroll, taking spell discovery into account. If, for some reason, this gets
* called server-side, it uses the deprecated server version of I18n, with a warning. Since any likely server-side
* use of this method will be for text-based logic purposes (like Bibliocraft's book checking system), and since no
* particular player instance can be accessed, spell discovery is ignored.
*/
* particular player instance can be accessed, spell discovery is ignored. */
public String getScrollDisplayName(ItemStack scroll){
// I have now learnt that the server side I18n always translates to the default en_US, so I could just return
// a hardcoded name in English instead.
// Commented because it's just really annoying.
//Wizardry.logger.info("A mod has called ItemScroll#getItemStackDisplayName from the server side. Using the"
// + "deprecated server-side translation methods as a fallback.");
// Displays [Empty slot] if spell is continuous.
Spell spell = Spell.get(scroll.getItemDamage());
if(spell.isContinuous) spell = Spells.none;
return I18n.translateToLocalFormatted("item." + Wizardry.MODID + ":scroll.name",
I18n.translateToLocal("spell." + spell.getUnlocalisedName())).trim();
if(spell.isContinuous) spell = WizardryRegistry.none;
return StatCollector.translateToLocalFormatted("item.scroll.name", StatCollector.translateToLocal("spell." + spell.getUnlocalisedName())).trim();
}
public double getConjuredBowDurability(ItemStack stack){
return ((ItemSpectralBow)WizardryItems.spectral_bow).getDefaultDurabilityForDisplay(stack);
}
public void handlePlayerSyncPacket(PacketPlayerSync.Message message){}
// SECTION Packet Handlers
// ===============================================================================================================
public void handleGlyphDataPacket(PacketGlyphData.Message message){}
public void handlePlayerSyncPacket(PacketPlayerSync.Message message){
}
public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){}
public void handleGlyphDataPacket(PacketGlyphData.Message message){
}
public void setToNumberSliderEntry(Property property){}
public void handleCastSpellPacket(PacketCastSpell.Message message){
}
public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){
}
public void handleNPCCastSpellPacket(Message message){
}
public void handleTransportationPacket(PacketTransportation.Message message){
}
public void handleClairvoyancePacket(PacketClairvoyance.Message message){
}
// SECTION Misc
// ===============================================================================================================
public void setToNumberSliderEntry(Property property){
}
// public void setToEntityNameEntry(Property property){}
/**
* Plays a sound which moves with the given entity.
*
* @param entity The source of the sound
* @param sound The SoundEvent to play
* @param volume Volume relative to 1
* @param pitch Pitch relative to 1
* @param repeat Whether to repeat the sound for as long as the entity is alive (or until stopped manually)
*/
public void playMovingSound(Entity entity, SoundEvent sound, float volume, float pitch, boolean repeat){
}
/**
* Gets the client side world using Minecraft.getMinecraft().world. <b>Only to be called client side!</b> Returns
* null on the server side.
*/
public World getTheWorld(){
return null;
}
public void handleClairvoyancePacket(PacketClairvoyance.Message message){}
}
@@ -0,0 +1,39 @@
package electroblob.wizardry;
import net.minecraft.util.StatCollector;
public enum EnumElement {
MAGIC("\u00A77", "simple"),
FIRE("\u00A74", "fire"),
ICE("\u00A7b", "ice"),
LIGHTNING("\u00A73", "lightning"),
NECROMANCY("\u00A75", "necromancy"),
EARTH("\u00A72", "earth"),
SORCERY("\u00A7a", "sorcery"),
HEALING("\u00A7e", "healing");
/** Display colour for this element */
public final String colour;
/** Unlocalised name for this element */
public final String unlocalisedName;
private EnumElement(String colour, String name){
this.colour = colour;
this.unlocalisedName = name;
}
public EnumElement get(int id){
return this.values()[id];
}
/** Returns the translated display name of this element, without formatting. */
public String getDisplayName() {
return StatCollector.translateToLocal("element." + unlocalisedName);
}
/** Returns the translated display name for wizards of this element, shown in the trading GUI */
public String getWizardName() {
return StatCollector.translateToLocal("element." + unlocalisedName + ".wizard");
}
}
@@ -0,0 +1,16 @@
package electroblob.wizardry;
public enum EnumParticleType {
BLIZZARD,
BRIGHT_DUST,
DARK_MAGIC,
DUST,
ICE,
LEAF,
MAGIC_BUBBLE,
MAGIC_FIRE,
PATH,
SNOW,
SPARK,
SPARKLE
}
@@ -0,0 +1,21 @@
package electroblob.wizardry;
import net.minecraft.util.StatCollector;
public enum EnumSpellType {
ATTACK("attack"),
DEFENCE("defence"),
UTILITY("utility"),
MINION("minion");
private final String unlocalisedName;
EnumSpellType(String name){
this.unlocalisedName = name;
}
public String getDisplayName() {
return StatCollector.translateToLocal("spelltype." + unlocalisedName);
}
}
@@ -0,0 +1,38 @@
package electroblob.wizardry;
import net.minecraft.util.StatCollector;
public enum EnumTier {
BASIC(700, 3, "\u00A7f", "basic"),
APPRENTICE(1000, 4, "\u00A7b", "apprentice"),
ADVANCED(1500, 5, "\u00A71", "advanced"),
MASTER(2500, 6, "\u00A75", "master");
/** Maximum mana a wand of this tier can store. */
public final int maxCharge;
/** Just an ordinal. Shouldn't really be needed but no point changing it now. */
public final int level;
/** The maximum number of upgrades that can be applied to a wand of this tier. */
public final int upgradeLimit;
/** The colour of text associated with this tier */
public final String colour;
private final String unlocalisedName;
private EnumTier(int maxCharge, int upgradeLimit, String colour, String name){
this.maxCharge = maxCharge;
this.level = ordinal();
this.upgradeLimit = upgradeLimit;
this.colour = colour;
this.unlocalisedName = name;
}
public String getDisplayName() {
return StatCollector.translateToLocal("tier." + unlocalisedName);
}
public String getDisplayNameWithFormatting() {
return this.colour + StatCollector.translateToLocal("tier." + unlocalisedName);
}
}
@@ -0,0 +1,485 @@
package electroblob.wizardry;
import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Random;
import java.util.UUID;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import electroblob.wizardry.MagicDamage.DamageType;
import electroblob.wizardry.entity.EntityShield;
import electroblob.wizardry.entity.living.EntitySummonedCreature;
import electroblob.wizardry.packet.PacketCastContinuousSpell;
import electroblob.wizardry.packet.PacketPlayerSync;
import electroblob.wizardry.packet.PacketTransportation;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.spell.None;
import electroblob.wizardry.spell.Spell;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.world.World;
import net.minecraftforge.common.IExtendedEntityProperties;
import net.minecraftforge.common.util.Constants.NBT;
/** IExtendedEntityProperties for players. Everything player-data-related that is needed by wizardry is handled here,
* including the ADS, soulbinding, conjured items, summoned wolves and horses, transportation and clairvoyance. */
public class ExtendedPlayer implements IExtendedEntityProperties {
public final static String name = "WizardryExtendedPlayer";
private final EntityPlayer player;
public int damageToApply;
// These were originally done using the item damage directly, but this caused the annoying re-equip animation
// to keep happening so they were moved to here instead.
public int conjuredSwordDuration;
public int conjuredPickaxeDuration;
public int conjuredBowDuration;
public int conjuredArmourDuration;
public int flamingAxeDuration;
public int frostAxeDuration;
public int magicWeaponDuration;
public int flamingWeaponDuration;
public int freezingWeaponDuration;
public boolean hasSpiritWolf;
public boolean hasSpiritHorse;
/** Whether this player is currently casting a continuous spell via commands. Not saved over world reload
* and reset on player death. */
private Spell currentlyCasting;
/** The time for which this player has been casting a continuous spell via commands. Increments by 1 each tick.
* Not saved over world reload and reset on player death. */
private int castingTick;
/** The damage multiplier for the current continuous spell cast via commands. Not saved over world reload and
* reset on player death. */
private float spellDamageMultiplier;
/** The range multiplier for the current continuous spell cast via commands. Not saved over world reload and
* reset on player death. */
private float spellRangeMultiplier;
/** The duration multiplier for the current continuous spell cast via commands. Not saved over world reload and
* reset on player death. */
private float spellDurationMultiplier;
/** The blast multiplier for the current continuous spell cast via commands. Not saved over world reload and
* reset on player death. */
private float spellBlastMultiplier;
/** Coordinate for the saved transportation stone location. Will be -1 if no location is saved. */
public int transportX, transportY, transportZ;
/** Dimension id which the saved stone circle is in. */
public int transportDimension;
/** Time left until the player teleports under the effect of transportation */
public int tpTimer;
/** Coordinate for the saved clairvoyance location. Will be -1 if no location is saved. */
public int clairvoyanceX, clairvoyanceY, clairvoyanceZ;
/** Dimension id which the saved clairvoyance point is in. */
public int clairvoyanceDimension;
public EntityShield shield;
public WeakReference<EntitySummonedCreature> selectedMinion;
public HashSet<Spell> spellsDiscovered;
private HashSet<UUID> allies;
/** List of usernames of this player's allies. May not be accurate 100% of the time. This is here so that a player
* can view the usernames of their allies even when those allies are not online.
* <b> Do not use this for any other purpose than displaying the names! */
public HashSet<String> allyNames;
private HashSet<UUID> soulboundCreatures;
public ExtendedPlayer(EntityPlayer player){
this.player = player;
this.damageToApply = 0;
this.conjuredSwordDuration = 0;
this.conjuredPickaxeDuration = 0;
this.conjuredBowDuration = 0;
this.conjuredArmourDuration = 0;
this.flamingAxeDuration = 0;
this.frostAxeDuration = 0;
this.magicWeaponDuration = 0;
this.flamingWeaponDuration = 0;
this.freezingWeaponDuration = 0;
this.spellsDiscovered = new HashSet<Spell>();
// All players can recognise magic missile. This is not done using discoverSpell because that seems to cause
// a crash on load occasionally (probably something to do with achievements being initalised)
this.spellsDiscovered.add(WizardryRegistry.magicMissile);
this.hasSpiritWolf = false;
this.hasSpiritHorse = false;
this.currentlyCasting = WizardryRegistry.none;
this.spellDamageMultiplier = 1;
this.spellRangeMultiplier = 1;
this.spellDurationMultiplier = 1;
this.spellBlastMultiplier = 1;
this.castingTick = 0;
this.transportX = -1;
this.transportY = -1;
this.transportZ = -1;
this.transportDimension = 0;
this.clairvoyanceX = -1;
this.clairvoyanceY = -1;
this.clairvoyanceZ = -1;
this.clairvoyanceDimension = 0;
this.tpTimer = 0;
this.allies = new HashSet<UUID>();
this.allyNames = new HashSet<String>();
this.soulboundCreatures = new HashSet<UUID>();
}
public boolean hasSpellBeenDiscovered(Spell spell){
return spellsDiscovered.contains(spell) || spell instanceof None;
}
/**
* Adds the spell to the list of discovered spells for this player. Automatically takes into account
* whether the spell has been discovered. Use this method rather than adding directly to the list
* because it handles the mage of all trades achievement.
* @param spell
*/
public void discoverSpell(Spell spell){
if(spellsDiscovered == null){
spellsDiscovered = new HashSet<Spell>();
}
if(!(spell instanceof None)){
spellsDiscovered.add(spell);
}
if(spellsDiscovered.containsAll(Spell.getSpells(Spell.enabledSpells))){
this.player.triggerAchievement(Wizardry.allSpells);
}
for(EnumElement element : EnumElement.values()){
if(element != EnumElement.MAGIC && spellsDiscovered.containsAll(Spell.getSpells(new Spell.TierElementFilter(null, element)))){
this.player.triggerAchievement(Wizardry.elementMaster);
}
}
}
/** Sets the player's saved transportation stone location. */
public void setStoneLocation(int x, int y, int z, int dimensionID){
this.transportX = x;
this.transportY = y;
this.transportZ = z;
this.transportDimension = dimensionID;
}
/** Sets the player's saved clairvoyance location. */
public void setClairvoyancePoint(int x, int y, int z, int dimensionID){
this.clairvoyanceX = x;
this.clairvoyanceY = y;
this.clairvoyanceZ = z;
this.clairvoyanceDimension = dimensionID;
}
/** Adds the given player to the list of allies belonging to the associated player, or removes the player if
* they are already in the list of allies. Returns true if the player was added, false if they were removed. */
public boolean toggleAlly(EntityPlayer player){
if(this.isPlayerAlly(player)){
this.allies.remove(player.getUniqueID());
// The remove method uses .equals() rather than == so this will work fine.
this.allyNames.remove(player.getCommandSenderName());
return false;
}else{
this.allies.add(player.getUniqueID());
this.allyNames.add(player.getCommandSenderName());
return true;
}
}
/** Returns whether the given player is in this player's list of allies, or is on the same team as this player. */
public boolean isPlayerAlly(EntityPlayer player){
return this.allies.contains(player.getUniqueID()) || this.player.isOnSameTeam(player);
}
/** Adds the given entity to this player's list of soulbound creatures, and returns whether it succeeded. */
public boolean soulbind(EntityLivingBase target){
return this.soulboundCreatures.add(target.getUniqueID());
}
/** Returns whether the given entity has been soulbound to this player. */
public boolean isCreatureSoulbound(EntityPlayer target){
return this.soulboundCreatures.contains(target.getUniqueID());
}
/** Damages all creatures soulbound to this player by the given amount, and removes from the list any that no
* longer exist. */
public void damageAllSoulboundCreatures(float damage){
for(Iterator<UUID> iterator = this.soulboundCreatures.iterator(); iterator.hasNext();){
Entity entity = WizardryUtilities.getEntityByUUID(this.player.worldObj, iterator.next());
if(entity == null) iterator.remove();
if(entity instanceof EntityLivingBase){
if(entity.attackEntityFrom(MagicDamage.causeDirectMagicDamage(this.player, DamageType.MAGIC), damage)){
// Sound only plays if the damage succeeds
player.worldObj.playSoundAtEntity(entity, "mob.wither.hurt", 1.0F, player.worldObj.rand.nextFloat() * 0.2F + 1.0F);
}
}
}
}
/** Starts casting the given spell with the given modifiers. */
public void startCastingContinuousSpell(Spell spell, float damageMultiplier, float rangeMultiplier, float durationMultiplier, float blastMultiplier){
this.currentlyCasting = spell;
this.spellDamageMultiplier = damageMultiplier;
this.spellRangeMultiplier = rangeMultiplier;
this.spellDurationMultiplier = durationMultiplier;
this.spellBlastMultiplier = blastMultiplier;
if(!this.player.worldObj.isRemote){
PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(), spell.id(), damageMultiplier, rangeMultiplier, blastMultiplier);
WizardryPacketHandler.net.sendToDimension(message, this.player.worldObj.provider.dimensionId);
}
}
/** Stops casting the current spell. */
public void stopCastingContinuousSpell(){
this.currentlyCasting = WizardryRegistry.none;
this.castingTick = 0;
this.spellDamageMultiplier = 1;
this.spellRangeMultiplier = 1;
this.spellDurationMultiplier = 1;
this.spellBlastMultiplier = 1;
if(!this.player.worldObj.isRemote){
PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(), WizardryRegistry.none.id(), 1, 1, 1);
WizardryPacketHandler.net.sendToDimension(message, this.player.worldObj.provider.dimensionId);
}
}
/** Returns whether this player is currently casting a continuous spell via commands. */
public boolean isCasting(){
return this.currentlyCasting != null && this.currentlyCasting != WizardryRegistry.none;
}
/** Returns the continuous spell this player is currently casting via commands, or the 'none' spell if they aren't
* casting anything. */
public Spell currentlyCasting(){
return currentlyCasting;
}
/** Called from the event handler each time the associated player is updated. */
public void update(EntityPlayer entityplayer){
if(this.selectedMinion != null && this.selectedMinion.get() == null) this.selectedMinion = null;
Random random = entityplayer.worldObj.rand;
// Annoyingly, it seems that the armour inventory is dealt with completely separately.
if(entityplayer.inventory.hasItem(Wizardry.spectralHelmet)
|| entityplayer.inventory.hasItem(Wizardry.spectralChestplate)
|| entityplayer.inventory.hasItem(Wizardry.spectralLeggings)
|| entityplayer.inventory.hasItem(Wizardry.spectralBoots)
|| (entityplayer.inventory.armorInventory[3] != null && entityplayer.inventory.armorInventory[3].getItem() == Wizardry.spectralHelmet)
|| (entityplayer.inventory.armorInventory[2] != null && entityplayer.inventory.armorInventory[2].getItem() == Wizardry.spectralChestplate)
|| (entityplayer.inventory.armorInventory[1] != null && entityplayer.inventory.armorInventory[1].getItem() == Wizardry.spectralLeggings)
|| (entityplayer.inventory.armorInventory[0] != null && entityplayer.inventory.armorInventory[0].getItem() == Wizardry.spectralBoots)){
this.conjuredArmourDuration++;
}else{
this.conjuredArmourDuration = 0;
}
if(!entityplayer.worldObj.isRemote){
if(tpTimer == 1){
entityplayer.setPositionAndUpdate(this.transportX + 0.5, this.transportY, this.transportZ + 0.5);
entityplayer.worldObj.playSoundAtEntity(entityplayer, "portal.travel", 1.0f, 1.0f);
entityplayer.addPotionEffect(new PotionEffect(Potion.blindness.id, 50, 0));
IMessage msg = new PacketTransportation.Message(entityplayer.getEntityId());
WizardryPacketHandler.net.sendToDimension(msg, entityplayer.worldObj.provider.dimensionId);
}
if(tpTimer > 0){
tpTimer--;
}
}
if(this.currentlyCasting != null && this.currentlyCasting.isContinuous){
this.currentlyCasting.cast(player.worldObj, player, castingTick++, spellDamageMultiplier, spellRangeMultiplier, spellDurationMultiplier, spellBlastMultiplier);
}else{
this.castingTick = 0;
}
}
/** Called from the event handler each time the associated player dies. Used to reset any variables that shouldn't
* persist over player death. */
public void onPlayerDeath(){
this.conjuredSwordDuration = 0;
this.conjuredPickaxeDuration = 0;
this.conjuredBowDuration = 0;
this.conjuredArmourDuration = 0;
this.flamingAxeDuration = 0;
this.frostAxeDuration = 0;
this.magicWeaponDuration = 0;
this.flamingWeaponDuration = 0;
this.freezingWeaponDuration = 0;
// Death cancels transportation spell.
this.tpTimer = 0;
this.soulboundCreatures = new HashSet<UUID>();
this.currentlyCasting = WizardryRegistry.none;
this.castingTick = 0;
this.spellDamageMultiplier = 1;
this.spellRangeMultiplier = 1;
this.spellDurationMultiplier = 1;
this.spellBlastMultiplier = 1;
}
/**
* Returns the string key to be used when saving and loading the extended player data on respawn.
*/
public static String getSaveKey(EntityPlayer player) {
return player.getUniqueID().toString() + ":" + name;
}
/**
* Used to register these extended properties for the player during EntityConstructing event
* This method is for convenience only; it will make your code look nicer
*/
public static final void register(EntityPlayer player){
player.registerExtendedProperties(ExtendedPlayer.name, new ExtendedPlayer(player));
}
/**
* Returns the ExtendedPlayer properties for the specified player.
*/
public static final ExtendedPlayer get(EntityPlayer player){
return (ExtendedPlayer) player.getExtendedProperties(name);
}
/** Sends a packet to this player's client to synchronise necessary information. Only called server side. */
public void sync(){
if(this.player instanceof EntityPlayerMP){
int id = -1;
if(this.selectedMinion != null && this.selectedMinion.get() != null) id = this.selectedMinion.get().getEntityId();
IMessage msg = new PacketPlayerSync.Message(this.spellsDiscovered, id);
WizardryPacketHandler.net.sendTo(msg, (EntityPlayerMP)this.player);
}
}
@Override
public void saveNBTData(NBTTagCompound compound) {
// NBTTagCompound is for Maps, NBTTagList is for Lists/Sets
NBTTagCompound properties = new NBTTagCompound();
properties.setInteger("conjuredSwordDuration", this.conjuredSwordDuration);
properties.setInteger("conjuredPickaxeDuration", this.conjuredPickaxeDuration);
properties.setInteger("conjuredBowDuration", this.conjuredBowDuration);
properties.setInteger("conjuredArmourDuration", this.conjuredArmourDuration);
properties.setInteger("flamingAxeDuration", this.flamingAxeDuration);
properties.setInteger("frostAxeDuration", this.frostAxeDuration);
properties.setInteger("magicWeaponDuration", this.magicWeaponDuration);
properties.setInteger("flamingWeaponDuration", this.flamingWeaponDuration);
properties.setInteger("freezingWeaponDuration", this.freezingWeaponDuration);
properties.setBoolean("hasSpiritWolf", this.hasSpiritWolf);
properties.setBoolean("hasSpiritHorse", this.hasSpiritHorse);
properties.setInteger("x", this.transportX);
properties.setInteger("y", this.transportY);
properties.setInteger("z", this.transportZ);
properties.setInteger("dimension", this.transportDimension);
properties.setInteger("x2", this.clairvoyanceX);
properties.setInteger("y2", this.clairvoyanceY);
properties.setInteger("z2", this.clairvoyanceZ);
properties.setInteger("dimension2", this.clairvoyanceDimension);
properties.setInteger("tpTimer", this.tpTimer);
NBTTagList tagList = new NBTTagList();
for(UUID id : this.allies){
tagList.appendTag(new NBTTagString(id.toString()));
}
properties.setTag("allies", tagList);
NBTTagList tagList2 = new NBTTagList();
for(String name : this.allyNames){
tagList2.appendTag(new NBTTagString(name));
}
properties.setTag("allyNames", tagList2);
NBTTagList tagList3 = new NBTTagList();
for(UUID id : this.soulboundCreatures){
tagList3.appendTag(new NBTTagString(id.toString()));
}
properties.setTag("soulboundCreatures", tagList3);
int[] spells = new int[this.spellsDiscovered.size()];
int i=0;
for(Spell spell : this.spellsDiscovered){
spells[i] = spell.id();
i++;
}
properties.setIntArray("discoveredSpells", spells);
compound.setTag(name, properties);
}
@Override
public void loadNBTData(NBTTagCompound compound) {
NBTTagCompound properties = (NBTTagCompound) compound.getTag(name);
if(properties != null){
this.conjuredSwordDuration = properties.getInteger("conjuredSwordDuration");
this.conjuredPickaxeDuration = properties.getInteger("conjuredPickaxeDuration");
this.conjuredBowDuration = properties.getInteger("conjuredBowDuration");
this.conjuredArmourDuration = properties.getInteger("conjuredArmourDuration");
this.flamingAxeDuration = properties.getInteger("flamingAxeDuration");
this.frostAxeDuration = properties.getInteger("frostAxeDuration");
this.magicWeaponDuration = properties.getInteger("magicWeaponDuration");
this.flamingWeaponDuration = properties.getInteger("flamingWeaponDuration");
this.freezingWeaponDuration = properties.getInteger("freezingWeaponDuration");
this.hasSpiritWolf = properties.getBoolean("hasSpiritWolf");
this.hasSpiritHorse = properties.getBoolean("hasSpiritHorse");
this.transportX = properties.getInteger("x");
this.transportY = properties.getInteger("y");
this.transportZ = properties.getInteger("z");
this.transportDimension = properties.getInteger("dimension");
this.clairvoyanceX = properties.getInteger("x2");
this.clairvoyanceY = properties.getInteger("y2");
this.clairvoyanceZ = properties.getInteger("z2");
this.clairvoyanceDimension = properties.getInteger("dimension2");
this.tpTimer = properties.getInteger("tpTimer");
this.allies = new HashSet<UUID>();
NBTTagList tagList = properties.getTagList("allies", NBT.TAG_STRING);
for(int i=0; i<tagList.tagCount(); i++){
allies.add(UUID.fromString(tagList.getStringTagAt(i)));
}
this.allyNames = new HashSet<String>();
NBTTagList tagList2 = properties.getTagList("allyNames", NBT.TAG_STRING);
for(int i=0; i<tagList2.tagCount(); i++){
allyNames.add(tagList2.getStringTagAt(i));
}
this.soulboundCreatures = new HashSet<UUID>();
NBTTagList tagList3 = properties.getTagList("soulboundCreatures", NBT.TAG_STRING);
for(int i=0; i<tagList3.tagCount(); i++){
soulboundCreatures.add(UUID.fromString(tagList3.getStringTagAt(i)));
}
this.spellsDiscovered = new HashSet<Spell>();
for(int id : properties.getIntArray("discoveredSpells")){
spellsDiscovered.add(Spell.get(id));
}
}
}
@Override
public void init(Entity entity, World world) {
// For reference, apparently there is a strange error that causes 'this' to be null here.
}
}
@@ -0,0 +1,16 @@
package electroblob.wizardry;
import electroblob.wizardry.MagicDamage.DamageType;
import net.minecraft.entity.Entity;
import scala.actors.threadpool.Arrays;
/** This interface allows {@link MagicDamage} and {@link IndirectMagicDamage} to both be treated as instances of a
* single type so that the damage type field can be accessed, rather than having to deal with each of them separately,
* which would be inefficient and cumbersome (the latter of those classes cannot extend the former because they both
* need to extend different subclasses of {@link net.minecraft.util.DamageSource DamageSource}).
* @since Wizardry 1.1 */
public interface IElementalDamage {
DamageType getType();
}
@@ -1,18 +1,16 @@
package electroblob.wizardry.util;
package electroblob.wizardry;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.MagicDamage.DamageType;
import net.minecraft.entity.Entity;
import net.minecraft.util.EntityDamageSourceIndirect;
public class IndirectMagicDamage extends EntityDamageSourceIndirect implements IElementalDamage {
private final DamageType type;
private final boolean isRetaliatory;
public IndirectMagicDamage(String name, Entity magic, Entity caster, DamageType type, boolean isRetaliatory){
public IndirectMagicDamage(String name, Entity magic, Entity caster, DamageType type) {
super(name, magic, caster);
this.type = type;
this.isRetaliatory = isRetaliatory;
}
@Override
@@ -20,9 +18,4 @@ public class IndirectMagicDamage extends EntityDamageSourceIndirect implements I
return type;
}
@Override
public boolean isRetaliatory(){
return isRetaliatory;
}
}
@@ -1,4 +1,4 @@
package electroblob.wizardry.util;
package electroblob.wizardry;
import java.util.Arrays;
import java.util.HashMap;
@@ -16,6 +16,7 @@ import electroblob.wizardry.entity.living.EntitySpiderMinion;
import electroblob.wizardry.entity.living.EntityStormElemental;
import electroblob.wizardry.entity.living.EntityZombieMinion;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.monster.EntityBlaze;
@@ -26,64 +27,57 @@ import net.minecraft.entity.monster.EntityPigZombie;
import net.minecraft.entity.monster.EntitySkeleton;
import net.minecraft.entity.monster.EntitySnowman;
import net.minecraft.entity.monster.EntitySpider;
import net.minecraft.entity.monster.EntityWitherSkeleton;
import net.minecraft.entity.monster.EntityZombie;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
// A note on the use of the vanilla damagesources:
// When using indirect damage sources, the SECOND argument is the original entity (i.e. the caster), and the
// FIRST argument is the actual projectile or whatever that does the damage. getTrueSource() will return
// the original entity, and getImmediateSource() will return the projectile.
// FIRST argument is the actual projectile or whatever that does the damage. getEntity() will return
// the original entity, and getSourceOfDamage() will return the projectile.
// The vanilla approach to damage types is inconsistent, to say the least. Poison is simply 'magic', and relies on
// EntityLivingBase.isPotionApplicable to determine whether an entity is affected or not. Wither, on the other hand, is
// its own damage type, but again relies on the potion to determine what is immune (which in vanilla is nothing). Fire
// its own damage type, but again relies on the potion to determine what is immune (which in this case is nothing). Fire
// has a proper implementation of course, with both block-based and projectile-based types, and any other damagesource
// can also be designated as fire damage with setFireDamage(). Likewise, projectile and explosion damage can also be
// applied to any damagesource, but these aren't considered types in their own right; rather, they seem to be damage
// type 'attributes'. This is my attempt to collect all of these into a reasonably coherent system.
// applied to any damagesource, but these aren't condsidered types in their own right; rather, they seem to be damage
// type 'attributes'.
/**
* As of wizardry 1.1, this class has replaced the damagesource-related methods in WizardryUtilities, allowing a
* {@link DamageType} to be specified with the damage. The main reason for this is so that damage sources can fit with
* the vanilla behaviour on armour enchantments and such like whilst still being classified as wizardry damage for the
* purposes of friendly fire, etc.
* <p>
* <i> In the future, there is scope for an entirely standalone mod based on this idea. Perhaps 'Elemental Damage' could
* be a config-only mod which allows its users to define any number of specific damage types, then give any creature a
/** As of wizardry 1.1, this class has replaced the damagesource-related methods in WizardryUtilities, allowing a
* {@link DamageType} to be specified with the damage. The main reason for this is so that damage sources can fit with the
* vanilla behaviour on armour enchantments and such like whilst still being classified as wizardry damage for the purposes
* of friendly fire, etc.
* <p><i>
* In the future, there is scope for an entirely standalone mod based on this idea. Perhaps 'Elemental Damage' could be
* a config-only mod which allows its users to define any number of specific damage types, then give any creature a
* resistance, immunity or vulnerability to each, as well as being able to specify the sources for each type, such as
* enchantments, potions, specific items, certain entities, even particular situations and string damagesource names
* from other mods. </i>
*
* from other mods.
* </i>
* @see IndirectMagicDamage
* @see IElementalDamage
* @since Wizardry 1.1
* @author Electroblob
*/
* @since Wizardry 1.1 */
public class MagicDamage extends EntityDamageSource implements IElementalDamage {
/** The name of the damagesource for direct magic damage from the wizardry mod. */
public static final String DIRECT_MAGIC_DAMAGE = "wizardry_magic";
/** The name of the damagesource for indirect magic damage from the wizardry mod. */
public static final String INDIRECT_MAGIC_DAMAGE = "indirect_wizardry_magic";
/** The name of the damagesource for direct magic damage from the wizardry mod. Defined here so that any
* references get changed automatically. */
public static final String DIRECT_MAGIC_DAMAGE = "wizardryMagic";
/** The name of the damagesource for indirect magic damage from the wizardry mod. Defined here so that any
* references get changed automatically. */
public static final String INDIRECT_MAGIC_DAMAGE = "indirectWizardryMagic";
// Technically, I don't need to specify that the classes in this map must extend entity, but it's good practice to.
private static final Map<Class<? extends Entity>, DamageType[]> immunityMapping = new HashMap<Class<? extends Entity>, DamageType[]>();
private final DamageType type;
private final boolean isRetaliatory;
/**
* A simple set of constants for the types of damage. The names are deliberately different to those in EnumElement
* to avoid confusion. All types are classified as magic damage in the vanilla system, so witches are resistant to
* them.
*/
/** A simple set of constants for the types of damage. The names are deliberately different to those in EnumElement
* to avoid confusion. All types are classified as magic damage in the vanilla system, so witches are resistant to them. */
public enum DamageType {
/** Generic magic damage from the wizardry mod. Like vanilla magic damage, except it doesn't bypass armour. */
MAGIC,
/** Fire damage from the wizardry mod. Counts as fire damage in the vanilla system, so is blocked by any mobs
* that are immune to fire and entities with the fire resistance effect, and is affected by the fire protection
* enchantment. */
/** Fire damage from the wizardry mod. Counts as fire damage in the vanilla system, so is blocked by any mobs that
* are immune to fire and entities with the fire resistance effect. */
FIRE,
/** Frost (ice) damage from the wizardry mod. Snow golems, ice wraiths and ice giants are immune. */
FROST,
@@ -93,15 +87,15 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
WITHER,
/** Poison damage from the wizardry mod. Spiders, cave spiders and undead mobs are immune. */
POISON,
/** Force damage from the wizardry mod. */ // Insubstantial creatures (ghast, shadow wraith, etc.) are immune?
/** Force damage from the wizardry mod. Insubstantial creatures (ghast, shadow wraith, etc.) are immune. */
FORCE,
/** Blast damage from the wizardry mod. Affected by the blast protection enchantment. */
BLAST,
/** Radiant damage from the wizardry mod. */
RADIANT;
}
static{
static {
// Of course, the entities that are immune to fire already are since there's a vanilla system for that, but
// they're included here anyway for completeness and in case anyone wants to check if an entity is immune to
// an unspecified element for reasons other than dealing damage.
@@ -119,7 +113,6 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
setEntityImmunities(EntityIceGiant.class, DamageType.FROST);
setEntityImmunities(EntityLightningWraith.class, DamageType.SHOCK);
setEntityImmunities(EntityShadowWraith.class, DamageType.WITHER);
setEntityImmunities(EntityWitherSkeleton.class, DamageType.WITHER);
setEntityImmunities(EntitySpider.class, DamageType.POISON);
setEntityImmunities(EntitySpiderMinion.class, DamageType.POISON);
setEntityImmunities(EntityCaveSpider.class, DamageType.POISON);
@@ -129,38 +122,44 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
setEntityImmunities(EntitySkeletonMinion.class, DamageType.POISON);
}
public MagicDamage(String name, Entity caster, DamageType type, boolean isRetaliatory){
public MagicDamage(String name, Entity caster, DamageType type) {
super(name, caster);
this.type = type;
this.isRetaliatory = isRetaliatory;
this.setMagicDamage();
if(type == DamageType.FIRE) this.setFireDamage();
if(type == DamageType.BLAST) this.setExplosion();
}
/**
* Returns true if the given entity is immune to the given damage type according to the entity immunity mappings,
/** Returns true if the given entity is immune to the given damage type according to the entity immunity mappings,
* false otherwise. When you want to check for resistances, check this method rather than just checking the result
* of attackEntityFrom, since that could return false for all sorts of reasons besides immunities. However, if you
* don't need to know whether the damage succeeded or not, there's no point in checking this method. A common use of
* this method is to check for immunity and if so display the "[mob] resisted [spell]" chat message. See
* {@link electroblob.wizardry.spell.Arc Arc} for a good example of this, and also of when not to use it.
*/
* don't need to know whether the damage succeeded or not, there's no point in checking this method. A common use
* of this method is to check for immunity and if so display the "[mob] resisted [spell]" chat message. See
* {@link electroblob.wizardry.spell.Arc Arc} for a good example of this, and also of when not to use it. */
public static boolean isEntityImmune(DamageType type, Entity entity){
// Because Mojang, in their infinite wisdom, did not make wither skeletons their own separate class (despite the
// fact that cave spiders are), I have to test for this manually. Realistically, no mod author would be stupid
// enough to put two entities in one class, so this should be the only time I ever have to do this.
if(type == DamageType.WITHER && (
(entity instanceof EntitySkeleton && ((EntitySkeleton)entity).getSkeletonType() == 1)
|| (entity instanceof EntitySkeletonMinion && ((EntitySkeletonMinion)entity).getSkeletonType() == 1))){
return true;
}
if(type == DamageType.FIRE && entity.isImmuneToFire()) return true;
DamageType[] immunities = MagicDamage.immunityMapping.get(entity.getClass());
return immunities != null && Arrays.asList(immunities).contains(type);
}
// I found a use for varargs!
/** Registers the given type of entity as immune to all of the passed in damage types. */
public static void setEntityImmunities(Class<? extends Entity> entityType, DamageType... immunities){
immunityMapping.put(entityType, immunities);
}
/** Adds the passed in damage type to the list of damage types to which the given entity is immune. */
/** Registers the given type of entity as immune to all of the passed in damage types. */
public static void addEntityImmunity(Class<? extends Entity> entityType, DamageType immunity){
List<DamageType> immunities = Arrays.asList(immunityMapping.get(entityType));
immunities.add(immunity);
@@ -169,92 +168,44 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
}
/**
* Returns a DamageSource called "wizardry_magic" with the given entity as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.MAGIC, it does
* not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for
* the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
* isRetaliatory defaults to false.
* <p>
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the
* entire mod just to get rid of this method and use the constructor instead.
*
* @param caster The player or other living entity causing the damage
* @param type The type that this damage belongs to; used for resistances and wand perks. Use
* {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them
* might reasonably affect creatures that are ususally immune to wither effects).
* @return A damagesource object of type EntityDamageSource
*/
public static DamageSource causeDirectMagicDamage(Entity caster, DamageType type){
return causeDirectMagicDamage(caster, type, false);
}
/**
* Returns a DamageSource called "wizardry_magic" with the given entity as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.MAGIC, it does
* Returns a DamageSource called "wizardryMagic" with the given entity as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular melee/swords. Unlike DamageSource.magic, it does
* not bypass armour and has a player as the source (rather than nothing). It is still classed as magic damage (for
* the record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
* <p>
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the
* entire mod just to get rid of this method and use the constructor instead.
*
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the entire
* mod just to get rid of this method and use the constructor instead.
* @param caster The player or other living entity causing the damage
* @param type The type that this damage belongs to; used for resistances and wand perks. Use
* {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them
* might reasonably affect creatures that are ususally immune to wither effects).
* @param isRetaliatory whether this damage source came from a retaliatory attack; prevents infinite loops occurring
* when two entities damage each other with retaliatory effects.
* {@link EnumElement#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them might
* reasonably affect creatures that are ususally immune to wither effects).
* @return A damagesource object of type EntityDamageSource
*/
public static DamageSource causeDirectMagicDamage(Entity caster, DamageType type, boolean isRetaliatory){
return new MagicDamage(DIRECT_MAGIC_DAMAGE, caster, type, isRetaliatory);
public static DamageSource causeDirectMagicDamage(EntityLivingBase caster, DamageType type)
{
return new MagicDamage(DIRECT_MAGIC_DAMAGE, caster, type);
}
/**
* Returns a DamageSource called "indirect_wizardry_magic" with the player as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular arrows/throwables. Unlike
* DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the
* record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
* isRetaliatory defaults to false.
* <p>
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the
* entire mod just to get rid of this method and use the constructor instead.
*
* @param magic The entity that actually caused the damage
* @param caster The player or other living entity that cast the spell originally
* @param type The type that this damage belongs to; used for resistances and wand perks. Use
* {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them
* might reasonably affect creatures that are ususally immune to wither effects).
* @return A damagesource object of type EntityDamageSourceIndirect
*/
public static DamageSource causeIndirectMagicDamage(Entity magic, Entity caster, DamageType type){
return causeIndirectMagicDamage(magic, caster, type, false);
}
/**
* Returns a DamageSource called "indirect_wizardry_magic" with the player as the caster. Use in preference to vanilla
* Returns a DamageSource called "indirectWizardryMagic" with the player as the caster. Use in preference to vanilla
* types to allow things to distinguish between magic and regular arrows/throwables. Unlike
* DamageSource.causeIndirectMagicDamage, it does not bypass armour. It is still classed as magic damage (for the
* record, all this does in vanilla is make witches 85% resistant to it - but that seems kinda right anyway).
* <p>
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the
* entire mod just to get rid of this method and use the constructor instead.
*
* Now that this is its own class, this static method is largely redundant, but it's not worth refactoring the entire
* mod just to get rid of this method and use the constructor instead.
* @param magic The entity that actually caused the damage
* @param caster The player or other living entity that cast the spell originally
* @param type The type that this damage belongs to; used for resistances and wand perks. Use
* {@link DamageType#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them
* might reasonably affect creatures that are ususally immune to wither effects).
* @param isRetaliatory whether this damage source came from a retaliatory attack; prevents infinite loops occurring
* when two entities damage each other with retaliatory effects.
* {@link EnumElement#MAGIC} for regular, non-elemental magic damage (sometimes you might not want an element
* even though the spell has one - for example, not all necromancy spells are 'withery', so some of them might
* reasonably affect creatures that are ususally immune to wither effects).
* @return A damagesource object of type EntityDamageSourceIndirect
*/
public static DamageSource causeIndirectMagicDamage(Entity magic, Entity caster, DamageType type,
boolean isRetaliatory){
return new IndirectMagicDamage(INDIRECT_MAGIC_DAMAGE, magic, caster, type, isRetaliatory);
public static DamageSource causeIndirectEntityMagicDamage(Entity magic, EntityLivingBase caster, DamageType type)
{
return new IndirectMagicDamage(INDIRECT_MAGIC_DAMAGE, magic, caster, type);
}
@Override
@@ -262,9 +213,4 @@ public class MagicDamage extends EntityDamageSource implements IElementalDamage
return type;
}
@Override
public boolean isRetaliatory(){
return isRetaliatory;
}
}
@@ -1,591 +0,0 @@
package electroblob.wizardry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import electroblob.wizardry.packet.PacketSyncSettings;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.translation.I18n;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
/**
* Singleton class which deals with everything related to wizardry's config file. To access individual settings, use
* {@link Wizardry#settings}. Also stores a few string constants for easy access.
* <p>
* As part of the 1.2 update and code overhaul, the way the config settings work in multiplayer has been tightened up.
* Importantly, there are <b>three</b> different types of config options:
* <p>
* <li>Server-only settings. These only affect server-side code and hence are not synced. Changing these locally only
* has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world. Examples
* include worldgen, mob drops and commands.
* <li>Synchronised settings. These settings affect both client-side AND server-side code, and are synchronised with
* each client on login via {@link Settings#sync(EntityPlayerMP)}. Changing these locally only has an effect if the
* local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world. Examples include discovery mode
* and crafting recipes. <i> Note that as far as users are concerned, there is no difference in behaviour between
* server-only and synchronised settings.</i>
* <li>Client-only settings. These settings only affect client-side code and hence are not synced. Each client obeys its
* own values for these, and changing them on a dedicated server will have no effect. These are usually only display and
* controls settings.</li>
* <p>
* Each of the settings fields in this class is marked with one of the above categories to indicate which it belongs to.
* This in turn dictates which logical side it should be called from: client, server or both. <b> Do not access a config
* setting from the wrong side, because it may cause unexpected or strange behaviour.</b>
*
* @since Wizardry 1.2
* @author Electroblob
*/
// TODO: New plan: convert to the @Config system BUT separate the spells config out so it doesn't break stuff. (Maybe even
// make it a JSON instead? Either way, there's scope for then adding more options for adjusting the base attributes etc.)
// @Config(modid = Wizardry.MODID)
@SuppressWarnings("deprecation") // Used server I18n deliberately; we want to write the comments in english.
public final class Settings {
// Category names
/** The unlocalised name of the spells config category. */
public static final String SPELLS_CATEGORY = "spells";
/** The unlocalised name of the resistances config category. */
public static final String RESISTANCES_CATEGORY = "resistances";
/** The unlocalised name of the client config category. */
public static final String CLIENT_CATEGORY = "client";
/** The unlocalised name of the commands config category. */
public static final String COMMANDS_CATEGORY = "commands";
/** The unlocalised name of the worldgen config category. */
public static final String WORLDGEN_CATEGORY = "worldgen";
/** The unlocalised name of the gameplay config category. */
public static final String GAMEPLAY_CATEGORY = "gameplay";
/** The wizardry config file. */
private Configuration config;
// Server-only settings. These only affect server-side code and hence are not synced. Changing these locally only
// has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world.
// Worldgen
/** <b>[Server-only]</b> The rarity of wizard towers, used by the world generator. Larger numbers are rarer. */
public int towerRarity = 8;
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal ore. */
public int[] oreDimensions = {0};
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal ore. */
public int[] flowerDimensions = {0};
/** <b>[Server-only]</b> List of dimension ids in which to generate crystal ore. */
public int[] towerDimensions = {0};
/**
* <b>[Server-only]</b> Whether or not wizardry loot should generate in dungeon chests. Note that this does not
* affect the generation of loot in wizard towers.
*/
public boolean generateLoot = true;
// Entities' drops, targeting, damage, etc.
/** <b>[Server-only]</b> Chance (out of 200) for mobs to drop spell books. */
public int spellBookDropChance = 3;
/**
* <b>[Server-only]</b> Whether or not players can teleport through unbreakable blocks (e.g. bedrock) using the
* phase step spell.
*/
public boolean teleportThroughUnbreakableBlocks = false;
/** <b>[Server-only]</b> Whether to allow players to damage their designated allies using magic. */
public boolean friendlyFire = true;
/** <b>[Server-only]</b> Whether to allow players to disarm other players using the telekinesis spell. */
public boolean telekineticDisarmament = true;
/** <b>[Server-only]</b> Whether summoned creatures can revenge attack their caster if their caster attacks them. */
public boolean minionRevengeTargeting = true;
/**
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are allowed to attack, in addition
* to the defaults.
*/
public ResourceLocation[] summonedCreatureTargetsWhitelist = {};
/**
* <b>[Server-only]</b> List of registry names of entities which summoned creatures are specifically not allowed to
* attack, overriding the defaults and the whitelist.
*/
public ResourceLocation[] summonedCreatureTargetsBlacklist = {new ResourceLocation("creeper")};
/**
* <b>[Server-only]</b> List of registry names of entities which are immune to the mind control spell, in addition to
* the defaults.
*/
public ResourceLocation[] mindControlTargetsBlacklist = {};
/** <b>[Server-only]</b> Global damage scaling factor for all player magic damage. */
public double playerDamageScale = 1.0f;
/** <b>[Server-only]</b> Global damage scaling factor for all npc magic damage. */
public double npcDamageScale = 1.0f;
/** <b>[Server-only]</b> List of dimension ids in which evil wizards can spawn. */
public int[] evilWizardDimensions = {0};
// Commands (these don't need synchronising since typing a command always queries the server).
/**
* <b>[Server-only]</b> The maximum allowed multiplier for the /cast command. This limit is here to stop people from
* accidentally breaking their worlds!
*/
public double maxSpellCommandMultiplier = 20d;
/** <b>[Server-only]</b> The name of the /cast command. */
public String castCommandName = "cast";
/** <b>[Server-only]</b> The name of the /discoverspell command. */
public String discoverspellCommandName = "discoverspell";
/** <b>[Server-only]</b> The name of the /ally command. */
public String allyCommandName = "ally";
/** <b>[Server-only]</b> The name of the /allies command. */
public String alliesCommandName = "allies";
// Synchronised settings. These settings affect both client-side AND server-side code. Changing these locally
// only has an effect if the local game is the host, i.e. a dedicated server, a LAN host or a singleplayer world.
// Gamemodes
/**
* <b>[Synchronised]</b> When set to true, spells a player hasn't cast yet will be unreadable until they are cast
* (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in
* survival mode if this is false.
*/
public boolean discoveryMode = true;
// Client-only settings. These settings only affect client-side code and hence are not synced. Each client obeys
// its own values for these, and changing them on a dedicated server will have no effect.
// Controls
/**
* <b>[Client-only]</b> Whether the player can switch between spells on a wand by scrolling with the mouse wheel
* while sneaking.
*/
public boolean enableShiftScrolling = true;
// Display
/** <b>[Client-only]</b> Whether to show summoned creatures' names and owners above their heads. */
public boolean showSummonedCreatureNames = true;
/** <b>[Client-only]</b> The position of the spell HUD. */
public GuiPosition spellHUDPosition = GuiPosition.BOTTOM_LEFT;
/** Set of constants for each of the four positions that the spell HUD can be in. */
public enum GuiPosition {
BOTTOM_LEFT("Bottom left"), TOP_LEFT("Top left"), TOP_RIGHT("Top right"), BOTTOM_RIGHT("Bottom right");
/** Constant array storing the names of each of the constants, in the order they are declared. */
public static final String[] names;
static{
names = new String[values().length];
for(GuiPosition position : values()){
names[position.ordinal()] = position.name;
}
}
/** The readable name for this GUI position that will be displayed on the button in the config GUI. */
public final String name;
GuiPosition(String name){
this.name = name;
}
/**
* Gets a GUI position from its string name (ignoring case), or BOTTOM_LEFT if the given name is not a valid
* position.
*/
public static GuiPosition fromName(String name){
for(GuiPosition position : values()){
if(position.name.equalsIgnoreCase(name)) return position;
}
Wizardry.logger.info("Invalid string for the spell HUD position. Using default (bottom left) instead.");
return BOTTOM_LEFT;
}
}
// As of Wizardry 1.1, all keys used in the config file itself are now hardcoded, not localised. The localisations
// are done in the config GUI. The config file has to be written in one language or it will end up with multiple
// options for different languages.
// These methods are package-protected to stop anyone else from calling them.
/**
* Called from preInit to initialise the config file. The first part of the config file has to be done here (as is
* conventional) so that the various registries can change what they do accordingly. The spell part of the config
* and the resistance part of the config have to be done in the init method since they depend on the registry events.
*/
void initConfig(FMLPreInitializationEvent event){
config = new Configuration(event.getSuggestedConfigurationFile());
config.load();
Wizardry.logger.info("Setting up main config");
setupGeneralConfig();
setupWorldgenConfig();
setupClientConfig();
setupCommandsConfig();
config.save();
}
/**
* Called from init to initialise the parts of the config file that have to be done after registry events are fired.
* For example, the spell config is done here and not in preInit because all spells must be registered before it is
* added, including those in other mods.
*/
void initConfigExtras(){
Wizardry.logger.info("Setting up spells config for " + Spell.getTotalSpellCount() + " spells");
setupSpellsConfig();
Wizardry.logger.info("Setting up resistances config");
setupResistancesConfig();
config.save();
}
/** Called to save changes to the config file after it has been edited in game from the menus. */
void saveConfigChanges(){
Wizardry.logger.info("Saving in-game config changes");
setupGeneralConfig();
setupWorldgenConfig();
setupClientConfig();
setupCommandsConfig();
setupSpellsConfig();
setupResistancesConfig();
config.save();
}
/** Sends a packet to the specified player's client containing all the <b>synchronised</b> settings. */
public void sync(EntityPlayerMP player){
Wizardry.logger.info("Synchronising config settings for " + player.getName());
IMessage message = new PacketSyncSettings.Message(this);
WizardryPacketHandler.net.sendTo(message, player);
}
public ConfigCategory getConfigCategory(String name){
return config.getCategory(name);
}
private void setupSpellsConfig(){
config.addCustomCategoryComment(SPELLS_CATEGORY,
"Set a spell to false to disable it. Disabled spells will still have their associated spell book (mainly so the spell books don't all change) and can still be bound to wands, but cannot be cast in game, will not appear in any subsequently generated chests or wizard trades and will not drop from mobs. Disable a spell if it is causing problems, conflicts with another mod or creates an unintended exploit.");
Property property;
for(Spell spell : Spell.getSpells(Spell.allSpells)){
property = config.get(SPELLS_CATEGORY, spell.getRegistryName().toString(), true,
I18n.translateToLocal("spell." + spell.getUnlocalisedName() + ".desc"));
// Uses the same config key as the spell name, because - well, that's what it's called!
property.setLanguageKey("spell." + spell.getUnlocalisedName());
spell.setEnabled(property.getBoolean());
}
}
private void setupGeneralConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(GAMEPLAY_CATEGORY, "Global settings that affect game mechanics. In multiplayer, the server/LAN host settings will apply. Please note that changing some of these settings may make the mod very difficult to play.");
property = config.get(GAMEPLAY_CATEGORY, "discoveryMode", true,
"For those who like a sense of mystery! When set to true, spells you haven't cast yet will be unreadable until you cast them (on a per-world basis). Has no effect when in creative mode. Spells of identification will be unobtainable in survival mode if this is false.");
property.setLanguageKey("config." + Wizardry.MODID + ".discovery_mode");
property.setRequiresWorldRestart(true);
discoveryMode = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "friendlyFire", true,
"Whether to allow players to damage their designated allies using magic.");
property.setLanguageKey("config." + Wizardry.MODID + ".friendly_fire");
friendlyFire = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "spellBookDropChance", 3,
"The chance for mobs to drop a spell book when killed. The greater this number, the more often they will drop. Set to 0 to disable spell book drops. Set to 200 for guaranteed drops.",
0, 200);
property.setLanguageKey("config." + Wizardry.MODID + ".spell_book_drop_chance");
Wizardry.proxy.setToNumberSliderEntry(property);
spellBookDropChance = property.getInt();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "evilWizardDimensions", new int[]{0},
"List of dimension ids in which evil wizards can spawn.");
property.setLanguageKey("config." + Wizardry.MODID + ".evil_wizard_dimensions");
property.setRequiresMcRestart(true);
evilWizardDimensions = property.getIntList();
propOrder.add(property.getName());
// These two aren't sliders because using a slider makes it difficult to fine-tune the numbers; the nature of a
// scaling factor means that 0.5 is as big a change as 2.0, so whilst a slider is fine for increasing the
// damage, it doesn't give fine enough control for values less than 1.
property = config.get(GAMEPLAY_CATEGORY, "playerDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by players casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".player_damage_scaling");
playerDamageScale = property.getDouble();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "npcDamageScaling", 1.0,
"Global damage scaling factor for the damage dealt by NPCs casting spells, relative to 1.", 0, 20);
property.setLanguageKey("config." + Wizardry.MODID + ".npc_damage_scaling");
npcDamageScale = property.getDouble();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "minionRevengeTargeting", true,
"Whether summoned creatures can revenge attack their owner if their owner attacks them.");
property.setLanguageKey("config." + Wizardry.MODID + ".minion_revenge_targeting");
property.setRequiresWorldRestart(false);
minionRevengeTargeting = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsWhitelist", new String[0],
"List of names of entities which summoned creatures and wizards are allowed to attack, in addition to the defaults. Add mod creatures to this list if you want summoned creatures to attack them and they aren't already doing so. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_whitelist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
summonedCreatureTargetsWhitelist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "summonedCreatureTargetsBlacklist",
new String[]{"creeper"},
"List of names of entities which summoned creatures and wizards are specifically not allowed to attack, overriding the defaults and the whitelist. Add creatures to this list if allowing them to be attacked causes problems or is too destructive (removing creepers from this list is done at your own risk!). Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".summoned_creature_targets_blacklist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
summonedCreatureTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "telekineticDisarmament", true,
"Whether to allow players to disarm other players using the telekinesis spell. Set to false to prevent stealing of items.");
property.setLanguageKey("config." + Wizardry.MODID + ".telekinetic_disarmament");
telekineticDisarmament = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "teleportThroughUnbreakableBlocks", false,
"Whether players are allowed to teleport through unbreakable blocks (e.g. bedrock) using the phase step spell.");
property.setLanguageKey("config." + Wizardry.MODID + ".teleport_through_unbreakable_blocks");
teleportThroughUnbreakableBlocks = property.getBoolean();
propOrder.add(property.getName());
property = config.get(GAMEPLAY_CATEGORY, "mindControlTargetsBlacklist", new String[]{},
"List of names of entities which cannot be mind controlled, in addition to the defaults. Add creatures to this list if allowing them to be mind-controlled causes problems or could be exploited. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mind_control_targets_blacklist");
property.setRequiresWorldRestart(true);
// Converts all strings in the list to a ResourceLocation.
mindControlTargetsBlacklist = Arrays.stream(property.getStringList()).map(s -> new ResourceLocation(s.toLowerCase(Locale.ROOT).trim())).toArray(ResourceLocation[]::new);
propOrder.add(property.getName());
config.setCategoryPropertyOrder(GAMEPLAY_CATEGORY, propOrder);
}
private void setupWorldgenConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(WORLDGEN_CATEGORY, "Settings that affect world generation. In multiplayer, the server/LAN host settings will apply.");
property = config.get(WORLDGEN_CATEGORY, "towerRarity", 8, "Rarity of wizard towers. Higher numbers are rarer. Set to 0 to disable wizard towers completely.", 0, 50);
property.setLanguageKey("config." + Wizardry.MODID + ".tower_rarity");
property.setRequiresWorldRestart(true);
Wizardry.proxy.setToNumberSliderEntry(property);
towerRarity = property.getInt();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "towerDimensions", new int[]{0}, "List of dimension ids in which wizard towers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".tower_dimensions");
property.setRequiresWorldRestart(true);
towerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "oreDimensions", new int[]{0}, "List of dimension ids in which crystal ore will generate. Note that removing the overworld (id 0) from this list will make the mod VERY difficult to play!");
property.setLanguageKey("config." + Wizardry.MODID + ".ore_dimensions");
property.setRequiresWorldRestart(true);
oreDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "flowerDimensions", new int[]{0}, "List of dimension ids in which crystal flowers will generate.");
property.setLanguageKey("config." + Wizardry.MODID + ".flower_dimensions");
property.setRequiresWorldRestart(true);
flowerDimensions = property.getIntList();
propOrder.add(property.getName());
property = config.get(WORLDGEN_CATEGORY, "generateLoot", true, "Whether to inject wizardry loot (as specified in loot_tables/chests/dungeon_additions.json) into the loot tables for vanilla dungeon chests.");
property.setLanguageKey("config." + Wizardry.MODID + ".generate_loot");
property.setRequiresWorldRestart(true);
generateLoot = property.getBoolean();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(WORLDGEN_CATEGORY, propOrder);
}
private void setupClientConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(CLIENT_CATEGORY, "Client-side settings that only affect the local minecraft game. If this file is on a dedicated server, these settings will have no effect; in multiplayer, each player obeys their own settings.");
property = config.get(CLIENT_CATEGORY, "enableShiftScrolling", true,
"Whether you can switch between spells on a wand by scrolling with the mouse wheel while sneaking. Note that this will only affect you; other players connected to the same server obey their own settings.");
property.setLanguageKey("config." + Wizardry.MODID + ".enable_shift_scrolling");
property.setRequiresWorldRestart(false);
enableShiftScrolling = property.getBoolean();
propOrder.add(property.getName());
property = config.get(CLIENT_CATEGORY, "spellHUDPosition", GuiPosition.BOTTOM_LEFT.name, "The position of the spell HUD.", GuiPosition.names);
property.setLanguageKey("config." + Wizardry.MODID + ".spell_hud_position");
spellHUDPosition = GuiPosition.fromName(property.getString());
propOrder.add(property.getName());
property = config.get(CLIENT_CATEGORY, "showSummonedCreatureNames", true, "Whether to show summoned creatures' names and owners above their heads.");
property.setLanguageKey("config." + Wizardry.MODID + ".show_summoned_creature_names");
showSummonedCreatureNames = property.getBoolean();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(CLIENT_CATEGORY, propOrder);
}
private void setupCommandsConfig(){
// This trick is borrowed from forge; it sorts the config options into the order you want them.
List<String> propOrder = new ArrayList<String>();
Property property;
config.addCustomCategoryComment(COMMANDS_CATEGORY, "Settings for the commands added by Wizardry. In multiplayer, the server/LAN host settings will apply.");
// This one isn't a slider either because people are likely to want exact values ("it must be at most 50.3" is a
// bit strange!).
property = config.get(COMMANDS_CATEGORY, "castCommandMultiplierLimit", 20.0,
"Upper limit for the multipliers passed into the /cast command. This is here to stop players from accidentally breaking a world/server. Large blast mutipliers can cause extreme lag - you have been warned!",
1, 255);
property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_multiplier_limit");
maxSpellCommandMultiplier = property.getDouble();
propOrder.add(property.getName());
property = config.get(COMMANDS_CATEGORY, "castCommandName", "cast",
"The name of the /cast command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /cast you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".cast_command_name");
property.setRequiresWorldRestart(true);
castCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(COMMANDS_CATEGORY, "discoverspellCommandName", "discoverspell",
"The name of the /discoverspell command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /discoverspell you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".discoverspell_command_name");
property.setRequiresWorldRestart(true);
discoverspellCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(COMMANDS_CATEGORY, "allyCommandName", "ally",
"The name of the /ally command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /ally you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".ally_command_name");
property.setRequiresWorldRestart(true);
allyCommandName = property.getString();
propOrder.add(property.getName());
property = config.get(COMMANDS_CATEGORY, "alliesCommandName", "allies",
"The name of the /allies command. This is what you type directly after the /; for example if this was set to 'magic' then instead of typing /allies you would type /magic instead.");
property.setLanguageKey("config." + Wizardry.MODID + ".allies_command_name");
property.setRequiresWorldRestart(true);
alliesCommandName = property.getString();
propOrder.add(property.getName());
config.setCategoryPropertyOrder(COMMANDS_CATEGORY, propOrder);
}
private void setupResistancesConfig(){
Property property;
List<String> propOrder = new ArrayList<String>();
config.addCustomCategoryComment(RESISTANCES_CATEGORY,
"Settings which allow entities to be made immune to certain types of magic. In multiplayer, the server/LAN host settings will apply.");
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToFire", new String[]{},
"List of names of entities that are immune to fire, in addition to the defaults. Add mod creatures to this list if you want them to be immune to fire magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_fire");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < property.getStringList().length; i++){
property.getStringList()[i] = property.getStringList()[i].toLowerCase(Locale.ROOT).trim();
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.FIRE);
}
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToIce", new String[]{},
"List of names of entities that are immune to ice, in addition to the defaults. Add mod creatures to this list if you want them to be immune to ice magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_ice");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < property.getStringList().length; i++){
property.getStringList()[i] = property.getStringList()[i].toLowerCase(Locale.ROOT).trim();
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.FROST);
}
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToLightning", new String[]{},
"List of names of entities that are immune to lightning, in addition to the defaults. Add mod creatures to this list if you want them to be immune to lightning magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_lightning");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < property.getStringList().length; i++){
property.getStringList()[i] = property.getStringList()[i].toLowerCase(Locale.ROOT).trim();
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.SHOCK);
}
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToWither", new String[]{},
"List of names of entities that are immune to wither effects, in addition to the defaults. Add mod creatures to this list if you want them to be immune to withering magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_wither");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < property.getStringList().length; i++){
property.getStringList()[i] = property.getStringList()[i].toLowerCase(Locale.ROOT).trim();
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.WITHER);
}
propOrder.add(property.getName());
property = config.get(RESISTANCES_CATEGORY, "mobsImmuneToPoison", new String[]{},
"List of names of entities that are immune to poison, in addition to the defaults. Add mod creatures to this list if you want them to be immune to poison magic and they aren't already. Entity names are not case sensitive. For mod entities, prefix with the mod ID (e.g. " + Wizardry.MODID + ":wizard).");
property.setLanguageKey("config." + Wizardry.MODID + ".mobs_immune_to_poison");
property.setRequiresMcRestart(true);
// Wizardry.proxy.setToEntityNameEntry(property);
// Converts all strings in the list to lower case, to ignore case sensitivity, and trims them.
for(int i = 0; i < property.getStringList().length; i++){
property.getStringList()[i] = property.getStringList()[i].toLowerCase(Locale.ROOT).trim();
MagicDamage.addEntityImmunity(EntityList.getClass(new ResourceLocation(property.getStringList()[i])),
DamageType.POISON);
}
propOrder.add(property.getName());
config.setCategoryPropertyOrder(RESISTANCES_CATEGORY, propOrder);
}
}
@@ -15,127 +15,110 @@ import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World;
import net.minecraft.world.storage.WorldSavedData;
import net.minecraft.world.WorldSavedData;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
/**
* Class responsible for generating and storing the randomised spell names and descriptions for each world, which are
/** Class responsible for generating and storing the randomised spell names and descriptions for each world, which are
* displayed as glyphs using the SGA font renderer.
*
* @since Wizardry 1.1
*/
@Mod.EventBusSubscriber
* @since Wizardry 1.1 */
public class SpellGlyphData extends WorldSavedData {
public static final String NAME = Wizardry.MODID + "_glyphData";
private static final String NAME = Wizardry.MODID + "_glyphData";
public Map<Spell, String> randomNames = new HashMap<Spell, String>(Spell.getTotalSpellCount());
public Map<Spell, String> randomDescriptions = new HashMap<Spell, String>(Spell.getTotalSpellCount());
// Required constructors
public SpellGlyphData(){
public SpellGlyphData() {
this(NAME);
}
public SpellGlyphData(String name){
super(name);
}
/** Generates random names and descriptions for any spells which don't already have them. */
public void generateGlyphNames(World world){
for(Spell spell : Spell.getSpells(Spell.allSpells)){
if(!randomNames.containsKey(spell)) randomNames.put(spell, generateRandomName(world.rand));
}
for(Spell spell : Spell.getSpells(Spell.allSpells)){
if(!randomDescriptions.containsKey(spell))
randomDescriptions.put(spell, generateRandomDescription(world.rand));
if(!randomDescriptions.containsKey(spell)) randomDescriptions.put(spell, generateRandomDescription(world.rand));
}
this.markDirty();
}
private String generateRandomName(Random random){
String name = "";
for(int i = 0; i < random.nextInt(2) + 2; i++){
for(int i=0; i<random.nextInt(2)+2; i++){
name = name + RandomStringUtils.random(3 + random.nextInt(5), "abcdefghijklmnopqrstuvwxyz") + " ";
}
return name.trim();
}
private String generateRandomDescription(Random random){
String name = "";
for(int i = 0; i < random.nextInt(16) + 8; i++){
for(int i=0; i<random.nextInt(16)+8; i++){
name = name + RandomStringUtils.random(2 + random.nextInt(7), "abcdefghijklmnopqrstuvwxyz") + " ";
}
return name.trim();
}
/**
* Returns the spell glyph data for this world, or creates a new instance if it doesn't exist yet. Also checks for
* any spells that are missing glyph data and adds it accordingly.
*/
public static SpellGlyphData get(World world){
/** Returns the spell glyph data for this world, or creates a new instance if it doesn't exist yet. Also checks
* for any spells that are missing glyph data and adds it accordingly. */
public static SpellGlyphData get(World world) {
SpellGlyphData instance = (SpellGlyphData)world.loadData(SpellGlyphData.class, NAME);
SpellGlyphData instance = (SpellGlyphData) world.loadItemData(SpellGlyphData.class, NAME);
if(instance == null){
instance = new SpellGlyphData();
}
// These two conditions are a bit of backwards compatibility from when I added the descriptions to the
// glyph data. Shouldn't be needed in normal operation, but I might as well leave it here.
// Edit: More backwards compatibility, this time for the future - should any new spells be added, this now
// ensures
// Edit: More backwards compatibility, this time for the future - should any new spells be added, this now ensures
// existing worlds will generate random names and descriptions for any new spells whilst keeping the old ones.
if(instance.randomNames.size() < Spell.getTotalSpellCount()
|| instance.randomDescriptions.size() < Spell.getTotalSpellCount()){
if(instance.randomNames.size() < Spell.getTotalSpellCount() || instance.randomDescriptions.size() < Spell.getTotalSpellCount()){
instance.generateGlyphNames(world);
world.setData(NAME, instance);
world.setItemData(NAME, instance);
}
return instance;
}
/** Sends the random spell names for this world to the specified player's client. */
public void sync(EntityPlayerMP player){
List<String> names = new ArrayList<String>();
List<String> descriptions = new ArrayList<String>();
for(Spell spell : Spell.getSpells(Spell.allSpells)){
names.add(this.randomNames.get(spell));
descriptions.add(this.randomDescriptions.get(spell));
}
PacketGlyphData.Message msg = new PacketGlyphData.Message(names, descriptions);
WizardryPacketHandler.net.sendTo(msg, player);
Wizardry.logger.info("Synchronising spell glyph data for " + player.getName());
}
/** Helper method to retrieve the random glyph name for the given spell from the map stored in the given world. */
public static String getGlyphName(Spell spell, World world){
Map<Spell, String> names = SpellGlyphData.get(world).randomNames;
return names == null ? "" : names.get(spell);
}
/**
* Helper method to retrieve the random glyph description for the given spell from the map stored in the given
* world.
*/
/** Helper method to retrieve the random glyph description for the given spell from the map stored in the given world. */
public static String getGlyphDescription(Spell spell, World world){
Map<Spell, String> descriptions = SpellGlyphData.get(world).randomDescriptions;
return descriptions == null ? "" : descriptions.get(spell);
@@ -143,13 +126,13 @@ public class SpellGlyphData extends WorldSavedData {
@Override
public void readFromNBT(NBTTagCompound nbt){
this.randomNames = new HashMap<Spell, String>();
this.randomDescriptions = new HashMap<Spell, String>();
NBTTagList tagList = nbt.getTagList("spellGlyphData", NBT.TAG_COMPOUND);
for(int i = 0; i < tagList.tagCount(); i++){
for(int i=0; i<tagList.tagCount(); i++){
NBTTagCompound tag = tagList.getCompoundTagAt(i);
randomNames.put(Spell.get(tag.getInteger("spell")), tag.getString("name"));
randomDescriptions.put(Spell.get(tag.getInteger("spell")), tag.getString("description"));
@@ -157,10 +140,10 @@ public class SpellGlyphData extends WorldSavedData {
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt){
public void writeToNBT(NBTTagCompound nbt){
NBTTagList tagList = new NBTTagList();
for(Spell spell : Spell.getSpells(Spell.allSpells)){
// Much like the enchantments tag for items, this stores a list of spell-id-to-name tag pairs
// The description is now also included; there's no point in making a second compound tag!
@@ -170,18 +153,7 @@ public class SpellGlyphData extends WorldSavedData {
tag.setString("description", this.randomDescriptions.get(spell));
tagList.appendTag(tag);
}
nbt.setTag("spellGlyphData", tagList);
return nbt;
}
@SubscribeEvent
public static void onWorldLoadEvent(WorldEvent.Load event){
if(!event.getWorld().isRemote && event.getWorld().provider.getDimension() == 0){
// Called to initialise the spell glyph data when a world loads, if it isn't already.
// NOTE: Do we actually need this, or can we just let it initialise the first time it is needed? (see below)
SpellGlyphData.get(event.getWorld());
}
}
}
@@ -1,43 +1,34 @@
package electroblob.wizardry.util;
package electroblob.wizardry;
import java.util.Collections;
import java.util.HashMap;
import java.util.Set;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.spell.Spell;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
/**
* Much like {@link net.minecraft.enchantment.EnchantmentHelper EnchantmentHelper}, this class has some static methods
/** Much like {@link net.minecraft.enchantment.EnchantmentHelper EnchantmentHelper}, this class has some static methods
* which allow cleaner and more concise interaction with the wand NBT data, which is quite a complex structure. Such
* interaction previously resulted in rather verbose and repetitive code which was hard to read and even harder to
* debug! For example, this class allowed {@link electroblob.wizardry.item.ItemWand ItemWand} to be shortened by about
* 80 lines. In addition, by having all the various null checks and array size checks in one place, the chance of
* accidental errors due to forgetting to check these things is greatly reduced.
* interaction previously resulted in rather verbose and repetitive code which was hard to read and even harder to debug!
* For example, this class allowed {@link electroblob.wizardry.item.ItemWand ItemWand} to be shortened by about 80 lines.
* In addition, by having all the various null checks and array size checks in one place, the chance of accidental errors
* due to forgetting to check these things is greatly reduced.
* <p>
* Note that these methods contain no game logic at all; they are purely for interacting with the NBT data. Conversely,
* you should never need to access the wand's NBT data directly when using this class, but the keys are public in the
* unlikely case that this is necessary.
* <p>
* Also note that none of the methods in this class actually check that the given ItemStack contains an ItemWand; you
* can, for example, pass in a stack of snowballs without causing problems, but that is of course pointless! However, if
* you have your own spell casting item (which doesn't extend ItemWand), this setup means you can still use this class
* to manage its NBT structure.
* can, for example, pass in a stack of snowballs without causing problems, but that is of course pointless!
* <p>
* All <b>get</b> methods in this class return some kind of default if the passed-in wand stack has no nbt data. See
* individual method descriptions for more details.<br>
* All <b>set</b> methods in this class create a new nbt data for the passed-in wand if it has none, before doing
* All <b>get</b> methods in this class return some kind of default if the passed-in wand stack has no nbt data.<br>
* All <b>set</b> methods in this class create a new nbt data for the passed-in wand if it has none, before doing
* whatever else they do.
*
* @see electroblob.wizardry.item.ItemWand ItemWand
* @see electroblob.wizardry.packet.PacketControlInput PacketControlInput
* @since Wizardry 1.1
*/
public final class WandHelper {
* @since Wizardry 1.1 */
public class WandHelper {
// NBT tag keys
public static final String SPELL_ARRAY_KEY = "spells";
@@ -47,33 +38,31 @@ public final class WandHelper {
private static final HashMap<Item, String> upgradeMap = new HashMap<Item, String>();
static{
upgradeMap.put(WizardryItems.condenser_upgrade, "condenser");
upgradeMap.put(WizardryItems.storage_upgrade, "storage");
upgradeMap.put(WizardryItems.siphon_upgrade, "siphon");
upgradeMap.put(WizardryItems.range_upgrade, "range");
upgradeMap.put(WizardryItems.duration_upgrade, "duration");
upgradeMap.put(WizardryItems.cooldown_upgrade, "cooldown");
upgradeMap.put(WizardryItems.blast_upgrade, "blast");
upgradeMap.put(WizardryItems.attunement_upgrade, "attunement");
static {
upgradeMap.put(Wizardry.condenserUpgrade, "condenser");
upgradeMap.put(Wizardry.storageUpgrade, "storage");
upgradeMap.put(Wizardry.siphonUpgrade, "siphon");
upgradeMap.put(Wizardry.rangeUpgrade, "range");
upgradeMap.put(Wizardry.durationUpgrade, "duration");
upgradeMap.put(Wizardry.cooldownUpgrade, "cooldown");
upgradeMap.put(Wizardry.blastUpgrade, "blast");
upgradeMap.put(Wizardry.attunementUpgrade, "attunement");
}
/**
* Returns an array containing the spells currently bound to the given wand. As of Wizardry 1.1, this array is not
/** Returns an array containing the spells currently bound to the given wand. As of Wizardry 1.1, this array is not
* always the same size; it can be anywhere between 5 and 8 (inclusive) in length. If the wand has no spell data,
* returns an array of length 0.
*/
* returns an array of length 0. */
public static Spell[] getSpells(ItemStack wand){
Spell[] spells = new Spell[0];
if(wand.getTagCompound() != null){
if(wand.stackTagCompound != null){
int[] spellIDs = wand.getTagCompound().getIntArray(SPELL_ARRAY_KEY);
int[] spellIDs = wand.stackTagCompound.getIntArray(SPELL_ARRAY_KEY);
spells = new Spell[spellIDs.length];
for(int i = 0; i < spellIDs.length; i++){
for(int i=0; i<spellIDs.length; i++){
spells[i] = Spell.get(spellIDs[i]);
}
}
@@ -81,21 +70,18 @@ public final class WandHelper {
return spells;
}
/**
* Binds the given array of spells to the given wand. The array can be anywhere between 5 and 8 (inclusive) in
* length.
*/
/** Binds the given array of spells to the given wand. The array can be anywhere between 5 and 8 (inclusive) in length. */
public static void setSpells(ItemStack wand, Spell[] spells){
if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound()));
if(wand.stackTagCompound == null) wand.stackTagCompound = new NBTTagCompound();
int[] spellIDs = new int[spells.length];
for(int i = 0; i < spells.length; i++){
spellIDs[i] = spells[i] != null ? spells[i].id() : Spells.none.id();
for(int i=0; i<spells.length; i++){
spellIDs[i] = spells[i] != null ? spells[i].id() : WizardryRegistry.none.id();
}
wand.getTagCompound().setIntArray(SPELL_ARRAY_KEY, spellIDs);
wand.stackTagCompound.setIntArray(SPELL_ARRAY_KEY, spellIDs);
}
/** Returns the currently selected spell for the given wand, or the 'none' spell if the wand has no spell data. */
@@ -103,28 +89,28 @@ public final class WandHelper {
Spell[] spells = getSpells(wand);
if(wand.getTagCompound() != null){
if(wand.stackTagCompound != null){
int selectedSpell = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY);
int selectedSpell = wand.stackTagCompound.getInteger(SELECTED_SPELL_KEY);
if(selectedSpell >= 0 && selectedSpell < spells.length){
if(selectedSpell < spells.length && selectedSpell >= 0){
return spells[selectedSpell];
}
}
return Spells.none;
return WizardryRegistry.none;
}
/** Selects the next spell in this wand's list of spells. */
public static void selectNextSpell(ItemStack wand){
// 5 here because if the spell array doesn't exist, the wand can't possibly have attunement upgrades
if(getSpells(wand).length < 0) setSpells(wand, new Spell[5]);
if(wand.getTagCompound() != null){
if(wand.stackTagCompound != null){
int numberOfSpells = getSpells(wand).length;
int selectedSpell = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY);
int selectedSpell = wand.stackTagCompound.getInteger(SELECTED_SPELL_KEY);
// Greater than or equal to so that if attunement upgrades are somehow removed by NBT modification it just
// resets.
if(selectedSpell >= numberOfSpells - 1){
@@ -132,45 +118,43 @@ public final class WandHelper {
}else{
selectedSpell++;
}
wand.getTagCompound().setInteger(SELECTED_SPELL_KEY, selectedSpell);
wand.stackTagCompound.setInteger(SELECTED_SPELL_KEY, selectedSpell);
}
}
/** Selects the previous spell in this wand's list of spells. */
public static void selectPreviousSpell(ItemStack wand){
// 5 here because if the spell array doesn't exist, the wand can't possibly have attunement upgrades
if(getSpells(wand).length < 0) setSpells(wand, new Spell[5]);
// This cannot possibly be null here, and yet I am getting an NPE...
if(wand.getTagCompound() != null){
if(wand.stackTagCompound != null){
int numberOfSpells = getSpells(wand).length;
int selectedSpell = wand.getTagCompound().getInteger(SELECTED_SPELL_KEY);
int selectedSpell = wand.stackTagCompound.getInteger(SELECTED_SPELL_KEY);
if(selectedSpell <= 0){
selectedSpell = numberOfSpells - 1;
}else{
selectedSpell--;
}
wand.getTagCompound().setInteger(SELECTED_SPELL_KEY, selectedSpell);
wand.stackTagCompound.setInteger(SELECTED_SPELL_KEY, selectedSpell);
}
}
/**
* Returns an array of the cooldowns for each spell bound to the given wand. As of Wizardry 1.1, this array is not
/** Returns an array of the cooldowns for each spell bound to the given wand. As of Wizardry 1.1, this array is not
* always the same size; it can be anywhere between 5 and 8 (inclusive) in length. If the wand has no cooldown data,
* returns an array of length 0.
*/
* returns an array of length 0. */
public static int[] getCooldowns(ItemStack wand){
int[] cooldowns = new int[0];
if(wand.getTagCompound() != null){
if(wand.stackTagCompound != null){
return wand.getTagCompound().getIntArray(COOLDOWN_ARRAY_KEY);
return wand.stackTagCompound.getIntArray(COOLDOWN_ARRAY_KEY);
}
return cooldowns;
@@ -179,9 +163,9 @@ public final class WandHelper {
/** Sets the given wand's cooldown array. The array can be anywhere between 5 and 8 (inclusive) in length. */
public static void setCooldowns(ItemStack wand, int[] cooldowns){
if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound()));
if(wand.stackTagCompound == null) wand.stackTagCompound = new NBTTagCompound();
wand.getTagCompound().setIntArray(COOLDOWN_ARRAY_KEY, cooldowns);
wand.stackTagCompound.setIntArray(COOLDOWN_ARRAY_KEY, cooldowns);
}
/** Decrements the cooldown for each spell bound to the given wand by 1, if that cooldown is greater than 0. */
@@ -192,7 +176,7 @@ public final class WandHelper {
// If there are no cooldowns, it is assumed that they are all zero and therefore nothing needs to be done.
if(cooldowns.length == 0) return;
for(int i = 0; i < cooldowns.length; i++){
for(int i=0; i<cooldowns.length; i++){
if(cooldowns[i] > 0) cooldowns[i]--;
}
@@ -206,13 +190,13 @@ public final class WandHelper {
if(cooldowns.length == 0) return 0;
// Don't need to check if the tag compound is null since the above check is equivalent.
return cooldowns[wand.getTagCompound().getInteger(SELECTED_SPELL_KEY)];
return cooldowns[wand.stackTagCompound.getInteger(SELECTED_SPELL_KEY)];
}
/** Sets the given wand's cooldown for the currently selected spell. */
public static void setCurrentCooldown(ItemStack wand, int cooldown){
if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound()));
if(wand.stackTagCompound == null) wand.stackTagCompound = new NBTTagCompound();
int[] cooldowns = getCooldowns(wand);
@@ -220,31 +204,27 @@ public final class WandHelper {
// cast, which is impossible if there are no spells.
if(cooldowns.length == 0) cooldowns = new int[getSpells(wand).length];
cooldowns[wand.getTagCompound().getInteger(SELECTED_SPELL_KEY)] = cooldown;
cooldowns[wand.stackTagCompound.getInteger(SELECTED_SPELL_KEY)] = cooldown;
setCooldowns(wand, cooldowns);
}
/**
* Returns the number of upgrades of the given type that have been applied to the given wand, or 0 if the wand has
* no upgrade data or the given item is not a valid wand upgrade.
*/
/** Returns the number of upgrades of the given type that have been applied to the given wand, or 0 if the wand has
* no upgrade data or the given item is not a valid wand upgrade. */
public static int getUpgradeLevel(ItemStack wand, Item upgrade){
String key = upgradeMap.get(upgrade);
if(wand.getTagCompound() != null && wand.getTagCompound().hasKey(UPGRADES_KEY) && key != null){
return wand.getTagCompound().getCompoundTag(UPGRADES_KEY).getInteger(key);
if(wand.stackTagCompound != null && wand.stackTagCompound.hasKey(UPGRADES_KEY) && key != null){
return wand.stackTagCompound.getCompoundTag(UPGRADES_KEY).getInteger(key);
}
return 0;
}
/**
* Returns the total number of upgrades that have been applied to the given wand, or 0 if the wand has no upgrade
* data.
*/
/** Returns the total number of upgrades that have been applied to the given wand, or 0 if the wand has no upgrade
* data. */
public static int getTotalUpgrades(ItemStack wand){
int totalUpgrades = 0;
@@ -256,61 +236,42 @@ public final class WandHelper {
return totalUpgrades;
}
/**
* Applies the given upgrade to the given wand, or in other words increases the level for that upgrade by 1. This
* does <b>not</b> account for the individual or total upgrade stack limits.
*/
/** Applies the given upgrade to the given wand, or in other words increases the level for that upgrade by 1. This
* does <b>not</b> account for the individual or total upgrade stack limits. */
public static void applyUpgrade(ItemStack wand, Item upgrade){
if(wand.getTagCompound() == null) wand.setTagCompound((new NBTTagCompound()));
if(wand.stackTagCompound == null) wand.stackTagCompound = new NBTTagCompound();
if(!wand.getTagCompound().hasKey(UPGRADES_KEY))
wand.getTagCompound().setTag(UPGRADES_KEY, new NBTTagCompound());
if(!wand.stackTagCompound.hasKey(UPGRADES_KEY)) wand.stackTagCompound.setTag(UPGRADES_KEY, new NBTTagCompound());
NBTTagCompound upgrades = wand.getTagCompound().getCompoundTag(UPGRADES_KEY);
NBTTagCompound upgrades = wand.stackTagCompound.getCompoundTag(UPGRADES_KEY);
String key = upgradeMap.get(upgrade);
if(key != null) upgrades.setInteger(key, upgrades.getInteger(key) + 1);
wand.getTagCompound().setTag(UPGRADES_KEY, upgrades);
wand.stackTagCompound.setTag(UPGRADES_KEY, upgrades);
}
/** Returns true if the given item is a valid special wand upgrade. */
public static boolean isWandUpgrade(Item upgrade){
return upgradeMap.containsKey(upgrade);
}
/** Returns an unmodifiable set of all the items which are valid special wand upgrades. */
/** Returns a set of all the items which are valid special wand upgrades. */
public static Set<Item> getSpecialUpgrades(){
return Collections.unmodifiableSet(WandHelper.upgradeMap.keySet());
return WandHelper.upgradeMap.keySet();
}
/**
* Package-protected getter for the identifier that corresponds to the given item, used only in the
* {@link SpellModifiers} class. Internal to Wizardry.
*
* @throws IllegalArgumentException if the given item is not a registered special wand upgrade.
*/
static String getIdentifier(Item upgrade){
if(!isWandUpgrade(upgrade)) throw new IllegalArgumentException(
"Tried to get a wand upgrade key for an item" + "that is not a registered special wand upgrade.");
return upgradeMap.get(upgrade);
}
/**
* Registers a special upgrade with wizardry. Not used in the base mod, but I've put it here to make it easy for
* add-ons to add new wand upgrades.
*
/** Registers a special upgrade with wizardry. Not used in the base mod, but I've put it here to make it easy
* for add-ons to add new wand upgrades.
* @param upgrade The wand upgrade item
* @param identifier A unique string, used as a key for wand nbt tags
* @throws IllegalArgumentException if the passed in identifier is already used for another wand upgrade
*/
* @throws IllegalArgumentException if the passed in identifier is already used for another wand upgrade */
public static void registerSpecialUpgrade(Item upgrade, String identifier){
// Throwing an exception is the best thing to do here, since if a duplicate was allowed weird things would
// happen later with wand NBT.
if(upgradeMap.containsValue(identifier))
throw new IllegalArgumentException("Duplicate wand upgrade identifier: " + identifier);
if(upgradeMap.containsValue(identifier)) throw new IllegalArgumentException("Duplicate wand upgrade identifier: " + identifier);
upgradeMap.put(upgrade, identifier);
}
}
@@ -0,0 +1,64 @@
package electroblob.wizardry;
import java.util.Random;
import electroblob.wizardry.item.ItemScroll;
import electroblob.wizardry.item.ItemSpellBook;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.item.ItemWizardArmour;
import electroblob.wizardry.spell.Spell;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraftforge.common.ChestGenHooks;
public class WeightedRandomSpellBook extends WeightedRandomChestContent{
public WeightedRandomSpellBook(ItemStack par1ItemStack, int par2, int par3,
int par4) {
super(par1ItemStack, par2, par3, par4);
}
/* A brief comment about dungeon loot:
* Tiers are weighted as per usual. Elements all have equal chance, INCLUDING simple stuff. The main reason for
* this is that dungeon loot is not that common anyway, so making elemental gear even rarer would be too much.
*/
protected ItemStack[] generateChestContent(Random random, IInventory newInventory){
if(theItemId.getItem() instanceof ItemSpellBook){
theItemId = new ItemStack(theItemId.getItem(), 1, WizardryUtilities.getStandardWeightedRandomSpellId(random));
}else if(theItemId.getItem() instanceof ItemWand){
theItemId = new ItemStack(WizardryUtilities.getWand(EnumTier.BASIC, EnumElement.values()[random.nextInt(EnumElement.values().length)]));
}else if(theItemId.getItem() instanceof ItemWizardArmour){
theItemId = new ItemStack(WizardryUtilities.getArmour(EnumElement.values()[random.nextInt(EnumElement.values().length)], random.nextInt(3)));
}else if(theItemId.getItem() instanceof ItemScroll){
int spellId = WizardryUtilities.getStandardWeightedRandomSpellId(random, true);
theItemId = new ItemStack(theItemId.getItem(), 1, spellId);
}else if(theItemId.getItem() == Wizardry.condenserUpgrade){
switch(random.nextInt(8)){
case 0: theItemId = new ItemStack(Wizardry.condenserUpgrade); break;
case 1: theItemId = new ItemStack(Wizardry.siphonUpgrade); break;
case 2: theItemId = new ItemStack(Wizardry.rangeUpgrade); break;
case 3: theItemId = new ItemStack(Wizardry.cooldownUpgrade); break;
case 4: theItemId = new ItemStack(Wizardry.durationUpgrade); break;
case 5: theItemId = new ItemStack(Wizardry.storageUpgrade); break;
case 6: theItemId = new ItemStack(Wizardry.blastUpgrade); break;
case 7: theItemId = new ItemStack(Wizardry.attunementUpgrade); break;
}
}
return ChestGenHooks.generateStacks(random, theItemId, theMinimumChanceToGenerateItem, theMaximumChanceToGenerateItem);
}
}
@@ -1,715 +0,0 @@
package electroblob.wizardry;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.enchantment.Imbuement;
import electroblob.wizardry.entity.EntityShield;
import electroblob.wizardry.entity.living.ISummonedCreature;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.event.SpellCastEvent.Source;
import electroblob.wizardry.packet.PacketCastContinuousSpell;
import electroblob.wizardry.packet.PacketPlayerSync;
import electroblob.wizardry.packet.PacketTransportation;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryAdvancementTriggers;
import electroblob.wizardry.spell.None;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.SpellModifiers;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
/**
* Capability-based replacement for the old ExtendedPlayer class from 1.7.10. This has been reworked to leave minimum
* external changes (for my own sanity, mainly!). Turns out the only major difference between an internal capability and
* an IEEP is a couple of redundant classes and a different way of registering it.
* <p>
* Forge seems to have separate classes to hold the Capability<...> instance ('key') and methods for getting the
* capability, but in my opinion there are already too many classes to deal with, so I'm not adding any more than are
* necessary, meaning those constants and values are kept here instead.
*
* @since Wizardry 2.1
* @author Electroblob
*/
// On the plus side, having to rethink this class allowed me to clean it up a lot.
@Mod.EventBusSubscriber
public class WizardData implements INBTSerializable<NBTTagCompound> {
/** Static instance of what I like to refer to as the capability key. Private because, well, it's internal! */
// This annotation does some crazy Forge magic behind the scenes and assigns this field a value.
@CapabilityInject(WizardData.class)
private static final Capability<WizardData> WIZARD_DATA_CAPABILITY = null;
/** The player this WizardData instance belongs to. */
private final EntityPlayer player;
// This one is still necessary, because I can't override the equip animation for items that aren't from Wizardry.
private Map<Imbuement, Integer> imbuementDurations;
public boolean hasSpiritWolf;
public boolean hasSpiritHorse;
/**
* Whether this player is currently casting a continuous spell via commands. Not saved over world reload and reset
* on player death.
*/
private Spell currentlyCasting;
/**
* The time for which this player has been casting a continuous spell via commands. Increments by 1 each tick. Not
* saved over world reload and reset on player death.
*/
private int castingTick;
/**
* SpellModifiers object for the current continuous spell cast via commands. Not saved over world reload and reset
* on player death.
*/
private SpellModifiers spellModifiers;
/** Coordinates for the saved transportation stone circle location. Will be null if no location is saved. */
private BlockPos stoneCircleLocation;
/** Dimension id which the saved stone circle is in. */
private int stoneCircleDimension;
/** Time left until the player teleports under the effect of transportation */
private int tpCountdown;
/** Coordinates for the saved clairvoyance location. Will be null if no location is saved. */
private BlockPos clairvoyanceLocation;
/** Dimension id which the saved clairvoyance point is in. */
private int clairvoyanceDimension;
public EntityShield shield;
public WeakReference<ISummonedCreature> selectedMinion;
/**
* Set of this player's discovered spells. <b>Do not write to this list directly</b>, use
* {@link WizardData#discoverSpell(Spell)} instead.
*/
public Set<Spell> spellsDiscovered;
private Set<UUID> allies;
/**
* List of usernames of this player's allies. May not be accurate 100% of the time. This is here so that a player
* can view the usernames of their allies even when those allies are not online. <b> Do not use this for any other
* purpose than displaying the names!
*/
public Set<String> allyNames;
private Set<UUID> soulboundCreatures;
public WizardData(){
this(null); // Nullary constructor for the registration method factory parameter
}
public WizardData(EntityPlayer player){
this.player = player;
this.imbuementDurations = new HashMap<Imbuement, Integer>();
this.spellsDiscovered = new HashSet<Spell>();
// All players can recognise magic missile. This is not done using discoverSpell because that seems to cause
// a crash on load occasionally (probably something to do with achievements being initalised)
this.spellsDiscovered.add(Spells.magic_missile);
this.hasSpiritWolf = false;
this.hasSpiritHorse = false;
this.currentlyCasting = Spells.none;
this.spellModifiers = new SpellModifiers();
this.castingTick = 0;
this.stoneCircleDimension = 0;
this.clairvoyanceDimension = 0;
this.setTpCountdown(0);
this.allies = new HashSet<UUID>();
this.allyNames = new HashSet<String>();
this.soulboundCreatures = new HashSet<UUID>();
}
public boolean hasSpellBeenDiscovered(Spell spell){
return spellsDiscovered.contains(spell) || spell instanceof None;
}
/**
* Adds the given spell to the list of discovered spells for this player. Automatically takes into account whether
* the spell has been discovered. Use this method rather than adding directly to the list because it handles
* achievements.
*
* @param spell The spell to be discovered
* @return True if the spell had not already been discovered; false otherwise.
*/
public boolean discoverSpell(Spell spell){
if(spellsDiscovered == null){
spellsDiscovered = new HashSet<Spell>();
}
// The 'none' spell cannot be discovered
if(spell instanceof None) return false;
// Tries to add the spell to the list of discovered spells, and returns false if it was already present
if(!spellsDiscovered.add(spell)) return false;
// If the spell had not already been discovered, achievements can be triggered and the method returns true
if(spellsDiscovered.containsAll(Spell.getSpells(Spell::isEnabled))){
WizardryAdvancementTriggers.all_spells.triggerFor(this.player);
}
for(Element element : Element.values()){
if(element != Element.MAGIC
&& spellsDiscovered.containsAll(Spell.getSpells(new Spell.TierElementFilter(null, element)))){
WizardryAdvancementTriggers.element_master.triggerFor(this.player);
}
}
return true;
}
/** Sets the player's saved transportation stone location and dimension. */
public void setStoneCircleLocation(BlockPos pos, int dimensionID){
this.stoneCircleLocation = pos;
this.stoneCircleDimension = dimensionID;
}
/** Returns the coordinates of the associated player's saved transportation stone circle. */
public BlockPos getStoneCircleLocation(){
return stoneCircleLocation;
}
/** Returns the dimension ID of the associated player's saved transportation stone circle. */
public int getStoneCircleDimension(){
return stoneCircleDimension;
}
public int getTpCountdown(){
return tpCountdown;
}
public void setTpCountdown(int tpCountdown){
this.tpCountdown = tpCountdown;
}
/** Sets the player's saved clairvoyance location. */
public void setClairvoyancePoint(BlockPos pos, int dimensionID){
this.clairvoyanceLocation = pos;
this.clairvoyanceDimension = dimensionID;
}
/** Returns the coordinates for the saved clairvoyance location. Will be null if no location is saved. */
public BlockPos getClairvoyanceLocation(){
return clairvoyanceLocation;
}
/** Returns the dimension ID for the saved clairvoyance location. Will be null if no location is saved. */
public int getClairvoyanceDimension(){
return clairvoyanceDimension;
}
/**
* Overwrites the imbuement duration associated with the given imubement for this player, or creates it if there was
* none previously.
*
* @throws IllegalArgumentException if the given {@link Enchantment} is not an {@link Imbuement}.
*/
public void setImbuementDuration(Enchantment enchantment, int duration){
// It is best to throw an exception here, because otherwise the error would either go unnoticed (if
// non-imbuements
// were ignored) or cause a ClassCastException later (if non-imbuements were allowed to be added).
if(enchantment instanceof Imbuement){
this.imbuementDurations.put((Imbuement)enchantment, duration);
}else{
throw new IllegalArgumentException(
"Attempted to set an imbuement duration for something that isn't an Imbuement! (This exception has been thrown now to prevent a ClassCastException from occurring later.)");
}
}
/**
* Returns the imbuement duration associated with the given imbuement for this player, or 0 if it does not exist.
*/
@SuppressWarnings("unlikely-arg-type")
public int getImbuementDuration(Enchantment enchantment){
// Need to check that i is not null, otherwise it throws an NPE when Java auto-unboxes it.
// What's nice here is that the map simply accepts objects as keys, so there's no need to cast or throw
// exceptions.
Integer i = this.imbuementDurations.get(enchantment);
// If i is null, returns 0; otherwise returns i, auto-unboxed to an int.
return i == null ? 0 : i;
}
/**
* Decrements the duration for each conjured item by 1, and removes from the map any that are 0 or less or that the
* player no longer has. Also deletes the item from the player's inventory if it runs out of time.
*/
private void updateImbuedItems(){
Set<Imbuement> activeImbuements = new HashSet<Imbuement>();
// For each item in the player's inventory
for(ItemStack stack : player.inventory.mainInventory){
if(stack.isItemEnchanted()){
NBTTagList enchantmentList = stack.getItem() == Items.ENCHANTED_BOOK ?
ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList();
Iterator<NBTBase> iterator =enchantmentList.iterator();
// For each of the item's enchantments
while(iterator.hasNext()){
NBTTagCompound enchantmentTag = (NBTTagCompound) iterator.next();
Enchantment enchantment = Enchantment.getEnchantmentByID(enchantmentTag.getShort("id"));
// Ignores the enchantment unless it is an imbuement
if(enchantment instanceof Imbuement){
int duration = this.getImbuementDuration(enchantment);
// If the imbuement is still active:
if(duration > 0){
// Decrements the timer
this.imbuementDurations.put((Imbuement)enchantment, duration - 1);
// Adds this imbuement to the set of imbuements that need to be kept
activeImbuements.add((Imbuement)enchantment);
// Otherwise:
}else{
// Removes the enchantment from the item
iterator.remove();
}
}
}
}
}
// Removes all imbuements from the map that are no longer active
this.imbuementDurations.keySet().retainAll(activeImbuements);
}
/**
* Adds the given player to the list of allies belonging to the associated player, or removes the player if they are
* already in the list of allies. Returns true if the player was added, false if they were removed.
*/
public boolean toggleAlly(EntityPlayer player){
if(this.isPlayerAlly(player)){
this.allies.remove(player.getUniqueID());
// The remove method uses .equals() rather than == so this will work fine.
this.allyNames.remove(player.getName());
return false;
}else{
this.allies.add(player.getUniqueID());
this.allyNames.add(player.getName());
return true;
}
}
/** Returns whether the given player is in this player's list of allies, or is on the same team as this player. */
public boolean isPlayerAlly(EntityPlayer player){
return this.allies.contains(player.getUniqueID()) || this.player.isOnSameTeam(player);
}
/** Adds the given entity to this player's list of soulbound creatures, and returns whether it succeeded. */
public boolean soulbind(EntityLivingBase target){
return this.soulboundCreatures.add(target.getUniqueID());
}
/** Returns whether the given entity has been soulbound to this player. */
public boolean isCreatureSoulbound(EntityPlayer target){
return this.soulboundCreatures.contains(target.getUniqueID());
}
/**
* Damages all creatures soulbound to this player by the given amount, and removes from the list any that no longer
* exist.
*/
public void damageAllSoulboundCreatures(float damage){
for(Iterator<UUID> iterator = this.soulboundCreatures.iterator(); iterator.hasNext();){
Entity entity = WizardryUtilities.getEntityByUUID(this.player.world, iterator.next());
if(entity == null) iterator.remove();
if(entity instanceof EntityLivingBase){
// Retaliatory effect
if(entity.attackEntityFrom(MagicDamage.causeDirectMagicDamage(this.player, DamageType.MAGIC, true),
damage)){
// Sound only plays if the damage succeeds
player.playSound(SoundEvents.ENTITY_WITHER_HURT, 1.0F, player.world.rand.nextFloat() * 0.2F + 1.0F);
}
}
}
}
/** Starts casting the given spell with the given modifiers. */
public void startCastingContinuousSpell(Spell spell, SpellModifiers modifiers){
this.currentlyCasting = spell;
this.spellModifiers = modifiers;
if(!this.player.world.isRemote){
PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(),
spell.id(), this.spellModifiers);
WizardryPacketHandler.net.sendToDimension(message, this.player.world.provider.getDimension());
}
}
/** Stops casting the current spell. */
public void stopCastingContinuousSpell(){
this.currentlyCasting = Spells.none;
this.castingTick = 0;
this.spellModifiers.reset();
if(!this.player.world.isRemote){
PacketCastContinuousSpell.Message message = new PacketCastContinuousSpell.Message(this.player.getEntityId(),
Spells.none.id(), this.spellModifiers);
WizardryPacketHandler.net.sendToDimension(message, this.player.world.provider.getDimension());
}
}
/** Casts the current continuous spell, fires relevant events and updates the castingTick field. */
public void updateContinuousSpellCasting(){
if(this.currentlyCasting != null && this.currentlyCasting.isContinuous){
if(MinecraftForge.EVENT_BUS.post(
new SpellCastEvent.Tick(player, currentlyCasting, spellModifiers, Source.COMMAND, castingTick))){
this.stopCastingContinuousSpell();
return;
}
if(this.currentlyCasting.cast(player.world, player, EnumHand.MAIN_HAND, castingTick, this.spellModifiers)
&& this.castingTick == 0){
// On the first tick casting a continuous spell via commands, SpellCastEvent.Post is fired.
MinecraftForge.EVENT_BUS
.post(new SpellCastEvent.Post(player, currentlyCasting, spellModifiers, Source.COMMAND));
}
castingTick++;
}else{
// Why is this here? Surely castingTick will always be 0 if currentlyCasting is null?
this.castingTick = 0;
}
}
/** Returns whether this player is currently casting a continuous spell via commands. */
public boolean isCasting(){
return this.currentlyCasting != null && this.currentlyCasting != Spells.none;
}
/**
* Returns the continuous spell this player is currently casting via commands, or the 'none' spell if they aren't
* casting anything.
*/
public Spell currentlyCasting(){
return currentlyCasting;
}
/** Called each time the associated player is updated. */
private void update(){
if(this.selectedMinion != null && this.selectedMinion.get() == null) this.selectedMinion = null;
// This new system removes a lot of repetitive event handler code and inflexible variables which had duplicate
// functions, just for different enchantments.
updateImbuedItems();
if(!player.world.isRemote){
if(getTpCountdown() == 1){
player.setPositionAndUpdate(this.stoneCircleLocation.getX() + 0.5, this.stoneCircleLocation.getY(),
this.stoneCircleLocation.getZ() + 0.5);
player.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, 50, 0));
IMessage msg = new PacketTransportation.Message(player.getEntityId());
WizardryPacketHandler.net.sendToDimension(msg, player.world.provider.getDimension());
}
if(getTpCountdown() > 0){
setTpCountdown(getTpCountdown() - 1);
}
}
updateContinuousSpellCasting();
}
/**
* Returns the WizardData instance for the specified player.
*/
public static final WizardData get(EntityPlayer player){
return player.getCapability(WIZARD_DATA_CAPABILITY, null);
}
/**
* Called from the event handler each time the associated player entity is cloned, i.e. on respawn or when
* travelling to a different dimension. Used to copy over any variables that should persist over player death. This
* is the inverse of the old onPlayerDeath method, which reset the variables that shouldn't persist.
*
* @param data The old WizardData whose variables are to be copied over.
* @param respawn True if the player died and is respawning, false if they are just travelling between dimensions.
*/
public void copyFrom(WizardData data, boolean respawn){
// TODO: What happens with spirit wolf and spirit horse?
this.hasSpiritHorse = data.hasSpiritHorse;
this.hasSpiritWolf = data.hasSpiritWolf;
this.allies = data.allies;
this.allyNames = data.allyNames;
this.clairvoyanceDimension = data.clairvoyanceDimension;
this.clairvoyanceLocation = data.clairvoyanceLocation;
this.selectedMinion = data.selectedMinion;
// Curse of soulbinding is lifted when the caster dies, but not when they switch dimensions.
if(!respawn) this.soulboundCreatures = data.soulboundCreatures;
this.spellsDiscovered = data.spellsDiscovered;
this.stoneCircleDimension = data.stoneCircleDimension;
this.stoneCircleLocation = data.stoneCircleLocation;
// Imbuements are lost on death so their durations do not persist.
// Command spell casting is reset on death so the associated variables do not persist.
// tpCountdown is reset both when the player dies and when they switch dimensions.
}
/** Sends a packet to this player's client to synchronise necessary information. Only called server side. */
public void sync(){
if(this.player instanceof EntityPlayerMP){
int id = -1;
if(this.selectedMinion != null && this.selectedMinion.get() instanceof Entity)
id = ((Entity)this.selectedMinion.get()).getEntityId();
IMessage msg = new PacketPlayerSync.Message(this.spellsDiscovered, id);
WizardryPacketHandler.net.sendTo(msg, (EntityPlayerMP)this.player);
}
}
@Override
public NBTTagCompound serializeNBT(){
NBTTagCompound properties = new NBTTagCompound();
// ...so Java 8 allows you to do stuff like this:
properties.setTag("imbuements", WizardryUtilities.mapToNBT(this.imbuementDurations,
imbuement -> new NBTTagInt(Enchantment.getEnchantmentID((Enchantment)imbuement)), NBTTagInt::new));
properties.setBoolean("hasSpiritWolf", this.hasSpiritWolf);
properties.setBoolean("hasSpiritHorse", this.hasSpiritHorse);
if(this.stoneCircleLocation != null)
properties.setLong("stoneCircleLocation", this.stoneCircleLocation.toLong());
properties.setInteger("stoneCircleDimension", this.stoneCircleDimension);
properties.setInteger("tpCountdown", this.tpCountdown);
if(this.clairvoyanceLocation != null)
properties.setLong("clairvoyanceLocation", this.clairvoyanceLocation.toLong());
properties.setInteger("clairvoyanceDimension", this.getClairvoyanceDimension());
// THIS is why I wrote the list/map <-> NBT methods. Look how neat this is!
properties.setTag("allies", WizardryUtilities.listToNBT(this.allies, WizardryUtilities::UUIDtoTagCompound));
properties.setTag("allyNames", WizardryUtilities.listToNBT(this.allyNames, NBTTagString::new));
properties.setTag("soulboundCreatures",
WizardryUtilities.listToNBT(this.soulboundCreatures, WizardryUtilities::UUIDtoTagCompound));
// Might be worth converting this over to WizardryUtilities.listToNBT.
int[] spells = new int[this.spellsDiscovered.size()];
int i = 0;
for(Spell spell : this.spellsDiscovered){
spells[i] = spell.id();
i++;
}
properties.setIntArray("discoveredSpells", spells);
return properties;
}
@Override
public void deserializeNBT(NBTTagCompound nbt){
if(nbt != null){
this.imbuementDurations = WizardryUtilities.NBTToMap(nbt.getTagList("imbuements", NBT.TAG_COMPOUND),
(NBTTagInt tag) -> (Imbuement)Enchantment.getEnchantmentByID(tag.getInt()), NBTTagInt::getInt);
this.hasSpiritWolf = nbt.getBoolean("hasSpiritWolf");
this.hasSpiritHorse = nbt.getBoolean("hasSpiritHorse");
this.stoneCircleLocation = BlockPos.fromLong(nbt.getLong("stoneCircleLocation"));
this.stoneCircleDimension = nbt.getInteger("stoneCircleDimension");
this.tpCountdown = nbt.getInteger("tpCountdown");
this.clairvoyanceLocation = BlockPos.fromLong(nbt.getLong("clairvoyanceLocation"));
this.clairvoyanceDimension = nbt.getInteger("clairvoyanceDimension");
this.allies = new HashSet<UUID>(WizardryUtilities.NBTToList(nbt.getTagList("allies", NBT.TAG_COMPOUND),
WizardryUtilities::tagCompoundToUUID));
this.allyNames = new HashSet<String>(
WizardryUtilities.NBTToList(nbt.getTagList("allyNames", NBT.TAG_STRING), NBTTagString::getString));
this.soulboundCreatures = new HashSet<UUID>(WizardryUtilities.NBTToList(
nbt.getTagList("soulboundCreatures", NBT.TAG_COMPOUND), WizardryUtilities::tagCompoundToUUID));
this.spellsDiscovered = new HashSet<Spell>();
for(int id : nbt.getIntArray("discoveredSpells")){
spellsDiscovered.add(Spell.get(id));
}
}
}
// Event handlers
@SubscribeEvent
// The type parameter here has to be Entity, not EntityPlayer, or the event won't get fired.
public static void onCapabilityLoad(AttachCapabilitiesEvent<Entity> event){
if(event.getObject() instanceof EntityPlayer)
event.addCapability(new ResourceLocation(Wizardry.MODID, "WizardData"),
new WizardData.Provider((EntityPlayer)event.getObject()));
// This demonstrates why capabilities are badly structured: The following code compiles, but what it does is put
// a player into a CapabilityDispatcher, which is in turn stored in that very same player, which makes no sense
// at all!
// event.addCapability(new ResourceLocation(Wizardry.MODID, "WizardData"), event.getObject());
}
@SubscribeEvent
public static void onPlayerCloneEvent(PlayerEvent.Clone event){
WizardData newData = WizardData.get(event.getEntityPlayer());
WizardData oldData = WizardData.get(event.getOriginal());
newData.copyFrom(oldData, event.isWasDeath());
}
@SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event){
if(!event.getEntity().world.isRemote && event.getEntity() instanceof EntityPlayerMP){
// Synchronises wizard data after loading.
WizardData data = WizardData.get((EntityPlayer)event.getEntity());
if(data != null) data.sync();
}
}
@SubscribeEvent
public static void onLivingUpdateEvent(LivingUpdateEvent event){
if(event.getEntityLiving() instanceof EntityPlayer){
EntityPlayer player = (EntityPlayer)event.getEntityLiving();
if(WizardData.get(player) != null){
WizardData.get(player).update();
}
}
}
/**
* This is a nested class for a few reasons: firstly, it makes sense because instances of this and WizardData go
* hand-in-hand; secondly, it's too short to be worth a separate file; and thirdly (and most importantly) it allows
* me to access WIZARD_DATA_CAPABILITY while keeping it private.
*/
public static class Provider implements ICapabilitySerializable<NBTTagCompound> {
private final WizardData data;
public Provider(EntityPlayer player){
data = new WizardData(player);
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing){
return capability == WIZARD_DATA_CAPABILITY;
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing){
if(capability == WIZARD_DATA_CAPABILITY){
return WIZARD_DATA_CAPABILITY.cast(data);
}
return null;
}
@Override
public NBTTagCompound serializeNBT(){
return data.serializeNBT();
}
@Override
public void deserializeNBT(NBTTagCompound nbt){
data.deserializeNBT(nbt);
}
}
// Ended up deleting IWizardData because it was unnecessary. This is the comment that was at the start of it:
/* I'm not going to lie, I will never find the capabilities system even remotely intuitive so this is a bare-minimum
* approach just to get things working (four classes where one would have done?!) At one point I considered simply
* wrapping my old IEEP inside a single-field capability, but I eventually decided I would at least *try* to do it
* properly.
*
* "...without having to directly implement many interfaces." - Forge Docs. I still can't see what's wrong with
* implementing many interfaces; surely that's what Java interfaces are designed for?
*
* Other things I find annoying: - IStorage. It's completely redundant in the majority of cases, and I don't
* understand why we need yet another separate class. - Making an interface, only to implement it once and once
* only. This completely defeats the point of interfaces. - The EnumFacing parameter, which is again redundant for
* everything that isn't a tile entity. So much for a clean, neat system.
*
* What Forge has effectively done is conflated two different functions: attaching data to stuff and cross-mod
* integration/soft dependencies. I think this is bad design; it would have been better to keep the two features
* separate.
*
* Here's my current understanding of how the capability system works: - You make an interface which defines the
* things your capability can do (this class). I will call this the TEMPLATE. - You implement that interface with
* your default implementation (WizardData). This is the closest analog to your old IEEP implementation class. THIS
* CLASS STORES ALL THE VARIABLES, and hence has one instance for each instance of whatever it is attached to. I
* will call this the DATA. - The DATA class implements INBTSerializable (assuming you want it to be saved, which is
* nearly always the case) - Despite its name, Capability<T> does NOT represent a capability itself. Instead, it
* acts as a sort of identifier/key, the idea being that you can access a particular instance of your DATA given the
* key (which tells forge that you want a capability of type TEMPLATE) and the object you want the DATA for. This is
* what Entity.getCapability(...) does.
*
* To really understand what's going on though, you need to sift through Forge's verbose data structures and find
* where capabilities are actually hooked into vanilla: - Anything that implements ICapabilityProvider will have a
* private CapabilityDispatcher field. This holds other ICapabilityProviders. (I know. This inheritance pattern DOES
* NOT MAKE SENSE, because these could, in theory, be OTHER ENTITIES!) - This field is assigned a value through
* Forge's event factory, which, as we are all familiar with, calls all the methods marked with @SubscribeEvent.
* These methods add individual ICapabilityProviders to a Map stored in the event, which the event factory then
* wraps in a CapabilityDispatcher (which is itself an ICapabilityProvider) for the object that called it. - In your
* event handler, you return a custom ICapabilityProvider which is effectively bolted on to the player, and
* duplicates the ICapabilityProvider methods so you can hook into them and return an instance of your DATA class. -
* Where before there was a simple collection of IEEPs stored in the player, there is now a tree of
* ICapabilityProviders:
*
* - Entity/TileEntity/ItemStack - Vanilla ICapabilityProviders, mostly IItemHandlers, stored as fields. -
* CapabilityDispatcher, stored as a field. - Custom ICapabilityProviders - Custom CapabilityDispatchers - ...
*
* Most importantly, EACH PLAYER HOLDS THEIR OWN INSTANCE OF THIS TREE.
*
* When a capability is retrieved, the following process happens: 1. For the Entity/TileEntity/ItemStack instance,
* ICapabilityProvider.getCapability(...) is called. 2. The request propogates through the tree and finds the
* requested capability. */
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -2,29 +2,34 @@ package electroblob.wizardry;
import java.util.Set;
import cpw.mods.fml.client.IModGuiFactory;
import electroblob.wizardry.client.GuiConfigWizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.IModGuiFactory;
public class WizardryGuiFactory implements IModGuiFactory {
@Override
public void initialize(Minecraft minecraftInstance){
}
@Override
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories(){
return null;
}
@Override
public boolean hasConfigGui(){
return true;
}
@Override
public GuiScreen createConfigGui(GuiScreen parentScreen){
return new GuiConfigWizardry(parentScreen);
}
@Override
public void initialize(Minecraft minecraftInstance)
{
}
@Override
public Class<? extends GuiScreen> mainConfigGuiClass()
{
return GuiConfigWizardry.class;
}
@Override
public Set<RuntimeOptionCategoryElement> runtimeGuiCategories()
{
return null;
}
@Override
public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element)
{
return null;
}
}
@@ -1,5 +1,10 @@
package electroblob.wizardry;
import cpw.mods.fml.common.network.IGuiHandler;
import electroblob.wizardry.client.GuiArcaneWorkbench;
import electroblob.wizardry.client.GuiPortableCrafting;
import electroblob.wizardry.client.GuiSpellBook;
import electroblob.wizardry.client.GuiWizardHandbook;
import electroblob.wizardry.item.ItemSpellBook;
import electroblob.wizardry.item.ItemWizardHandbook;
import electroblob.wizardry.spell.Spell;
@@ -8,52 +13,50 @@ import electroblob.wizardry.tileentity.ContainerPortableWorkbench;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;
public class WizardryGuiHandler implements IGuiHandler {
/** Incrementable index for the gui ID */
private static int nextGuiId = 0;
public static final int SPELL_BOOK = nextGuiId++;
public static final int ARCANE_WORKBENCH = nextGuiId++;
public static final int WIZARD_HANDBOOK = nextGuiId++;
public static final int PORTABLE_CRAFTING = nextGuiId++;
@Override
public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z){
public Object getServerGuiElement(int id, EntityPlayer player, World world,
int x, int y, int z) {
if(id == ARCANE_WORKBENCH){
TileEntity tileEntity = world.getTileEntity(new BlockPos(x, y, z));
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(tileEntity instanceof TileEntityArcaneWorkbench){
return new ContainerArcaneWorkbench(player.inventory, (TileEntityArcaneWorkbench)tileEntity);
return new ContainerArcaneWorkbench(player.inventory, (TileEntityArcaneWorkbench) tileEntity);
}
}else if(id == PORTABLE_CRAFTING){
return new ContainerPortableWorkbench(player.inventory, world, new BlockPos(x, y, z));
}
else if(id == PORTABLE_CRAFTING){
return new ContainerPortableWorkbench(player.inventory, world, x, y, z);
}
return null;
}
@Override
public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z){
public Object getClientGuiElement(int id, EntityPlayer player, World world,
int x, int y, int z) {
if(id == ARCANE_WORKBENCH){
TileEntity tileEntity = world.getTileEntity(new BlockPos(x, y, z));
TileEntity tileEntity = world.getTileEntity(x, y, z);
if(tileEntity instanceof TileEntityArcaneWorkbench){
return new electroblob.wizardry.client.GuiArcaneWorkbench(player.inventory,
(TileEntityArcaneWorkbench)tileEntity);
return new GuiArcaneWorkbench(player.inventory, (TileEntityArcaneWorkbench) tileEntity);
}
}else if(id == WIZARD_HANDBOOK && (player.getHeldItemMainhand().getItem() instanceof ItemWizardHandbook
|| player.getHeldItemOffhand().getItem() instanceof ItemWizardHandbook)){
return new electroblob.wizardry.client.GuiWizardHandbook();
}else if(id == SPELL_BOOK){
if(player.getHeldItemMainhand().getItem() instanceof ItemSpellBook){
return new electroblob.wizardry.client.GuiSpellBook(Spell.get(player.getHeldItemMainhand().getItemDamage()));
}else if(player.getHeldItemOffhand().getItem() instanceof ItemSpellBook){
return new electroblob.wizardry.client.GuiSpellBook(Spell.get(player.getHeldItemOffhand().getItemDamage()));
}
}else if(id == PORTABLE_CRAFTING){
return new electroblob.wizardry.client.GuiPortableCrafting(player.inventory, world, new BlockPos(x, y, z));
}
else if(id == WIZARD_HANDBOOK && player.getHeldItem().getItem() instanceof ItemWizardHandbook){
return new GuiWizardHandbook();
}
else if(id == SPELL_BOOK && player.getHeldItem().getItem() instanceof ItemSpellBook){
return new GuiSpellBook(Spell.get(player.getHeldItem().getItemDamage()));
}
else if(id == PORTABLE_CRAFTING){
return new GuiPortableCrafting(player.inventory, world, x, y, z);
}
return null;
}
@@ -0,0 +1,69 @@
package electroblob.wizardry;
import org.lwjgl.input.Keyboard;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import electroblob.wizardry.client.ClientProxy;
import electroblob.wizardry.packet.PacketControlInput;
import electroblob.wizardry.packet.WizardryPacketHandler;
import net.minecraft.client.Minecraft;
public class WizardryKeyHandler {
boolean NkeyPressed = false;
boolean BkeyPressed = false;
boolean NkeyAlreadyPressed = false;
boolean BkeyAlreadyPressed = false;
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event) {
// Key pressed
if(Keyboard.getEventKeyState()){
if(Wizardry.proxy instanceof ClientProxy){
ClientProxy proxy = (ClientProxy)Wizardry.proxy;
if(proxy.nextSpell.isPressed() && Minecraft.getMinecraft().inGameHasFocus){
if(!NkeyPressed){
NkeyPressed = true;
}else{
NkeyAlreadyPressed = true;
}
if(!NkeyAlreadyPressed){
// Packet building
IMessage msg = new PacketControlInput.Message(1);
WizardryPacketHandler.net.sendToServer(msg);
}
}
if(proxy.previousSpell.isPressed() && Minecraft.getMinecraft().inGameHasFocus){
if(!BkeyPressed){
BkeyPressed = true;
}else{
BkeyAlreadyPressed = true;
}
if(!BkeyAlreadyPressed){
// Packet building
IMessage msg = new PacketControlInput.Message(2);
WizardryPacketHandler.net.sendToServer(msg);
}
}
}
}
// Key released
else{
if(NkeyPressed){
NkeyPressed = false;
NkeyAlreadyPressed = false;
}else if(BkeyPressed){
BkeyPressed = false;
BkeyAlreadyPressed = false;
}
}
}
}
@@ -0,0 +1,631 @@
package electroblob.wizardry;
import java.util.ArrayList;
import java.util.List;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;
import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.entity.EntityFallingGrass;
import electroblob.wizardry.entity.EntityMagicSlime;
import electroblob.wizardry.entity.EntityMeteor;
import electroblob.wizardry.entity.EntityShield;
import electroblob.wizardry.entity.construct.EntityArrowRain;
import electroblob.wizardry.entity.construct.EntityBlackHole;
import electroblob.wizardry.entity.construct.EntityBlizzard;
import electroblob.wizardry.entity.construct.EntityBubble;
import electroblob.wizardry.entity.construct.EntityDecay;
import electroblob.wizardry.entity.construct.EntityEarthquake;
import electroblob.wizardry.entity.construct.EntityFireRing;
import electroblob.wizardry.entity.construct.EntityFireSigil;
import electroblob.wizardry.entity.construct.EntityForcefield;
import electroblob.wizardry.entity.construct.EntityFrostSigil;
import electroblob.wizardry.entity.construct.EntityHailstorm;
import electroblob.wizardry.entity.construct.EntityHammer;
import electroblob.wizardry.entity.construct.EntityHealAura;
import electroblob.wizardry.entity.construct.EntityIceSpike;
import electroblob.wizardry.entity.construct.EntityLightningPulse;
import electroblob.wizardry.entity.construct.EntityLightningSigil;
import electroblob.wizardry.entity.construct.EntityTornado;
import electroblob.wizardry.entity.living.EntityBlazeMinion;
import electroblob.wizardry.entity.living.EntityDecoy;
import electroblob.wizardry.entity.living.EntityEvilWizard;
import electroblob.wizardry.entity.living.EntityIceGiant;
import electroblob.wizardry.entity.living.EntityIceWraith;
import electroblob.wizardry.entity.living.EntityLightningWraith;
import electroblob.wizardry.entity.living.EntityPhoenix;
import electroblob.wizardry.entity.living.EntityShadowWraith;
import electroblob.wizardry.entity.living.EntitySilverfishMinion;
import electroblob.wizardry.entity.living.EntitySkeletonMinion;
import electroblob.wizardry.entity.living.EntitySpiderMinion;
import electroblob.wizardry.entity.living.EntitySpiritHorse;
import electroblob.wizardry.entity.living.EntitySpiritWolf;
import electroblob.wizardry.entity.living.EntityStormElemental;
import electroblob.wizardry.entity.living.EntityWizard;
import electroblob.wizardry.entity.living.EntityZombieMinion;
import electroblob.wizardry.entity.projectile.EntityDarknessOrb;
import electroblob.wizardry.entity.projectile.EntityDart;
import electroblob.wizardry.entity.projectile.EntityFirebolt;
import electroblob.wizardry.entity.projectile.EntityFirebomb;
import electroblob.wizardry.entity.projectile.EntityForceArrow;
import electroblob.wizardry.entity.projectile.EntityForceOrb;
import electroblob.wizardry.entity.projectile.EntityIceCharge;
import electroblob.wizardry.entity.projectile.EntityIceLance;
import electroblob.wizardry.entity.projectile.EntityIceShard;
import electroblob.wizardry.entity.projectile.EntityLightningArrow;
import electroblob.wizardry.entity.projectile.EntityLightningDisc;
import electroblob.wizardry.entity.projectile.EntityMagicMissile;
import electroblob.wizardry.entity.projectile.EntityPoisonBomb;
import electroblob.wizardry.entity.projectile.EntitySmokeBomb;
import electroblob.wizardry.entity.projectile.EntitySpark;
import electroblob.wizardry.entity.projectile.EntitySparkBomb;
import electroblob.wizardry.entity.projectile.EntityThunderbolt;
import electroblob.wizardry.spell.*;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import electroblob.wizardry.tileentity.TileEntityMagicLight;
import electroblob.wizardry.tileentity.TileEntityPlayerSave;
import electroblob.wizardry.tileentity.TileEntityStatue;
import electroblob.wizardry.tileentity.TileEntityTimer;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.WeightedRandomChestContent;
import net.minecraft.world.biome.BiomeGenBase;
import net.minecraftforge.common.ChestGenHooks;
import net.minecraftforge.oredict.OreDictionary;
public final class WizardryRegistry {
// Usage note on ChestGenHooks: First number is minimum, second is maximum. Third is rarity, lower numbers are more rare [bread = 100].
// i starts at 1 here so that 'none' does not spawn.
// Earlier problem solved using clever forge hook - extend WeightedRandomChestContent and override generateChestContent.
// Apparently this seems to be incompatible with roguelike dungeons (any others?), in that it generates the same spell book in
// all of the chests that have a spell book in the same dungeon (usually, though it has been known to do different ones on
// different floors). It also appears to be able to generate the 'none' book, which should be impossible... never mind.
// I don't think that's my fault, or I would have seen a 'none' book in a vanilla dungeon by now.
// Another curious observation: Recurrent complex's generators also seem to always generate the same book/wand/armour
// until you restart the game and can generate the 'none' book as well.
// My best guess as to what's happening is that some mods hook into the dungeon loot differently to others, in that
// they take all the WeightedRandomChestContent objects once and pick from them each time rather than making new ones
// for each chest - which is, in theory, a more efficient way of doing things and will speed up world gen a bit, but
// does of course result in custom chest content implementations behaving strangely. The 'none' book thing remains a
// mystery, however.
/** Called from the preInit method in the main mod class to register the custom dungeon loot. */
public static void registerLoot(){
// The generate loot option only applies to vanilla chests, not wizard tower chests.
if(Wizardry.generateLoot){
String[] chestTypes = {
ChestGenHooks.DUNGEON_CHEST,
ChestGenHooks.PYRAMID_JUNGLE_CHEST,
ChestGenHooks.PYRAMID_DESERT_CHEST,
ChestGenHooks.MINESHAFT_CORRIDOR,
ChestGenHooks.STRONGHOLD_CORRIDOR,
ChestGenHooks.STRONGHOLD_CROSSING,
ChestGenHooks.STRONGHOLD_LIBRARY
};
for(String chest : chestTypes){
ChestGenHooks.addItem(chest, new WeightedRandomSpellBook(new ItemStack(Wizardry.spellBook), 1, 1, Wizardry.SPELL_BOOK_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomSpellBook(new ItemStack(Wizardry.magicWand), 1, 1, Wizardry.WAND_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomSpellBook(new ItemStack(Wizardry.wizardHat), 1, 1, Wizardry.ARMOUR_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomSpellBook(new ItemStack(Wizardry.scroll), 1, 1, Wizardry.SCROLL_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomSpellBook(new ItemStack(Wizardry.condenserUpgrade), 1, 1, Wizardry.WAND_UPGRADE_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.magicCrystal), 1, 4, Wizardry.CRYSTAL_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 1), 1, 1, Wizardry.APPRENTICE_TOME_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 2), 1, 1, Wizardry.ADVANCED_TOME_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 3), 1, 1, Wizardry.MASTER_TOME_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.armourUpgrade), 1, 1, Wizardry.ARMOUR_UPGRADE_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.firebomb), 1, 5, Wizardry.FIREBOMB_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.poisonBomb), 1, 5, Wizardry.POISON_BOMB_FREQUENCY));
ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.smokeBomb), 1, 5, Wizardry.SMOKE_BOMB_FREQUENCY));
if(Wizardry.discoveryMode) ChestGenHooks.addItem(chest, new WeightedRandomChestContent(new ItemStack(Wizardry.identificationScroll), 1, 1, Wizardry.IDENTIFICATION_SCROLL_FREQUENCY));
}
}
// Creates a new ChestGenHooks for wizard towers.
ChestGenHooks chestGen = ChestGenHooks.getInfo(WizardryWorldGenerator.WIZARD_TOWER);
chestGen.setMax(7);
chestGen.setMin(3);
// Wizard tower chests use exactly the same things, minus the firebombs, poison bombs and smoke bombs
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomSpellBook(new ItemStack(Wizardry.spellBook), 1, 1, Wizardry.SPELL_BOOK_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomSpellBook(new ItemStack(Wizardry.magicWand), 1, 1, Wizardry.WAND_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomSpellBook(new ItemStack(Wizardry.wizardHat), 1, 1, Wizardry.ARMOUR_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomSpellBook(new ItemStack(Wizardry.scroll), 1, 1, Wizardry.SCROLL_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomSpellBook(new ItemStack(Wizardry.condenserUpgrade), 1, 1, Wizardry.WAND_UPGRADE_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.magicCrystal), 1, 4, Wizardry.CRYSTAL_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 1), 1, 1, Wizardry.APPRENTICE_TOME_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 2), 1, 1, Wizardry.ADVANCED_TOME_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.arcaneTome, 1, 3), 1, 1, Wizardry.MASTER_TOME_FREQUENCY));
ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.armourUpgrade), 1, 1, Wizardry.ARMOUR_UPGRADE_FREQUENCY));
if(Wizardry.discoveryMode) ChestGenHooks.addItem(WizardryWorldGenerator.WIZARD_TOWER, new WeightedRandomChestContent(new ItemStack(Wizardry.identificationScroll), 1, 1, Wizardry.IDENTIFICATION_SCROLL_FREQUENCY));
}
/* The name defined here in the regitry is the one Minecraft uses in game for commands like /give, as
* opposed to the one defined earlier with setBlockName() or setUnlocalizedName() which is the one used by
* the lang files. Ideally these should both be the same, but I've written the lang file now, so... */
/** Called from the preInit method in the main mod class to register all the blocks. */
public static void registerBlocks(){
GameRegistry.registerBlock(Wizardry.arcaneWorkbench, "arcane_workbench");
GameRegistry.registerBlock(Wizardry.crystalOre, "crystal_ore");
GameRegistry.registerBlock(Wizardry.petrifiedStone, "petrified_stone");
GameRegistry.registerBlock(Wizardry.iceStatue, "ice_statue");
GameRegistry.registerBlock(Wizardry.magicLight, "magic_light");
GameRegistry.registerBlock(Wizardry.crystalFlower, "crystal_flower");
GameRegistry.registerBlock(Wizardry.snare, "snare");
GameRegistry.registerBlock(Wizardry.transportationStone, "transportation_stone");
GameRegistry.registerBlock(Wizardry.spectralBlock, "spectral_block");
GameRegistry.registerBlock(Wizardry.crystalBlock, "crystal_block");
GameRegistry.registerBlock(Wizardry.meteor, "meteor");
GameRegistry.registerBlock(Wizardry.vanishingCobweb, "vanishing_cobweb");
}
/** Called from the preInit method in the main mod class to register all the items. */
public static void registerItems(){
GameRegistry.registerItem(Wizardry.magicCrystal, "magic_crystal");
GameRegistry.registerItem(Wizardry.magicWand, "magic_wand");
GameRegistry.registerItem(Wizardry.apprenticeWand, "apprentice_wand");
GameRegistry.registerItem(Wizardry.advancedWand, "advanced_wand");
GameRegistry.registerItem(Wizardry.masterWand, "master_wand");
GameRegistry.registerItem(Wizardry.spellBook, "spell_book");
GameRegistry.registerItem(Wizardry.arcaneTome, "arcane_tome");
GameRegistry.registerItem(Wizardry.wizardHandbook, "wizard_handbook");
GameRegistry.registerItem(Wizardry.basicFireWand, "basic_fire_wand");
GameRegistry.registerItem(Wizardry.basicIceWand, "basic_ice_wand");
GameRegistry.registerItem(Wizardry.basicLightningWand, "basic_lightning_wand");
GameRegistry.registerItem(Wizardry.basicNecromancyWand, "basic_necromancy_wand");
GameRegistry.registerItem(Wizardry.basicEarthWand, "basic_earth_wand");
GameRegistry.registerItem(Wizardry.basicSorceryWand, "basic_sorcery_wand");
GameRegistry.registerItem(Wizardry.basicHealingWand, "basic_healing_wand");
GameRegistry.registerItem(Wizardry.apprenticeFireWand, "apprentice_fire_wand");
GameRegistry.registerItem(Wizardry.apprenticeIceWand, "apprentice_ice_wand");
GameRegistry.registerItem(Wizardry.apprenticeLightningWand, "apprentice_lightning_wand");
GameRegistry.registerItem(Wizardry.apprenticeNecromancyWand, "apprentice_necromancy_wand");
GameRegistry.registerItem(Wizardry.apprenticeEarthWand, "apprentice_earth_wand");
GameRegistry.registerItem(Wizardry.apprenticeSorceryWand, "apprentice_sorcery_wand");
GameRegistry.registerItem(Wizardry.apprenticeHealingWand, "apprentice_healing_wand");
GameRegistry.registerItem(Wizardry.advancedFireWand, "advanced_fire_wand");
GameRegistry.registerItem(Wizardry.advancedIceWand, "advanced_ice_wand");
GameRegistry.registerItem(Wizardry.advancedLightningWand, "advanced_lightning_wand");
GameRegistry.registerItem(Wizardry.advancedNecromancyWand, "advanced_necromancy_wand");
GameRegistry.registerItem(Wizardry.advancedEarthWand, "advanced_earth_wand");
GameRegistry.registerItem(Wizardry.advancedSorceryWand, "advanced_sorcery_wand");
GameRegistry.registerItem(Wizardry.advancedHealingWand, "advanced_healing_wand");
GameRegistry.registerItem(Wizardry.masterFireWand, "master_fire_wand");
GameRegistry.registerItem(Wizardry.masterIceWand, "master_ice_wand");
GameRegistry.registerItem(Wizardry.masterLightningWand, "master_lightning_wand");
GameRegistry.registerItem(Wizardry.masterNecromancyWand, "master_necromancy_wand");
GameRegistry.registerItem(Wizardry.masterEarthWand, "master_earth_wand");
GameRegistry.registerItem(Wizardry.masterSorceryWand, "master_sorcery_wand");
GameRegistry.registerItem(Wizardry.masterHealingWand, "master_healing_wand");
GameRegistry.registerItem(Wizardry.spectralSword, "spectral_sword");
GameRegistry.registerItem(Wizardry.spectralPickaxe, "spectral_pickaxe");
GameRegistry.registerItem(Wizardry.spectralBow, "spectral_bow");
GameRegistry.registerItem(Wizardry.manaFlask, "mana_flask");
GameRegistry.registerItem(Wizardry.storageUpgrade, "storage_upgrade");
GameRegistry.registerItem(Wizardry.siphonUpgrade, "siphon_upgrade");
GameRegistry.registerItem(Wizardry.condenserUpgrade, "condenser_upgrade");
GameRegistry.registerItem(Wizardry.rangeUpgrade, "range_upgrade");
GameRegistry.registerItem(Wizardry.durationUpgrade, "duration_upgrade");
GameRegistry.registerItem(Wizardry.cooldownUpgrade, "cooldown_upgrade");
GameRegistry.registerItem(Wizardry.blastUpgrade, "blast_upgrade");
GameRegistry.registerItem(Wizardry.attunementUpgrade, "attunement_upgrade");
GameRegistry.registerItem(Wizardry.flamingAxe, "flaming_axe");
GameRegistry.registerItem(Wizardry.frostAxe, "frost_axe");
GameRegistry.registerItem(Wizardry.firebomb, "firebomb");
GameRegistry.registerItem(Wizardry.poisonBomb, "poison_bomb");
GameRegistry.registerItem(Wizardry.blankScroll, "blank_scroll");
GameRegistry.registerItem(Wizardry.scroll, "scroll");
GameRegistry.registerItem(Wizardry.armourUpgrade, "armour_upgrade");
GameRegistry.registerItem(Wizardry.magicSilk, "magic_silk");
GameRegistry.registerItem(Wizardry.wizardHat, "wizard_hat");
GameRegistry.registerItem(Wizardry.wizardRobe, "wizard_robe");
GameRegistry.registerItem(Wizardry.wizardLeggings, "wizard_leggings");
GameRegistry.registerItem(Wizardry.wizardBoots, "wizard_boots");
GameRegistry.registerItem(Wizardry.wizardHatFire, "wizard_hat_fire");
GameRegistry.registerItem(Wizardry.wizardRobeFire, "wizard_robe_fire");
GameRegistry.registerItem(Wizardry.wizardLeggingsFire, "wizard_leggings_fire");
GameRegistry.registerItem(Wizardry.wizardBootsFire, "wizard_boots_fire");
GameRegistry.registerItem(Wizardry.wizardHatIce, "wizard_hat_ice");
GameRegistry.registerItem(Wizardry.wizardRobeIce, "wizard_robe_ice");
GameRegistry.registerItem(Wizardry.wizardLeggingsIce, "wizard_leggings_ice");
GameRegistry.registerItem(Wizardry.wizardBootsIce, "wizard_boots_ice");
GameRegistry.registerItem(Wizardry.wizardHatLightning, "wizard_hat_lightning");
GameRegistry.registerItem(Wizardry.wizardRobeLightning, "wizard_robe_lightning");
GameRegistry.registerItem(Wizardry.wizardLeggingsLightning, "wizard_leggings_lightning");
GameRegistry.registerItem(Wizardry.wizardBootsLightning, "wizard_boots_lightning");
GameRegistry.registerItem(Wizardry.wizardHatNecromancy, "wizard_hat_necromancy");
GameRegistry.registerItem(Wizardry.wizardRobeNecromancy, "wizard_robe_necromancy");
GameRegistry.registerItem(Wizardry.wizardLeggingsNecromancy, "wizard_leggings_necromancy");
GameRegistry.registerItem(Wizardry.wizardBootsNecromancy, "wizard_boots_necromancy");
GameRegistry.registerItem(Wizardry.wizardHatEarth, "wizard_hat_earth");
GameRegistry.registerItem(Wizardry.wizardRobeEarth, "wizard_robe_earth");
GameRegistry.registerItem(Wizardry.wizardLeggingsEarth, "wizard_leggings_earth");
GameRegistry.registerItem(Wizardry.wizardBootsEarth, "wizard_boots_earth");
GameRegistry.registerItem(Wizardry.wizardHatSorcery, "wizard_hat_sorcery");
GameRegistry.registerItem(Wizardry.wizardRobeSorcery, "wizard_robe_sorcery");
GameRegistry.registerItem(Wizardry.wizardLeggingsSorcery, "wizard_leggings_sorcery");
GameRegistry.registerItem(Wizardry.wizardBootsSorcery, "wizard_boots_sorcery");
GameRegistry.registerItem(Wizardry.wizardHatHealing, "wizard_hat_healing");
GameRegistry.registerItem(Wizardry.wizardRobeHealing, "wizard_robe_healing");
GameRegistry.registerItem(Wizardry.wizardLeggingsHealing, "wizard_leggings_healing");
GameRegistry.registerItem(Wizardry.wizardBootsHealing, "wizard_boots_healing");
GameRegistry.registerItem(Wizardry.spawnWizard, "spawn_wizard");
GameRegistry.registerItem(Wizardry.spectralHelmet, "spectral_helmet");
GameRegistry.registerItem(Wizardry.spectralChestplate, "spectral_chestplate");
GameRegistry.registerItem(Wizardry.spectralLeggings, "spectral_leggings");
GameRegistry.registerItem(Wizardry.spectralBoots, "spectral_boots");
GameRegistry.registerItem(Wizardry.smokeBomb, "smoke_bomb");
GameRegistry.registerItem(Wizardry.identificationScroll, "identification_scroll");
}
/** Called from the preInit method in the main mod class to register all the tileentities. */
public static void registerTileEntities(){
GameRegistry.registerTileEntity(TileEntityArcaneWorkbench.class, Wizardry.MODID + "ArcaneWorkbenchTileEntity");
GameRegistry.registerTileEntity(TileEntityStatue.class, Wizardry.MODID + "PetrifiedStoneTileEntity");
GameRegistry.registerTileEntity(TileEntityMagicLight.class, Wizardry.MODID + "MagicLightTileEntity");
GameRegistry.registerTileEntity(TileEntityTimer.class, Wizardry.MODID + "TimerTileEntity");
GameRegistry.registerTileEntity(TileEntityPlayerSave.class, Wizardry.MODID + "TileEntityPlayerSave");
}
/** Called from the preInit method in the main mod class to register all the entities. */
public static void registerEntities(Wizardry wizardry){
int id = 0; // Incrementable index for the mod specific entity id.
EntityRegistry.registerModEntity(EntityZombieMinion.class, "Zombie Minion", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityMagicMissile.class, "Magic Missile", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityArc.class, "Arc", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntitySkeletonMinion.class, "Skeleton Minion", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntitySparkBomb.class, "Spark Bomb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntitySpiritWolf.class, "Spirit Wolf", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityIceShard.class, "Ice Shard", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityBlazeMinion.class, "Blaze Minion", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityIceWraith.class, "Ice Wraith", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityLightningWraith.class, "Lightning Wraith", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityBlackHole.class, "Black Hole", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityShield.class, "Shield", id++, wizardry, 128, 1, true);
EntityRegistry.registerModEntity(EntityMeteor.class, "Meteor", id++, wizardry, 128, 5, true);
EntityRegistry.registerModEntity(EntityBlizzard.class, "Blizzard", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityWizard.class, "Wizard", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityBubble.class, "Bubble", id++, wizardry, 128, 3, false);
EntityRegistry.registerModEntity(EntityTornado.class, "Tornado", id++, wizardry, 128, 1, false);
EntityRegistry.registerModEntity(EntityHammer.class, "Lightning Hammer", id++, wizardry, 128, 1, true);
EntityRegistry.registerModEntity(EntityFirebomb.class, "Firebomb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityForceOrb.class, "Force Orb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityArrowRain.class, "Arrow Rain", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntitySpark.class, "Spark", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityShadowWraith.class, "Shadow Wraith", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityDarknessOrb.class, "Darkness Orb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntitySpiderMinion.class, "Spider Minion", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityHealAura.class, "Healing Aura", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityFireSigil.class, "Fire Sigil", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityFrostSigil.class, "Frost Sigil", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityLightningSigil.class, "Lightning Sigil", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityLightningArrow.class, "Lightning Arrow", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityFirebolt.class, "Firebolt", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityPoisonBomb.class, "Poison Bomb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityIceCharge.class, "Ice Charge", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityForceArrow.class, "Force Arrow", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityDart.class, "Dart", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityMagicSlime.class, "Magic Slime", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityForcefield.class, "Forcefield", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityFireRing.class, "Ring of Fire", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityLightningDisc.class, "Lightning Disc", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityThunderbolt.class, "Thunderbolt", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityIceGiant.class, "Ice Giant", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntitySpiritHorse.class, "Spirit Horse", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityPhoenix.class, "Phoenix", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntitySilverfishMinion.class, "Silverfish Minion", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityDecay.class, "Decay", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityStormElemental.class, "Storm Elemental", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityEarthquake.class, "Earthquake", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntityFallingGrass.class, "Falling Grass", id++, wizardry, 128, 5, true);
EntityRegistry.registerModEntity(EntityIceLance.class, "Ice Lance", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityHailstorm.class, "Hailstorm", id++, wizardry, 128, 10, false);
EntityRegistry.registerModEntity(EntitySmokeBomb.class, "Smoke Bomb", id++, wizardry, 128, 10, true);
EntityRegistry.registerModEntity(EntityEvilWizard.class, "Evil Wizard", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityDecoy.class, "Decoy", id++, wizardry, 128, 3, true);
EntityRegistry.registerModEntity(EntityIceSpike.class, "Ice Spike", id++, wizardry, 128, 1, true);
EntityRegistry.registerModEntity(EntityLightningPulse.class, "Lightning Pulse", id++, wizardry, 128, 10, false);
List<BiomeGenBase> biomes = new ArrayList<BiomeGenBase>();
for(BiomeGenBase biome : BiomeGenBase.getBiomeGenArray()){
if(biome != null){
biomes.add(biome);
}
}
// For reference: 5, 1, 1 are the parameters for the witch in vanilla.
EntityRegistry.addSpawn(EntityEvilWizard.class, 3, 1, 1, EnumCreatureType.monster, biomes.toArray(new BiomeGenBase[biomes.size()]));
}
/** Static instance of the none spell, used for various purposes. */
public static Spell none;
/** Static instance of the magic missile spell, used for crafting spell books and by wizards. */
public static Spell magicMissile;
/** Static instance of the transportation spell, used for chat messages. */
public static Spell transportation;
/** Static instance of the clairvoyance spell, used for chat messages. */
public static Spell clairvoyance;
/** Called from the preInit method in the main mod class to register all the spells in wizardry. */
public static void registerSpells(){
// Wizardry 1.0 spells
Spell.register(none = new None());
Spell.register(magicMissile = new MagicMissile());
Spell.register(new Ignite());
Spell.register(new Freeze());
Spell.register(new Snowball());
Spell.register(new Arc());
Spell.register(new Thunderbolt());
Spell.register(new SummonZombie());
Spell.register(new Snare());
Spell.register(new Dart());
Spell.register(new Light());
Spell.register(new Telekinesis());
Spell.register(new Heal());
Spell.register(new Fireball());
Spell.register(new FlameRay());
Spell.register(new Firebomb());
Spell.register(new FireSigil());
Spell.register(new Firebolt());
Spell.register(new FrostRay());
Spell.register(new SummonSnowGolem());
Spell.register(new IceShard());
Spell.register(new IceStatue());
Spell.register(new FrostSigil());
Spell.register(new LightningRay());
Spell.register(new SparkBomb());
Spell.register(new HomingSpark());
Spell.register(new LightningSigil());
Spell.register(new LightningArrow());
Spell.register(new LifeDrain());
Spell.register(new SummonSkeleton());
Spell.register(new Metamorphosis());
Spell.register(new Wither());
Spell.register(new Poison());
Spell.register(new GrowthAura());
Spell.register(new Bubble());
Spell.register(new Whirlwind());
Spell.register(new PoisonBomb());
Spell.register(new SummonSpiritWolf());
Spell.register(new Blink());
Spell.register(new Agility());
Spell.register(new ConjureSword());
Spell.register(new ConjurePickaxe());
Spell.register(new ConjureBow());
Spell.register(new ForceArrow());
Spell.register(new Shield());
Spell.register(new ReplenishHunger());
Spell.register(new CureEffects());
Spell.register(new HealAlly());
Spell.register(new SummonBlaze());
Spell.register(new RingOfFire());
Spell.register(new Detonate());
Spell.register(new FireResistance());
Spell.register(new Fireskin());
Spell.register(new FlamingAxe());
Spell.register(new Blizzard());
Spell.register(new SummonIceWraith());
Spell.register(new IceShroud());
Spell.register(new IceCharge());
Spell.register(new FrostAxe());
Spell.register(new InvokeWeather());
Spell.register(new ChainLightning());
Spell.register(new LightningBolt());
Spell.register(new SummonLightningWraith());
Spell.register(new StaticAura());
Spell.register(new LightningDisc());
Spell.register(new MindControl());
Spell.register(new SummonWitherSkeleton());
Spell.register(new Entrapment());
Spell.register(new WitherSkull());
Spell.register(new DarknessOrb());
Spell.register(new ShadowWard());
Spell.register(new Decay());
Spell.register(new WaterBreathing());
Spell.register(new Tornado());
Spell.register(new Glide());
Spell.register(new SummonSpiritHorse());
Spell.register(new SpiderSwarm());
Spell.register(new Slime());
Spell.register(new Petrify());
Spell.register(new Invisibility());
Spell.register(new Levitation());
Spell.register(new ForceOrb());
Spell.register(transportation = new Transportation());
Spell.register(new SpectralPathway());
Spell.register(new PhaseStep());
Spell.register(new VanishingBox());
Spell.register(new GreaterHeal());
Spell.register(new HealingAura());
Spell.register(new Forcefield());
Spell.register(new Ironflesh());
Spell.register(new Transience());
Spell.register(new Meteor());
Spell.register(new Firestorm());
Spell.register(new SummonPhoenix());
Spell.register(new IceAge());
Spell.register(new WallOfFrost());
Spell.register(new SummonIceGiant());
Spell.register(new Thunderstorm());
Spell.register(new LightningHammer());
Spell.register(new PlagueOfDarkness());
Spell.register(new SummonSkeletonLegion());
Spell.register(new SummonShadowWraith());
Spell.register(new ForestsCurse());
Spell.register(new Flight());
Spell.register(new SilverfishSwarm());
Spell.register(new BlackHole());
Spell.register(new Shockwave());
Spell.register(new SummonIronGolem());
Spell.register(new ArrowRain());
Spell.register(new Diamondflesh());
Spell.register(new FontOfVitality());
// Wizardry 1.1 spells
Spell.register(new SmokeBomb());
Spell.register(new MindTrick());
Spell.register(new Leap());
Spell.register(new PocketFurnace());
Spell.register(new Intimidate());
Spell.register(new Banish());
Spell.register(new SixthSense());
Spell.register(new Darkvision());
Spell.register(clairvoyance = new Clairvoyance());
Spell.register(new PocketWorkbench());
Spell.register(new ImbueWeapon());
Spell.register(new InvigoratingPresence());
Spell.register(new Oakflesh());
Spell.register(new GreaterFireball());
Spell.register(new FlamingWeapon());
Spell.register(new IceLance());
Spell.register(new FreezingWeapon());
Spell.register(new IceSpikes());
Spell.register(new LightningPulse());
Spell.register(new CurseOfSoulbinding());
Spell.register(new Cobwebs());
Spell.register(new Decoy());
Spell.register(new ArcaneJammer());
Spell.register(new ConjureArmour());
Spell.register(new GroupHeal());
Spell.register(new Hailstorm());
Spell.register(new LightningWeb());
Spell.register(new SummonStormElemental());
Spell.register(new Earthquake());
Spell.register(new FontOfMana());
}
/** Called from the init method in the main mod class to register all the recipes. */
public static void registerRecipes(){
ItemStack ironIngotStack = new ItemStack(Items.iron_ingot);
ItemStack magicCrystalStack = new ItemStack(Wizardry.magicCrystal);
ItemStack magicWandStack = new ItemStack(Wizardry.magicWand, 1, EnumTier.BASIC.maxCharge);
ItemStack goldNuggetStack = new ItemStack(Items.gold_nugget);
ItemStack stickStack = new ItemStack(Items.stick);
ItemStack bookStack = new ItemStack(Items.book);
ItemStack stringStack = new ItemStack(Items.string);
ItemStack spellBookStack = new ItemStack(Wizardry.spellBook, 1, WizardryRegistry.magicMissile.id());
ItemStack arcaneWorkbenchStack = new ItemStack(Wizardry.arcaneWorkbench);
ItemStack stoneStack = new ItemStack(Blocks.stone);
ItemStack lapisBlockStack = new ItemStack(Blocks.lapis_block);
ItemStack purpleCarpetStack = new ItemStack(Blocks.carpet, 1, 10);
ItemStack wizardHandbookStack = new ItemStack(Wizardry.wizardHandbook);
ItemStack crystalFlowerStack = new ItemStack(Wizardry.crystalFlower);
ItemStack magicCrystalStack1 = new ItemStack(Wizardry.magicCrystal, 2);
ItemStack magicCrystalStack2 = new ItemStack(Wizardry.magicCrystal, 9);
ItemStack crystalBlockStack = new ItemStack(Wizardry.crystalBlock);
ItemStack manaFlaskStack = new ItemStack(Wizardry.manaFlask);
ItemStack bottleStack = new ItemStack(Items.glass_bottle);
ItemStack gunpowderStack = new ItemStack(Items.gunpowder);
ItemStack blazePowderStack = new ItemStack(Items.blaze_powder);
ItemStack spiderEyeStack = new ItemStack(Items.spider_eye);
// Coal or charcoal is equally fine, hence the wildcard value
ItemStack coalStack = new ItemStack(Items.coal, 1, OreDictionary.WILDCARD_VALUE);
ItemStack firebombStack = new ItemStack(Wizardry.firebomb, 3);
ItemStack poisonBombStack = new ItemStack(Wizardry.poisonBomb, 3);
ItemStack smokeBombStack = new ItemStack(Wizardry.smokeBomb, 3);
ItemStack transportationStoneStack = new ItemStack(Wizardry.transportationStone, 2);
ItemStack silkStack = new ItemStack(Wizardry.magicSilk);
ItemStack silkStack1 = new ItemStack(Wizardry.magicSilk, 2);
ItemStack hatStack = new ItemStack(Wizardry.wizardHat);
ItemStack robeStack = new ItemStack(Wizardry.wizardRobe);
ItemStack leggingsStack = new ItemStack(Wizardry.wizardLeggings);
ItemStack bootsStack = new ItemStack(Wizardry.wizardBoots);
ItemStack scrollStack = new ItemStack(Wizardry.blankScroll);
ItemStack paperStack = new ItemStack(Items.paper);
GameRegistry.addRecipe(magicWandStack, " x", " y ", "z ", 'x', magicCrystalStack, 'y', stickStack, 'z', goldNuggetStack);
GameRegistry.addRecipe(spellBookStack, " x ", "xyx", " x ", 'x', magicCrystalStack, 'y', bookStack);
GameRegistry.addRecipe(arcaneWorkbenchStack, "vwv", "xyx", "zzz", 'v', goldNuggetStack, 'w', purpleCarpetStack, 'x', magicCrystalStack, 'y', lapisBlockStack, 'z', stoneStack);
GameRegistry.addRecipe(manaFlaskStack, "yyy", "yxy", "yyy", 'x', bottleStack, 'y', magicCrystalStack);
GameRegistry.addRecipe(transportationStoneStack, " x ", "xyx", " x ", 'x', stoneStack, 'y', magicCrystalStack);
GameRegistry.addRecipe(hatStack, "yyy", "y y", 'y', silkStack);
GameRegistry.addRecipe(robeStack, "y y", "yyy", "yyy", 'y', silkStack);
GameRegistry.addRecipe(leggingsStack, "yyy", "y y", "y y", 'y', silkStack);
GameRegistry.addRecipe(bootsStack, "y y", "y y", 'y', silkStack);
GameRegistry.addRecipe(silkStack1, " x ", "xyx", " x ", 'x', stringStack, 'y', magicCrystalStack);
GameRegistry.addRecipe(crystalBlockStack, "zzz", "zzz", "zzz", 'z', magicCrystalStack);
GameRegistry.addShapelessRecipe(wizardHandbookStack, bookStack, magicCrystalStack);
GameRegistry.addShapelessRecipe(magicCrystalStack1, crystalFlowerStack);
GameRegistry.addShapelessRecipe(magicCrystalStack2, crystalBlockStack);
if(Wizardry.firebombIsCraftable) GameRegistry.addShapelessRecipe(firebombStack, bottleStack, gunpowderStack, blazePowderStack, blazePowderStack);
if(Wizardry.poisonBombIsCraftable) GameRegistry.addShapelessRecipe(poisonBombStack, bottleStack, gunpowderStack, spiderEyeStack, spiderEyeStack);
if(Wizardry.smokeBombIsCraftable) GameRegistry.addShapelessRecipe(smokeBombStack, bottleStack, gunpowderStack, coalStack, coalStack);
if(Wizardry.useAlternateScrollRecipe){
GameRegistry.addShapelessRecipe(scrollStack, paperStack, stringStack, magicCrystalStack);
}else{
GameRegistry.addShapelessRecipe(scrollStack, paperStack, stringStack);
}
// Mana flask recipes
ItemStack miscWandStack;
for(int i=0; i<EnumElement.values().length; i++){
for(int j=0; j<EnumTier.values().length; j++){
miscWandStack = new ItemStack(WizardryUtilities.getWand(EnumTier.values()[j], EnumElement.values()[i]), 1, OreDictionary.WILDCARD_VALUE);
GameRegistry.addShapelessRecipe(miscWandStack, miscWandStack, manaFlaskStack);
}
}
ItemStack miscArmourStack;
for(int i=0; i<EnumElement.values().length; i++){
for(int j=0; j<4; j++){
miscArmourStack = new ItemStack(WizardryUtilities.getArmour(EnumElement.values()[i], j), 1, OreDictionary.WILDCARD_VALUE);
GameRegistry.addShapelessRecipe(miscArmourStack, miscArmourStack, manaFlaskStack);
}
}
}
}
@@ -0,0 +1,881 @@
package electroblob.wizardry;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import cpw.mods.fml.common.registry.EntityRegistry;
import electroblob.wizardry.entity.living.EntitySummonedCreature;
import electroblob.wizardry.entity.living.EntityWizard;
import electroblob.wizardry.spell.MindControl;
import electroblob.wizardry.spell.Spell;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.command.IEntitySelector;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityList.EntityEggInfo;
import net.minecraft.entity.monster.IMob;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.potion.Potion;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
/** This class contains some useful static methods for use anywhere - items, entities, spells, events, blocks, etc.
* @see CommonProxy
* @see WandHelper
* @since Wizardry 1.0 */
public final class WizardryUtilities {
/**
* Finds the nearest floor level to the given y coord within the range specified at the given x and z coords.
* Liquids and other blocks that cannot be built on top of do not count, but stuff like signs does.
* (Technically any block is allowed to be the floor according to the code, but seeing as it searches upwards and
* non-solid blocks usually need a supporting block, the floor is likely to always be solid).
* @param world
* @param x The x coordinate to search in
* @param y The y coordinate to search from
* @param z The z coordinate to search in
* @param range The maximum distance from the given y coordinate to search.
* @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the floor
* as would be seen in the debug screen when the player is standing on it.
* @see WizardryUtilities#getNearestFloorLevelB(World, int, int, int, int)
*/
public static int getNearestFloorLevel(World world, int x, int y, int z, int range){
int yCoord = -2;
for(int i=y-range;i<=y+range;i++){
// The last bit determines whether the block found to be a suitable floor is closer than the previous one found.
// Edit: Changed the first condition from blockExists() since that method includes air blocks!
if(world.doesBlockHaveSolidTopSurface(world, x, i, z) && (world.isAirBlock(x, i+1, z) || !world.doesBlockHaveSolidTopSurface(world, x, i+1, z))
&& (i-y < yCoord-y || yCoord == -2)){
yCoord = i;
}
}
return yCoord + 1;
}
/**
* Returns whether the block at the given coordinates can be replaced by another one (works as if a block is being placed by a player).
* True for air, liquids, vines, tall grass and snow layers but not for flowers, signs etc.
* This is a shortcut for world.getBlock(x, y, z).isReplaceable(world, x, y, z);
* Not much of a shortcut any more, since block ids have been phased out.
* @see WizardryUtilities#canBlockBeReplacedB(World, int, int, int)
*/
public static boolean canBlockBeReplaced(World world, int x, int y, int z){
// Why does isReplaceable have those arguments? I don't know. They aren't used. It's probably for overriding
// stuff in case these arguments affect whether it is replaceable or not. It is a forge method, after all.
return world.isAirBlock(x, y, z) || world.getBlock(x, y, z).isReplaceable(world, x, y, z);
}
/**
* Returns whether the block at the given coordinates can be replaced by another one (works as if a block is being placed by a player)
* and is not a liquid.
* True for air, vines, tall grass and snow layers but not for flowers, signs etc. or any liquids.
* @see WizardryUtilities#canBlockBeReplaced(World, int, int, int)
*/
public static boolean canBlockBeReplacedB(World world, int x, int y, int z){
return (world.isAirBlock(x, y, z) || world.getBlock(x, y, z).isReplaceable(world, x, y, z)) && !world.getBlock(x, y, z).getMaterial().isLiquid();
}
/**
* Returns whether the block at the given coordinates is unbreakable in survival mode. In vanilla this is true for
* bedrock and end portal frame, for example.
* This is a shortcut for world.getBlockId(x, y, z).getBlockHardness == -1.0f;
* Not much of a shortcut any more, since block ids have been phased out.
*/
public static boolean isBlockUnbreakable(World world, int x, int y, int z){
return world.isAirBlock(x, y, z) ? false : world.getBlock(x, y, z).getBlockHardness(world, x, y, z) == -1.0f;
}
/**
* Finds the nearest floor level to the given y coord within the range specified at the given x and z coords.
* Only works if the block above the floor is actually air and the floor is solid or a liquid.
* @param world
* @param x The x coordinate to search in
* @param y The y coordinate to search from
* @param z The z coordinate to search in
* @param range The maximum distance from the given y coordinate to search.
* @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the floor
* as would be seen in the debug screen when the player is standing on it.
* @see WizardryUtilities#getNearestFloorLevel(World, int, int, int, int)
*/
public static int getNearestFloorLevelB(World world, int x, int y, int z, int range){
int yCoord = -2;
for(int i=y-range;i<=y+range;i++){
if(world.isAirBlock(x, i+1, z) && (world.getBlock(x, i, z).getMaterial().isLiquid() || world.doesBlockHaveSolidTopSurface(world, x, i, z))
&& (i-y < yCoord-y || yCoord == -2)){
// The last bit determines whether the block found to be a suitable floor is closer than the previous one found.
yCoord = i;
}
}
return yCoord + 1;
}
/**
* Finds the nearest floor level to the given y coord within the range specified at the given x and z coords.
* Everything that is not air is treated as floor, even stuff that can't be walked on.
* @param world
* @param x The x coordinate to search in
* @param y The y coordinate to search from
* @param z The z coordinate to search in
* @param range The maximum distance from the given y coordinate to search.
* @return The y coordinate of the closest floor level, or -1 if there is none. Returns the actual level of the floor
* as would be seen in the debug screen when the player is standing on it.
* @see WizardryUtilities#getNearestFloorLevel(World, int, int, int, int)
*/
public static int getNearestFloorLevelC(World world, int x, int y, int z, int range){
int yCoord = -2;
for(int i=y-range;i<=y+range;i++){
if(world.isAirBlock(x, i+1, z) && (i-y < yCoord-y || yCoord == -2)){
// The last bit determines whether the block found to be a suitable floor is closer than the previous one found.
yCoord = i;
}
}
return yCoord + 1;
}
/**
* Gets the block the specified entity is standing on. Uses {@link MathHelper#floor_double(double)} because casting to int will not
* return the correct coordinate when x or z is negative.
*/
public static Block getBlockEntityIsStandingOn(Entity entity){
return entity.worldObj.getBlock(MathHelper.floor_double(entity.posX), (int)WizardryUtilities.getEntityFeetPos(entity)-1, MathHelper.floor_double(entity.posZ));
}
/**
* Shorthand for {@link WizardryUtilities#getEntitiesWithinRadius(double, double, double, double, World, Class)}
* with EntityLivingBase as the entity type. This is by far the most common use for that method, which is why this
* shorthand exists.
* @param radius The search radius
* @param x The x coordinate to search around
* @param y The y coordinate to search around
* @param z The z coordinate to search around
* @param world The world to search in
*/
public static List<EntityLivingBase> getEntitiesWithinRadius(double radius, double x, double y, double z, World world){
return getEntitiesWithinRadius(radius, x, y, z, world, EntityLivingBase.class);
}
/**
* Returns all entities of the specified type within the specified radius of the given coordinates. This is different to using
* a raw AABB because a raw AABB will search in a cube volume rather than a sphere.
* Note that this does not exclude any entities; if any specific entities are to be excluded this must be
* checked when iterating through the list.
* @see {@link WizardryUtilities#getEntitiesWithinRadius(double, double, double, double, World)}
* @param radius The search radius
* @param x The x coordinate to search around
* @param y The y coordinate to search around
* @param z The z coordinate to search around
* @param world The world to search in
* @param entityType The class of entity to search for; pass in Entity.class for all entities
*/
public static <T extends Entity> List<T> getEntitiesWithinRadius(double radius, double x, double y, double z, World world, Class<T> entityType){
AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(x - radius, y - radius, z - radius, x + radius, y + radius, z + radius);
List entityList = world.getEntitiesWithinAABB(entityType, aabb);
for(int i=0;i<entityList.size();i++){
if(((Entity)entityList.get(i)).getDistance(x, y, z) > radius){
entityList.remove(i);
}
}
return entityList;
}
// ^ Handy syntax using type parameters here!
// I *think* that eclipse, for whatever reason, was not showing an 'unchecked' warning here. If you think about it,
// if this method returns a generic list type I could, in theory, put strings or something in it and then when
// invoking the method store its result as a List<EntityLivingBase>, which would cause a ClassCastException. Using
// this handy syntax prevents that from happening. TL;DR: Always use type parameters when available, they're there
// for a reason. Minecraft is bad in this respect because it doesn't use them in places like World.
/**
* Gets an entity from its UUID. Note that you should check this isn't null.
* @param world The world the entity is in
* @param id The entity's UUID
* @return The Entity that has the given UUID, or null if no such entity exists in the specified world.
*/
public static Entity getEntityByUUID(World world, UUID id){
for(Object object : world.loadedEntityList){
if(object instanceof Entity){
Entity entity = (Entity)object;
// This is a perfect example of where you need to use .equals() and not ==. For most applications,
// this was unnoticeable until world reload because the UUID instance or entity instance is stored.
// Fixed now though. Of course, you could alternatively compare the string representations.
if(entity.getUniqueID().equals(id)){
return entity;
}
}
}
return null;
}
/**
* Does a block ray trace (NOT entities) from an entity's eyes (i.e. properly...)
*/
public static MovingObjectPosition rayTrace(double range, World world, EntityLivingBase entity, boolean hitLiquids)
{
Vec3 vec3 = Vec3.createVectorHelper(entity.posX, entity.posY + entity.getEyeHeight(), entity.posZ);
Vec3 vec31 = entity.getLookVec();
Vec3 vec32 = vec3.addVector(vec31.xCoord * range, vec31.yCoord * range, vec31.zCoord * range);
return world.rayTraceBlocks(vec3, vec32, hitLiquids);
}
/**
* Helper method which does a rayTrace for entities from an entity's eye level in the direction they are looking
* with a specified range, using the tracePath method. Tidies up the code a bit. Border size defaults to 1.
*
* @param world
* @param entity
* @param range
* @return
*/
public static MovingObjectPosition standardEntityRayTrace(World world, EntityLivingBase entity, double range){
double dx = entity.getLookVec().xCoord * range;
double dy = entity.getLookVec().yCoord * range;
double dz = entity.getLookVec().zCoord * range;
HashSet hashset = new HashSet(1);
hashset.add(entity);
return WizardryUtilities.tracePath(world, (float)entity.posX, (float)(entity.posY + entity.getEyeHeight()), (float)entity.posZ, (float)(entity.posX + dx), (float)(entity.posY + entity.getEyeHeight() + dy), (float)(entity.posZ + dz), 1.0f, hashset, false);
}
/**
* Helper method which does a rayTrace for entities from a entity's eye level in the direction they are looking
* with a specified range and radius, using the tracePath method. Tidies up the code a bit.
*
* @param world
* @param entity
* @param range
* @param borderSize
* @return
*/
public static MovingObjectPosition standardEntityRayTrace(World world, EntityLivingBase entity, double range, float borderSize){
double dx = entity.getLookVec().xCoord * range;
double dy = entity.getLookVec().yCoord * range;
double dz = entity.getLookVec().zCoord * range;
HashSet hashset = new HashSet(1);
hashset.add(entity);
return WizardryUtilities.tracePath(world, (float)entity.posX, (float)(entity.posY + entity.getEyeHeight()), (float)entity.posZ, (float)(entity.posX + dx), (float)(entity.posY + entity.getEyeHeight() + dy), (float)(entity.posZ + dz), borderSize, hashset, false);
}
/**
* Method for ray tracing entities (the useless default method doesn't work, despite EnumHitType having an ENTITY field...)
* You can also use this for seeking.
*
* @param world
* @param x startX
* @param y startY
* @param z startZ
* @param tx endX
* @param ty endY
* @param tz endZ
* @param borderSize extra area to examine around line for entities
* @param excluded any excluded entities (the player, etc)
* @return a MovingObjectPosition of either the block hit (no entity hit), the entity hit (hit an entity), or null for nothing hit
*/
public static MovingObjectPosition tracePath(World world, float x, float y, float z, float tx, float ty, float tz, float borderSize, HashSet<Entity> excluded, boolean collideablesOnly){
Vec3 startVec = Vec3.createVectorHelper(x, y, z);
Vec3 lookVec = Vec3.createVectorHelper(tx-x, ty-y, tz-z);
Vec3 endVec = Vec3.createVectorHelper(tx, ty, tz);
float minX = x < tx ? x : tx;
float minY = y < ty ? y : ty;
float minZ = z < tz ? z : tz;
float maxX = x > tx ? x : tx;
float maxY = y > ty ? y : ty;
float maxZ = z > tz ? z : tz;
AxisAlignedBB bb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX, maxY, maxZ).expand(borderSize, borderSize, borderSize);
List<Entity> allEntities = world.getEntitiesWithinAABBExcludingEntity(null, bb);
MovingObjectPosition blockHit = world.rayTraceBlocks(startVec, endVec);
startVec = Vec3.createVectorHelper(x, y, z);
endVec = Vec3.createVectorHelper(tx, ty, tz);
float maxDistance = (float) endVec.distanceTo(startVec);
if(blockHit!=null)
{
maxDistance = (float) blockHit.hitVec.distanceTo(startVec);
}
Entity closestHitEntity = null;
float closestHit = maxDistance;
float currentHit = 0.f;
AxisAlignedBB entityBb;// = ent.getBoundingBox();
MovingObjectPosition intercept;
for(Entity ent : allEntities)
{
if((ent.canBeCollidedWith() || !collideablesOnly) && ((excluded != null && !excluded.contains(ent)) || excluded == null))
{
float entBorder = ent.getCollisionBorderSize();
entityBb = ent.boundingBox;
if(entityBb!=null)
{
entityBb = entityBb.expand(entBorder, entBorder, entBorder);
intercept = entityBb.calculateIntercept(startVec, endVec);
if(intercept!=null)
{
currentHit = (float) intercept.hitVec.distanceTo(startVec);
if(currentHit < closestHit || currentHit==0)
{
closestHit = currentHit;
closestHitEntity = ent;
}
}
}
}
}
if(closestHitEntity!=null)
{
blockHit = new MovingObjectPosition(closestHitEntity);
}
return blockHit;
}
// Just what benefit does having posY be the eye position on the first person client actually give?
/**
* Gets the y coordinate of the given player's eyes. This is to cover an inconsistency between the value of
* EntityPlayer.posY on the first person client and everywhere else; in first person (i.e. when
* Minecraft.getMinecraft().thePlayer == player) player.posY is the eye position, but everywhere else it is the
* feet position. This is intended for use when spawning particles, since this is the only situation where the
* discrepancy is likely to matter.
*/
public static double getPlayerEyesPos(EntityPlayer player){
return Wizardry.proxy.getPlayerEyesPos(player);
}
/**
* Gets the y coordinate of the given entity's feet. This is to cover an inconsistency between the value of
* EntityPlayer.posY on the first person client and everywhere else; in first person (i.e. when
* Minecraft.getMinecraft().thePlayer == player) player.posY is the eye position, but everywhere else it is the
* feet position. This is intended for use when spawning particles, since this is the only situation where the
* discrepancy is likely to matter.
*/
public static double getEntityFeetPos(Entity entity){
if(entity instanceof EntityPlayer){
// For some reason, EntityPlayer.getEyeHeight() always returns 0.12, so I have replicated the behaviour
// of the same method from EntityLivingBase and subtracted that instead.
return getPlayerEyesPos((EntityPlayer)entity) - entity.height*0.85f;
}else{
return entity.posY;
}
}
/**
* Verifies that the given string is a valid string representation of a UUID. More specifically, returns true if and
* only if the given string is not null and matches the regular expression:<p>
* <center><code>/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/<p></code></center>
* which is the regex equivlent of the standard string representation of a UUID as described in {@link UUID#toString()}.
* This method is intended to be used as a check to prevent an {@link IllegalArgumentException} from occurring when
* calling {@link UUID#fromString(String)}.
* @param string The string to be checked
* @return Whether the given string is a valid string representation of a UUID
*/
public static boolean verifyUUIDString(String string){
return string != null && string.matches("/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/");
}
/**
* Returns whether the given target can be attacked by the given attacker. It is up to the caller of this method
* to work out what this means; it doesn't necessarily mean the target is completely immune (for example, revenge
* targeting might reasonably bypass this). This method is intended for use where the damage is indirect and/or
* unavoidable; direct attacks should not check this method. Currently this means the following situations check
* this method:
* <p>
* - AI targeting for summoned creatures<br>
* - AI targeting for mind-controlled creatures<br>
* - Constructs with an area of effect<br>
* - Instantaneous spells with an area of effect around the caster (e.g. forest's curse, thunderstorm)<br>
* - Any lightning chaining effects<br>
* - Any projectiles which seek targets
* <p>
* Also note that the friendly fire option is dealt with
* in the event handler. This method acts as a sort of wrapper for all the ADS stuff in {@link ExtendedPlayer}; more
* details about the ally designation system can be found there.
*
* @param attacker The entity that cast the spell originally
* @param target The entity being attacked
*
* @return False under any of the following circumstances, true otherwise:
* <p>
* - The target is the attacker (this isn't as stupid as it sounds - anything with an AoE might cause this to be
* true, as can summoned creatures)
* <p>
* - The target and the attacker are both players and the target is an ally of the attacker (but the
* attacker need not be an ally of the target)
* <p>
* - The target is a creature that was summoned/controlled by the attacker or by an ally of the attacker.
*/
public static boolean isValidTarget(Entity attacker, Entity target){
// Don't need to check if either entity is null since instanceof does this anyway.
// Tests whether the target is the attacker
if(target == attacker) return false;
// Tests whether the target is a creature that was summoned by the attacker
if(target instanceof EntitySummonedCreature && ((EntitySummonedCreature)target).getCaster() == attacker){
return false;
}
// Tests whether the target is a creature that was mind controlled by the attacker
if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(Wizardry.mindControl)){
NBTTagCompound entityNBT = target.getEntityData();
if(entityNBT != null && entityNBT.hasKey(MindControl.NBT_KEY)){
if(attacker == WizardryUtilities.getEntityByUUID(target.worldObj, UUID.fromString(entityNBT.getString(MindControl.NBT_KEY)))){
return false;
}
}
}
// Ally section
if(attacker instanceof EntityPlayer && ExtendedPlayer.get((EntityPlayer)attacker) != null){
if(target instanceof EntityPlayer){
// Tests whether the target is an ally of the attacker
if(ExtendedPlayer.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)target)){
return false;
}
}else if(target instanceof EntitySummonedCreature){
// Tests whether the target is a creature that was summoned by an ally of the attacker
if(((EntitySummonedCreature)target).getCaster() instanceof EntityPlayer
&& ExtendedPlayer.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)((EntitySummonedCreature)target).getCaster())){
return false;
}
}else if(target instanceof EntityLiving && ((EntityLivingBase)target).isPotionActive(Wizardry.mindControl)){
// Tests whether the target is a creature that was mind controlled by an ally of the attacker
NBTTagCompound entityNBT = target.getEntityData();
if(entityNBT != null && entityNBT.hasKey(MindControl.NBT_KEY)){
Entity controller = WizardryUtilities.getEntityByUUID(target.worldObj, UUID.fromString(entityNBT.getString(MindControl.NBT_KEY)));
if(controller instanceof EntityPlayer && ExtendedPlayer.get((EntityPlayer)attacker).isPlayerAlly((EntityPlayer)controller)){
return false;
}
}
}
}
return true;
}
/** Helper method for testing if the second player is an ally of the first player. Makes the code neater. */
public static boolean isPlayerAlly(EntityPlayer allyOf, EntityPlayer possibleAlly) {
ExtendedPlayer properties = ExtendedPlayer.get(allyOf);
if(properties != null && properties.isPlayerAlly(possibleAlly)) return true;
return false;
}
/**
* See {@link WizardryUtilities#getStandardWeightedRandomSpellId(Random, boolean)}. isContinuous defaults to false.
*/
public static int getStandardWeightedRandomSpellId(Random random){
return getStandardWeightedRandomSpellId(random, false);
}
/**
* Helper method which gets a spell id according to the standard weighting. The tier is a weighted random value;
* the actual spell within that tier is completely random. Will not return the id of a spell which has been
* disabled in the config. This is for simple stuff like chests and drops; more complex generators like wizard
* trades don't use this method.
* <p>
* For reference, the standard weighting is as follows:
* Basic: 60%, Apprentice: 25%, Advanced: 10%, Master: 5%
*
* @param random An instance of the Random class
* @param nonContinuous Whether the spells must be non-continuous (used for scrolls)
* @return A random spell id number
*/
public static int getStandardWeightedRandomSpellId(Random random, boolean nonContinuous){
int randomiser = random.nextInt(20);
EnumTier tier;
if(randomiser < 12){
tier = EnumTier.BASIC;
}else if(randomiser < 17){
tier = EnumTier.APPRENTICE;
}else if(randomiser < 19){
tier = EnumTier.ADVANCED;
}else{
tier = EnumTier.MASTER;
}
List<Spell> spells = Spell.getSpells(new Spell.TierElementFilter(tier, null));
if(nonContinuous) spells.retainAll(Spell.getSpells(Spell.nonContinuousSpells));
// Ensures the tier chosen actually has spells in it, and if not uses BASIC instead. BASIC always has at least
// the NONE spell since this spell cannot be disabled.
if(spells.isEmpty()){
spells = Spell.getSpells(new Spell.TierElementFilter(EnumTier.BASIC, null));
if(nonContinuous) spells.retainAll(Spell.getSpells(Spell.nonContinuousSpells));
}
// Finds a random spell in the list and returns its id.
return spells.get(random.nextInt(spells.size())).id();
}
/**
* Helper method to return the appropriate armour item based on element and slot.
* Currently used to iterate through armour for registering charging recipes and for chest generation.
* @param slot 0 = head, 1 = body, 2 = legs, 3 = feet
*/
public static Item getArmour(EnumElement element, int slot){
Item armour = null;
if(element == null){
switch(slot){
case 0:
armour = Wizardry.wizardHat;
break;
case 1:
armour = Wizardry.wizardRobe;
break;
case 2:
armour = Wizardry.wizardLeggings;
break;
case 3:
armour = Wizardry.wizardBoots;
break;
default:
break;
}
}else{
switch(element){
case FIRE:
switch(slot){
case 0:
armour = Wizardry.wizardHatFire;
break;
case 1:
armour = Wizardry.wizardRobeFire;
break;
case 2:
armour = Wizardry.wizardLeggingsFire;
break;
case 3:
armour = Wizardry.wizardBootsFire;
break;
default:
break;
}
break;
case HEALING:
switch(slot){
case 0:
armour = Wizardry.wizardHatHealing;
break;
case 1:
armour = Wizardry.wizardRobeHealing;
break;
case 2:
armour = Wizardry.wizardLeggingsHealing;
break;
case 3:
armour = Wizardry.wizardBootsHealing;
break;
default:
break;
}
break;
case ICE:
switch(slot){
case 0:
armour = Wizardry.wizardHatIce;
break;
case 1:
armour = Wizardry.wizardRobeIce;
break;
case 2:
armour = Wizardry.wizardLeggingsIce;
break;
case 3:
armour = Wizardry.wizardBootsIce;
break;
default:
break;
}
break;
case LIGHTNING:
switch(slot){
case 0:
armour = Wizardry.wizardHatLightning;
break;
case 1:
armour = Wizardry.wizardRobeLightning;
break;
case 2:
armour = Wizardry.wizardLeggingsLightning;
break;
case 3:
armour = Wizardry.wizardBootsLightning;
break;
default:
break;
}
break;
case NECROMANCY:
switch(slot){
case 0:
armour = Wizardry.wizardHatNecromancy;
break;
case 1:
armour = Wizardry.wizardRobeNecromancy;
break;
case 2:
armour = Wizardry.wizardLeggingsNecromancy;
break;
case 3:
armour = Wizardry.wizardBootsNecromancy;
break;
default:
break;
}
break;
case SORCERY:
switch(slot){
case 0:
armour = Wizardry.wizardHatSorcery;
break;
case 1:
armour = Wizardry.wizardRobeSorcery;
break;
case 2:
armour = Wizardry.wizardLeggingsSorcery;
break;
case 3:
armour = Wizardry.wizardBootsSorcery;
break;
default:
break;
}
break;
case EARTH:
switch(slot){
case 0:
armour = Wizardry.wizardHatEarth;
break;
case 1:
armour = Wizardry.wizardRobeEarth;
break;
case 2:
armour = Wizardry.wizardLeggingsEarth;
break;
case 3:
armour = Wizardry.wizardBootsEarth;
break;
default:
break;
}
break;
default:
switch(slot){
case 0:
armour = Wizardry.wizardHat;
break;
case 1:
armour = Wizardry.wizardRobe;
break;
case 2:
armour = Wizardry.wizardLeggings;
break;
case 3:
armour = Wizardry.wizardBoots;
break;
default:
break;
}
break;
}
}
return armour;
}
/**
* Helper method to return the appropriate wand based on tier and element.
* Currently used in the packet handler for upgrading wands, for chest generation and to iterate through
* wands for charging recipes.
*/
public static Item getWand(EnumTier tier, EnumElement element){
Item wand = null;
if(element == null){
switch(tier){
case BASIC:
wand = Wizardry.magicWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeWand;
break;
case ADVANCED:
wand = Wizardry.advancedWand;
break;
case MASTER:
wand = Wizardry.masterWand;
break;
default:
break;
}
}else{
switch(element){
case FIRE:
switch(tier){
case BASIC:
wand = Wizardry.basicFireWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeFireWand;
break;
case ADVANCED:
wand = Wizardry.advancedFireWand;
break;
case MASTER:
wand = Wizardry.masterFireWand;
break;
default:
break;
}
break;
case HEALING:
switch(tier){
case BASIC:
wand = Wizardry.basicHealingWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeHealingWand;
break;
case ADVANCED:
wand = Wizardry.advancedHealingWand;
break;
case MASTER:
wand = Wizardry.masterHealingWand;
break;
default:
break;
}
break;
case ICE:
switch(tier){
case BASIC:
wand = Wizardry.basicIceWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeIceWand;
break;
case ADVANCED:
wand = Wizardry.advancedIceWand;
break;
case MASTER:
wand = Wizardry.masterIceWand;
break;
default:
break;
}
break;
case LIGHTNING:
switch(tier){
case BASIC:
wand = Wizardry.basicLightningWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeLightningWand;
break;
case ADVANCED:
wand = Wizardry.advancedLightningWand;
break;
case MASTER:
wand = Wizardry.masterLightningWand;
break;
default:
break;
}
break;
case NECROMANCY:
switch(tier){
case BASIC:
wand = Wizardry.basicNecromancyWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeNecromancyWand;
break;
case ADVANCED:
wand = Wizardry.advancedNecromancyWand;
break;
case MASTER:
wand = Wizardry.masterNecromancyWand;
break;
default:
break;
}
break;
case SORCERY:
switch(tier){
case BASIC:
wand = Wizardry.basicSorceryWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeSorceryWand;
break;
case ADVANCED:
wand = Wizardry.advancedSorceryWand;
break;
case MASTER:
wand = Wizardry.masterSorceryWand;
break;
default:
break;
}
break;
case EARTH:
switch(tier){
case BASIC:
wand = Wizardry.basicEarthWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeEarthWand;
break;
case ADVANCED:
wand = Wizardry.advancedEarthWand;
break;
case MASTER:
wand = Wizardry.masterEarthWand;
break;
default:
break;
}
break;
default:
switch(tier){
case BASIC:
wand = Wizardry.magicWand;
break;
case APPRENTICE:
wand = Wizardry.apprenticeWand;
break;
case ADVANCED:
wand = Wizardry.advancedWand;
break;
case MASTER:
wand = Wizardry.masterWand;
break;
default:
break;
}
break;
}
}
return wand;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,61 +0,0 @@
package electroblob.wizardry.advancement;
import electroblob.wizardry.Wizardry;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementManager;
import net.minecraft.advancements.AdvancementProgress;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.ResourceLocation;
/**
* This is a provisory class for the transition to 1.12
* It contains an enum with all the advancements of this mod
* and an helper to grant advancements on the server side only (like the command)
* @author Corail31
* @since Wizardry 4.1
*/
public class AdvancementHelper {
public enum EnumAdvancement {
crystal,
arcane_initiate,
apprentice,
master,
all_spells,
wizard_trade,
buy_master_spell,
freeze_blaze,
charge_creeper,
frankenstein,
special_upgrade,
craft_flask,
elemental,
armour_set,
legendary,
self_destruct,
pig_tornado,
jam_wizard,
slime_skeleton,
anger_wizard,
defeat_evil_wizard,
max_out_wand,
element_master,
identify_spell;
}
public static boolean grantAdvancement(EntityPlayer player, EnumAdvancement advancementName) {
if (player == null) { return false; }
if (player.world.isRemote) { return true; }
EntityPlayerMP player_mp = player.getServer().getPlayerList().getPlayerByUUID(player.getUniqueID());
AdvancementManager am = player_mp.getServerWorld().getAdvancementManager();
Advancement advancement = am.getAdvancement(new ResourceLocation(Wizardry.MODID, advancementName.name()));
if (advancement == null) { return false; }
AdvancementProgress advancementprogress = player_mp.getAdvancements().getProgress(advancement);
if (!advancementprogress.isDone()) {
for (String criteria : advancementprogress.getRemaningCriteria()) {
player_mp.getAdvancements().grantCriterion(advancement, criteria);
}
}
return true;
}
}
@@ -1,80 +1,126 @@
package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.WizardryGuiHandler;
import electroblob.wizardry.client.GuiArcaneWorkbench;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.InventoryHelper;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
public class BlockArcaneWorkbench extends BlockContainer {
private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.75D, 1.0D);
public class BlockArcaneWorkbench extends BlockContainer{
public IIcon[] icons = new IIcon[6];
public BlockArcaneWorkbench(){
super(Material.ROCK);
this.setLightLevel(0.8f);
super(Material.rock);
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.75F, 1.0F);
this.setLightLevel(0.8f);
this.setCreativeTab(CreativeTabs.tabDecorations);
this.setBlockTextureName("wizardry:arcane_workbench");
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){
return AABB;
public void registerBlockIcons(IIconRegister par1IconRegister) {
this.icons[0] = par1IconRegister.registerIcon(this.textureName + "_bottom");
this.icons[1] = par1IconRegister.registerIcon(this.textureName + "_top");
this.icons[2] = par1IconRegister.registerIcon(this.textureName + "_side");
this.icons[3] = par1IconRegister.registerIcon(this.textureName + "_side");
this.icons[4] = par1IconRegister.registerIcon(this.textureName + "_side");
this.icons[5] = par1IconRegister.registerIcon(this.textureName + "_side");
}
@Override
public IIcon getIcon(int side, int meta) {
return this.icons[side];
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityArcaneWorkbench();
}
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){
return false;
}
public boolean renderAsNormalBlock()
{
return false;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return EnumBlockRenderType.MODEL;
}
public boolean isOpaqueCube()
{
return false;
}
@Override
public boolean isOpaqueCube(IBlockState state){
return false;
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState block, EntityPlayer player, EnumHand hand,
EnumFacing side, float hitX, float hitY, float hitZ){
TileEntity tileEntity = world.getTileEntity(pos);
if(tileEntity == null || player.isSneaking()){
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int metadata, float what, float these, float are) {
TileEntity tileEntity = world.getTileEntity(x, y, z);
if (tileEntity == null || player.isSneaking()) {
return false;
}
player.openGui(Wizardry.instance, WizardryGuiHandler.ARCANE_WORKBENCH, world, pos.getX(), pos.getY(), pos.getZ());
player.openGui(Wizardry.instance, WizardryGuiHandler.ARCANE_WORKBENCH, world, x, y, z);
return true;
}
@Override
public void breakBlock(World world, BlockPos pos, IBlockState block){
TileEntity tileentity = world.getTileEntity(pos);
public void breakBlock(World par1World, int par2, int par3, int par4, Block block, int par6)
{
Random random = new Random();
TileEntityArcaneWorkbench tileentityarcaneworkbench = (TileEntityArcaneWorkbench)par1World.getTileEntity(par2, par3, par4);
if(tileentity instanceof TileEntityArcaneWorkbench){
InventoryHelper.dropInventoryItems(world, pos, (TileEntityArcaneWorkbench)tileentity);
if (tileentityarcaneworkbench != null)
{
for (int j1 = 0; j1 < tileentityarcaneworkbench.getSizeInventory(); ++j1)
{
ItemStack itemstack = tileentityarcaneworkbench.getStackInSlot(j1);
if (itemstack != null)
{
float f = random.nextFloat() * 0.8F + 0.1F;
float f1 = random.nextFloat() * 0.8F + 0.1F;
EntityItem entityitem;
for (float f2 = random.nextFloat() * 0.8F + 0.1F; itemstack.stackSize > 0; par1World.spawnEntityInWorld(entityitem))
{
int k1 = random.nextInt(21) + 10;
if (k1 > itemstack.stackSize)
{
k1 = itemstack.stackSize;
}
itemstack.stackSize -= k1;
entityitem = new EntityItem(par1World, (double)((float)par2 + f), (double)((float)par3 + f1), (double)((float)par4 + f2), new ItemStack(itemstack.getItem(), k1, itemstack.getItemDamage()));
float f3 = 0.05F;
entityitem.motionX = (double)((float)random.nextGaussian() * f3);
entityitem.motionY = (double)((float)random.nextGaussian() * f3 + 0.2F);
entityitem.motionZ = (double)((float)random.nextGaussian() * f3);
if (itemstack.hasTagCompound())
{
entityitem.getEntityItem().setTagCompound((NBTTagCompound)itemstack.getTagCompound().copy());
}
}
}
}
//par1World.func_96440_m(par2, par3, par4, block);
}
super.breakBlock(world, pos, block);
}
super.breakBlock(par1World, par2, par3, par4, block, par6);
}
}
@@ -0,0 +1,16 @@
package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.Wizardry;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
public class BlockCrystal extends Block {
public BlockCrystal(Material material) {
super(material);
setHarvestLevel("pickaxe", 2);
}
}
@@ -2,71 +2,142 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.EnumParticleType;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.util.WizardryParticleType;
import net.minecraft.block.BlockBush;
import net.minecraft.block.SoundType;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.event.entity.player.BonemealEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.util.ForgeDirection;
// Extending BlockBush allows me to remove nearly everything from this class.
@Mod.EventBusSubscriber
public class BlockCrystalFlower extends BlockBush {
public class BlockCrystalFlower extends Block implements IPlantable {
private static final AxisAlignedBB AABB = new AxisAlignedBB(0.5F - 0.2f, 0.0F, 0.5F - 0.2f, 0.5F + 0.2f,
0.2f * 3.0F, 0.5F + 0.2f);
public BlockCrystalFlower(Material par2Material){
public BlockCrystalFlower(Material par2Material) {
super(par2Material);
this.setLightLevel(0.5f);
this.setTickRandomly(true);
this.setSoundType(SoundType.PLANT);
this.setBlockBounds(0.5F - 0.2f, 0.0F, 0.5F - 0.2f, 0.5F + 0.2f, 0.2f * 3.0F, 0.5F + 0.2f);
this.setTickRandomly(true);
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){
return AABB;
}
@Override
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random random){
public void randomDisplayTick(World world, int x, int y, int z, Random random){
if(world.isRemote && random.nextBoolean()){
Wizardry.proxy.spawnParticle(WizardryParticleType.SPARKLE, world, pos.getX() + random.nextDouble(),
pos.getY() + random.nextDouble() / 2 + 0.5, pos.getZ() + random.nextDouble(), 0d, 0.01, 0d,
20 + random.nextInt(10), 0.5f + (random.nextFloat() / 2), 0.5f + (random.nextFloat() / 2),
0.5f + (random.nextFloat() / 2));
Wizardry.proxy.spawnParticle(EnumParticleType.SPARKLE, world, x+random.nextDouble(), y+random.nextDouble()/2+0.5, z+random.nextDouble(), 0d, 0.01, 0d, 20 + random.nextInt(10), 0.5f + (random.nextFloat()/2), 0.5f + (random.nextFloat()/2), 0.5f + (random.nextFloat()/2));
}
}
/**
* Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
*/
@Override
public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
{
return super.canPlaceBlockAt(par1World, par2, par3, par4) && canBlockStay(par1World, par2, par3, par4);
}
/**
* Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
* cleared to be reused)
*/
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
return null;
}
/**
* Gets passed in the blockID of the block below and supposed to return true if its allowed to grow on the type of
* blockID passed in. Args: blockID
*/
protected boolean canThisPlantGrowOnThisBlockID(Block par1)
{
return par1 == Blocks.grass || par1 == Blocks.dirt || par1 == Blocks.farmland;
}
/**
* Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
* their own) Args: x, y, z, neighbor blockID
*/
@Override
public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, Block par5)
{
super.onNeighborBlockChange(par1World, par2, par3, par4, par5);
this.checkFlowerChange(par1World, par2, par3, par4);
}
/**
* Ticks the block if it's been scheduled
*/
@Override
public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random)
{
this.checkFlowerChange(par1World, par2, par3, par4);
}
protected final void checkFlowerChange(World par1World, int par2, int par3, int par4)
{
if (!this.canBlockStay(par1World, par2, par3, par4))
{
this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0);
par1World.setBlock(par2, par3, par4, Blocks.air, 0, 2);
}
}
/**
* Can this block stay at this position. Similar to canPlaceBlockAt except gets checked often with plants.
*/
@Override
public boolean canBlockStay(World par1World, int par2, int par3, int par4)
{
Block soil = par1World.getBlock(par2, par3 - 1, par4);
return (par1World.getFullBlockLightValue(par2, par3, par4) >= 8 || par1World.canBlockSeeTheSky(par2, par3, par4)) &&
(soil != null && soil.canSustainPlant(par1World, par2, par3 - 1, par4, ForgeDirection.UP, this));
}
/**
* Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two
* adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
*/
@Override
public boolean isOpaqueCube()
{
return false;
}
/**
* If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
*/
@Override
public boolean renderAsNormalBlock()
{
return false;
}
/**
* The type of render function that is called for this block
*/
@Override
public int getRenderType()
{
return 1;
}
@Override
public EnumPlantType getPlantType(IBlockAccess world, BlockPos pos){
public EnumPlantType getPlantType(IBlockAccess world, int x, int y, int z) {
return EnumPlantType.Plains;
}
@SubscribeEvent
public static void onBonemealEvent(BonemealEvent event){
// Grows crystal flowers when bonemeal is used on grass
if(event.getBlock().getBlock() == Blocks.GRASS){
@Override
public Block getPlant(IBlockAccess world, int x, int y, int z) {
return this;
}
BlockPos pos = event.getPos().add(event.getWorld().rand.nextInt(8) - event.getWorld().rand.nextInt(8),
event.getWorld().rand.nextInt(4) - event.getWorld().rand.nextInt(4),
event.getWorld().rand.nextInt(8) - event.getWorld().rand.nextInt(8));
if(event.getWorld().isAirBlock(new BlockPos(pos))
&& (!event.getWorld().provider.isNether() || pos.getY() < 127)
&& WizardryBlocks.crystal_flower.canPlaceBlockAt(event.getWorld(), pos)){
event.getWorld().setBlockState(pos, WizardryBlocks.crystal_flower.getDefaultState(), 2);
}
}
@Override
public int getPlantMetadata(IBlockAccess world, int x, int y, int z) {
return 0;
}
}
@@ -2,56 +2,33 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.Wizardry;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockCrystalOre extends Block {
public BlockCrystalOre(Material material){
public BlockCrystalOre(Material material) {
super(material);
this.setSoundType(SoundType.STONE);
setStepSound(Block.soundTypeStone);
setBlockName("crystalOre");
setResistance(5.0F);
setHarvestLevel("pickaxe", 2);
}
@Override
public int quantityDropped(IBlockState state, int fortune, Random random){
// This now works the same way as vanilla ores
if(fortune > 0){
int i = random.nextInt(fortune + 2) - 1;
if(i < 0) i = 0;
return (random.nextInt(3) + 1) * (i + 1);
}else{
return random.nextInt(3) + 1;
}
}
@Override
public Item getItemDropped(IBlockState state, Random random, int fortune){
return WizardryItems.magic_crystal;
}
@Override
public int getExpDrop(IBlockState state, IBlockAccess world, BlockPos pos, int fortune){
Random rand = world instanceof World ? ((World)world).rand : RANDOM;
if(this.getItemDropped(state, rand, fortune) != Item.getItemFromBlock(this)){
return MathHelper.getInt(rand, 1, 4);
}
return 0;
public int quantityDropped(int meta, int fortune, Random random)
{
if(fortune > 0){
return random.nextInt(2) + 1 + random.nextInt(fortune);
}else{
return random.nextInt(2) + 1;
}
}
@Override
public Item getItemDropped(int Metadata, Random random, int fortune){
return Wizardry.magicCrystal;
}
}
@@ -1,59 +1,40 @@
package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.tileentity.TileEntityMagicLight;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
public class BlockMagicLight extends BlockContainer {
private static final AxisAlignedBB AABB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
public BlockMagicLight(Material par2Material){
public BlockMagicLight(Material par2Material) {
super(par2Material);
this.setLightLevel(1.0f);
this.setBlockBounds(0, 0, 0, 0, 0, 0);
}
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
return null;
}
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState blockState, IBlockAccess worldIn, BlockPos pos){
// The other two bounding box methods in Block aren't nullable, so this is the
// only one that can return NULL_AABB.
return NULL_AABB;
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){
return AABB;
}
@Override
public boolean isCollidable(){
return false;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityMagicLight(600);
}
@Override
public boolean isOpaqueCube(IBlockState state){
public boolean renderAsNormalBlock()
{
return false;
}
@Override
public boolean isOpaqueCube(){
return false;
}
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){
return false;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
}
}
@@ -2,110 +2,89 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.EnumElement;
import electroblob.wizardry.MagicDamage;
import electroblob.wizardry.MagicDamage.DamageType;
import electroblob.wizardry.WizardryUtilities;
import electroblob.wizardry.tileentity.TileEntityPlayerSave;
import electroblob.wizardry.util.MagicDamage;
import electroblob.wizardry.util.MagicDamage.DamageType;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.MobEffects;
import net.minecraft.item.Item;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
// TODO: Apparently you shouldn't extend BlockContainer. I feel like BlockArcaneWorkbench should, but what about the rest?
public class BlockSnare extends BlockContainer {
private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0f, 0.0f, 0.0f, 1.0f, 0.0625f, 1.0f);
public BlockSnare(Material material){
super(material);
this.setSoundType(SoundType.PLANT);
public BlockSnare(Material par2Material){
super(par2Material);
this.setBlockBounds(0.0f, 0.0f, 0.0f, 1.0f, 0.0625f, 1.0f);
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){
return AABB;
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4){
return null;
}
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos){
return NULL_AABB;
}
@Override
public boolean hasTileEntity(IBlockState state){
public boolean hasTileEntity(int metadata){
return true;
}
@Override
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity){
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity){
if(!world.isRemote && entity instanceof EntityLivingBase){
if(world.getTileEntity(pos) instanceof TileEntityPlayerSave){
TileEntityPlayerSave tileentity = (TileEntityPlayerSave)world.getTileEntity(pos);
if(world.getTileEntity(x, y, z) instanceof TileEntityPlayerSave){
TileEntityPlayerSave tileentity = (TileEntityPlayerSave)world.getTileEntity(x, y, z);
if(WizardryUtilities.isValidTarget(tileentity.getCaster(), entity)){
((EntityLivingBase)entity).attackEntityFrom(
MagicDamage.causeDirectMagicDamage(tileentity.getCaster(), DamageType.MAGIC), 6);
((EntityLivingBase)entity).addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 100, 2));
world.destroyBlock(pos, false);
((EntityLivingBase)entity).attackEntityFrom(MagicDamage.causeDirectMagicDamage(tileentity.getCaster(), DamageType.MAGIC), 6);
((EntityLivingBase)entity).addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 100, 2));
world.func_147480_a(x, y, z, false);
}
}
}
}
// The similarly named onNeighborChange method does NOT do the same thing.
@SuppressWarnings("deprecation")
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos){
super.neighborChanged(state, world, pos, block, fromPos);
if(!world.isSideSolid(pos.down(), EnumFacing.UP, false)){
world.setBlockToAir(pos);
}
public void onNeighborBlockChange(World world, int x, int y, int z, Block block)
{
super.onNeighborBlockChange(world, x, y, z, block);
if(!world.isSideSolid(x, y-1, z, ForgeDirection.UP)){
world.setBlockToAir(x, y, z);
}
}
@Override
public boolean renderAsNormalBlock()
{
return false;
}
@Override
public boolean isOpaqueCube()
{
return false;
}
@Override
public int getRenderType(){
return 23;
}
@Override
public BlockRenderLayer getRenderLayer() {
return BlockRenderLayer.CUTOUT;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return EnumBlockRenderType.MODEL;
}
@Override
public boolean isOpaqueCube(IBlockState state){
return false;
}
@Override
public boolean isFullCube(IBlockState state){
return false;
}
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune){
public Item getItemDropped(int a, Random random, int b){
return null;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityPlayerSave();
}
@@ -2,114 +2,73 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.EnumParticleType;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.tileentity.TileEntityTimer;
import electroblob.wizardry.util.WizardryParticleType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
// For future reference - extend BlockContainer whenever possible because it has methods for removing tile entities on
// block break.
@Mod.EventBusSubscriber
// For future reference - extend BlockContainer whenever possible because it has methods for removing tile entities on block break.
public class BlockSpectral extends BlockContainer {
public BlockSpectral(Material material){
public BlockSpectral(Material material) {
super(material);
this.setSoundType(SoundType.GLASS);
}
// Replaces getRenderBlockPass
@Override
public BlockRenderLayer getRenderLayer(){
return BlockRenderLayer.TRANSLUCENT;
}
public int getRenderBlockPass()
{
return 1;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return EnumBlockRenderType.MODEL;
}
// Apparently it's OK to override this, despite it being deprecated. More
// importantly, it being deprecated is not
// Forge's doing, rather it is Mojang themselves misusing the @Deprecated
// annotation to mean 'internal, don't call'.
public boolean isOpaqueCube()
{
return false;
}
@Override
public boolean isOpaqueCube(IBlockState state){
return false;
}
public boolean shouldSideBeRendered(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
{
Block block = par1IBlockAccess.getBlock(par2, par3, par4);
return block == this ? false : super.shouldSideBeRendered(par1IBlockAccess, par2, par3, par4, par5);
}
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){
return false;
}
public void randomDisplayTick(World world, int x, int y, int z, Random random){
// Middle of block
Wizardry.proxy.spawnParticle(EnumParticleType.DUST, world, x+random.nextDouble(), y+random.nextDouble(), z+random.nextDouble(), 0, 0, 0, (int)(16.0D / (Math.random() * 0.8D + 0.2D)),
0.4f + random.nextFloat()*0.2f, 0.6f + random.nextFloat()*0.4f, 0.6f + random.nextFloat()*0.4f);
// Top surface
Wizardry.proxy.spawnParticle(EnumParticleType.DUST, world, x+random.nextDouble(), y+1, z+random.nextDouble(), 0, 0, 0, (int)(16.0D / (Math.random() * 0.8D + 0.2D)),
0.4f + random.nextFloat()*0.2f, 0.6f + random.nextFloat()*0.4f, 0.6f + random.nextFloat()*0.4f);
Wizardry.proxy.spawnParticle(EnumParticleType.DUST, world, x+random.nextDouble(), y+1, z+random.nextDouble(), 0, 0, 0, (int)(16.0D / (Math.random() * 0.8D + 0.2D)),
0.4f + random.nextFloat()*0.2f, 0.6f + random.nextFloat()*0.4f, 0.6f + random.nextFloat()*0.4f);
}
// Overriden to make the block always look full brightness despite not emitting full light.
@Override
public void randomDisplayTick(IBlockState state, World world, BlockPos pos, Random random){
// Middle of block
Wizardry.proxy.spawnParticle(WizardryParticleType.DUST, world, pos.getX() + random.nextDouble(),
pos.getY() + random.nextDouble(), pos.getZ() + random.nextDouble(), 0, 0, 0,
(int)(16.0D / (Math.random() * 0.8D + 0.2D)), 0.4f + random.nextFloat() * 0.2f,
0.6f + random.nextFloat() * 0.4f, 0.6f + random.nextFloat() * 0.4f);
// Top surface
Wizardry.proxy.spawnParticle(WizardryParticleType.DUST, world, pos.getX() + random.nextDouble(), pos.getY() + 1,
pos.getZ() + random.nextDouble(), 0, 0, 0, (int)(16.0D / (Math.random() * 0.8D + 0.2D)),
0.4f + random.nextFloat() * 0.2f, 0.6f + random.nextFloat() * 0.4f, 0.6f + random.nextFloat() * 0.4f);
Wizardry.proxy.spawnParticle(WizardryParticleType.DUST, world, pos.getX() + random.nextDouble(), pos.getY() + 1,
pos.getZ() + random.nextDouble(), 0, 0, 0, (int)(16.0D / (Math.random() * 0.8D + 0.2D)),
0.4f + random.nextFloat() * 0.2f, 0.6f + random.nextFloat() * 0.4f, 0.6f + random.nextFloat() * 0.4f);
}
// Overriden to make the block always look full brightness despite not emitting
// full light.
@Override
public int getPackedLightmapCoords(IBlockState state, IBlockAccess source, BlockPos pos){
return 15;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public int getMixedBrightnessForBlock(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
{
return 15;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityTimer(1200);
}
@Override
public int quantityDropped(Random par1Random){
return 0;
}
@SuppressWarnings("deprecation")
@SideOnly(Side.CLIENT)
@Override
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos,
EnumFacing side){
IBlockState iblockstate = blockAccess.getBlockState(pos.offset(side));
Block block = iblockstate.getBlock();
return block == this ? false : super.shouldSideBeRendered(blockState, blockAccess, pos, side);
}
@SubscribeEvent
public static void onBlockPlaceEvent(BlockEvent.PlaceEvent event){
// Spectral blocks cannot be built on
if(event.getPlacedAgainst() == WizardryBlocks.spectral_block){
event.setCanceled(true);
}
}
/**
* Returns the quantity of items to drop on block destruction.
*/
@Override
public int quantityDropped(Random par1Random)
{
return 0;
}
}
@@ -2,168 +2,171 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.spell.Petrify;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.tileentity.TileEntityStatue;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Facing;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class BlockStatue extends BlockContainer {
private boolean isIce;
public BlockStatue(Material material){
super(material);
this.isIce = material == Material.ICE;
public BlockStatue(Material par2Material) {
super(par2Material);
this.isIce = par2Material == Material.ice;
if(this.isIce){
this.setDefaultSlipperiness(0.98f);
this.setSoundType(SoundType.GLASS);
this.slipperiness = 0.98F;
}
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos){
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) {
// Not a good idea to call getBlockBoundsMinX() or whatever from in here, since this method changes those!
if(!this.isIce){
if(world.getTileEntity(pos) instanceof TileEntityStatue){
if(world.getTileEntity(x, y, z) instanceof TileEntityStatue){
TileEntityStatue statue = (TileEntityStatue)world.getTileEntity(pos);
TileEntityStatue statue = (TileEntityStatue)world.getTileEntity(x, y, z);
if(statue.creature != null){
// Block bounds are set to match the width and height of the entity, clamped to within 1 block.
return new AxisAlignedBB((float)Math.max(0.5 - statue.creature.width / 2, 0), 0,
(float)Math.max(0.5 - statue.creature.width / 2, 0),
(float)Math.min(0.5 + statue.creature.width / 2, 1),
// This checks if the block is the top one and if so reduces its height so the top lines up
// with
this.setBlockBounds((float)Math.max(0.5 - statue.creature.width/2, 0), 0,
(float)Math.max(0.5 - statue.creature.width/2, 0),
(float)Math.min(0.5 + statue.creature.width/2, 1),
// This checks if the block is the top one and if so reduces its height so the top lines up with
// the top of the entity model.
statue.position == statue.parts
? (float)Math.min(statue.creature.height - statue.parts + 1, 1)
: 1,
(float)Math.min(0.5 + statue.creature.width / 2, 1));
statue.position == statue.parts ? (float)Math.min(statue.creature.height - statue.parts + 1, 1) : 1,
(float)Math.min(0.5 + statue.creature.width/2, 1));
}
}
}
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
if(!this.isIce){
if(world.getTileEntity(x, y, z) instanceof TileEntityStatue){
TileEntityStatue statue = (TileEntityStatue)world.getTileEntity(x, y, z);
if(statue.creature != null){
// Block bounds are set to match the width and height of the entity, clamped to within 1 block.
return AxisAlignedBB.getBoundingBox(x + Math.max(0.5 - statue.creature.width/2, 0),
y, z + Math.max(0.5 - statue.creature.width/2, 0),
x + Math.min(0.5 + statue.creature.width/2, 1),
// This checks if the block is the top one and if so reduces its height so the top lines up with
// the top of the entity model
statue.position == statue.parts ? y + (float)Math.min(statue.creature.height - statue.parts + 1, 1) : y + 1,
z + Math.min(0.5 + statue.creature.width/2, 1));
}
}
}
return FULL_BLOCK_AABB;
return super.getCollisionBoundingBoxFromPool(world, x, y, z);
}
// getCollisionBoundingBox eventually calls getBoundingBox anyway, and since I want the collision box and the block
// outline to be the same here, I've removed that getCollisionBoundingBox entirely.
// The number of these methods is quite simply ridiculous. This one seems to be for placement logic and block
// connections (fences, glass panes, etc.)...
@Override
public boolean isFullCube(IBlockState state){
return false;
}
// ...this one isn't used much but has something to do with redstone...
@Override
public boolean isBlockNormalCube(IBlockState state){
return false;
}
// ... this one is for most other game logic...
@Override
public boolean isNormalCube(IBlockState state){
return false;
}
// Forge version of the above method. I still need to override both though because vanilla uses the other one.
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){
return false;
}
// ... and this one is for rendering.
@Override
public boolean isOpaqueCube(IBlockState state){
public boolean renderAsNormalBlock(){
return false;
}
@Override
public BlockRenderLayer getRenderLayer(){
return this.isIce ? BlockRenderLayer.TRANSLUCENT : BlockRenderLayer.SOLID;
public boolean canRenderInPass(int pass){
return this.isIce ? super.canRenderInPass(pass) : false;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return this.isIce ? EnumBlockRenderType.MODEL : EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
public boolean isOpaqueCube(){
return false;// !this.isIce;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public int getRenderBlockPass()
{
return this.isIce? 1 : 0;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityStatue(this.isIce);
}
/*
@Override
public int quantityDropped(Random random){
public void randomDisplayTick(World world, int x, int y, int z, Random random){
if(this.isIce){
float brightness = 0.5f + (random.nextFloat()/2);
Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySparkleFX(world, x + random.nextDouble(), y + random.nextDouble(), z + random.nextDouble(), 0, 0, 0, null, brightness, brightness + 0.1f, 1.0f, true));
}
}
*/
/**
* Returns the quantity of items to drop on block destruction.
*/
@Override
public int quantityDropped(Random par1Random)
{
return 0;
}
/**
* Returns true if the given side of this block type should be rendered, if the adjacent block is at the given
* coordinates. Args: blockAccess, x, y, z, side
*/
@Override
public void breakBlock(World world, BlockPos pos, IBlockState state){
@SideOnly(Side.CLIENT)
public boolean shouldSideBeRendered(IBlockAccess p_149646_1_, int p_149646_2_, int p_149646_3_, int p_149646_4_, int p_149646_5_)
{
Block block = p_149646_1_.getBlock(p_149646_2_, p_149646_3_, p_149646_4_);
if(!world.isRemote){
TileEntityStatue tileentity = (TileEntityStatue)world.getTileEntity(pos);
return block == this ? false : super.shouldSideBeRendered(p_149646_1_, p_149646_2_, p_149646_3_, p_149646_4_, p_149646_5_);
}
@Override
public void breakBlock(World par1World, int x, int y, int z, Block block, int par6)
{
if(!par1World.isRemote){
TileEntityStatue tileentity = (TileEntityStatue)par1World.getTileEntity(x, y, z);
if(tileentity != null){
if(tileentity.parts == 2){
if(tileentity.position == 2){
world.destroyBlock(pos.down(), false);
// func_147480_a is the method that causes the block to smash as if broken by a player.
// Used to be called destroyBlock. The boolean is whether the block should drop items.
par1World.func_147480_a(x, y-1, z, false);
}else{
world.destroyBlock(pos.up(), false);
par1World.func_147480_a(x, y+1, z, false);
}
}else if(tileentity.parts == 3){
if(tileentity.position == 3){
world.destroyBlock(pos.down(), false);
world.destroyBlock(pos.down(2), false);
par1World.func_147480_a(x, y-1, z, false);
par1World.func_147480_a(x, y-2, z, false);
}else if(tileentity.position == 2){
world.destroyBlock(pos.down(), false);
world.destroyBlock(pos.up(), false);
par1World.func_147480_a(x, y-1, z, false);
par1World.func_147480_a(x, y+1, z, false);
}else{
world.destroyBlock(pos.up(), false);
world.destroyBlock(pos.up(2), false);
par1World.func_147480_a(x, y+1, z, false);
par1World.func_147480_a(x, y+2, z, false);
}
}
}
// This is only when position == 1 because world.destroyBlock calls this function for the other blocks.
if(tileentity != null && tileentity.position == 1 && tileentity.creature != null){
tileentity.creature.getEntityData().removeTag(Petrify.NBT_KEY);
tileentity.creature.isDead = false;
world.spawnEntity(tileentity.creature);
par1World.spawnEntityInWorld(tileentity.creature);
}
}
super.breakBlock(world, pos, state);
}
@SuppressWarnings("deprecation")
@SideOnly(Side.CLIENT)
@Override
public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos,
EnumFacing side){
IBlockState iblockstate = blockAccess.getBlockState(pos.offset(side));
Block block = iblockstate.getBlock();
return this.isIce && block == this ? false : super.shouldSideBeRendered(blockState, blockAccess, pos, side);
super.breakBlock(par1World, x, y, z, block, par6);
}
}
@@ -2,141 +2,148 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.ExtendedPlayer;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.WizardryRegistry;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.spell.Spell;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.IBlockAccess;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class BlockTransportationStone extends Block {
private static final AxisAlignedBB AABB = new AxisAlignedBB(0.0625f * 5, 0, 0.0625f * 5, 0.0625f * 11, 0.0625f * 6,
0.0625f * 11);
public class BlockTransportationStone extends Block{
public BlockTransportationStone(Material material){
super(material);
this.setTickRandomly(true);
this.setBlockBounds(0.0625f*5, 0, 0.0625f*5, 0.0625f*11, 0.0625f*6, 0.0625f*11);
this.setTickRandomly(true);
}
@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos){
return AABB;
}
// The number of these methods is quite simply ridiculous. This one seems to be for placement logic and block
// connections (fences, glass panes, etc.)...
@Override
public boolean isFullCube(IBlockState state){
public boolean isOpaqueCube(){
return false;
}
// ...this one isn't used much but has something to do with redstone...
@Override
public boolean isBlockNormalCube(IBlockState state){
public boolean renderAsNormalBlock(){
return false;
}
// ... this one is for most other game logic...
@Override
public boolean isNormalCube(IBlockState state){
return false;
}
// Forge version of the above method. I still need to override both though because vanilla uses the other one.
public void onNeighborBlockChange(World world, int x, int y, int z, Block block)
{
super.onNeighborBlockChange(world, x, y, z, block);
if(!world.isSideSolid(x, y-1, z, ForgeDirection.UP)){
this.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0);
world.setBlockToAir(x, y, z);
}
}
@Override
public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos){
return false;
}
// ... and this one is for rendering.
public void updateTick(World world, int x, int y, int z, Random random)
{
if(!world.isSideSolid(x, y-1, z, ForgeDirection.UP)){
this.dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0);
world.setBlockToAir(x, y, z);
}
}
@Override
public boolean isOpaqueCube(IBlockState state){
return false;
}
@SuppressWarnings("deprecation")
public boolean canPlaceBlockAt(World par1World, int x, int y, int z)
{
return super.canPlaceBlockAt(par1World, x, y, z) && par1World.isSideSolid(x, y-1, z, ForgeDirection.UP);
}
@Override
public void neighborChanged(IBlockState state, World world, BlockPos pos, Block block, BlockPos fromPos){
super.neighborChanged(state, world, pos, block, fromPos);
if(!world.isSideSolid(pos.down(), EnumFacing.UP, false)){
this.dropBlockAsItem(world, pos, world.getBlockState(pos), 0);
world.setBlockToAir(pos);
}
}
@Override
public void updateTick(World world, BlockPos pos, IBlockState state, Random random){
if(!world.isSideSolid(pos.down(), EnumFacing.UP)){
this.dropBlockAsItem(world, pos, world.getBlockState(pos), 0);
world.setBlockToAir(pos);
}
}
@Override
public boolean canPlaceBlockAt(World world, BlockPos pos){
return super.canPlaceBlockAt(world, pos) && world.isSideSolid(pos.down(), EnumFacing.UP);
}
@Override
public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand,
EnumFacing side, float hitX, float hitY, float hitZ){
ItemStack stack = player.getHeldItem(hand);
if(stack.getItem() instanceof ItemWand){
if(WizardData.get(player) != null){
WizardData data = WizardData.get(player);
for(int x = -1; x <= 1; x++){
for(int z = -1; z <= 1; z++){
BlockPos pos1 = pos.add(x, 0, z);
if(testForCircle(world, pos1)){
data.setStoneCircleLocation(pos1, world.provider.getDimension());
if(!world.isRemote) player.sendMessage(
new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.confirm",
Spells.transportation.getNameForTranslationFormatted()));
return true;
}
}
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityplayer, int par6, float par7, float par8, float par9)
{
if(entityplayer.getHeldItem() != null && entityplayer.getHeldItem().getItem() instanceof ItemWand){
if(ExtendedPlayer.get(entityplayer) != null){
ExtendedPlayer extendedplayer = ExtendedPlayer.get(entityplayer);
int x1=x-1, z1=z-1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
if(!world.isRemote)
player.sendMessage(new TextComponentTranslation("tile." + Wizardry.MODID + ":transportation_stone.invalid"));
x1=x;
z1=z-1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x+1;
z1=z-1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x-1;
z1=z;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x+1;
z1=z;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x-1;
z1=z+1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x;
z1=z+1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
x1=x+1;
z1=z+1;
if(testForCircle(world, x1, y, z1)){
extendedplayer.setStoneLocation(x1, y, z1, world.provider.dimensionId);
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.confirm", WizardryRegistry.transportation.getDisplayNameWithFormatting()));//"You will now be returned here upon casting " + EnumSpell.TRANSPORTATION.name);
return true;
}
if(!world.isRemote) entityplayer.addChatMessage(new ChatComponentTranslation("tile.transportationStone.invalid"));//"You must make a circle with 8 stones of transportation first!");
return true;
}
}
return false;
}
return false;
}
/** Returns whether the specified location is surrounded by a complete cicle of 8 transportation stones. */
public static boolean testForCircle(World world, BlockPos pos){
if(world.getBlockState(pos).getMaterial().blocksMovement()) return false;
for(int x = -1; x <= 1; x++){
for(int z = -1; z <= 1; z++){
if(world.getBlockState(pos.add(x, 0, z)).getBlock() != WizardryBlocks.transportation_stone){
if(x != 0 || z != 0) return false;
}
}
}
return true;
public static boolean testForCircle(World world, int x, int y, int z){
return world.getBlock(x-1, y, z-1) == Wizardry.transportationStone
&& world.getBlock(x, y, z-1) == Wizardry.transportationStone
&& world.getBlock(x+1, y, z-1) == Wizardry.transportationStone
&& world.getBlock(x-1, y, z) == Wizardry.transportationStone
&& !world.getBlock(x, y, z).getMaterial().blocksMovement()
&& world.getBlock(x+1, y, z) == Wizardry.transportationStone
&& world.getBlock(x-1, y, z+1) == Wizardry.transportationStone
&& world.getBlock(x, y, z+1) == Wizardry.transportationStone
&& world.getBlock(x+1, y, z+1) == Wizardry.transportationStone;
}
}
@@ -2,66 +2,60 @@ package electroblob.wizardry.block;
import java.util.Random;
import electroblob.wizardry.EnumParticleType;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.tileentity.TileEntityTimer;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
// For future reference - extend BlockContainer whenever possible because it has methods for removing tile entities on block break.
public class BlockVanishingCobweb extends BlockContainer {
public BlockVanishingCobweb(Material material){
public BlockVanishingCobweb(Material material) {
super(material);
}
@SideOnly(Side.CLIENT)
public BlockRenderLayer getBlockLayer(){
return BlockRenderLayer.CUTOUT;
}
@Override
public EnumBlockRenderType getRenderType(IBlockState state){
return EnumBlockRenderType.MODEL;
}
public int getRenderType()
{
return 1;
}
@Override
public boolean isOpaqueCube(IBlockState state){
return false;
}
@Override
public AxisAlignedBB getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos){
return NULL_AABB;
}
@Override
public boolean isFullCube(IBlockState state){
return false;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata){
public boolean isOpaqueCube()
{
return false;
}
@Override
public TileEntity createNewTileEntity(World world, int metadata) {
return new TileEntityTimer(400);
}
@Override
public void onEntityCollision(World world, BlockPos pos, IBlockState state, Entity entity){
entity.setInWeb();
}
@Override
public int quantityDropped(Random par1Random){
return 0;
}
@Override
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity)
{
entity.setInWeb();
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World p_149668_1_, int p_149668_2_, int p_149668_3_, int p_149668_4_) {
return null;
}
/**
* Returns the quantity of items to drop on block destruction.
*/
@Override
public int quantityDropped(Random par1Random)
{
return 0;
}
}
@@ -5,25 +5,32 @@ import java.util.HashMap;
import org.lwjgl.input.Keyboard;
import cpw.mods.fml.client.config.GuiConfigEntries.NumberSliderEntry;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.client.registry.RenderingRegistry;
import electroblob.wizardry.CommonProxy;
import electroblob.wizardry.EnumParticleType;
import electroblob.wizardry.ExtendedPlayer;
import electroblob.wizardry.SpellGlyphData;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.WandHelper;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.WizardryRegistry;
import electroblob.wizardry.WizardryUtilities;
import electroblob.wizardry.client.model.ModelSpiritHorse;
import electroblob.wizardry.client.model.ModelSpiritWolf;
import electroblob.wizardry.client.model.ModelWizardArmour;
import electroblob.wizardry.client.particle.ParticleBlizzard;
import electroblob.wizardry.client.particle.ParticleDarkMagic;
import electroblob.wizardry.client.particle.ParticleDust;
import electroblob.wizardry.client.particle.ParticleGiantBubble;
import electroblob.wizardry.client.particle.ParticleIce;
import electroblob.wizardry.client.particle.ParticleLeaf;
import electroblob.wizardry.client.particle.ParticleMagicFlame;
import electroblob.wizardry.client.particle.ParticlePath;
import electroblob.wizardry.client.particle.ParticleRotatingSparkle;
import electroblob.wizardry.client.particle.ParticleSnow;
import electroblob.wizardry.client.particle.ParticleSpark;
import electroblob.wizardry.client.particle.ParticleSparkle;
import electroblob.wizardry.client.particle.ParticleTornado;
import electroblob.wizardry.client.renderer.LayerStone;
import electroblob.wizardry.client.particle.EntityBlizzardFX;
import electroblob.wizardry.client.particle.EntityDarkMagicFX;
import electroblob.wizardry.client.particle.EntityDustFX;
import electroblob.wizardry.client.particle.EntityIceFX;
import electroblob.wizardry.client.particle.EntityLeafFX;
import electroblob.wizardry.client.particle.EntityMagicBubbleFX;
import electroblob.wizardry.client.particle.EntityMagicFireFX;
import electroblob.wizardry.client.particle.EntityPathFX;
import electroblob.wizardry.client.particle.EntitySnowFX;
import electroblob.wizardry.client.particle.EntitySparkFX;
import electroblob.wizardry.client.particle.EntitySparkleFX;
import electroblob.wizardry.client.particle.EntityTornadoFX;
import electroblob.wizardry.client.renderer.RenderArc;
import electroblob.wizardry.client.renderer.RenderArcaneWorkbench;
import electroblob.wizardry.client.renderer.RenderBlackHole;
@@ -32,6 +39,7 @@ import electroblob.wizardry.client.renderer.RenderBubble;
import electroblob.wizardry.client.renderer.RenderDecay;
import electroblob.wizardry.client.renderer.RenderDecoy;
import electroblob.wizardry.client.renderer.RenderEvilWizard;
import electroblob.wizardry.client.renderer.RenderFallingGrass;
import electroblob.wizardry.client.renderer.RenderFireRing;
import electroblob.wizardry.client.renderer.RenderForceArrow;
import electroblob.wizardry.client.renderer.RenderHammer;
@@ -41,14 +49,25 @@ import electroblob.wizardry.client.renderer.RenderLightningDisc;
import electroblob.wizardry.client.renderer.RenderLightningPulse;
import electroblob.wizardry.client.renderer.RenderMagicArrow;
import electroblob.wizardry.client.renderer.RenderMagicLight;
import electroblob.wizardry.client.renderer.RenderMagicSlime;
import electroblob.wizardry.client.renderer.RenderMeteor;
import electroblob.wizardry.client.renderer.RenderPhoenix;
import electroblob.wizardry.client.renderer.RenderProjectile;
import electroblob.wizardry.client.renderer.RenderSigil;
import electroblob.wizardry.client.renderer.RenderSilverfishMinion;
import electroblob.wizardry.client.renderer.RenderSkeletonMinion;
import electroblob.wizardry.client.renderer.RenderSpiderMinion;
import electroblob.wizardry.client.renderer.RenderSpiritHorse;
import electroblob.wizardry.client.renderer.RenderSpiritWolf;
import electroblob.wizardry.client.renderer.RenderStatue;
import electroblob.wizardry.client.renderer.RenderTranslucentItem;
import electroblob.wizardry.client.renderer.RenderWizard;
import electroblob.wizardry.client.renderer.RenderWraithMinion;
import electroblob.wizardry.client.renderer.RenderZombieMinion;
import electroblob.wizardry.entity.EntityArc;
import electroblob.wizardry.entity.EntityFallingGrass;
import electroblob.wizardry.entity.EntityMagicSlime;
import electroblob.wizardry.entity.EntityMeteor;
import electroblob.wizardry.entity.EntityShield;
import electroblob.wizardry.entity.construct.EntityArrowRain;
import electroblob.wizardry.entity.construct.EntityBlackHole;
@@ -67,6 +86,7 @@ import electroblob.wizardry.entity.construct.EntityIceSpike;
import electroblob.wizardry.entity.construct.EntityLightningPulse;
import electroblob.wizardry.entity.construct.EntityLightningSigil;
import electroblob.wizardry.entity.construct.EntityTornado;
import electroblob.wizardry.entity.living.EntityBlazeMinion;
import electroblob.wizardry.entity.living.EntityDecoy;
import electroblob.wizardry.entity.living.EntityEvilWizard;
import electroblob.wizardry.entity.living.EntityIceGiant;
@@ -74,12 +94,15 @@ import electroblob.wizardry.entity.living.EntityIceWraith;
import electroblob.wizardry.entity.living.EntityLightningWraith;
import electroblob.wizardry.entity.living.EntityPhoenix;
import electroblob.wizardry.entity.living.EntityShadowWraith;
import electroblob.wizardry.entity.living.EntitySilverfishMinion;
import electroblob.wizardry.entity.living.EntitySkeletonMinion;
import electroblob.wizardry.entity.living.EntitySpiderMinion;
import electroblob.wizardry.entity.living.EntitySpiritHorse;
import electroblob.wizardry.entity.living.EntitySpiritWolf;
import electroblob.wizardry.entity.living.EntityStormElemental;
import electroblob.wizardry.entity.living.EntitySummonedCreature;
import electroblob.wizardry.entity.living.EntityWizard;
import electroblob.wizardry.entity.living.ISpellCaster;
import electroblob.wizardry.entity.living.ISummonedCreature;
import electroblob.wizardry.entity.living.EntityZombieMinion;
import electroblob.wizardry.entity.projectile.EntityDarknessOrb;
import electroblob.wizardry.entity.projectile.EntityDart;
import electroblob.wizardry.entity.projectile.EntityFirebolt;
@@ -97,523 +120,459 @@ import electroblob.wizardry.entity.projectile.EntitySmokeBomb;
import electroblob.wizardry.entity.projectile.EntitySpark;
import electroblob.wizardry.entity.projectile.EntitySparkBomb;
import electroblob.wizardry.entity.projectile.EntityThunderbolt;
import electroblob.wizardry.event.SpellCastEvent;
import electroblob.wizardry.event.SpellCastEvent.Source;
import electroblob.wizardry.item.ItemFlamingAxe;
import electroblob.wizardry.item.ItemFrostAxe;
import electroblob.wizardry.item.ItemScroll;
import electroblob.wizardry.item.ItemSpectralArmour;
import electroblob.wizardry.item.ItemSpectralBow;
import electroblob.wizardry.item.ItemSpectralPickaxe;
import electroblob.wizardry.item.ItemSpectralSword;
import electroblob.wizardry.item.ItemSpellBook;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.packet.PacketCastContinuousSpell;
import electroblob.wizardry.packet.PacketCastSpell;
import electroblob.wizardry.packet.PacketNPCCastSpell;
import electroblob.wizardry.packet.PacketPlayerSync.Message;
import electroblob.wizardry.packet.PacketTransportation;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.spell.Clairvoyance;
import electroblob.wizardry.spell.None;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import electroblob.wizardry.tileentity.TileEntityMagicLight;
import electroblob.wizardry.tileentity.TileEntityStatue;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryParticleType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.renderer.entity.RenderBlaze;
import net.minecraft.client.model.ModelSlime;
import net.minecraft.client.particle.EntityDiggingFX;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.config.Property;
import net.minecraftforge.fml.client.config.GuiConfigEntries.NumberSliderEntry;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
/**
* The client proxy for wizardry.
*
* @author Electroblob
* @since Wizardry 1.0
*/
public class ClientProxy extends CommonProxy {
/** Static instance of the mixed font renderer */
public static MixedFontRenderer mixedFontRenderer;
// Key Bindings
public static final KeyBinding NEXT_SPELL = new KeyBinding("key." + Wizardry.MODID + ".next_spell", Keyboard.KEY_N, "key.categories." + Wizardry.MODID);
public static final KeyBinding PREVIOUS_SPELL = new KeyBinding("key." + Wizardry.MODID + ".previous_spell", Keyboard.KEY_B, "key.categories." + Wizardry.MODID);
public static final KeyBinding nextSpell = new KeyBinding("key.next_spell", Keyboard.KEY_N, "key.categories.wizardry");
public static final KeyBinding previousSpell = new KeyBinding("key.previous_spell", Keyboard.KEY_B, "key.categories.wizardry");
// Armour Model
public static final ModelBiped WIZARD_ARMOUR_MODEL = new ModelWizardArmour(0.75f);
// SECTION Registry
// ===============================================================================================================
public static ModelBiped wizardArmourModel = new ModelWizardArmour(0.75f);
@Override
public ModelBiped getWizardArmourModel(){
return WIZARD_ARMOUR_MODEL;
return wizardArmourModel;
}
@Override
public void registerKeyBindings(){
ClientRegistry.registerKeyBinding(NEXT_SPELL);
ClientRegistry.registerKeyBinding(PREVIOUS_SPELL);
public double getPlayerEyesPos(EntityPlayer player){
return Minecraft.getMinecraft().thePlayer == player ? player.posY : player.posY + player.eyeHeight;
}
@Override
public Vec3 getWandTipPosition(EntityLivingBase entity){
// Behaves differently in first person
if(Minecraft.getMinecraft().thePlayer == entity && Minecraft.getMinecraft().gameSettings.thirdPersonView == 0){
return Vec3.createVectorHelper(entity.posX, entity.boundingBox.minY + 1.2, entity.posZ);
}else{
return super.getWandTipPosition(entity);
}
}
@Override
public void registerSpellHUD(){
public void registerKeyBindings(){
ClientRegistry.registerKeyBinding(nextSpell);
ClientRegistry.registerKeyBinding(previousSpell);
}
@Override
public void registerEventHandlers(){
super.registerEventHandlers();
MinecraftForge.EVENT_BUS.register(new WizardryClientEventHandler());
}
@Override
public void registerSpellHUD(){
MinecraftForge.EVENT_BUS.register(new GuiSpellDisplay(Minecraft.getMinecraft()));
}
@Override
public void initGuiBits(){
mixedFontRenderer = new MixedFontRenderer(Minecraft.getMinecraft().gameSettings, new ResourceLocation("textures/font/ascii.png"),
Minecraft.getMinecraft().renderEngine, false);
GuiWizardHandbook.initDisplayRecipes();
}
// SECTION Misc
// ===============================================================================================================
@Override
public void setToNumberSliderEntry(Property property){
public void setToNumberSliderEntry(Property property) {
property.setConfigEntryClass(NumberSliderEntry.class);
}
@Override
public World getTheWorld(){
return Minecraft.getMinecraft().world;
}
@Override
public void playMovingSound(Entity entity, SoundEvent sound, float volume, float pitch, boolean repeat){
Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity(entity, sound, volume, pitch, repeat));
}
// SECTION Items
// ===============================================================================================================
@Override
public FontRenderer getFontRenderer(ItemStack stack){
Spell spell = Spells.none;
Spell spell = WizardryRegistry.none;
if(stack.getItem() instanceof ItemWand){
spell = WandHelper.getCurrentSpell(stack);
}else if(stack.getItem() instanceof ItemSpellBook || stack.getItem() instanceof ItemScroll){
spell = Spell.get(stack.getItemDamage());
}
if(Minecraft.getMinecraft().player != null && Wizardry.settings.discoveryMode && WizardData.get(Minecraft.getMinecraft().player) != null
&& !Minecraft.getMinecraft().player.capabilities.isCreativeMode
&& !WizardData.get(Minecraft.getMinecraft().player).hasSpellBeenDiscovered(spell)){
if(Wizardry.discoveryMode && ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer) != null && !Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode
&& !ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer).hasSpellBeenDiscovered(spell)){
return mixedFontRenderer;
}
return null;
}
@Override
public String getScrollDisplayName(ItemStack scroll){
// Displays [Empty slot] if spell is continuous.
Spell spell = Spell.get(scroll.getItemDamage());
if(spell.isContinuous) spell = Spells.none;
EntityPlayer player = Minecraft.getMinecraft().player;
boolean discovered = true;
// It seems that this method is called when the world is loading, before thePlayer has been initialised.
// If the player is null, the spell is assumed to be discovered.
if(player != null && Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null
&& !WizardData.get(player).hasSpellBeenDiscovered(spell)){
if(spell.isContinuous) spell = WizardryRegistry.none;
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
boolean discovered = true;
// It seems that this method is called when the world is loading, before thePlayer has been initialised.
// If the player is null, the spell is assumed to be discovered.
if(player != null && Wizardry.discoveryMode && !player.capabilities.isCreativeMode
&& ExtendedPlayer.get(player) != null && !ExtendedPlayer.get(player).hasSpellBeenDiscovered(spell)){
discovered = false;
}
if(discovered){
return I18n.format("item." + Wizardry.MODID + ":scroll.name", spell.getDisplayName()).trim();
return I18n.format("item.scroll.name", spell.getDisplayName()).trim();
}else{
return I18n.format("item." + Wizardry.MODID + ":scroll.undiscovered.name", "#" + SpellGlyphData.getGlyphName(spell, player.world) + "#").trim();
return I18n.format("item.scroll.undiscovered.name", "#" + SpellGlyphData.getGlyphName(spell, player.worldObj) + "#").trim();
}
}
@Override
public double getConjuredBowDurability(ItemStack stack){
EntityPlayer player = Minecraft.getMinecraft().player;
if(player.getActiveItemStack() == stack){
return (double)(stack.getItemDamage() + (player.getItemInUseMaxCount())) / (double)stack.getMaxDamage();
}
return super.getConjuredBowDurability(stack);
}
// SECTION Particles
// ===============================================================================================================
@Override
public void spawnParticle(WizardryParticleType type, World world, double x, double y, double z, double velX, double velY, double velZ, int maxAge,
float r, float g, float b, boolean doGravity, double radius){
// Colour values are now automatically clamped to between 0 and 1, as values outside this range seem to
// cause strange effects in 1.10 (or more specifically, particles that are bright pink!)
// TODO: This is a terrible dirty fix, but it'll do for now. Find a nicer way in future.
if(type != WizardryParticleType.MAGIC_FIRE) r = MathHelper.clamp(r, 0, 1);
g = MathHelper.clamp(g, 0, 1);
b = MathHelper.clamp(b, 0, 1);
public void spawnParticle(EnumParticleType type, World world, double x, double y, double z, double velX, double velY, double velZ, int maxAge, float r, float g, float b, boolean doGravity, double radius){
switch(type){
case BLIZZARD:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleBlizzard(world, maxAge, x, z, radius, y));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityBlizzardFX(world, r, g, b, maxAge, x, z, radius, y));
break;
case BRIGHT_DUST:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleDust(world, x, y, z, velX, velY, velZ, r, g, b, false));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityDustFX(world, x, y, z, velX, velY, velZ, r, g, b, false));
break;
case DARK_MAGIC:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleDarkMagic(world, x, y, z, velX, velY, velZ, r, g, b));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityDarkMagicFX(world, x, y, z, velX, velY, velZ, r, g, b));
break;
case DUST:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleDust(world, x, y, z, velX, velY, velZ, r, g, b, true));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityDustFX(world, x, y, z, velX, velY, velZ, r, g, b, true));
break;
case ICE:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleIce(world, x, y, z, velX, velY, velZ, maxAge));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityIceFX(world, x, y, z, velX, velY, velZ, maxAge));
break;
case LEAF:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleLeaf(world, x, y, z, velX, velY, velZ, maxAge));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityLeafFX(world, x, y, z, velX, velY, velZ, maxAge));
break;
case MAGIC_BUBBLE:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleGiantBubble(world, x, y, z, velX, velY, velZ));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityMagicBubbleFX(world, x, y, z, velX, velY, velZ));
break;
case MAGIC_FIRE:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleMagicFlame(world, x, y, z, velX, velY, velZ, maxAge, r == 0 ? 1 + world.rand.nextFloat() : r));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityMagicFireFX(world, x, y, z, velX, velY, velZ, maxAge, r == 0 ? 1 + world.rand.nextFloat() : r));
break;
case PATH:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticlePath(world, x, y, z, velX, velY, velZ, r, g, b, maxAge));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityPathFX(world, x, y, z, velX, velY, velZ, r, g, b, maxAge));
break;
case SNOW:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleSnow(world, x, y, z, velX, velY, velZ));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySnowFX(world, x, y, z, velX, velY, velZ));
break;
case SPARK:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleSpark(world, x, y, z, velX, velY, velZ));
Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySparkFX(world, x, y, z, velX, velY, velZ));
break;
case SPARKLE:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleSparkle(world, x, y, z, velX, velY, velZ, r, g, b, maxAge, doGravity));
break;
case SPARKLE_ROTATING:
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleRotatingSparkle(world, maxAge, x, z, radius, y, r, g, b));
break;
default:
Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySparkleFX(world, x, y, z, velX, velY, velZ, r, g, b, maxAge, doGravity));
break;
}
}
@Override
public void spawnDigParticle(World world, double x, double y, double z, double velX, double velY, double velZ, Block block){
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityDiggingFX(world, x, y, z, velX, velY, velZ, block, 0));
}
@Override
public void spawnTornadoParticle(World world, double x, double y, double z, double velX, double velZ, double radius, int maxAge, Block block, int metadata){
Minecraft.getMinecraft().effectRenderer.addEffect(new EntityTornadoFX(world, maxAge, x, z, radius, y, velX, velZ, block, metadata, world.rand.nextInt(6)));
}
@Override
public void spawnTornadoParticle(World world, double x, double y, double z, double velX, double velZ, double radius, int maxAge,
IBlockState block, BlockPos pos){
Minecraft.getMinecraft().effectRenderer.addEffect(new ParticleTornado(world, maxAge, x, z, radius, y, velX, velZ, block).setBlockPos(pos));// ,
// world.rand.nextInt(6)));
public void playMovingSound(Entity entity, String soundName, float volume, float pitch, boolean repeat){
Minecraft.getMinecraft().getSoundHandler().playSound(new MovingSoundEntity(entity, soundName, volume, pitch, repeat));
}
// SECTION Packet Handlers
// ===============================================================================================================
@Override
public void handleCastSpellPacket(PacketCastSpell.Message message){
World world = Minecraft.getMinecraft().world;
World world = Minecraft.getMinecraft().theWorld;
Entity caster = world.getEntityByID(message.casterID);
Entity target = world.getEntityByID(message.targetID);
Spell spell = Spell.get(message.spellID);
// Should always be true
if(caster instanceof EntityPlayer){
((EntityPlayer)caster).setActiveHand(message.hand);
ItemStack stack = ((EntityPlayer)caster).getHeldItem();
if(stack != null) ((EntityPlayer)caster).setItemInUse(stack, stack.getMaxItemUseDuration());
// Duration isn't needed because it only ever affects things server-side, and anything that is
// seen client-side gets synced elsewhere.
spell.cast(world, (EntityPlayer)caster, message.hand, 0, message.modifiers);
Source source = Source.OTHER;
Item item = ((EntityPlayer)caster).getHeldItem(message.hand).getItem();
if(item instanceof ItemWand){
source = Source.WAND;
}else if(item instanceof ItemScroll){
source = Source.SCROLL;
spell.cast(world, (EntityPlayer)caster, 0, message.damageMultiplier, message.rangeMultiplier, 1, message.blastMultiplier);
// Updates the spell discovery data client-side. Could be done by calling sync(), but that means sending
// another packet unnecessarily.
if(ExtendedPlayer.get((EntityPlayer)caster) != null){
ExtendedPlayer.get((EntityPlayer)caster).discoverSpell(spell);
}
// No need to check if the spell succeeded, because the packet is only ever sent when it succeeds.
// The handler for this event now deals with discovery.
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post((EntityPlayer)caster, spell, message.modifiers, source));
}else{
Wizardry.logger.warn("Recieved a PacketCastSpell, but the caster ID was not the ID of a player");
}
else if(caster instanceof EntityLiving && target instanceof EntityLivingBase){
spell.cast(world, (EntityLiving)caster, (EntityLivingBase)target, message.damageMultiplier, message.rangeMultiplier, 1, message.blastMultiplier);
}
}
@Override
public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){
World world = Minecraft.getMinecraft().world;
Entity caster = world.getEntityByID(message.casterID);
Spell spell = Spell.get(message.spellID);
// Should always be true
if(caster instanceof EntityPlayer){
WizardData data = WizardData.get((EntityPlayer)caster);
if(data != null){
if(data.isCasting()){
WizardData.get((EntityPlayer)caster).stopCastingContinuousSpell();
}else{
WizardData.get((EntityPlayer)caster).startCastingContinuousSpell(spell, message.modifiers);
}
}
}else{
Wizardry.logger.warn("Recieved a PacketCastContinuousSpell, but the caster ID was not the ID of a player");
}
}
@Override
public void handleNPCCastSpellPacket(PacketNPCCastSpell.Message message){
World world = Minecraft.getMinecraft().world;
Entity caster = world.getEntityByID(message.casterID);
Entity target = message.targetID == -1 ? null : world.getEntityByID(message.targetID);
Spell spell = Spell.get(message.spellID);
// Should always be true
if(caster instanceof EntityLiving){
if(target instanceof EntityLivingBase){
spell.cast(world, (EntityLiving)caster, message.hand, 0, (EntityLivingBase)target, message.modifiers);
// Again, no need to check if the spell succeeded, because the packet is only ever sent when it
// succeeds.
MinecraftForge.EVENT_BUS.post(new SpellCastEvent.Post((EntityLiving)caster, spell, message.modifiers, Source.NPC));
}
if(caster instanceof ISpellCaster){
if(spell.isContinuous || spell instanceof None){
((ISpellCaster)caster).setContinuousSpell(spell);
((EntityLiving)caster).setAttackTarget((EntityLivingBase)target);
}
}
}else{
Wizardry.logger.warn("Recieved a PacketNPCCastSpell, but the caster ID was not the ID of an EntityLiving");
}
}
@Override
public void handleTransportationPacket(PacketTransportation.Message message){
World world = Minecraft.getMinecraft().world;
World world = Minecraft.getMinecraft().theWorld;
Entity caster = world.getEntityByID(message.casterID);
// Moved from when the packet is sent to when it is received; fixes the sound not playing in first person.
caster.playSound(SoundEvents.BLOCK_PORTAL_TRAVEL, 1, 1);
for(int i = 0; i < 20; i++){
for(int i=0; i<20; i++){
double radius = 1;
double angle = world.rand.nextDouble() * Math.PI * 2;
double x = caster.posX + radius * Math.cos(angle);
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
double z = caster.posZ + radius * Math.sin(angle);
Minecraft.getMinecraft().effectRenderer
.addEffect(new ParticleSparkle(world, x, y, z, 0, 0.02, 0, 0.6f, 1.0f, 0.6f, 80 + world.rand.nextInt(10)));
double angle = world.rand.nextDouble()*Math.PI*2;
double x = caster.posX + radius*Math.cos(angle);
double y = WizardryUtilities.getEntityFeetPos(caster) + world.rand.nextDouble()*2;
double z = caster.posZ + radius*Math.sin(angle);
Minecraft.getMinecraft().effectRenderer.addEffect(new EntitySparkleFX(world, x, y, z, 0, 0.02, 0, 0.6f, 1.0f, 0.6f, 80 + world.rand.nextInt(10)));
}
for(int i = 0; i < 20; i++){
for(int i=0; i<20; i++){
double radius = 1;
double angle = world.rand.nextDouble() * Math.PI * 2;
double x = caster.posX + radius * Math.cos(angle);
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
double z = caster.posZ + radius * Math.sin(angle);
world.spawnParticle(EnumParticleTypes.VILLAGER_HAPPY, x, y, z, 0, 0.02, 0);
double angle = world.rand.nextDouble()*Math.PI*2;
double x = caster.posX + radius*Math.cos(angle);
double y = WizardryUtilities.getEntityFeetPos(caster) + world.rand.nextDouble()*2;
double z = caster.posZ + radius*Math.sin(angle);
world.spawnParticle("happyVillager", x, y, z, 0, 0.02, 0);
}
for(int i = 0; i < 20; i++){
for(int i=0; i<20; i++){
double radius = 1;
double angle = world.rand.nextDouble() * Math.PI * 2;
double x = caster.posX + radius * Math.cos(angle);
double y = caster.getEntityBoundingBox().minY + world.rand.nextDouble() * 2;
double z = caster.posZ + radius * Math.sin(angle);
world.spawnParticle(EnumParticleTypes.ENCHANTMENT_TABLE, x, y, z, 0, 0.02, 0);
double angle = world.rand.nextDouble()*Math.PI*2;
double x = caster.posX + radius*Math.cos(angle);
double y = WizardryUtilities.getEntityFeetPos(caster) + world.rand.nextDouble()*2;
double z = caster.posZ + radius*Math.sin(angle);
world.spawnParticle("enchantmenttable", x, y, z, 0, 0.02, 0);
}
}
@Override
public void handlePlayerSyncPacket(Message message){
WizardData properties = WizardData.get(Minecraft.getMinecraft().player);
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
if(properties != null){
properties.spellsDiscovered = message.spellsDiscovered;
if(message.selectedMinionID == -1){
properties.selectedMinion = null;
}else{
Entity entity = Minecraft.getMinecraft().world.getEntityByID(message.selectedMinionID);
if(entity instanceof ISummonedCreature){
properties.selectedMinion = new WeakReference<ISummonedCreature>((ISummonedCreature)entity);
Entity entity = Minecraft.getMinecraft().theWorld.getEntityByID(message.selectedMinionID);
if(entity instanceof EntitySummonedCreature){
properties.selectedMinion = new WeakReference(entity);
}else{
properties.selectedMinion = null;
}
}
}
}
@Override
public void handleGlyphDataPacket(electroblob.wizardry.packet.PacketGlyphData.Message message){
SpellGlyphData data = SpellGlyphData.get(Minecraft.getMinecraft().world);
SpellGlyphData data = SpellGlyphData.get(Minecraft.getMinecraft().theWorld);
data.randomNames = new HashMap<Spell, String>();
data.randomDescriptions = new HashMap<Spell, String>();
for(Spell spell : Spell.getSpells(Spell.allSpells)){
// -1 because the none spell isn't included
data.randomNames.put(spell, message.names.get(spell.id() - 1));
data.randomDescriptions.put(spell, message.descriptions.get(spell.id() - 1));
}
}
@Override
public void handleClairvoyancePacket(electroblob.wizardry.packet.PacketClairvoyance.Message message){
Clairvoyance.spawnPathPaticles(Minecraft.getMinecraft().world, message.path, message.durationMultiplier);
public void handleCastContinuousSpellPacket(PacketCastContinuousSpell.Message message){
World world = Minecraft.getMinecraft().theWorld;
Entity caster = world.getEntityByID(message.casterID);
Spell spell = Spell.get(message.spellID);
// This should always be true
if(caster instanceof EntityPlayer){
ExtendedPlayer properties = ExtendedPlayer.get((EntityPlayer)caster);
if(properties != null){
if(properties.isCasting()){
ExtendedPlayer.get((EntityPlayer)caster).stopCastingContinuousSpell();
}else{
ExtendedPlayer.get((EntityPlayer)caster).startCastingContinuousSpell(spell, message.damageMultiplier, message.rangeMultiplier, 1, message.blastMultiplier);
}
}
}
}
// SECTION Rendering
// ===============================================================================================================
private static final ResourceLocation ICE_WRAITH_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/ice_wraith.png");
private static final ResourceLocation LIGHTNING_WRAITH_TEXTURE = new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_wraith.png");
/** Static instance of the statue renderer, used to access the block breaking texture. */
public static RenderStatue renderStatue;
@Override
public void initialiseLayers(){
LayerStone.initialiseLayers();
public void handleClairvoyancePacket(electroblob.wizardry.packet.PacketClairvoyance.Message message) {
Clairvoyance.spawnPathPaticles(Minecraft.getMinecraft().theWorld, message.path, message.durationMultiplier);
}
@Override
public void registerRenderers(){
public double getWandDisplayDamage(ItemStack stack){
ExtendedPlayer properties = ExtendedPlayer.get(net.minecraft.client.Minecraft.getMinecraft().thePlayer);
// If the player is creative or this wand is not the wand being used, the arbitrary placeholder damage is not displayed.
if(net.minecraft.client.Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode || net.minecraft.client.Minecraft.getMinecraft().thePlayer.getHeldItem() != stack){
return (double)stack.getItemDamageForDisplay() / (double)stack.getMaxDamage();
}else{
return (double)(stack.getItemDamageForDisplay() + properties.damageToApply) / (double)stack.getMaxDamage();
}
}
@Override
public int getConjuredItemDisplayDamage(ItemStack stack){
if(stack.getItem() instanceof ItemSpectralSword){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.conjuredSwordDuration;
}else if(stack.getItem() instanceof ItemSpectralPickaxe){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.conjuredPickaxeDuration;
}else if(stack.getItem() instanceof ItemSpectralBow){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.conjuredBowDuration;
}else if(stack.getItem() instanceof ItemSpectralArmour){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.conjuredArmourDuration;
}else if(stack.getItem() instanceof ItemFlamingAxe){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.flamingAxeDuration;
}else if(stack.getItem() instanceof ItemFrostAxe){
ExtendedPlayer properties = ExtendedPlayer.get(Minecraft.getMinecraft().thePlayer);
return stack.getItemDamage() + properties.frostAxeDuration;
}
return 0;
}
@Override
public void registerRenderers() {
mixedFontRenderer = new MixedFontRenderer(Minecraft.getMinecraft().gameSettings,
new ResourceLocation("textures/font/ascii.png"), Minecraft.getMinecraft().renderEngine, false);
// Minions
// Yet another advantage to the new system: turns out you don't even need to register the renderer if you
// just want the vanilla one for the mob you're extending.
// An anonymous class in a lambda expression! No point writing a separate class really, is there?
RenderingRegistry.registerEntityRenderingHandler(EntityLightningWraith.class, manager -> new RenderBlaze(manager){
@Override
protected ResourceLocation getEntityTexture(EntityBlaze entity){
return LIGHTNING_WRAITH_TEXTURE;
}
});
RenderingRegistry.registerEntityRenderingHandler(EntityIceWraith.class, manager -> new RenderBlaze(manager){
@Override
protected ResourceLocation getEntityTexture(EntityBlaze entity){
return ICE_WRAITH_TEXTURE;
}
});
RenderingRegistry.registerEntityRenderingHandler(EntityIceGiant.class, RenderIceGiant::new);
RenderingRegistry.registerEntityRenderingHandler(EntityPhoenix.class, RenderPhoenix::new);
RenderingRegistry.registerEntityRenderingHandler(EntityZombieMinion.class, new RenderZombieMinion());
RenderingRegistry.registerEntityRenderingHandler(EntitySkeletonMinion.class, new RenderSkeletonMinion());
RenderingRegistry.registerEntityRenderingHandler(EntitySpiderMinion.class, new RenderSpiderMinion());
RenderingRegistry.registerEntityRenderingHandler(EntityBlazeMinion.class, new RenderWraithMinion(new ResourceLocation("textures/entity/blaze.png")));
RenderingRegistry.registerEntityRenderingHandler(EntityIceWraith.class, new RenderWraithMinion(new ResourceLocation("wizardry:textures/entity/ice_wraith.png")));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningWraith.class, new RenderWraithMinion(new ResourceLocation("wizardry:textures/entity/lightning_wraith.png")));
RenderingRegistry.registerEntityRenderingHandler(EntityMagicSlime.class, new RenderMagicSlime(new ModelSlime(16), new ModelSlime(0), 0.25F));
RenderingRegistry.registerEntityRenderingHandler(EntityIceGiant.class, new RenderIceGiant());
RenderingRegistry.registerEntityRenderingHandler(EntityPhoenix.class, new RenderPhoenix());
RenderingRegistry.registerEntityRenderingHandler(EntitySilverfishMinion.class, new RenderSilverfishMinion());
// Projectiles
RenderingRegistry.registerEntityRenderingHandler(EntityMagicMissile.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/magic_missile.png"), false, 8.0, 4.0, 16, 9, false));
RenderingRegistry.registerEntityRenderingHandler(EntityIceShard.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/ice_shard.png"), false, 8.0, 2.0, 16, 5, false));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningArrow.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_arrow.png"), true, 8.0, 2.0, 16, 5, false));
RenderingRegistry.registerEntityRenderingHandler(EntityDart.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/dart.png"), false, 8.0, 2.0, 16, 5, true));
RenderingRegistry.registerEntityRenderingHandler(EntityIceLance.class, manager -> new RenderMagicArrow(manager,
new ResourceLocation(Wizardry.MODID, "textures/entity/ice_lance.png"), false, 16.0, 3.0, 22, 5, true));
RenderingRegistry.registerEntityRenderingHandler(EntityMagicMissile.class, new RenderMagicArrow(new ResourceLocation("wizardry:textures/entity/magic_missile.png"), false, 8.0, 4.0, 16, 9, false));
RenderingRegistry.registerEntityRenderingHandler(EntityIceShard.class, new RenderMagicArrow(new ResourceLocation("wizardry:textures/entity/ice_shard.png"), false, 8.0, 2.0, 16, 5, false));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningArrow.class, new RenderMagicArrow(new ResourceLocation("wizardry:textures/entity/lightning_arrow.png"), true, 8.0, 2.0, 16, 5, false));
RenderingRegistry.registerEntityRenderingHandler(EntityDart.class, new RenderMagicArrow(new ResourceLocation("wizardry:textures/entity/dart.png"), false, 8.0, 2.0, 16, 5, true));
RenderingRegistry.registerEntityRenderingHandler(EntityIceLance.class, new RenderMagicArrow(new ResourceLocation("wizardry:textures/entity/ice_lance.png"), false, 16.0, 3.0, 22, 5, true));
RenderingRegistry.registerEntityRenderingHandler(EntityForceArrow.class, RenderForceArrow::new);
RenderingRegistry.registerEntityRenderingHandler(EntityForceArrow.class, new RenderForceArrow());
// Creatures
RenderingRegistry.registerEntityRenderingHandler(EntitySpiritWolf.class, manager -> new RenderSpiritWolf(manager));
RenderingRegistry.registerEntityRenderingHandler(EntitySpiritHorse.class, manager -> new RenderSpiritHorse(manager));
RenderingRegistry.registerEntityRenderingHandler(EntityWizard.class, RenderWizard::new);
RenderingRegistry.registerEntityRenderingHandler(EntityEvilWizard.class, RenderEvilWizard::new);
RenderingRegistry.registerEntityRenderingHandler(EntityDecoy.class, RenderDecoy::new);
RenderingRegistry.registerEntityRenderingHandler(EntitySpiritWolf.class, new RenderSpiritWolf(new ModelSpiritWolf(), new ModelSpiritWolf(), 0.5f));
RenderingRegistry.registerEntityRenderingHandler(EntitySpiritHorse.class, new RenderSpiritHorse(new ModelSpiritHorse(), 0.5f));
RenderingRegistry.registerEntityRenderingHandler(EntityWizard.class, new RenderWizard());
RenderingRegistry.registerEntityRenderingHandler(EntityEvilWizard.class, new RenderEvilWizard());
RenderingRegistry.registerEntityRenderingHandler(EntityDecoy.class, new RenderDecoy());
// Throwables
RenderingRegistry.registerEntityRenderingHandler(EntitySparkBomb.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/entity/spark_bomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityFirebomb.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/firebomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityPoisonBomb.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/poison_bomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityIceCharge.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/entity/ice_charge.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityForceOrb.class,
manager -> new RenderProjectile(manager, 0.7f, new ResourceLocation(Wizardry.MODID, "textures/entity/force_orb.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntitySpark.class,
manager -> new RenderProjectile(manager, 0.4f, new ResourceLocation(Wizardry.MODID, "textures/entity/spark.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntityDarknessOrb.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/entity/darkness_orb.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntityFirebolt.class,
manager -> new RenderProjectile(manager, 0.2f, new ResourceLocation(Wizardry.MODID, "textures/entity/firebolt.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningDisc.class,
manager -> new RenderLightningDisc(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_sigil.png"), 2.0f));
RenderingRegistry.registerEntityRenderingHandler(EntitySmokeBomb.class,
manager -> new RenderProjectile(manager, 0.6f, new ResourceLocation(Wizardry.MODID, "textures/items/smoke_bomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntitySparkBomb.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/entity/spark_bomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityFirebomb.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/items/firebomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityPoisonBomb.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/items/poison_bomb.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityIceCharge.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/entity/ice_charge.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityForceOrb.class, new RenderProjectile(0.7f, new ResourceLocation("wizardry:textures/entity/force_orb.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntitySpark.class, new RenderProjectile(0.4f, new ResourceLocation("wizardry:textures/entity/spark.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntityDarknessOrb.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/entity/darkness_orb.png"), true));
RenderingRegistry.registerEntityRenderingHandler(EntityFirebolt.class, new RenderProjectile(0.2f, new ResourceLocation("wizardry:textures/entity/firebolt.png"), false));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningDisc.class, new RenderLightningDisc(new ResourceLocation("wizardry:textures/entity/lightning_sigil.png"), 2.0f));
RenderingRegistry.registerEntityRenderingHandler(EntitySmokeBomb.class, new RenderProjectile(0.6f, new ResourceLocation("wizardry:textures/items/smoke_bomb.png"), false));
// Effects and constructs
RenderingRegistry.registerEntityRenderingHandler(EntityArc.class, RenderArc::new);
RenderingRegistry.registerEntityRenderingHandler(EntityBlackHole.class, RenderBlackHole::new);
RenderingRegistry.registerEntityRenderingHandler(EntityShield.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityBubble.class, RenderBubble::new);
RenderingRegistry.registerEntityRenderingHandler(EntityHammer.class, RenderHammer::new);
RenderingRegistry.registerEntityRenderingHandler(EntityIceSpike.class, RenderIceSpike::new);
RenderingRegistry.registerEntityRenderingHandler(EntityArc.class, new RenderArc());
RenderingRegistry.registerEntityRenderingHandler(EntityBlackHole.class, new RenderBlackHole());
RenderingRegistry.registerEntityRenderingHandler(EntityShield.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityMeteor.class, new RenderMeteor());
RenderingRegistry.registerEntityRenderingHandler(EntityBubble.class, new RenderBubble());
RenderingRegistry.registerEntityRenderingHandler(EntityHammer.class, new RenderHammer());
RenderingRegistry.registerEntityRenderingHandler(EntityFallingGrass.class, new RenderFallingGrass());
RenderingRegistry.registerEntityRenderingHandler(EntityIceSpike.class, new RenderIceSpike());
// Stuff that doesn't render
RenderingRegistry.registerEntityRenderingHandler(EntityBlizzard.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityTornado.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityArrowRain.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityShadowWraith.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityForcefield.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityThunderbolt.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityStormElemental.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityEarthquake.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityHailstorm.class, RenderBlank::new);
RenderingRegistry.registerEntityRenderingHandler(EntityBlizzard.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityTornado.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityArrowRain.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityShadowWraith.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityForcefield.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityThunderbolt.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityStormElemental.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityEarthquake.class, new RenderBlank());
RenderingRegistry.registerEntityRenderingHandler(EntityHailstorm.class, new RenderBlank());
// Runes on ground
RenderingRegistry.registerEntityRenderingHandler(EntityHealAura.class,
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/healing_aura.png"), 5.0f, false));
RenderingRegistry.registerEntityRenderingHandler(EntityFireSigil.class,
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/fire_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityFrostSigil.class,
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/frost_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningSigil.class,
manager -> new RenderSigil(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/lightning_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityFireRing.class,
manager -> new RenderFireRing(manager, new ResourceLocation(Wizardry.MODID, "textures/entity/ring_of_fire.png"), 5.0f));
RenderingRegistry.registerEntityRenderingHandler(EntityDecay.class, RenderDecay::new);
RenderingRegistry.registerEntityRenderingHandler(EntityLightningPulse.class, manager -> new RenderLightningPulse(manager, 8.0f));
RenderingRegistry.registerEntityRenderingHandler(EntityHealAura.class, new RenderSigil(new ResourceLocation("wizardry:textures/entity/healing_aura.png"), 5.0f, false));
RenderingRegistry.registerEntityRenderingHandler(EntityFireSigil.class, new RenderSigil(new ResourceLocation("wizardry:textures/entity/fire_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityFrostSigil.class, new RenderSigil(new ResourceLocation("wizardry:textures/entity/frost_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityLightningSigil.class, new RenderSigil(new ResourceLocation("wizardry:textures/entity/lightning_sigil.png"), 2.0f, true));
RenderingRegistry.registerEntityRenderingHandler(EntityFireRing.class, new RenderFireRing(new ResourceLocation("wizardry:textures/entity/ring_of_fire.png"), 5.0f));
RenderingRegistry.registerEntityRenderingHandler(EntityDecay.class, new RenderDecay());
RenderingRegistry.registerEntityRenderingHandler(EntityLightningPulse.class, new RenderLightningPulse(8.0f));
//RenderingRegistry.registerBlockHandler(new RenderSigilBlock());
// TESRs
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityArcaneWorkbench.class, new RenderArcaneWorkbench());
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStatue.class, renderStatue = new RenderStatue());
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityStatue.class, new RenderStatue());
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMagicLight.class, new RenderMagicLight());
// Items
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralSword, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralPickaxe, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralBow, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralHelmet, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralChestplate, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralLeggings, new RenderTranslucentItem());
MinecraftForgeClient.registerItemRenderer(Wizardry.spectralBoots, new RenderTranslucentItem());
}
}
@@ -1,81 +1,77 @@
package electroblob.wizardry.client;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import cpw.mods.fml.client.config.GuiButtonExt;
import cpw.mods.fml.client.config.GuiEditArray;
import cpw.mods.fml.client.config.GuiEditArrayEntries;
import cpw.mods.fml.client.config.GuiSelectString;
import cpw.mods.fml.client.config.GuiUtils;
import cpw.mods.fml.client.config.GuiEditArrayEntries.StringEntry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.client.config.GuiButtonExt;
import net.minecraftforge.fml.client.config.GuiEditArray;
import net.minecraftforge.fml.client.config.GuiEditArrayEntries;
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.StringEntry;
import net.minecraftforge.fml.client.config.GuiSelectString;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.common.registry.EntityEntry;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraft.entity.EntityList;
import cpw.mods.fml.client.config.IConfigElement;
/**
* [NYI] Intended as a way of choosing entities by name from all those currently registered, within the config file, so
* that users don't have to look up the entity IDs. I can't get this to work correctly at the moment.
*/
public class EntityNameEntry extends StringEntry {
protected final GuiButtonExt btnValue;
protected Object entityClass;
public EntityNameEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement,
Object value){
super(owningScreen, owningEntryList, configElement, value);
this.btnValue = new GuiButtonExt(0, 0, 0, owningEntryList.controlWidth, 18,
I18n.format(this.textFieldValue.getText()));
// this.btnValue.enabled = owningScreen.enabled;
}
public EntityNameEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Object value)
{
super(owningScreen, owningEntryList, configElement, value);
this.btnValue = new GuiButtonExt(0, 0, 0, owningEntryList.controlWidth, 18, I18n.format(this.textFieldValue.getText()));
//this.btnValue.enabled = owningScreen.enabled;
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks){
//super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partial);
this.btnValue.x = listWidth / 4;
this.btnValue.y = y;
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, Tessellator tessellator, int mouseX, int mouseY, boolean isSelected)
{
//super.drawEntry(slotIndex, x, y, listWidth, slotHeight, tessellator, mouseX, mouseY, isSelected);
this.btnValue.xPosition = listWidth / 4;
this.btnValue.yPosition = y;
String trans = I18n.format(this.textFieldValue.getText());
if(!trans.equals(this.textFieldValue.getText()))
this.btnValue.displayString = trans;
else
this.btnValue.displayString = this.textFieldValue.getText();
// btnValue.packedFGColour = value ? GuiUtils.getColorCode('2', true) : GuiUtils.getColorCode('4', true);
String trans = I18n.format(this.textFieldValue.getText());
if (!trans.equals(this.textFieldValue.getText()))
this.btnValue.displayString = trans;
else
this.btnValue.displayString = this.textFieldValue.getText();
//btnValue.packedFGColour = value ? GuiUtils.getColorCode('2', true) : GuiUtils.getColorCode('4', true);
this.btnValue.drawButton(owningEntryList.getMC(), mouseX, mouseY, partialTicks);
}
this.btnValue.drawButton(owningEntryList.mc, mouseX, mouseY);
}
@Override
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY){
if(this.btnValue.mousePressed(owningEntryList.getMC(), x, y)){
btnValue.playPressSound(owningEntryList.getMC().getSoundHandler());
// Goodness only knows if this works, but the class is unimplemented right now so it doesn't really matter.
Map<Object, String> map = ForgeRegistries.ENTITIES.getEntries().stream().collect(
Collectors.<Entry<ResourceLocation, EntityEntry>, Object, String>toMap(e -> e.getValue().getClass(),
e -> e.getValue().getName()));
Minecraft.getMinecraft().displayGuiScreen(
new GuiSelectString(this.owningScreen, configElement, index, map, this.getValue(), true));
owningEntryList.recalculateState();
return true;
}
/**
* Returns true if the mouse has been pressed on this control.
*/
@Override
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
if (this.btnValue.mousePressed(owningEntryList.mc, x, y))
{
btnValue.func_146113_a(owningEntryList.mc.getSoundHandler());
Minecraft.getMinecraft().displayGuiScreen(new GuiSelectString(this.owningScreen, configElement, index, EntityList.classToStringMapping, this.getValue(), true));
owningEntryList.recalculateState();
return true;
}
return super.mousePressed(index, x, y, mouseEvent, relativeX, relativeY);
}
return super.mousePressed(index, x, y, mouseEvent, relativeX, relativeY);
}
@Override
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY){
this.btnValue.mouseReleased(x, y);
super.mouseReleased(index, x, y, mouseEvent, relativeX, relativeY);
}
/**
* Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY
*/
@Override
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
{
this.btnValue.mouseReleased(x, y);
super.mouseReleased(index, x, y, mouseEvent, relativeX, relativeY);
}
@Override
public Object getValue(){
return this.textFieldValue.getText();
}
@Override
public Object getValue()
{
return this.textFieldValue.getText();
}
}
@@ -1,178 +1,90 @@
package electroblob.wizardry.client;
import org.lwjgl.input.Keyboard;
import codechicken.nei.VisiblityData;
import codechicken.nei.api.INEIGuiHandler;
import codechicken.nei.api.TaggedInventoryArea;
import cpw.mods.fml.common.Optional.Interface;
import cpw.mods.fml.common.Optional.Method;
import cpw.mods.fml.common.network.simpleimpl.IMessage;
import electroblob.wizardry.ExtendedPlayer;
import electroblob.wizardry.SpellGlyphData;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.WandHelper;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.constants.Element;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.packet.PacketControlInput;
import electroblob.wizardry.packet.WizardryPacketHandler;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.tileentity.ContainerArcaneWorkbench;
import electroblob.wizardry.tileentity.SlotWizardry;
import electroblob.wizardry.tileentity.TileEntityArcaneWorkbench;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryUtilities;
import java.awt.Rectangle;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraft.util.StatCollector;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
public class GuiArcaneWorkbench extends GuiContainer {
@Interface(iface = "codechicken.nei.api.INEIGuiHandler", modid = "NotEnoughItems")
public class GuiArcaneWorkbench extends GuiContainer implements INEIGuiHandler {
private GuiButton applyBtn;
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID,
"textures/gui/arcane_workbench.png");
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/arcane_workbench.png");
private IInventory playerInventory;
private IInventory arcaneWorkbenchInventory;
private static final int tooltipWidth = 164;
private static final int tooltipHeight = 155;
private final int tooltipWidth = 164;
// We report the actual size of the GUI to Minecraft when a wand is in so JEI doesn't overdraw it.
// For calculations, we use the size without the tooltip.
private final int xSizeNoTip = 176;
public GuiArcaneWorkbench(InventoryPlayer invPlayer, TileEntityArcaneWorkbench entity){
public GuiArcaneWorkbench(InventoryPlayer invPlayer, TileEntityArcaneWorkbench entity) {
super(new ContainerArcaneWorkbench(invPlayer, entity));
this.playerInventory = invPlayer;
this.arcaneWorkbenchInventory = entity;
xSize = xSizeNoTip;
xSize = 176;
ySize = 220;
}
@Override
public void drawScreen(int p_73863_1_, int p_73863_2_, float p_73863_3_){
this.drawDefaultBackground();
// Tests if there is a wand in the workbench and edits the positioning accordingly
if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack() && this.inventorySlots
.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack().getItem() instanceof ItemWand){
xSize = xSizeNoTip + tooltipWidth;
guiLeft = (this.width - this.xSize) / 2;
this.applyBtn.x = (this.width - tooltipWidth) / 2 + 48;
}else{
xSize = xSizeNoTip;
guiLeft = (this.width - this.xSize) / 2;
this.applyBtn.x = this.width / 2 + 48;
}
if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack()){
if(this.hasWand()){
this.applyBtn.enabled = true;
}else{
this.applyBtn.enabled = false;
}
super.drawScreen(p_73863_1_, p_73863_2_, p_73863_3_);
// Required now, or item mouseover tooltips won't render.
this.renderHoveredToolTip(p_73863_1_, p_73863_2_);
}
@Override
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY){
GlStateManager.color(1F, 1F, 1F, 1F);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
// Main inventory
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSizeNoTip, ySize);
// Changing slots
for(int i = 0; i < ContainerArcaneWorkbench.CRYSTAL_SLOT; i++){
Slot slot = this.inventorySlots.getSlot(i);
if(slot.xPos >= 0 && slot.yPos >= 0)
this.drawTexturedModalRect(guiLeft + slot.xPos - 10, guiTop + slot.yPos - 10, 0, 220, 36, 36);
}
// Tooltip only drawn if there is a wand
if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack() && this.inventorySlots
.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack().getItem() instanceof ItemWand){
// Tooltip box
drawTexturedModalRect(guiLeft + xSizeNoTip, guiTop, xSizeNoTip, 0, 256 - xSizeNoTip - 4, ySize);
drawTexturedModalRect(guiLeft + 252, guiTop, xSizeNoTip + 4, 0, tooltipWidth - 2 * (256 - xSizeNoTip - 4), ySize);
drawTexturedModalRect(guiLeft + xSize - (256 - xSizeNoTip - 4), guiTop, xSizeNoTip + 4, 0,
256 - xSizeNoTip - 4, ySize);
ItemStack wand = this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack();
Spell[] spells = WandHelper.getSpells(wand);
int i = 0;
for(Spell spell : spells){
boolean discovered = true;
if(!this.mc.player.capabilities.isCreativeMode && WizardData.get(this.mc.player) != null){
discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell);
}
// As of Wizardry 1.2, the icons have been split off into their own texture files to allow for add-on
// mods to add their own.
Minecraft.getMinecraft().renderEngine
.bindTexture(discovered ? spell.element.getIcon() : Element.MAGIC.getIcon());
// Renders the little element icon
WizardryUtilities.drawTexturedRect(guiLeft + xSizeNoTip + 5, guiTop + 34 + 10 * i++, 8, 8);
}
int x = 0;
int y = guiTop + 50 + spells.length * 10;
// Look how much shorter this is with the WandHelper class!
for(Item item : WandHelper.getSpecialUpgrades()){
int level = WandHelper.getUpgradeLevel(wand, item);
if(level > 0){
ItemStack stack = new ItemStack(item, level);
GlStateManager.enableDepth();
this.itemRender.renderItemAndEffectIntoGUI(stack, guiLeft + xSizeNoTip + 6 + x, y);
this.itemRender.renderItemOverlayIntoGUI(this.fontRenderer, stack, guiLeft + xSizeNoTip + 6 + x, y,
null);
x += 18;
GlStateManager.disableDepth();
}
}
}
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
// Fixes the bug that caused the slot hightlight to render opaque. I don't know why it works, it just works!
GlStateManager.disableBlend();
GlStateManager.enableAlpha();
}
@Override
/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY){
this.fontRenderer
.drawString(this.arcaneWorkbenchInventory.hasCustomName() ? this.arcaneWorkbenchInventory.getName()
: I18n.format(this.arcaneWorkbenchInventory.getName()), 8, 6, 4210752);
this.fontRenderer.drawString(this.playerInventory.hasCustomName() ? this.playerInventory.getName()
: I18n.format(this.playerInventory.getName()), 8, this.ySize - 96 + 2, 4210752);
this.fontRendererObj.drawString(this.arcaneWorkbenchInventory.hasCustomInventoryName() ? this.arcaneWorkbenchInventory.getInventoryName() : I18n.format(this.arcaneWorkbenchInventory.getInventoryName()), 8, 6, 4210752);
this.fontRendererObj.drawString(this.playerInventory.hasCustomInventoryName() ? this.playerInventory.getInventoryName() : I18n.format(this.playerInventory.getInventoryName()), 8, this.ySize - 96 + 2, 4210752);
if(this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack() && this.inventorySlots
.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack().getItem() instanceof ItemWand){
if(this.hasWand()){
ItemStack wand = this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack();
this.fontRenderer.drawStringWithShadow("\u00A7f" + wand.getDisplayName(), xSizeNoTip + 6, 6, 0);
this.fontRenderer.drawStringWithShadow(
"\u00A77" + I18n.format("container." + Wizardry.MODID + ":arcane_workbench.mana") + " "
+ (wand.getMaxDamage() - wand.getItemDamage()) + "/" + wand.getMaxDamage(),
xSizeNoTip + 6, 20, 0);
this.fontRendererObj.drawStringWithShadow("\u00A7f" + wand.getDisplayName(), xSize + 6, 6, 0);
this.fontRendererObj.drawStringWithShadow("\u00A77" + StatCollector.translateToLocal("container.arcaneWorkbench.mana") + " " + (wand.getMaxDamage() - wand.getItemDamage()) + "/" + wand.getMaxDamage(), xSize + 6, 20, 0);
Spell[] spells = WandHelper.getSpells(wand);
@@ -182,37 +94,34 @@ public class GuiArcaneWorkbench extends GuiContainer {
boolean discovered = true;
if(!this.mc.player.capabilities.isCreativeMode && WizardData.get(this.mc.player) != null){
discovered = WizardData.get(this.mc.player).hasSpellBeenDiscovered(spell);
if(!this.mc.thePlayer.capabilities.isCreativeMode && ExtendedPlayer.get(this.mc.thePlayer) != null){
discovered = ExtendedPlayer.get(this.mc.thePlayer).hasSpellBeenDiscovered(spell);
}
if(discovered){
this.fontRenderer.drawStringWithShadow(spell.getDisplayNameWithFormatting(), xSizeNoTip + 16, y, 0);
this.fontRendererObj.drawStringWithShadow(spell.getDisplayNameWithFormatting(), xSize + 16, y, 0);
}else{
this.mc.standardGalacticFontRenderer.drawStringWithShadow(
"\u00A79" + SpellGlyphData.getGlyphName(spell, this.mc.world), xSizeNoTip + 16, y, 0);
this.mc.standardGalacticFontRenderer.drawStringWithShadow("\u00A79" + SpellGlyphData.getGlyphName(spell, this.mc.theWorld), xSize + 16, y, 0);
}
y += 10;
}
if(WandHelper.getTotalUpgrades(wand) > 0){
this.fontRenderer.drawStringWithShadow(
"\u00A7f" + I18n.format("container." + Wizardry.MODID + ":arcane_workbench.upgrades"), xSizeNoTip + 6, y + 6, 0);
this.fontRendererObj.drawStringWithShadow("\u00A7f" + StatCollector.translateToLocal("container.arcaneWorkbench.upgrades"), xSize + 6, y + 6, 0);
int x = 0;
y = 50 + spells.length * 10;
y = guiTop + 50 + spells.length*10;
// Wand upgrade tooltips
for(Item item : WandHelper.getSpecialUpgrades()){
int level = WandHelper.getUpgradeLevel(wand, item);
if(level > 0){
// The javadoc for isPointInRegion is ambiguous; what it means is that the REGION is
// relative to the GUI but the POINT isn't.
if(isPointInRegion(xSizeNoTip + 6 + x, y, 16, 16, mouseX, mouseY)){
// No idea why this is -16 instead of +6, but it works!
if(isPointInRegion(xSize -16 + x, y, 16, 16, mouseX + guiLeft, mouseY + guiTop)){
ItemStack stack = new ItemStack(item, level);
this.renderToolTip(stack, mouseX - guiLeft, mouseY - guiTop);
this.drawItemStackTooltip(stack, mouseX - guiLeft, mouseY - guiTop);
}
x += 18;
}
@@ -222,30 +131,295 @@ public class GuiArcaneWorkbench extends GuiContainer {
}
@Override
public void initGui(){
this.mc.player.openContainer = this.inventorySlots;
this.guiLeft = (this.width - this.xSize) / 2;
this.guiTop = (this.height - this.ySize) / 2;
Keyboard.enableRepeatEvents(true);
this.buttonList.clear();
this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width / 2 + 48, this.height / 2 + 3));
}
public void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
@Override
public void onGuiClosed(){
super.onGuiClosed();
Keyboard.enableRepeatEvents(false);
}
GL11.glColor4f(1F, 1F, 1F, 1F);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
@Override
protected void actionPerformed(GuiButton button){
if(button.enabled){
if(button.id == 0){
// Packet building
IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.APPLY_BUTTON);
WizardryPacketHandler.net.sendToServer(msg);
// Main inventory
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
// Changing slots
for(int i=0; i<ContainerArcaneWorkbench.CRYSTAL_SLOT; i++){
Slot slot = this.inventorySlots.getSlot(i);
if(slot.xDisplayPosition >=0 && slot.yDisplayPosition >= 0)
this.drawTexturedModalRect(guiLeft + slot.xDisplayPosition - 10, guiTop + slot.yDisplayPosition - 10,
64, 220, 36, 36);
}
// Tooltip only drawn if there is a wand
if(this.hasWand()){
// Tooltip box
drawTexturedModalRect(guiLeft + xSize, guiTop, xSize, 0, 256 - xSize - 4, ySize);
drawTexturedModalRect(guiLeft + 252, guiTop, xSize + 4, 0, tooltipWidth - 2*(256 - xSize - 4), ySize);
drawTexturedModalRect(guiLeft + xSize + tooltipWidth - (256 - xSize - 4), guiTop, xSize + 4, 0, 256 - xSize - 4, ySize);
ItemStack wand = this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack();
Spell[] spells = WandHelper.getSpells(wand);
int i=0;
for(Spell spell : spells){
boolean discovered = true;
if(!this.mc.thePlayer.capabilities.isCreativeMode && ExtendedPlayer.get(this.mc.thePlayer) != null){
discovered = ExtendedPlayer.get(this.mc.thePlayer).hasSpellBeenDiscovered(spell);
}
// Renders the little element icon if there is an element
this.drawTexturedModalRect(guiLeft + xSize + 5, guiTop + 34 + 10*i++, discovered ? spell.element.ordinal()*8 : 0, 220, 8, 8);
}
int x = 0;
int y = guiTop + 50 + spells.length*10;
// Look how much shorter this is with the WandHelper class!
for(Item item : WandHelper.getSpecialUpgrades()){
int level = WandHelper.getUpgradeLevel(wand, item);
if(level > 0){
ItemStack stack = new ItemStack(item, level);
itemRender.renderItemAndEffectIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), stack, guiLeft + xSize + 6 + x, y);
itemRender.renderItemOverlayIntoGUI(this.fontRendererObj, this.mc.getTextureManager(), stack, guiLeft + xSize + 6 + x, y);
x += 18;
}
}
}
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
for(Object object : this.inventorySlots.inventorySlots){
if(object instanceof Slot){
Slot slot = (Slot)object;
// Tests whether I have added a background texture and if so actually renders it
if(!slot.getHasStack() && slot instanceof SlotWizardry && ((SlotWizardry)slot).backgroundIndex > -1){
// Taken directly from GuiContainer#func_146977_a, with a few changes.
this.zLevel = 100.0F;
itemRender.zLevel = 100.0F;
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_BLEND);
this.drawTexturedModalRect(guiLeft + slot.xDisplayPosition, guiTop + slot.yDisplayPosition, ((SlotWizardry)slot).backgroundIndex*16, 240, 16, 16);
GL11.glDisable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_LIGHTING);
itemRender.zLevel = 0.0F;
this.zLevel = 0.0F;
}
}
}
}
}
@SuppressWarnings("unchecked")
public void initGui()
{
this.mc.thePlayer.openContainer = this.inventorySlots;
this.guiLeft = (this.width - this.xSize) / 2;
this.guiTop = (this.height - this.ySize) / 2;
Keyboard.enableRepeatEvents(true);
this.buttonList.clear();
this.buttonList.add(this.applyBtn = new GuiButtonApply(0, this.width/2 + 48, this.height/2 + 3));
}
public void onGuiClosed()
{
super.onGuiClosed();
Keyboard.enableRepeatEvents(false);
}
/**
* Fired when a control is clicked. This is the equivalent of ActionListener.actionPerformed(ActionEvent e).
*/
protected void actionPerformed(GuiButton par1GuiButton)
{
if (par1GuiButton.enabled)
{
if (par1GuiButton.id == 0)
{
// Packet building
IMessage msg = new PacketControlInput.Message(0);
WizardryPacketHandler.net.sendToServer(msg);
}
}
}
protected boolean isPointInRegion(int par1, int par2, int par3, int par4, int par5, int par6)
{
int k1 = this.width/2 - xSize/2;
int l1 = this.height/2 - this.ySize/2;
par5 -= k1;
par6 -= l1;
return par5 >= par1 - 1 && par5 < par1 + par3 + 1 && par6 >= par2 - 1 && par6 < par2 + par4 + 1;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void drawItemStackTooltip(ItemStack par1ItemStack, int par2, int par3)
{
List list = par1ItemStack.getTooltip(this.mc.thePlayer, this.mc.gameSettings.advancedItemTooltips);
for (int k = 0; k < list.size(); ++k)
{
if (k == 0)
{
list.set(k, par1ItemStack.getRarity().rarityColor + (String)list.get(k));
}
else
{
list.set(k, EnumChatFormatting.GRAY + (String)list.get(k));
}
}
FontRenderer font = par1ItemStack.getItem().getFontRenderer(par1ItemStack);
drawHoveringText(list, par2, par3, (font == null ? fontRendererObj : font));
}
@SuppressWarnings("rawtypes")
protected void drawHoveringText(List par1List, int par2, int par3, FontRenderer font)
{
if (!par1List.isEmpty())
{
GL11.glDisable(GL12.GL_RESCALE_NORMAL);
RenderHelper.disableStandardItemLighting();
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_DEPTH_TEST);
int k = 0;
Iterator iterator = par1List.iterator();
while (iterator.hasNext())
{
String s = (String)iterator.next();
int l = font.getStringWidth(s);
if (l > k)
{
k = l;
}
}
int i1 = par2 + 12;
int j1 = par3 - 12;
int k1 = 8;
if (par1List.size() > 1)
{
k1 += 2 + (par1List.size() - 1) * 10;
}
if (i1 + k > this.width)
{
i1 -= 28 + k;
}
if (j1 + k1 + 6 > this.height)
{
j1 = this.height - k1 - 6;
}
this.zLevel = 300.0F;
itemRender.zLevel = 300.0F;
int l1 = -267386864;
this.drawGradientRect(i1 - 3, j1 - 4, i1 + k + 3, j1 - 3, l1, l1);
this.drawGradientRect(i1 - 3, j1 + k1 + 3, i1 + k + 3, j1 + k1 + 4, l1, l1);
this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 + k1 + 3, l1, l1);
this.drawGradientRect(i1 - 4, j1 - 3, i1 - 3, j1 + k1 + 3, l1, l1);
this.drawGradientRect(i1 + k + 3, j1 - 3, i1 + k + 4, j1 + k1 + 3, l1, l1);
int i2 = 1347420415;
int j2 = (i2 & 16711422) >> 1 | i2 & -16777216;
this.drawGradientRect(i1 - 3, j1 - 3 + 1, i1 - 3 + 1, j1 + k1 + 3 - 1, i2, j2);
this.drawGradientRect(i1 + k + 2, j1 - 3 + 1, i1 + k + 3, j1 + k1 + 3 - 1, i2, j2);
this.drawGradientRect(i1 - 3, j1 - 3, i1 + k + 3, j1 - 3 + 1, i2, i2);
this.drawGradientRect(i1 - 3, j1 + k1 + 2, i1 + k + 3, j1 + k1 + 3, j2, j2);
for(int k2 = 0; k2 < par1List.size(); ++k2){
String s1 = (String)par1List.get(k2);
font.drawStringWithShadow(s1, i1, j1, -1);
if(k2 == 0){
j1 += 2;
}
j1 += 10;
}
this.zLevel = 0.0F;
itemRender.zLevel = 0.0F;
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_DEPTH_TEST);
RenderHelper.enableStandardItemLighting();
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
}
}
/**
* @return A list of TaggedInventoryAreas that will be used with the savestates.
*/
@Method(modid = "NotEnoughItems")
@Override
public List<TaggedInventoryArea> getInventoryAreas(GuiContainer gui) {
return Collections.emptyList();
}
/**
* NEI will give the specified item to the InventoryRange returned if the player's inventory is full.
* Should not return null, just an empty list
*/
@Method(modid = "NotEnoughItems")
@Override
public Iterable<Integer> getItemSpawnSlots(GuiContainer gui, ItemStack item) {
return Collections.emptyList();
}
/**
* Handles clicks while an itemstack has been dragged from the item panel. Use this to set configurable slots and the like.
* Changes made to the stackSize of the dragged stack will be kept
* @param gui The current gui instance
* @param mousex The x position of the mouse
* @param mousey The y position of the mouse
* @param draggedStack The stack being dragged from the item panel
* @param button The button presed
* @return True if the drag n drop was handled. False to resume processing through other routes. The held stack will be deleted if draggedStack.stackSize == 0
*/
@Method(modid = "NotEnoughItems")
@Override
public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) {
return false;
}
/**
* Used to prevent the item panel from drawing on top of other gui elements.
* This function will also be called with a 1x1 size rectangle on the mouse position for determining if the given coordinate should override item panel functions such as scrolling
* @param x The x coordinate of the rectangle bounding the slot
* @param y The y coordinate of the rectangle bounding the slot
* @param w The w coordinate of the rectangle bounding the slot
* @param h The h coordinate of the rectangle bounding the slot
* @return true if the item panel slot within the specified rectangle should not be rendered.
*/
@Method(modid = "NotEnoughItems")
@Override
public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) {
if(this.hasWand()) {
Rectangle itemPanel = new Rectangle(x, y, w, h);
Rectangle tooltip = new Rectangle(this.guiLeft + this.xSize, this.guiTop, tooltipWidth, tooltipHeight);
return itemPanel.intersects(tooltip);
}
return false;
}
@Method(modid = "NotEnoughItems")
@Override
public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) {
return currentVisibility;
}
private boolean hasWand() {
return this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getHasStack()
&& this.inventorySlots.getSlot(ContainerArcaneWorkbench.WAND_SLOT).getStack().getItem() instanceof ItemWand;
}
}
@@ -1,42 +1,73 @@
package electroblob.wizardry.client;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.WizardryUtilities;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.resources.I18n;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
class GuiButtonApply extends GuiButton {
private static final ResourceLocation texture = new ResourceLocation("wizardry:textures/gui/handbook.png");
public GuiButtonApply(int id, int x, int y){
super(id, x, y, 32, 16, I18n.format("container." + Wizardry.MODID + ":arcane_workbench.apply"));
}
public GuiButtonApply(int id, int x, int y){
super(id, x, y, 32, 16, StatCollector.translateToLocal("container.arcaneWorkbench.apply"));
}
@Override
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
// Whether the button is highlighted
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
/**
* Draws this button to the screen.
*/
public void drawButton(Minecraft minecraft, int par2, int par3){
// Whether the button is highlighted
this.field_146123_n = par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width && par3 < this.yPosition + this.height;
int k = 36;
int l = 220;
int colour = 14737632;
int k = 100;
int l = 220;
int colour = 14737632;
if(this.enabled){
if(this.field_146123_n){
k += this.width*2;
colour = 16777120;
}
}else{
k += this.width;
colour = 10526880;
}
this.drawTexturedRect(this.xPosition, this.yPosition, k, l, this.width, this.height, 256, 256);
this.drawCenteredString(minecraft.fontRenderer, this.displayString, this.xPosition + this.width / 2, this.yPosition + (this.height - 8) / 2, colour);
if(this.enabled){
if(this.hovered){
k += this.width * 2;
colour = 16777120;
}
}else{
k += this.width;
colour = 10526880;
}
}
WizardryUtilities.drawTexturedRect(this.x, this.y, k, l, this.width, this.height, 256, 256);
this.drawCenteredString(minecraft.fontRenderer, this.displayString, this.x + this.width / 2,
this.y + (this.height - 8) / 2, colour);
}
}
/**
* Draws a textured rectangle, taking the size of the image and the bit needed into account.
* @param x The x position of the rectangle
* @param y The y position of the rectangle
* @param u The x position of the top left corner of the section of the image wanted
* @param v The y position of the top left corner of the section of the image wanted
* @param width The width of the section
* @param height The height of the section
* @param textureWidth The width of the actual image.
* @param textureHeight The height of the actual image.
*/
public void drawTexturedRect(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight)
{
float f = 1F / (float)textureWidth;
float f1 = 1F / (float)textureHeight;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((double)(x), (double)(y + height), 0, (double)((float)(u) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y + height), 0, (double)((float)(u + width) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y), 0, (double)((float)(u + width) * f), (double)((float)(v) * f1));
tessellator.addVertexWithUV((double)(x), (double)(y), 0, (double)((float)(u) * f), (double)((float)(v) * f1));
tessellator.draw();
}
}
@@ -1,20 +1,27 @@
package electroblob.wizardry.client;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
class GuiButtonInvisible extends GuiButton {
public GuiButtonInvisible(int id, int x, int y, int width, int height){
super(id, x, y, width, height, "");
}
@Override
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
}
public GuiButtonInvisible(int id, int x, int y, int width, int height){
super(id, x, y, width, height, "");
}
/**
* Draws this button to the screen.
*/
public void drawButton(Minecraft par1Minecraft, int par2, int par3){
this.field_146123_n = par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width && par3 < this.yPosition + this.height;
}
}
@@ -0,0 +1,78 @@
package electroblob.wizardry.client;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
@SideOnly(Side.CLIENT)
class GuiButtonNextPage extends GuiButton
{
/**
* True for pointing right (next page), false for pointing left (previous page).
*/
private final boolean nextPage;
private static final ResourceLocation texture = new ResourceLocation("wizardry:textures/gui/handbook.png");
public GuiButtonNextPage(int id, int x, int y, boolean par4)
{
super(id, x, y, 23, 13, "");
this.nextPage = par4;
}
/**
* Draws this button to the screen.
*/
public void drawButton(Minecraft par1Minecraft, int par2, int par3)
{
if (this.visible)
{
boolean flag = par2 >= this.xPosition && par3 >= this.yPosition && par2 < this.xPosition + this.width && par3 < this.yPosition + this.height;
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
par1Minecraft.getTextureManager().bindTexture(texture);
int k = 0;
int l = 192;
if (flag)
{
k += 23;
}
if (!this.nextPage)
{
l += 13;
}
this.drawTexturedRect(this.xPosition, this.yPosition, k, l, 23, 13, 288, 256);
}
}
/**
* Draws a textured rectangle, taking the size of the image and the bit needed into account.
* @param x The x position of the rectangle
* @param y The y position of the rectangle
* @param u The x position of the top left corner of the section of the image wanted
* @param v The y position of the top left corner of the section of the image wanted
* @param width The width of the section
* @param height The height of the section
* @param textureWidth The width of the actual image.
* @param textureHeight The height of the actual image.
*/
public void drawTexturedRect(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight)
{
float f = 1F / (float)textureWidth;
float f1 = 1F / (float)textureHeight;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((double)(x), (double)(y + height), 0, (double)((float)(u) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y + height), 0, (double)((float)(u + width) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y), 0, (double)((float)(u + width) * f), (double)((float)(v) * f1));
tessellator.addVertexWithUV((double)(x), (double)(y), 0, (double)((float)(u) * f), (double)((float)(v) * f1));
tessellator.draw();
}
}
@@ -1,47 +0,0 @@
package electroblob.wizardry.client;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
class GuiButtonTurnPage extends GuiButton {
/** True for pointing right (next page), false for pointing left (previous page). */
private final boolean nextPage;
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/handbook.png");
public GuiButtonTurnPage(int id, int x, int y, boolean isNextPage){
super(id, x, y, 23, 13, "");
this.nextPage = isNextPage;
}
@Override
public void drawButton(Minecraft minecraft, int mouseX, int mouseY, float partialTicks){
if(this.visible){
boolean flag = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
minecraft.getTextureManager().bindTexture(texture);
int k = 0;
int l = 192;
if(flag){
k += 23;
}
if(!this.nextPage){
l += 13;
}
WizardryUtilities.drawTexturedRect(this.x, this.y, k, l, 23, 13, 288, 256);
}
}
}
@@ -3,128 +3,102 @@ package electroblob.wizardry.client;
import java.util.ArrayList;
import java.util.List;
import electroblob.wizardry.Settings;
import cpw.mods.fml.client.config.DummyConfigElement.DummyCategoryElement;
import cpw.mods.fml.client.config.GuiConfig;
import cpw.mods.fml.client.config.GuiConfigEntries;
import cpw.mods.fml.client.config.GuiConfigEntries.CategoryEntry;
import cpw.mods.fml.client.config.IConfigElement;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.config.DummyConfigElement.DummyCategoryElement;
import net.minecraftforge.fml.client.config.GuiConfig;
import net.minecraftforge.fml.client.config.GuiConfigEntries;
import net.minecraftforge.fml.client.config.GuiConfigEntries.CategoryEntry;
import net.minecraftforge.fml.client.config.IConfigElement;
public class GuiConfigWizardry extends GuiConfig {
public GuiConfigWizardry(GuiScreen parent){
super(parent, getConfigEntries(), Wizardry.MODID, false, false,
Wizardry.NAME + " - " + I18n.format("config." + Wizardry.MODID + ".title.general"));
// this.titleLine2 = "File location: " + Wizardry.config.getConfigFile().getAbsolutePath();
super(parent, getConfigEntries(), Wizardry.MODID, false, false, Wizardry.NAME + " - " + StatCollector.translateToLocal("config.title.general"));
//this.titleLine2 = "File location: " + Wizardry.config.getConfigFile().getAbsolutePath();
}
private static List<IConfigElement> getConfigEntries(){
List<IConfigElement> configList = new ArrayList<IConfigElement>(1);
configList.add(new DummyCategoryElement("gameplayConfig", "config." + Wizardry.MODID + ".category." + Settings.GAMEPLAY_CATEGORY, GameplayCategory.class));
configList.add(new DummyCategoryElement("worldgenConfig", "config." + Wizardry.MODID + ".category." + Settings.WORLDGEN_CATEGORY, WorldgenCategory.class));
configList.add(new DummyCategoryElement("commandsConfig", "config." + Wizardry.MODID + ".category." + Settings.COMMANDS_CATEGORY, CommandsCategory.class));
configList.add(new DummyCategoryElement("clientConfig", "config." + Wizardry.MODID + ".category." + Settings.CLIENT_CATEGORY, ClientCategory.class));
configList.add(new DummyCategoryElement("spellsConfig", "config." + Wizardry.MODID + ".category." + Settings.SPELLS_CATEGORY, SpellsCategory.class));
configList.add(new DummyCategoryElement("resistancesConfig", "config." + Wizardry.MODID + ".category." + Settings.RESISTANCES_CATEGORY, ResistancesCategory.class));
configList.addAll(new ConfigElement(Wizardry.settings.getConfigCategory(Configuration.CATEGORY_GENERAL)).getChildElements());
configList.add(new DummyCategoryElement("spellsConfig", "config.category.spells", SpellsCategory.class));
configList.add(new DummyCategoryElement("resistancesConfig", "config.category.resistances", ResistancesCategory.class));
configList.add(new DummyCategoryElement("idsConfig", "config.category.ids", IDsCategory.class));
configList.addAll(new ConfigElement(Wizardry.config.getCategory(Configuration.CATEGORY_GENERAL)).getChildElements());
return configList;
}
// The reason this system is so convoluted is that it's designed for use with the @Config annotation. The problem is,
// I'm not sure whether that will play well with the load phases. Hmmm...
public static abstract class CategoryBase extends CategoryEntry {
public CategoryBase(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen(){
String category = this.getCategory();
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig childScreen = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.settings.getConfigCategory(category))).getChildElements(),
this.owningScreen.modID, category, false, false,
Wizardry.NAME + " - " + I18n.format("config." + Wizardry.MODID + ".title." + category));
childScreen.titleLine2 = I18n.format("config." + Wizardry.MODID + ".subtitle." + category);
return childScreen;
}
protected abstract String getCategory();
}
/** Gameplay category of the config gui. */
public static class GameplayCategory extends CategoryBase {
public GameplayCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.GAMEPLAY_CATEGORY; }
}
/** Spells category of the config gui. */
public static class SpellsCategory extends CategoryBase {
public SpellsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.SPELLS_CATEGORY; }
}
/** Resistances category of the config gui. */
public static class ResistancesCategory extends CategoryBase {
public ResistancesCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.RESISTANCES_CATEGORY; }
}
/** Worldgen category of the config gui. */
public static class WorldgenCategory extends CategoryBase {
public WorldgenCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.WORLDGEN_CATEGORY; }
}
/** Client category of the config gui. */
public static class ClientCategory extends CategoryBase {
public ClientCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.CLIENT_CATEGORY; }
}
/** Commands category of the config gui. */
public static class CommandsCategory extends CategoryBase {
public CommandsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop){
super(owningScreen, owningEntryList, prop);
}
@Override protected String getCategory() { return Settings.COMMANDS_CATEGORY; }
}
/** Spells category of the config gui. This adds a button which opens up the spells category config. */
public static class SpellsCategory extends CategoryEntry
{
public SpellsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig spellsMenu = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.config.getCategory(Wizardry.SPELLS_CATEGORY))).getChildElements(),
this.owningScreen.modID, Wizardry.SPELLS_CATEGORY, false, false,
Wizardry.NAME + " - " + StatCollector.translateToLocal("config.title.spells"));
spellsMenu.titleLine2 = StatCollector.translateToLocal("config.subtitle.spells");
return spellsMenu;
}
}
/** Resistances category of the config gui. */
public static class ResistancesCategory extends CategoryEntry
{
public ResistancesCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig idsMenu = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.config.getCategory(Wizardry.RESISTANCES_CATEGORY))).getChildElements(),
this.owningScreen.modID, Wizardry.RESISTANCES_CATEGORY, false, false,
Wizardry.NAME + " - " + StatCollector.translateToLocal("config.title.resistances"));
idsMenu.titleLine2 = StatCollector.translateToLocal("config.subtitle.resistances");
return idsMenu;
}
}
/** IDs category of the config gui. */
public static class IDsCategory extends CategoryEntry
{
public IDsCategory(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
{
super(owningScreen, owningEntryList, prop);
}
@Override
protected GuiScreen buildChildScreen()
{
// This GuiConfig object specifies the configID of the object and as such will force-save when it is closed.
// The parent GuiConfig object's entryList will also be refreshed to reflect the changes.
GuiConfig idsMenu = new GuiConfig(this.owningScreen,
(new ConfigElement(Wizardry.config.getCategory(Wizardry.IDS_CATEGORY))).getChildElements(),
this.owningScreen.modID, Wizardry.IDS_CATEGORY, false, false,
Wizardry.NAME + " - " + StatCollector.translateToLocal("config.title.ids"));
idsMenu.titleLine2 = StatCollector.translateToLocal("config.subtitle.ids");
return idsMenu;
}
}
}
@@ -1,37 +1,40 @@
package electroblob.wizardry.client;
import org.lwjgl.opengl.GL11;
import electroblob.wizardry.WizardryGuiHandler;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.ContainerWorkbench;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/** Crafting table GUI that doesn't require a crafting table container object. */
public class GuiPortableCrafting extends GuiContainer {
private static final ResourceLocation craftingTableGuiTextures = new ResourceLocation("textures/gui/container/crafting_table.png");
public GuiPortableCrafting(InventoryPlayer p_i1084_1_, World p_i1084_2_, int p_i1084_3_, int p_i1084_4_, int p_i1084_5_)
{
super(new ContainerWorkbench(p_i1084_1_, p_i1084_2_, p_i1084_3_, p_i1084_4_, p_i1084_5_));
}
private static final ResourceLocation craftingTableGuiTextures = new ResourceLocation(
"textures/gui/container/crafting_table.png");
/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_)
{
this.fontRendererObj.drawString(I18n.format("container.crafting"), 28, 6, 4210752);
this.fontRendererObj.drawString(I18n.format("container.inventory"), 8, this.ySize - 96 + 2, 4210752);
}
public GuiPortableCrafting(InventoryPlayer p_i1084_1_, World p_i1084_2_, BlockPos pos){
super(new ContainerWorkbench(p_i1084_1_, p_i1084_2_, pos));
}
/**
* Draw the foreground layer for the GuiContainer (everything in front of the items)
*/
protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_){
this.fontRenderer.drawString(I18n.format("container.crafting"), 28, 6, 4210752);
this.fontRenderer.drawString(I18n.format("container.inventory"), 8, this.ySize - 96 + 2, 4210752);
}
protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_){
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
this.mc.getTextureManager().bindTexture(craftingTableGuiTextures);
int k = (this.width - this.xSize) / 2;
int l = (this.height - this.ySize) / 2;
this.drawTexturedModalRect(k, l, 0, 0, this.xSize, this.ySize);
}
protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_)
{
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
this.mc.getTextureManager().bindTexture(craftingTableGuiTextures);
int k = (this.width - this.xSize) / 2;
int l = (this.height - this.ySize) / 2;
this.drawTexturedModalRect(k, l, 0, 0, this.xSize, this.ySize);
}
}
@@ -2,111 +2,152 @@ package electroblob.wizardry.client;
import org.lwjgl.input.Keyboard;
import electroblob.wizardry.EnumTier;
import electroblob.wizardry.ExtendedPlayer;
import electroblob.wizardry.SpellGlyphData;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.constants.Tier;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.WizardryGuiHandler;
import electroblob.wizardry.WizardryRegistry;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
public class GuiSpellBook extends GuiScreen {
private int xSize, ySize;
private Spell spell;
private static final ResourceLocation texture = new ResourceLocation(Wizardry.MODID, "textures/gui/spellbook.png");
public GuiSpellBook(Spell spell){
public GuiSpellBook(Spell spell) {
super();
xSize = 288;
ySize = 180;
this.spell = spell;
}
/**
* Draws the screen and all the components in it.
*/
public void drawScreen(int par1, int par2, float par3){
int xPos = this.width / 2 - xSize / 2;
int yPos = this.height / 2 - this.ySize / 2;
EntityPlayer player = Minecraft.getMinecraft().player;
boolean discovered = true;
if(Wizardry.settings.discoveryMode && !player.capabilities.isCreativeMode && WizardData.get(player) != null
&& !WizardData.get(player).hasSpellBeenDiscovered(spell)){
* Draws the screen and all the components in it.
*/
public void drawScreen(int par1, int par2, float par3) {
int xPos = this.width/2 - xSize/2;
int yPos = this.height/2 - this.ySize/2;
EntityPlayer player = Minecraft.getMinecraft().thePlayer;
boolean discovered = true;
if(Wizardry.discoveryMode && !player.capabilities.isCreativeMode && ExtendedPlayer.get(player) != null
&& !ExtendedPlayer.get(player).hasSpellBeenDiscovered(spell)){
discovered = false;
}
// Draws spell illustration on opposite page, underneath the book so it shows through the hole.
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
WizardryUtilities.drawTexturedRect(xPos + 145, yPos + 20, 0, 0, 128, 128, 128, 128);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
WizardryUtilities.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256);
super.drawScreen(par1, par2, par3);
// Draws spell illustration on opposite page, underneath the book so it shows through the hole.
Minecraft.getMinecraft().renderEngine.bindTexture(discovered ? spell.icon : WizardryRegistry.none.icon);
this.drawTexturedRect(xPos + 145, yPos + 20, 0, 0, 128, 128, 128, 128);
Minecraft.getMinecraft().renderEngine.bindTexture(texture);
this.drawTexturedRect(xPos, yPos, 0, 0, xSize, ySize, xSize, 256);
super.drawScreen(par1, par2, par3);
if(discovered){
this.fontRenderer.drawString(spell.getDisplayName(), xPos + 17, yPos + 14, 0);
this.fontRenderer.drawString(spell.type.getDisplayName(), xPos + 17, yPos + 25, 0x777777);
this.fontRendererObj.drawString(spell.getDisplayName(), xPos+17, yPos+14, 0);
this.fontRendererObj.drawString(spell.type.getDisplayName(), xPos+17, yPos+25, 0x777777);
}else{
this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(spell, player.world), xPos + 17,
yPos + 14, 0);
this.mc.standardGalacticFontRenderer.drawString(spell.type.getDisplayName(), xPos + 17, yPos + 25,
0x777777);
this.mc.standardGalacticFontRenderer.drawString(SpellGlyphData.getGlyphName(spell, player.worldObj), xPos+17, yPos+14, 0);
this.mc.standardGalacticFontRenderer.drawString(spell.type.getDisplayName(), xPos+17, yPos+25, 0x777777);
}
this.fontRendererObj.drawString("-------------------", xPos+17, yPos+34, 0);
if(spell.tier == EnumTier.BASIC){
// Basic is usually white but this doesn't show up.
this.fontRendererObj.drawString("Tier: \u00A77" + EnumTier.BASIC.getDisplayName(), xPos+17, yPos+44, 0);
}else{
this.fontRendererObj.drawString("Tier: " + spell.tier.getDisplayNameWithFormatting(), xPos+17, yPos+44, 0);
}
String element = "Element: " + spell.element.colour + spell.element.getDisplayName();
if(!discovered) element = "Element: ?";
this.fontRendererObj.drawString(element, xPos+17, yPos+56, 0);
String manaCost = "Mana Cost: " + spell.cost;
if(spell.isContinuous) manaCost = "Mana Cost: " + spell.cost + "/second";
if(!discovered) manaCost = "Mana Cost: ?";
this.fontRendererObj.drawString(manaCost, xPos+17, yPos+68, 0);
if(discovered){
this.fontRendererObj.drawSplitString(spell.getDescription(), xPos+17, yPos+82, 118, 0);
}else{
this.mc.standardGalacticFontRenderer.drawSplitString(SpellGlyphData.getGlyphDescription(spell, player.worldObj), xPos+17, yPos+82, 118, 0);
}
/*
// Word wrapping
int charNumber = 0;
int lineNumber = 0;
while(charNumber < spell.desc.length()){
int lineLength = 0;
String line;
if(spell.desc.length() - charNumber > 22){
for(int i = charNumber; i < charNumber+23; i++){
if(spell.desc.charAt(i) == ' '){
lineLength = i - charNumber;
}
}
line = spell.desc.substring(charNumber, charNumber + lineLength);
}else{
line = spell.desc.substring(charNumber, spell.desc.length());
charNumber = spell.desc.length();
}
this.fontRendererObj.drawString("\u00A7o" + line, xPos+17, yPos+82+10*lineNumber, 0);
charNumber+=(lineLength+1);
lineNumber++;
}
*/
}
this.fontRenderer.drawString("-------------------", xPos + 17, yPos + 34, 0);
if(spell.tier == Tier.BASIC){
// Basic is usually white but this doesn't show up.
this.fontRenderer.drawString("Tier: \u00A77" + Tier.BASIC.getDisplayName(), xPos + 17, yPos + 44, 0);
}else{
this.fontRenderer.drawString("Tier: " + spell.tier.getDisplayNameWithFormatting(), xPos + 17, yPos + 44,
0);
}
String element = "Element: " + spell.element.getFormattingCode() + spell.element.getDisplayName();
if(!discovered) element = "Element: ?";
this.fontRenderer.drawString(element, xPos + 17, yPos + 56, 0);
String manaCost = "Mana Cost: " + spell.cost;
if(spell.isContinuous) manaCost = "Mana Cost: " + spell.cost + "/second";
if(!discovered) manaCost = "Mana Cost: ?";
this.fontRenderer.drawString(manaCost, xPos + 17, yPos + 68, 0);
if(discovered){
this.fontRenderer.drawSplitString(spell.getDescription(), xPos + 17, yPos + 82, 118, 0);
}else{
this.mc.standardGalacticFontRenderer.drawSplitString(
SpellGlyphData.getGlyphDescription(spell, player.world), xPos + 17, yPos + 82, 118, 0);
}
/* // Word wrapping int charNumber = 0; int lineNumber = 0;
*
* while(charNumber < spell.desc.length()){ int lineLength = 0; String line; if(spell.desc.length() - charNumber
* > 22){ for(int i = charNumber; i < charNumber+23; i++){ if(spell.desc.charAt(i) == ' '){ lineLength = i -
* charNumber; } } line = spell.desc.substring(charNumber, charNumber + lineLength); }else{ line =
* spell.desc.substring(charNumber, spell.desc.length()); charNumber = spell.desc.length(); }
* this.fontRendererObj.drawString("\u00A7o" + line, xPos+17, yPos+82+10*lineNumber, 0);
* charNumber+=(lineLength+1); lineNumber++; } */
}
public void initGui(){
public void initGui()
{
super.initGui();
Keyboard.enableRepeatEvents(true);
this.buttonList.clear();
}
Keyboard.enableRepeatEvents(true);
this.buttonList.clear();
}
public void onGuiClosed()
{
super.onGuiClosed();
Keyboard.enableRepeatEvents(false);
}
public void onGuiClosed(){
super.onGuiClosed();
Keyboard.enableRepeatEvents(false);
/**
* Draws a textured rectangle, taking the size of the image and the bit needed into account. Client side only, of course.
* @param x The x position of the rectangle
* @param y The y position of the rectangle
* @param u The x position of the top left corner of the section of the image wanted
* @param v The y position of the top left corner of the section of the image wanted
* @param width The width of the section
* @param height The height of the section
* @param textureWidth The width of the actual image.
* @param textureHeight The height of the actual image.
*/
public static void drawTexturedRect(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight)
{
float f = 1F / (float)textureWidth;
float f1 = 1F / (float)textureHeight;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((double)(x), (double)(y + height), 0, (double)((float)(u) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y + height), 0, (double)((float)(u + width) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y), 0, (double)((float)(u + width) * f), (double)((float)(v) * f1));
tessellator.addVertexWithUV((double)(x), (double)(y), 0, (double)((float)(u) * f), (double)((float)(v) * f1));
tessellator.draw();
}
}
@@ -2,29 +2,26 @@ package electroblob.wizardry.client;
import java.util.List;
import electroblob.wizardry.Settings.GuiPosition;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import electroblob.wizardry.ExtendedPlayer;
import electroblob.wizardry.SpellGlyphData;
import electroblob.wizardry.WizardData;
import electroblob.wizardry.WandHelper;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.constants.Constants;
import electroblob.wizardry.WizardryRegistry;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.registry.Spells;
import electroblob.wizardry.registry.WizardryItems;
import electroblob.wizardry.registry.WizardryPotions;
import electroblob.wizardry.spell.None;
import electroblob.wizardry.spell.Spell;
import electroblob.wizardry.util.WandHelper;
import electroblob.wizardry.util.WizardryUtilities;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagIntArray;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
public class GuiSpellDisplay extends Gui {
@@ -32,7 +29,7 @@ public class GuiSpellDisplay extends Gui {
private static final ResourceLocation hudTexture = new ResourceLocation(Wizardry.MODID, "textures/gui/spell_hud.png");
public GuiSpellDisplay(Minecraft par1Minecraft){
public GuiSpellDisplay(Minecraft par1Minecraft) {
super();
this.mc = par1Minecraft;
}
@@ -40,113 +37,133 @@ public class GuiSpellDisplay extends Gui {
@SubscribeEvent
public void draw(RenderGameOverlayEvent event){
EntityPlayer player = this.mc.player;
EntityPlayer player = this.mc.thePlayer;
// If the player has a wand in each hand, only displays for the one in the main hand.
if(player.getHeldItem() != null && player.getHeldItem().getItem() instanceof ItemWand){
ItemStack wand = player.getHeldItemMainhand();
int width = event.resolution.getScaledWidth();
int height = event.resolution.getScaledHeight();
if(!(wand.getItem() instanceof ItemWand)){
wand = player.getHeldItemOffhand();
// If the player isn't holding a wand, then nothing else needs to be done.
if(!(wand.getItem() instanceof ItemWand)) return;
}
Spell spell = WandHelper.getCurrentSpell(player.getHeldItem());
int cooldown = WandHelper.getCurrentCooldown(player.getHeldItem());
int width = event.getResolution().getScaledWidth();
int height = event.getResolution().getScaledHeight();
float cooldownMultiplier = 1.0f - WandHelper.getUpgradeLevel(player.getHeldItem(), Wizardry.cooldownUpgrade)*Wizardry.COOLDOWN_REDUCTION_PER_LEVEL;
Spell spell = WandHelper.getCurrentSpell(wand);
int cooldown = WandHelper.getCurrentCooldown(wand);
if(player.isPotionActive(Wizardry.fontOfMana)){
// Dividing by this rather than setting it takes upgrades and font of mana into account simultaneously
cooldownMultiplier /= 2 + player.getActivePotionEffect(Wizardry.fontOfMana).getAmplifier();
}
float cooldownMultiplier = 1.0f - WandHelper.getUpgradeLevel(wand, WizardryItems.cooldown_upgrade) * Constants.COOLDOWN_REDUCTION_PER_LEVEL;
// Coordinates of the top left corner of the HUD.
int left = 0;
int top = 0;
boolean mirror = false;
if(player.isPotionActive(WizardryPotions.font_of_mana)){
// Dividing by this rather than setting it takes upgrades and font of mana into account simultaneously
cooldownMultiplier /= 2 + player.getActivePotionEffect(WizardryPotions.font_of_mana).getAmplifier();
}
if(Wizardry.spellHUDPosition.equals("Bottom left")){
left = 0;
top = height-36;
}else if(Wizardry.spellHUDPosition.equals("Top left")){
left = 0;
top = 0;
}else if(Wizardry.spellHUDPosition.equals("Top right")){
left = width-128;
top = 0;
mirror = true;
}else if(Wizardry.spellHUDPosition.equals("Bottom right")){
left = width-128;
top = height-36;
mirror = true;
}
// Coordinates of the top left corner of the HUD.
int left = 0;
int top = 0;
boolean mirror = false;
boolean discovered = true;
if(Wizardry.settings.spellHUDPosition == GuiPosition.BOTTOM_LEFT){
left = 0;
top = height - 36;
}else if(Wizardry.settings.spellHUDPosition == GuiPosition.TOP_LEFT){
left = 0;
top = 0;
}else if(Wizardry.settings.spellHUDPosition == GuiPosition.TOP_RIGHT){
left = width - 128;
top = 0;
mirror = true;
}else if(Wizardry.settings.spellHUDPosition == GuiPosition.BOTTOM_RIGHT){
left = width - 128;
top = height - 36;
mirror = true;
}
if(!player.capabilities.isCreativeMode && ExtendedPlayer.get(player) != null){
discovered = ExtendedPlayer.get(player).hasSpellBeenDiscovered(spell);
}
boolean discovered = true;
if(event.type == RenderGameOverlayEvent.ElementType.TEXT){
if(!player.capabilities.isCreativeMode && WizardData.get(player) != null){
discovered = WizardData.get(player).hasSpellBeenDiscovered(spell);
}
// Makes spells greyed out if they are in cooldown or if the player has the arcane jammer effect
String colour = cooldown > 0 || player.isPotionActive(Wizardry.arcaneJammer) ? "\u00A78" : spell.element.colour;
if(!discovered) colour = "\u00A79";
String spellName = discovered ? spell.getDisplayName() : SpellGlyphData.getGlyphName(spell, player.worldObj);
FontRenderer font = discovered ? this.mc.fontRenderer : this.mc.standardGalacticFontRenderer;
if(event.getType() == RenderGameOverlayEvent.ElementType.TEXT){
int maxWidth = 90;
// Makes spells greyed out if they are in cooldown or if the player has the arcane jammer effect
String colour = cooldown > 0 || player.isPotionActive(WizardryPotions.arcane_jammer) ? "\u00A78" : spell.element.getFormattingCode();
if(!discovered) colour = "\u00A79";
String spellName = discovered ? spell.getDisplayName() : SpellGlyphData.getGlyphName(spell, player.world);
FontRenderer font = discovered ? this.mc.fontRenderer : this.mc.standardGalacticFontRenderer;
if(font.getStringWidth(spellName) <= maxWidth){
// Single line is rendered more centrally
font.drawStringWithShadow(colour + spellName, mirror ? left+5 : left+41, top+13, 0xffffffff);
int maxWidth = 90;
}else{
if(font.getStringWidth(spellName) <= maxWidth){
// Single line is rendered more centrally
font.drawStringWithShadow(colour + spellName, mirror ? left + 5 : left + 41, top + 13, 0xffffffff);
int lineNumber = 0;
}else{
List lines = font.listFormattedStringToWidth(spellName, maxWidth);
int lineNumber = 0;
List<String> lines = font.listFormattedStringToWidth(spellName, maxWidth);
for(Object line : lines){
if(line instanceof String){
font.drawStringWithShadow(colour + (String)line, mirror ? left + 5 : left + 41, top + 6 + 11 * lineNumber, 0xffffffff);
for(Object line : lines){
if(line instanceof String){
font.drawStringWithShadow(colour + (String)line, mirror ? left+5 : left+41, top+6 + 11*lineNumber, 0xffffffff);
}
lineNumber++;
}
lineNumber++;
}
}else if(event.type == RenderGameOverlayEvent.ElementType.HOTBAR){
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glColor3f(1.0f, 1.0f, 1.0f);
this.mc.renderEngine.bindTexture(hudTexture);
// Background of spell hud
this.drawTexturedModalRect(left, top, 0, mirror ? 36 : 0, 128, 36);
// Cooldown bar
if(cooldown > 0){
this.drawTexturedModalRect(mirror ? left+5 : left+41, height-8, 128, 6, 82, 6);
int l = (int)(((double)(spell.cooldown * cooldownMultiplier - cooldown)
/ (double)(spell.cooldown * cooldownMultiplier)) * 82);
this.drawTexturedModalRect(mirror ? left+5 : left+41, height-8, 128, 0, l, 6);
}
// Spell illustration
this.mc.renderEngine.bindTexture(discovered ? spell.icon : WizardryRegistry.none.icon);
this.drawTexturedRect(mirror ? left+94 : left+2, top+2, 0, 0, 32, 32, 32, 32);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
}else if(event.getType() == RenderGameOverlayEvent.ElementType.HOTBAR){
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
GlStateManager.color(1, 1, 1);
this.mc.renderEngine.bindTexture(hudTexture);
// Background of spell hud
this.drawTexturedModalRect(left, top, 0, mirror ? 36 : 0, 128, 36);
// Cooldown bar
if(cooldown > 0){
this.drawTexturedModalRect(mirror ? left + 5 : left + 41, top + 28, 128, 6, 82, 6);
int l = (int)(((double)(spell.cooldown * cooldownMultiplier - cooldown) / (double)(spell.cooldown * cooldownMultiplier)) * 82);
this.drawTexturedModalRect(mirror ? left + 5 : left + 41, top + 28, 128, 0, l, 6);
}
// Spell illustration
this.mc.renderEngine.bindTexture(discovered ? spell.getIcon() : Spells.none.getIcon());
WizardryUtilities.drawTexturedRect(mirror ? left + 94 : left + 2, top + 2, 0, 0, 32, 32, 32, 32);
// Blend needs to be left enabled here because otherwise the hotbar becomes opaque
}
}
/**
* Draws a textured rectangle, taking the size of the image and the bit needed into account. Client side only, of course.
* @param x The x position of the rectangle
* @param y The y position of the rectangle
* @param u The x position of the top left corner of the section of the image wanted
* @param v The y position of the top left corner of the section of the image wanted
* @param width The width of the section
* @param height The height of the section
* @param textureWidth The width of the actual image.
* @param textureHeight The height of the actual image.
*/
public static void drawTexturedRect(int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight)
{
float f = 1F / (float)textureWidth;
float f1 = 1F / (float)textureHeight;
Tessellator tessellator = Tessellator.instance;
tessellator.startDrawingQuads();
tessellator.addVertexWithUV((double)(x), (double)(y + height), 0, (double)((float)(u) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y + height), 0, (double)((float)(u + width) * f), (double)((float)(v + height) * f1));
tessellator.addVertexWithUV((double)(x + width), (double)(y), 0, (double)((float)(u + width) * f), (double)((float)(v) * f1));
tessellator.addVertexWithUV((double)(x), (double)(y), 0, (double)((float)(u) * f), (double)((float)(v) * f1));
tessellator.draw();
}
}
File diff suppressed because it is too large Load Diff
@@ -1,98 +1,97 @@
package electroblob.wizardry.client;
import java.util.ArrayList;
import java.util.List;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/**
* Font renderer that renders parts of strings surrounded by '#' (without quotes) in the SGA instead of normal text.
*
* @since Wizardry 1.1
*/
/** Font renderer that renders parts of strings surrounded by '#' (without quotes) in the SGA instead of normal text.
* @since Wizardry 1.1 */
@SideOnly(Side.CLIENT)
public class MixedFontRenderer extends FontRenderer {
public MixedFontRenderer(GameSettings p_i1035_1_, ResourceLocation p_i1035_2_, TextureManager p_i1035_3_,
boolean p_i1035_4_){
boolean p_i1035_4_) {
super(p_i1035_1_, p_i1035_2_, p_i1035_3_, p_i1035_4_);
}
@Override
public int drawString(String string, float x, float y, int colour, boolean shadow){
public int drawString(String string, int x, int y, int colour, boolean shadow){
int l = 0;
boolean sga = false;
while(string.indexOf('#') > -1){
String section = string.substring(0, string.indexOf('#'));
if(sga){
l += Minecraft.getMinecraft().standardGalacticFontRenderer.drawString(section, x, y, colour, shadow);
l += Minecraft.getMinecraft().standardGalacticFontRenderer.drawString(section, x, y, colour, shadow);
x += Minecraft.getMinecraft().standardGalacticFontRenderer.getStringWidth(section);
}else{
l += Minecraft.getMinecraft().fontRenderer.drawString(section, x, y, colour, shadow);
}else{
l += Minecraft.getMinecraft().fontRenderer.drawString(section, x, y, colour, shadow);
x += Minecraft.getMinecraft().fontRenderer.getStringWidth(section);
}
}
string = string.substring(string.indexOf('#') + 1);
sga = !sga;
}
if(sga){
l += Minecraft.getMinecraft().standardGalacticFontRenderer.drawString(string, x, y, colour, shadow);
}else{
l += Minecraft.getMinecraft().fontRenderer.drawString(string, x, y, colour, shadow);
}
return l;
}
l += Minecraft.getMinecraft().standardGalacticFontRenderer.drawString(string, x, y, colour, shadow);
}else{
l += Minecraft.getMinecraft().fontRenderer.drawString(string, x, y, colour, shadow);
}
return l;
}
@Override
public int getStringWidth(String string){
int l = 0;
boolean sga = false;
while(string.indexOf('#') > -1){
String section = string.substring(0, string.indexOf('#'));
if(sga){
l += Minecraft.getMinecraft().standardGalacticFontRenderer.getStringWidth(section);
}else{
l += Minecraft.getMinecraft().fontRenderer.getStringWidth(section);
}
l += Minecraft.getMinecraft().standardGalacticFontRenderer.getStringWidth(section);
}else{
l += Minecraft.getMinecraft().fontRenderer.getStringWidth(section);
}
string = string.substring(string.indexOf('#') + 1);
sga = !sga;
}
if(sga){
l += Minecraft.getMinecraft().standardGalacticFontRenderer.getStringWidth(string);
}else{
l += Minecraft.getMinecraft().fontRenderer.getStringWidth(string);
}
return l;
l += Minecraft.getMinecraft().standardGalacticFontRenderer.getStringWidth(string);
}else{
l += Minecraft.getMinecraft().fontRenderer.getStringWidth(string);
}
return l;
}
// This doesn't work the same way yet
@Override
public void drawSplitString(String string, int x, int y, int width, int colour){
public void drawSplitString(String string, int x, int y, int width, int colour){
if(string.contains("#")){
Minecraft.getMinecraft().standardGalacticFontRenderer.drawSplitString(string.substring(1), x, y, width,
colour);
}else{
Minecraft.getMinecraft().fontRenderer.drawSplitString(string, x, y, width, colour);
}
}
Minecraft.getMinecraft().standardGalacticFontRenderer.drawSplitString(string.substring(1), x, y, width, colour);
}else{
Minecraft.getMinecraft().fontRenderer.drawSplitString(string, x, y, width, colour);
}
}
}
@@ -1,52 +1,55 @@
package electroblob.wizardry.client;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.audio.MovingSound;
import net.minecraft.entity.Entity;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
// Copied from MovingSoundMinecart; if it ever breaks between updates take a look at that.
@SideOnly(Side.CLIENT)
public class MovingSoundEntity extends MovingSound {
private final Entity source;
private float distance = 0.0F;
public class MovingSoundEntity extends MovingSound
{
private final Entity source;
private float pitch = 0.0F;
public MovingSoundEntity(Entity entity, SoundEvent sound, float volume, float pitch, boolean repeat){
// Uses BLOCKS because that's the closest thing to inanimate entities. Could use NEUTRAL like
// MovingSoundMinecart.
super(sound, SoundCategory.BLOCKS);
this.source = entity;
this.repeat = repeat;
this.volume = volume;
this.pitch = pitch;
this.repeatDelay = 0;
}
public MovingSoundEntity(Entity entity, String soundName, float volume, float pitch, boolean repeat)
{
super(new ResourceLocation(soundName));
this.source = entity;
this.repeat = repeat;
this.volume = volume;
this.field_147663_c = pitch;
this.field_147665_h = 0;
}
/**
* Updates the JList with a new model.
*/
@Override
public void update(){
if(this.source.isDead && repeat){
this.donePlaying = true;
}else{
this.xPosF = (float)this.source.posX;
this.yPosF = (float)this.source.posY;
this.zPosF = (float)this.source.posZ;
float f = MathHelper.sqrt(this.source.motionX * this.source.motionX
+ this.source.motionY * this.source.motionY + this.source.motionZ * this.source.motionZ);
/**
* Updates the JList with a new model.
*/
public void update()
{
if (this.source.isDead && repeat)
{
this.donePlaying = true;
}
else
{
this.xPosF = (float)this.source.posX;
this.yPosF = (float)this.source.posY;
this.zPosF = (float)this.source.posZ;
float f = MathHelper.sqrt_double(this.source.motionX * this.source.motionX + this.source.motionY * this.source.motionY + this.source.motionZ * this.source.motionZ);
// Is this something to do with the Doppler effect?
if((double)f >= 0.01D){
this.distance = MathHelper.clamp(this.distance + 0.0025F, 0.0F, 1.0F);
this.volume = 0.0F + MathHelper.clamp(f, 0.0F, 0.5F) * 0.7F;
}else{
// this.pitch = 0.0F;
// this.volume = 0.0F;
}
}
}
// Is this something to do with the Doppler effect?
if ((double)f >= 0.01D)
{
this.pitch = MathHelper.clamp_float(this.pitch + 0.0025F, 0.0F, 1.0F);
this.volume = 0.0F + MathHelper.clamp_float(f, 0.0F, 0.5F) * 0.7F;
}
else
{
//this.pitch = 0.0F;
//this.volume = 0.0F;
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -1,70 +0,0 @@
package electroblob.wizardry.client;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.item.ItemWand;
import electroblob.wizardry.packet.PacketControlInput;
import electroblob.wizardry.packet.WizardryPacketHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
@Mod.EventBusSubscriber(Side.CLIENT)
public class WizardryKeyHandler {
static boolean NkeyPressed = false;
static boolean BkeyPressed = false;
// Changed to a tick event to allow mouse button keybinds
// The 'lag' that happened previously was actually because the code only fired when a keyboard key was pressed!
@SubscribeEvent
public static void onTickEvent(TickEvent.ClientTickEvent event){
if(event.phase == TickEvent.Phase.END) return; // Only really needs to be once per tick
if(Wizardry.proxy instanceof ClientProxy){
EntityPlayer player = Minecraft.getMinecraft().player;
if(player != null){
ItemStack wand = player.getHeldItemMainhand();
if(!(wand.getItem() instanceof ItemWand)){
wand = player.getHeldItemOffhand();
// If the player isn't holding a wand, then nothing else needs to be done.
if(!(wand.getItem() instanceof ItemWand)) return;
}
}
if(ClientProxy.NEXT_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
if(!NkeyPressed){
NkeyPressed = true;
// Packet building
IMessage msg = new PacketControlInput.Message(PacketControlInput.ControlType.NEXT_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
}else{
NkeyPressed = false;
}
if(ClientProxy.PREVIOUS_SPELL.isKeyDown() && Minecraft.getMinecraft().inGameHasFocus){
if(!BkeyPressed){
BkeyPressed = true;
// Packet building
IMessage msg = new PacketControlInput.Message(
PacketControlInput.ControlType.PREVIOUS_SPELL_KEY);
WizardryPacketHandler.net.sendToServer(msg);
}
}else{
BkeyPressed = false;
}
}
}
}
@@ -4,75 +4,80 @@ import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelHammer extends ModelBase {
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
ModelRenderer Shape4;
ModelRenderer Shape5;
ModelRenderer Shape6;
public ModelHammer(){
textureWidth = 64;
textureHeight = 64;
Shape1 = new ModelRenderer(this, 0, 0);
Shape1.addBox(0F, 0F, 0F, 20, 12, 12);
Shape1.setRotationPoint(-10F, 12F, -6F);
Shape1.setTextureSize(64, 64);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 24);
Shape2.addBox(0F, 0F, 0F, 4, 14, 4);
Shape2.setRotationPoint(-2F, -2F, -2F);
Shape2.setTextureSize(64, 64);
Shape2.mirror = true;
setRotation(Shape2, 0F, 0F, 0F);
Shape3 = new ModelRenderer(this, 0, 49);
Shape3.addBox(0F, 0F, 0F, 5, 5, 5);
Shape3.setRotationPoint(-2.5F, -7F, -2.5F);
Shape3.setTextureSize(64, 64);
Shape3.mirror = true;
setRotation(Shape3, 0F, 0F, 0F);
Shape4 = new ModelRenderer(this, 0, 42);
Shape4.addBox(0F, 0F, 0F, 5, 2, 5);
Shape4.setRotationPoint(-2.5F, 10F, -2.5F);
Shape4.setTextureSize(64, 64);
Shape4.mirror = true;
setRotation(Shape4, 0F, 0F, 0F);
Shape5 = new ModelRenderer(this, 20, 24);
Shape5.addBox(0F, 0F, 0F, 2, 14, 14);
Shape5.setRotationPoint(-8F, 11F, -7F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, 0F, 0F, 0F);
Shape6 = new ModelRenderer(this, 20, 24);
Shape6.addBox(0F, 0F, 0F, 2, 14, 14);
Shape6.setRotationPoint(6F, 11F, -7F);
Shape6.setTextureSize(64, 64);
Shape6.mirror = true;
setRotation(Shape6, 0F, 0F, 0F);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
Shape1.render(f5);
Shape2.render(f5);
Shape3.render(f5);
Shape4.render(f5);
Shape5.render(f5);
Shape6.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z){
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity){
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
public class ModelHammer extends ModelBase
{
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
ModelRenderer Shape4;
ModelRenderer Shape5;
ModelRenderer Shape6;
public ModelHammer()
{
textureWidth = 64;
textureHeight = 64;
Shape1 = new ModelRenderer(this, 0, 0);
Shape1.addBox(0F, 0F, 0F, 20, 12, 12);
Shape1.setRotationPoint(-10F, 12F, -6F);
Shape1.setTextureSize(64, 64);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 24);
Shape2.addBox(0F, 0F, 0F, 4, 14, 4);
Shape2.setRotationPoint(-2F, -2F, -2F);
Shape2.setTextureSize(64, 64);
Shape2.mirror = true;
setRotation(Shape2, 0F, 0F, 0F);
Shape3 = new ModelRenderer(this, 0, 49);
Shape3.addBox(0F, 0F, 0F, 5, 5, 5);
Shape3.setRotationPoint(-2.5F, -7F, -2.5F);
Shape3.setTextureSize(64, 64);
Shape3.mirror = true;
setRotation(Shape3, 0F, 0F, 0F);
Shape4 = new ModelRenderer(this, 0, 42);
Shape4.addBox(0F, 0F, 0F, 5, 2, 5);
Shape4.setRotationPoint(-2.5F, 10F, -2.5F);
Shape4.setTextureSize(64, 64);
Shape4.mirror = true;
setRotation(Shape4, 0F, 0F, 0F);
Shape5 = new ModelRenderer(this, 20, 24);
Shape5.addBox(0F, 0F, 0F, 2, 14, 14);
Shape5.setRotationPoint(-8F, 11F, -7F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, 0F, 0F, 0F);
Shape6 = new ModelRenderer(this, 20, 24);
Shape6.addBox(0F, 0F, 0F, 2, 14, 14);
Shape6.setRotationPoint(6F, 11F, -7F);
Shape6.setTextureSize(64, 64);
Shape6.mirror = true;
setRotation(Shape6, 0F, 0F, 0F);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
Shape1.render(f5);
Shape2.render(f5);
Shape3.render(f5);
Shape4.render(f5);
Shape5.render(f5);
Shape6.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
}
@@ -3,309 +3,319 @@ package electroblob.wizardry.client.model;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.entity.living.EntityIceGiant;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.util.MathHelper;
@SideOnly(Side.CLIENT)
public class ModelIceGiant extends ModelBase {
/** The head model for the iron golem. */
public ModelRenderer iceGiantHead;
public class ModelIceGiant extends ModelBase
{
/** The head model for the iron golem. */
public ModelRenderer iceGiantHead;
/** The body model for the iron golem. */
public ModelRenderer iceGiantBody;
/** The body model for the iron golem. */
public ModelRenderer iceGiantBody;
/** The right arm model for the iron golem. */
public ModelRenderer iceGiantRightArm;
/** The right arm model for the iron golem. */
public ModelRenderer iceGiantRightArm;
/** The left arm model for the iron golem. */
public ModelRenderer iceGiantLeftArm;
/** The left arm model for the iron golem. */
public ModelRenderer iceGiantLeftArm;
/** The left leg model for the Iron Golem. */
public ModelRenderer iceGiantLeftLeg;
/** The left leg model for the Iron Golem. */
public ModelRenderer iceGiantLeftLeg;
/** The right leg model for the Iron Golem. */
public ModelRenderer iceGiantRightLeg;
/** The right leg model for the Iron Golem. */
public ModelRenderer iceGiantRightLeg;
ModelRenderer headSpike1;
ModelRenderer headSpike2;
ModelRenderer headSpike3;
ModelRenderer headSpike4;
ModelRenderer headSpike5;
ModelRenderer headSpike6;
ModelRenderer headSpike7;
ModelRenderer rightArmSpike1;
ModelRenderer rightArmSpike2;
ModelRenderer leftArmSpike1;
ModelRenderer leftArmSpike2;
ModelRenderer bodySpike1;
ModelRenderer bodySpike2;
ModelRenderer bodySpike3;
ModelRenderer bodySpike4;
ModelRenderer bodySpike5;
ModelRenderer headSpike1;
ModelRenderer headSpike2;
ModelRenderer headSpike3;
ModelRenderer headSpike4;
ModelRenderer headSpike5;
ModelRenderer headSpike6;
ModelRenderer headSpike7;
ModelRenderer rightArmSpike1;
ModelRenderer rightArmSpike2;
ModelRenderer leftArmSpike1;
ModelRenderer leftArmSpike2;
ModelRenderer bodySpike1;
ModelRenderer bodySpike2;
ModelRenderer bodySpike3;
ModelRenderer bodySpike4;
ModelRenderer bodySpike5;
public ModelIceGiant()
{
this(0.0F);
}
public ModelIceGiant(){
this(0.0F);
}
public ModelIceGiant(float par1)
{
this(par1, -7.0F);
}
public ModelIceGiant(float par1){
this(par1, -7.0F);
}
public ModelIceGiant(float par1, float par2)
{
short short1 = 128;
short short2 = 128;
this.iceGiantHead = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantHead.setRotationPoint(0.0F, 0.0F + par2, -1.0F);
this.iceGiantHead.setTextureOffset(0, 10).addBox(-6.0F, -14.0F, -6.5F, 12, 12, 12, par1);
this.iceGiantBody = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantBody.setRotationPoint(0.0F, 0.0F + par2, 0.0F);
this.iceGiantBody.setTextureOffset(0, 40).addBox(-9.0F, -2.0F, -6.0F, 18, 12, 11, par1);
this.iceGiantBody.setTextureOffset(0, 70).addBox(-4.5F, 10.0F, -3.0F, 9, 5, 6, par1 + 0.5F);
this.iceGiantRightArm = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantRightArm.setRotationPoint(0.0F, -7.0F, 0.0F);
this.iceGiantRightArm.setTextureOffset(60, 21).addBox(-13.0F, -2.5F, -3.0F, 4, 30, 6, par1);
this.iceGiantLeftArm = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantLeftArm.setRotationPoint(0.0F, -7.0F, 0.0F);
this.iceGiantLeftArm.setTextureOffset(60, 58).addBox(9.0F, -2.5F, -3.0F, 4, 30, 6, par1);
this.iceGiantLeftLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);
this.iceGiantLeftLeg.setRotationPoint(-4.0F, 18.0F + par2, 0.0F);
this.iceGiantLeftLeg.setTextureOffset(37, 0).addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);
this.iceGiantRightLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);
this.iceGiantRightLeg.mirror = true;
this.iceGiantRightLeg.setTextureOffset(60, 0).setRotationPoint(5.0F, 18.0F + par2, 0.0F);
this.iceGiantRightLeg.addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);
headSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike1.addBox(-4F, -4F, 0F, 4, 4, 4);
headSpike1.setRotationPoint(-4F, -10F, -5F);
headSpike1.mirror = true;
setRotationWithEulerYzx(headSpike1, -0.1047198F, -0.5235988F, 0.9599311F);
headSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike2.addBox(0F, -4F, 0F, 4, 4, 4);
headSpike2.setRotationPoint(4F, -16F, 0F);
headSpike2.mirror = true;
setRotationWithEulerYzx(headSpike2, 0.5585054F, 0.9250245F, -0.5235988F);
headSpike3 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike3.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike3.setRotationPoint(4F, -13F, 4F);
headSpike3.mirror = true;
setRotationWithEulerYzx(headSpike3, 0.7853982F, -1.396263F, 0.7853982F);
headSpike4 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike4.addBox(-4F, -4F, 0F, 4, 4, 4);
headSpike4.setRotationPoint(-4F, -16F, 0F);
headSpike4.mirror = true;
setRotationWithEulerYzx(headSpike4, 0.5585054F, -0.9250245F, 0.5235988F);
headSpike5 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike5.addBox(0F, -4F, 0F, 4, 4, 4);
headSpike5.setRotationPoint(4F, -10F, -5F);
headSpike5.mirror = true;
setRotationWithEulerYzx(headSpike5, 0.5235988F, -0.9599311F, 0.1047198F);
rightArmSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
rightArmSpike1.addBox(-2F, -2F, -2F, 4, 4, 4);
rightArmSpike1.setRotationPoint(-11F, -8F, 0F);
rightArmSpike1.mirror = true;
setRotationWithEulerYzx(rightArmSpike1, 0.7853982F, 1.134464F, 0.9599311F);
headSpike6 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike6.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike6.setRotationPoint(-4F, -13F, 4F);
headSpike6.mirror = true;
setRotationWithEulerYzx(headSpike6, 0.7853982F, -1.745329F, 0.7853982F);
leftArmSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
leftArmSpike1.addBox(-2F, -2F, -2F, 4, 4, 4);
leftArmSpike1.setRotationPoint(11F, -8F, 0F);
leftArmSpike1.mirror = true;
setRotationWithEulerYzx(leftArmSpike1, 0.7853982F, -1.134464F, -0.9599311F);
leftArmSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
leftArmSpike2.addBox(-2F, -2F, -2F, 4, 4, 4);
leftArmSpike2.setRotationPoint(12F, -4F, 0F);
leftArmSpike2.mirror = true;
setRotationWithEulerYzx(leftArmSpike2, 0.7853982F, 0F, -0.9599311F);
bodySpike1 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike1.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike1.setRotationPoint(-4F, -4F, 3F);
bodySpike1.mirror = true;
setRotationWithEulerYzx(bodySpike1, 0.2808018F, 0.8096675F, 0.8339369F);
rightArmSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
rightArmSpike2.addBox(-2F, -2F, -2F, 4, 4, 4);
rightArmSpike2.setRotationPoint(-12F, -4F, 0F);
rightArmSpike2.mirror = true;
setRotationWithEulerYzx(rightArmSpike2, 0.7853982F, 0F, 0.9599311F);
bodySpike2 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike2.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike2.setRotationPoint(4F, -4F, 3F);
bodySpike2.mirror = true;
setRotationWithEulerYzx(bodySpike2, 0.2808018F, -0.8096757F, -0.8339358F);
bodySpike3 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
bodySpike3.addBox(-2F, -2F, -2F, 4, 4, 4);
bodySpike3.setRotationPoint(6F, -2F, -5F);
bodySpike3.mirror = true;
setRotationWithEulerYzx(bodySpike3, 1.120006F, -1.347726F, -0.8969422F);
bodySpike4 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike4.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike4.setRotationPoint(0F, -4F, -4F);
bodySpike4.mirror = true;
setRotationWithEulerYzx(bodySpike4, 0.7853982F, -1.570796F, 0.9599311F);
headSpike7 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike7.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike7.setRotationPoint(0F, -20F, 4F);
headSpike7.mirror = true;
setRotationWithEulerYzx(headSpike7, 0.7853982F, 1.570796F, 0.7853982F);
bodySpike5 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
bodySpike5.addBox(-2F, -2F, -2F, 4, 4, 4);
bodySpike5.setRotationPoint(-6F, -2F, -5F);
bodySpike5.mirror = true;
setRotationWithEulerYzx(bodySpike5, 1.120006F, 1.347725F, 0.896934F);
this.convertToChild(this.iceGiantHead, headSpike1);
this.convertToChild(this.iceGiantHead, headSpike2);
this.convertToChild(this.iceGiantHead, headSpike3);
this.convertToChild(this.iceGiantHead, headSpike4);
this.convertToChild(this.iceGiantHead, headSpike5);
this.convertToChild(this.iceGiantHead, headSpike6);
this.convertToChild(this.iceGiantHead, headSpike7);
this.convertToChild(this.iceGiantRightArm, rightArmSpike1);
this.convertToChild(this.iceGiantRightArm, rightArmSpike2);
this.convertToChild(this.iceGiantLeftArm, leftArmSpike1);
this.convertToChild(this.iceGiantLeftArm, leftArmSpike2);
this.convertToChild(this.iceGiantBody, bodySpike1);
this.convertToChild(this.iceGiantBody, bodySpike2);
this.convertToChild(this.iceGiantBody, bodySpike3);
this.convertToChild(this.iceGiantBody, bodySpike4);
this.convertToChild(this.iceGiantBody, bodySpike5);
}
public ModelIceGiant(float par1, float par2){
short short1 = 128;
short short2 = 128;
/**
* Sets the models various rotation angles then renders the model.
*/
public void render(Entity par1Entity, float par2, float par3, float par4, float par5, float par6, float par7)
{
this.setRotationAngles(par2, par3, par4, par5, par6, par7, par1Entity);
this.iceGiantHead.render(par7);
this.iceGiantBody.render(par7);
this.iceGiantLeftLeg.render(par7);
this.iceGiantRightLeg.render(par7);
this.iceGiantRightArm.render(par7);
this.iceGiantLeftArm.render(par7);
}
this.iceGiantHead = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantHead.setRotationPoint(0.0F, 0.0F + par2, -1.0F);
this.iceGiantHead.setTextureOffset(0, 10).addBox(-6.0F, -14.0F, -6.5F, 12, 12, 12, par1);
/**
* Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
* and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
* "far" arms and legs can swing at most.
*/
public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity)
{
this.iceGiantHead.rotateAngleY = par4 / (180F / (float)Math.PI);
this.iceGiantHead.rotateAngleX = par5 / (180F / (float)Math.PI);
this.iceGiantLeftLeg.rotateAngleX = -1.5F * this.func_78172_a(par1, 13.0F) * par2;
this.iceGiantRightLeg.rotateAngleX = 1.5F * this.func_78172_a(par1, 13.0F) * par2;
this.iceGiantLeftLeg.rotateAngleY = 0.0F;
this.iceGiantRightLeg.rotateAngleY = 0.0F;
}
this.iceGiantBody = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantBody.setRotationPoint(0.0F, 0.0F + par2, 0.0F);
this.iceGiantBody.setTextureOffset(0, 40).addBox(-9.0F, -2.0F, -6.0F, 18, 12, 11, par1);
this.iceGiantBody.setTextureOffset(0, 70).addBox(-4.5F, 10.0F, -3.0F, 9, 5, 6, par1 + 0.5F);
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4)
{
EntityIceGiant entityicegiant = (EntityIceGiant)par1EntityLivingBase;
int i = entityicegiant.getAttackTimer();
this.iceGiantRightArm = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantRightArm.setRotationPoint(0.0F, -7.0F, 0.0F);
this.iceGiantRightArm.setTextureOffset(60, 21).addBox(-13.0F, -2.5F, -3.0F, 4, 30, 6, par1);
if (i > 0)
{
this.iceGiantRightArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);
this.iceGiantLeftArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);
}
else
{
this.iceGiantRightArm.rotateAngleX = (-0.2F + 1.5F * this.func_78172_a(par2, 13.0F)) * par3;
this.iceGiantLeftArm.rotateAngleX = (-0.2F - 1.5F * this.func_78172_a(par2, 13.0F)) * par3;
}
}
this.iceGiantLeftArm = (new ModelRenderer(this)).setTextureSize(short1, short2);
this.iceGiantLeftArm.setRotationPoint(0.0F, -7.0F, 0.0F);
this.iceGiantLeftArm.setTextureOffset(60, 58).addBox(9.0F, -2.5F, -3.0F, 4, 30, 6, par1);
this.iceGiantLeftLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);
this.iceGiantLeftLeg.setRotationPoint(-4.0F, 18.0F + par2, 0.0F);
this.iceGiantLeftLeg.setTextureOffset(37, 0).addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);
this.iceGiantRightLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);
this.iceGiantRightLeg.mirror = true;
this.iceGiantRightLeg.setTextureOffset(60, 0).setRotationPoint(5.0F, 18.0F + par2, 0.0F);
this.iceGiantRightLeg.addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);
headSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike1.addBox(-4F, -4F, 0F, 4, 4, 4);
headSpike1.setRotationPoint(-4F, -10F, -5F);
headSpike1.mirror = true;
setRotationWithEulerYzx(headSpike1, -0.1047198F, -0.5235988F, 0.9599311F);
headSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike2.addBox(0F, -4F, 0F, 4, 4, 4);
headSpike2.setRotationPoint(4F, -16F, 0F);
headSpike2.mirror = true;
setRotationWithEulerYzx(headSpike2, 0.5585054F, 0.9250245F, -0.5235988F);
headSpike3 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike3.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike3.setRotationPoint(4F, -13F, 4F);
headSpike3.mirror = true;
setRotationWithEulerYzx(headSpike3, 0.7853982F, -1.396263F, 0.7853982F);
headSpike4 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike4.addBox(-4F, -4F, 0F, 4, 4, 4);
headSpike4.setRotationPoint(-4F, -16F, 0F);
headSpike4.mirror = true;
setRotationWithEulerYzx(headSpike4, 0.5585054F, -0.9250245F, 0.5235988F);
headSpike5 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike5.addBox(0F, -4F, 0F, 4, 4, 4);
headSpike5.setRotationPoint(4F, -10F, -5F);
headSpike5.mirror = true;
setRotationWithEulerYzx(headSpike5, 0.5235988F, -0.9599311F, 0.1047198F);
rightArmSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
rightArmSpike1.addBox(-2F, -2F, -2F, 4, 4, 4);
rightArmSpike1.setRotationPoint(-11F, -8F, 0F);
rightArmSpike1.mirror = true;
setRotationWithEulerYzx(rightArmSpike1, 0.7853982F, 1.134464F, 0.9599311F);
headSpike6 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike6.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike6.setRotationPoint(-4F, -13F, 4F);
headSpike6.mirror = true;
setRotationWithEulerYzx(headSpike6, 0.7853982F, -1.745329F, 0.7853982F);
leftArmSpike1 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
leftArmSpike1.addBox(-2F, -2F, -2F, 4, 4, 4);
leftArmSpike1.setRotationPoint(11F, -8F, 0F);
leftArmSpike1.mirror = true;
setRotationWithEulerYzx(leftArmSpike1, 0.7853982F, -1.134464F, -0.9599311F);
leftArmSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
leftArmSpike2.addBox(-2F, -2F, -2F, 4, 4, 4);
leftArmSpike2.setRotationPoint(12F, -4F, 0F);
leftArmSpike2.mirror = true;
setRotationWithEulerYzx(leftArmSpike2, 0.7853982F, 0F, -0.9599311F);
bodySpike1 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike1.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike1.setRotationPoint(-4F, -4F, 3F);
bodySpike1.mirror = true;
setRotationWithEulerYzx(bodySpike1, 0.2808018F, 0.8096675F, 0.8339369F);
rightArmSpike2 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
rightArmSpike2.addBox(-2F, -2F, -2F, 4, 4, 4);
rightArmSpike2.setRotationPoint(-12F, -4F, 0F);
rightArmSpike2.mirror = true;
setRotationWithEulerYzx(rightArmSpike2, 0.7853982F, 0F, 0.9599311F);
bodySpike2 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike2.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike2.setRotationPoint(4F, -4F, 3F);
bodySpike2.mirror = true;
setRotationWithEulerYzx(bodySpike2, 0.2808018F, -0.8096757F, -0.8339358F);
bodySpike3 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
bodySpike3.addBox(-2F, -2F, -2F, 4, 4, 4);
bodySpike3.setRotationPoint(6F, -2F, -5F);
bodySpike3.mirror = true;
setRotationWithEulerYzx(bodySpike3, 1.120006F, -1.347726F, -0.8969422F);
bodySpike4 = new ModelRenderer(this, 32, 69).setTextureSize(short1, short2);
bodySpike4.addBox(-3F, -3F, -3F, 6, 6, 6);
bodySpike4.setRotationPoint(0F, -4F, -4F);
bodySpike4.mirror = true;
setRotationWithEulerYzx(bodySpike4, 0.7853982F, -1.570796F, 0.9599311F);
headSpike7 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
headSpike7.addBox(-2F, -2F, -2F, 4, 4, 4);
headSpike7.setRotationPoint(0F, -20F, 4F);
headSpike7.mirror = true;
setRotationWithEulerYzx(headSpike7, 0.7853982F, 1.570796F, 0.7853982F);
bodySpike5 = new ModelRenderer(this, 0, 0).setTextureSize(short1, short2);
bodySpike5.addBox(-2F, -2F, -2F, 4, 4, 4);
bodySpike5.setRotationPoint(-6F, -2F, -5F);
bodySpike5.mirror = true;
setRotationWithEulerYzx(bodySpike5, 1.120006F, 1.347725F, 0.896934F);
this.convertToChild(this.iceGiantHead, headSpike1);
this.convertToChild(this.iceGiantHead, headSpike2);
this.convertToChild(this.iceGiantHead, headSpike3);
this.convertToChild(this.iceGiantHead, headSpike4);
this.convertToChild(this.iceGiantHead, headSpike5);
this.convertToChild(this.iceGiantHead, headSpike6);
this.convertToChild(this.iceGiantHead, headSpike7);
this.convertToChild(this.iceGiantRightArm, rightArmSpike1);
this.convertToChild(this.iceGiantRightArm, rightArmSpike2);
this.convertToChild(this.iceGiantLeftArm, leftArmSpike1);
this.convertToChild(this.iceGiantLeftArm, leftArmSpike2);
this.convertToChild(this.iceGiantBody, bodySpike1);
this.convertToChild(this.iceGiantBody, bodySpike2);
this.convertToChild(this.iceGiantBody, bodySpike3);
this.convertToChild(this.iceGiantBody, bodySpike4);
this.convertToChild(this.iceGiantBody, bodySpike5);
}
/**
* Sets the models various rotation angles then renders the model.
*/
public void render(Entity par1Entity, float par2, float par3, float par4, float par5, float par6, float par7){
this.setRotationAngles(par2, par3, par4, par5, par6, par7, par1Entity);
this.iceGiantHead.render(par7);
this.iceGiantBody.render(par7);
this.iceGiantLeftLeg.render(par7);
this.iceGiantRightLeg.render(par7);
this.iceGiantRightArm.render(par7);
this.iceGiantLeftArm.render(par7);
}
/**
* Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
* and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
* "far" arms and legs can swing at most.
*/
public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6,
Entity par7Entity){
this.iceGiantHead.rotateAngleY = par4 / (180F / (float)Math.PI);
this.iceGiantHead.rotateAngleX = par5 / (180F / (float)Math.PI);
this.iceGiantLeftLeg.rotateAngleX = -1.5F * this.func_78172_a(par1, 13.0F) * par2;
this.iceGiantRightLeg.rotateAngleX = 1.5F * this.func_78172_a(par1, 13.0F) * par2;
this.iceGiantLeftLeg.rotateAngleY = 0.0F;
this.iceGiantRightLeg.rotateAngleY = 0.0F;
}
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4){
EntityIceGiant entityicegiant = (EntityIceGiant)par1EntityLivingBase;
int i = entityicegiant.getAttackTimer();
if(i > 0){
this.iceGiantRightArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);
this.iceGiantLeftArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);
}else{
this.iceGiantRightArm.rotateAngleX = (-0.2F + 1.5F * this.func_78172_a(par2, 13.0F)) * par3;
this.iceGiantLeftArm.rotateAngleX = (-0.2F - 1.5F * this.func_78172_a(par2, 13.0F)) * par3;
}
}
private float func_78172_a(float par1, float par2){
return (Math.abs(par1 % par2 - par2 * 0.5F) - par2 * 0.25F) / (par2 * 0.25F);
}
/**
* This is really useful for converting the source from a Techne model export which will have absolute rotation
* points that need to be converted before creating the addChild() relationship. [Courtesy of jabelar]
*/
protected void convertToChild(ModelRenderer parent, ModelRenderer child){
// move child rotation point to be relative to parent
child.rotationPointX -= parent.rotationPointX;
child.rotationPointY -= parent.rotationPointY;
child.rotationPointZ -= parent.rotationPointZ;
// make rotations relative to parent
child.rotateAngleX -= parent.rotateAngleX;
child.rotateAngleY -= parent.rotateAngleY;
child.rotateAngleZ -= parent.rotateAngleZ;
// create relationship
parent.addChild(child);
}
/** Fixes the Techne rotation order bug. [Courtesy of tprk77] */
private Vector3f ConvertEulerYzxToZyx(Vector3f eulerYzx){
// Create a matrix from YZX ordered Euler angles
float a = MathHelper.cos(eulerYzx.x);
float b = MathHelper.sin(eulerYzx.x);
float c = MathHelper.cos(eulerYzx.y);
float d = MathHelper.sin(eulerYzx.y);
float e = MathHelper.cos(eulerYzx.z);
float f = MathHelper.sin(eulerYzx.z);
Matrix4f matrix = new Matrix4f();
matrix.m00 = c * e;
matrix.m01 = b * d - a * c * f;
matrix.m02 = b * c * f + a * d;
matrix.m10 = f;
matrix.m11 = a * e;
matrix.m12 = -b * e;
matrix.m20 = -d * e;
matrix.m21 = a * d * f + b * c;
matrix.m22 = a * c - b * d * f;
matrix.m33 = 1.0F;
// Create ZYX ordered Euler angles from the matrix
Vector3f eulerZyx = new Vector3f();
eulerZyx.y = (float)Math.asin(MathHelper.clamp(-matrix.m20, -1, 1));
if(MathHelper.abs(matrix.m20) < 0.99999){
eulerZyx.x = (float)Math.atan2(matrix.m21, matrix.m22);
eulerZyx.z = (float)Math.atan2(matrix.m10, matrix.m00);
}else{
eulerZyx.x = 0.0F;
eulerZyx.z = (float)Math.atan2(-matrix.m01, matrix.m11);
}
return eulerZyx;
}
private void setRotationWithEulerYzx(ModelRenderer model, float x, float y, float z){
Vector3f eulerYzx = new Vector3f(x, y, z);
Vector3f eulerZyx = ConvertEulerYzxToZyx(eulerYzx);
model.rotateAngleX = eulerZyx.x;
model.rotateAngleY = eulerZyx.y;
model.rotateAngleZ = eulerZyx.z;
}
private float func_78172_a(float par1, float par2)
{
return (Math.abs(par1 % par2 - par2 * 0.5F) - par2 * 0.25F) / (par2 * 0.25F);
}
/** This is really useful for converting the source from a Techne model export
* which will have absolute rotation points that need to be converted before
* creating the addChild() relationship. [Courtesy of jabelar] */
protected void convertToChild(ModelRenderer parent, ModelRenderer child)
{
// move child rotation point to be relative to parent
child.rotationPointX -= parent.rotationPointX;
child.rotationPointY -= parent.rotationPointY;
child.rotationPointZ -= parent.rotationPointZ;
// make rotations relative to parent
child.rotateAngleX -= parent.rotateAngleX;
child.rotateAngleY -= parent.rotateAngleY;
child.rotateAngleZ -= parent.rotateAngleZ;
// create relationship
parent.addChild(child);
}
/** Fixes the Techne rotation order bug. [Courtesy of tprk77] */
private Vector3f ConvertEulerYzxToZyx(Vector3f eulerYzx) {
// Create a matrix from YZX ordered Euler angles
float a = MathHelper.cos(eulerYzx.x);
float b = MathHelper.sin(eulerYzx.x);
float c = MathHelper.cos(eulerYzx.y);
float d = MathHelper.sin(eulerYzx.y);
float e = MathHelper.cos(eulerYzx.z);
float f = MathHelper.sin(eulerYzx.z);
Matrix4f matrix = new Matrix4f();
matrix.m00 = c * e;
matrix.m01 = b * d - a * c * f;
matrix.m02 = b * c * f + a * d;
matrix.m10 = f;
matrix.m11 = a * e;
matrix.m12 = -b * e;
matrix.m20 = -d * e;
matrix.m21 = a * d * f + b * c;
matrix.m22 = a * c - b * d * f;
matrix.m33 = 1.0F;
// Create ZYX ordered Euler angles from the matrix
Vector3f eulerZyx = new Vector3f();
eulerZyx.y = (float) Math.asin(MathHelper.clamp_float(-matrix.m20, -1, 1));
if (MathHelper.abs(matrix.m20) < 0.99999) {
eulerZyx.x = (float) Math.atan2(matrix.m21, matrix.m22);
eulerZyx.z = (float) Math.atan2(matrix.m10, matrix.m00);
} else {
eulerZyx.x = 0.0F;
eulerZyx.z = (float) Math.atan2(-matrix.m01, matrix.m11);
}
return eulerZyx;
}
private void setRotationWithEulerYzx(ModelRenderer model, float x, float y, float z) {
Vector3f eulerYzx = new Vector3f(x, y, z);
Vector3f eulerZyx = ConvertEulerYzxToZyx(eulerYzx);
model.rotateAngleX = eulerZyx.x;
model.rotateAngleY = eulerZyx.y;
model.rotateAngleZ = eulerZyx.z;
}
}
@@ -3,129 +3,137 @@ package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.MathHelper;
public class ModelPhoenix extends ModelBase {
ModelRenderer body;
ModelRenderer rightWing;
ModelRenderer leftWing;
ModelRenderer tailFeathers;
ModelRenderer tail;
ModelRenderer head;
ModelRenderer neck;
ModelRenderer beak;
ModelRenderer plume;
public ModelPhoenix(){
textureWidth = 64;
textureHeight = 64;
/* For future reference: - setRotationPoint sets the origin of a part relative to that of its parent. - The
* first 3 arguments of addBox set the position of a part relative to its rotation point, and the last 3
* arguments are the size of the part. (This means that rotation point and position seem to be the wrong way
* round, since changing the rotation point will move the component without changing which point on the
* component it rotates about.) - The two integer arguments in the ModelRenderer constructor are the texture
* offset. - Mirror does nothing unless you set it before addBox. - Rotation is the usual pitch, yaw, roll. */
body = new ModelRenderer(this, 0, 34);
body.addBox(0F, 0F, -3F, 6, 15, 6);
body.setRotationPoint(-3F, 0F, -5F);
body.setTextureSize(64, 64);
body.mirror = true;
setRotation(body, 0.296706F, 0F, 0F);
rightWing = new ModelRenderer(this, 0, 0);
rightWing.mirror = true;
rightWing.addBox(-27F, -27F, 0F, 27, 34, 0);
rightWing.setRotationPoint(0F, 5F, 0F);
rightWing.setTextureSize(64, 64);
setRotation(rightWing, 0.1745329F, 0F, 0F);
leftWing = new ModelRenderer(this, 0, 0);
leftWing.addBox(0F, -27F, 0F, 27, 34, 0);
leftWing.setRotationPoint(6F, 5F, 0F);
leftWing.setTextureSize(64, 64);
setRotation(leftWing, 0.1745329F, 0F, 0F);
tailFeathers = new ModelRenderer(this, 0, 57);
tailFeathers.addBox(-5F, 0F, 0F, 10, 7, 0);
tailFeathers.setRotationPoint(0F, 7F, 1F);
tailFeathers.setTextureSize(64, 64);
tailFeathers.mirror = true;
setRotation(tailFeathers, 0.5235988F, 0F, 0F);
tail = new ModelRenderer(this, 20, 55);
tail.addBox(-1F, 0F, -1F, 2, 7, 2);
tail.setRotationPoint(3F, 15F, 2F);
tail.setTextureSize(64, 64);
tail.mirror = true;
setRotation(tail, 0.4014257F, 0F, 0F);
head = new ModelRenderer(this, 24, 34);
head.addBox(-2F, -4F, -5F, 4, 4, 6);
head.setRotationPoint(0F, -4F, 0F);
head.setTextureSize(64, 64);
head.mirror = true;
setRotation(head, 0F, 0F, 0F);
neck = new ModelRenderer(this, 24, 44);
neck.addBox(-1F, -4F, -1F, 2, 4, 2);
neck.setRotationPoint(0F, 0F, -4F);
neck.setTextureSize(64, 64);
neck.mirror = true;
setRotation(neck, 0.2443461F, 0F, 0F);
beak = new ModelRenderer(this, 32, 44);
beak.addBox(-0.5F, 4F, -1F, 1, 2, 3);
beak.setRotationPoint(0F, -5F, -8F);
beak.setTextureSize(64, 64);
beak.mirror = true;
setRotation(beak, 0.2792527F, 0F, 0F);
plume = new ModelRenderer(this, 28, 50);
plume.addBox(-0.03333334F, 1F, 0F, 0, 5, 5);
plume.setRotationPoint(0F, -7F, 0F);
plume.setTextureSize(64, 64);
plume.mirror = true;
setRotation(plume, 0F, 0F, 0F);
neck.addChild(head);
head.addChild(plume);
head.addChild(beak);
tail.addChild(tailFeathers);
body.addChild(tail);
body.addChild(rightWing);
body.addChild(leftWing);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
// float f6 = (180F / (float)Math.PI);
this.neck.rotateAngleX = f4 / (180F / (float)Math.PI);
this.neck.rotateAngleY = f3 / (180F / (float)Math.PI);
this.neck.rotateAngleZ = 0.0F;
this.body.rotateAngleX = 0.3f + MathHelper.cos(f2 * 0.1F) * 0.15F;
this.body.rotateAngleY = 0.0F;
this.tail.rotateAngleX = this.body.rotateAngleX * 1.1f;
this.tailFeathers.rotateAngleX = this.body.rotateAngleX * 1.2f;
this.rightWing.rotateAngleY = MathHelper.cos(f2 * 0.3F) * (float)Math.PI * 0.15F;
this.leftWing.rotateAngleY = -this.rightWing.rotateAngleY;
body.render(f5);
neck.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z){
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity){
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
ModelRenderer body;
ModelRenderer rightWing;
ModelRenderer leftWing;
ModelRenderer tailFeathers;
ModelRenderer tail;
ModelRenderer head;
ModelRenderer neck;
ModelRenderer beak;
ModelRenderer plume;
public ModelPhoenix()
{
textureWidth = 64;
textureHeight = 64;
/* For future reference:
* - setRotationPoint sets the origin of a part relative to that of its parent.
* - The first 3 arguments of addBox set the position of a part relative to its rotation point, and the last
* 3 arguments are the size of the part.
* (This means that rotation point and position seem to be the wrong way round, since changing the rotation point
* will move the component without changing which point on the component it rotates about.)
* - The two integer arguments in the ModelRenderer constructor are the texture offset.
* - Mirror does nothing unless you set it before addBox.
* - Rotation is the usual pitch, yaw, roll.
*/
body = new ModelRenderer(this, 0, 34);
body.addBox(0F, 0F, -3F, 6, 15, 6);
body.setRotationPoint(-3F, 0F, -5F);
body.setTextureSize(64, 64);
body.mirror = true;
setRotation(body, 0.296706F, 0F, 0F);
rightWing = new ModelRenderer(this, 0, 0);
rightWing.mirror = true;
rightWing.addBox(-27F, -27F, 0F, 27, 34, 0);
rightWing.setRotationPoint(0F, 5F, 0F);
rightWing.setTextureSize(64, 64);
setRotation(rightWing, 0.1745329F, 0F, 0F);
leftWing = new ModelRenderer(this, 0, 0);
leftWing.addBox(0F, -27F, 0F, 27, 34, 0);
leftWing.setRotationPoint(6F, 5F, 0F);
leftWing.setTextureSize(64, 64);
setRotation(leftWing, 0.1745329F, 0F, 0F);
tailFeathers = new ModelRenderer(this, 0, 57);
tailFeathers.addBox(-5F, 0F, 0F, 10, 7, 0);
tailFeathers.setRotationPoint(0F, 7F, 1F);
tailFeathers.setTextureSize(64, 64);
tailFeathers.mirror = true;
setRotation(tailFeathers, 0.5235988F, 0F, 0F);
tail = new ModelRenderer(this, 20, 55);
tail.addBox(-1F, 0F, -1F, 2, 7, 2);
tail.setRotationPoint(3F, 15F, 2F);
tail.setTextureSize(64, 64);
tail.mirror = true;
setRotation(tail, 0.4014257F, 0F, 0F);
head = new ModelRenderer(this, 24, 34);
head.addBox(-2F, -4F, -5F, 4, 4, 6);
head.setRotationPoint(0F, -4F, 0F);
head.setTextureSize(64, 64);
head.mirror = true;
setRotation(head, 0F, 0F, 0F);
neck = new ModelRenderer(this, 24, 44);
neck.addBox(-1F, -4F, -1F, 2, 4, 2);
neck.setRotationPoint(0F, 0F, -4F);
neck.setTextureSize(64, 64);
neck.mirror = true;
setRotation(neck, 0.2443461F, 0F, 0F);
beak = new ModelRenderer(this, 32, 44);
beak.addBox(-0.5F, 4F, -1F, 1, 2, 3);
beak.setRotationPoint(0F, -5F, -8F);
beak.setTextureSize(64, 64);
beak.mirror = true;
setRotation(beak, 0.2792527F, 0F, 0F);
plume = new ModelRenderer(this, 28, 50);
plume.addBox(-0.03333334F, 1F, 0F, 0, 5, 5);
plume.setRotationPoint(0F, -7F, 0F);
plume.setTextureSize(64, 64);
plume.mirror = true;
setRotation(plume, 0F, 0F, 0F);
neck.addChild(head);
head.addChild(plume);
head.addChild(beak);
tail.addChild(tailFeathers);
body.addChild(tail);
body.addChild(rightWing);
body.addChild(leftWing);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
float f6 = (180F / (float)Math.PI);
this.neck.rotateAngleX = f4 / (180F / (float)Math.PI);
this.neck.rotateAngleY = f3 / (180F / (float)Math.PI);
this.neck.rotateAngleZ = 0.0F;
this.body.rotateAngleX = 0.3f + MathHelper.cos(f2 * 0.1F) * 0.15F;
this.body.rotateAngleY = 0.0F;
this.tail.rotateAngleX = this.body.rotateAngleX * 1.1f;
this.tailFeathers.rotateAngleX = this.body.rotateAngleX * 1.2f;
this.rightWing.rotateAngleY = MathHelper.cos(f2 * 0.3F) * (float)Math.PI * 0.15F;
this.leftWing.rotateAngleY = -this.rightWing.rotateAngleY;
body.render(f5);
neck.render(f5);
}
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
}
@@ -0,0 +1,58 @@
package electroblob.wizardry.client.model;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.entity.living.EntitySkeletonMinion;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.model.ModelZombie;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntitySkeleton;
@SideOnly(Side.CLIENT)
public class ModelSkeletonMinion extends ModelZombie
{
public ModelSkeletonMinion()
{
this(0.0F);
}
public ModelSkeletonMinion(float par1)
{
super(par1, 0.0F, 64, 32);
this.bipedRightArm = new ModelRenderer(this, 40, 16);
this.bipedRightArm.addBox(-1.0F, -2.0F, -1.0F, 2, 12, 2, par1);
this.bipedRightArm.setRotationPoint(-5.0F, 2.0F, 0.0F);
this.bipedLeftArm = new ModelRenderer(this, 40, 16);
this.bipedLeftArm.mirror = true;
this.bipedLeftArm.addBox(-1.0F, -2.0F, -1.0F, 2, 12, 2, par1);
this.bipedLeftArm.setRotationPoint(5.0F, 2.0F, 0.0F);
this.bipedRightLeg = new ModelRenderer(this, 0, 16);
this.bipedRightLeg.addBox(-1.0F, 0.0F, -1.0F, 2, 12, 2, par1);
this.bipedRightLeg.setRotationPoint(-2.0F, 12.0F, 0.0F);
this.bipedLeftLeg = new ModelRenderer(this, 0, 16);
this.bipedLeftLeg.mirror = true;
this.bipedLeftLeg.addBox(-1.0F, 0.0F, -1.0F, 2, 12, 2, par1);
this.bipedLeftLeg.setRotationPoint(2.0F, 12.0F, 0.0F);
}
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4)
{
this.aimedBow = ((EntitySkeletonMinion)par1EntityLivingBase).getSkeletonType() == 1;
super.setLivingAnimations(par1EntityLivingBase, par2, par3, par4);
}
/**
* Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
* and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
* "far" arms and legs can swing at most.
*/
public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity)
{
super.setRotationAngles(par1, par2, par3, par4, par5, par6, par7Entity);
}
}
@@ -0,0 +1,559 @@
package electroblob.wizardry.client.model;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.entity.living.EntitySpiritHorse;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.MathHelper;
@SideOnly(Side.CLIENT)
public class ModelSpiritHorse extends ModelBase
{
private ModelRenderer head;
private ModelRenderer mouthTop;
private ModelRenderer mouthBottom;
private ModelRenderer horseLeftEar;
private ModelRenderer horseRightEar;
private ModelRenderer field_110703_f;
private ModelRenderer field_110704_g;
private ModelRenderer neck;
private ModelRenderer field_110717_i;
private ModelRenderer mane;
private ModelRenderer body;
private ModelRenderer tailBase;
private ModelRenderer tailMiddle;
private ModelRenderer tailTip;
private ModelRenderer backLeftLeg;
private ModelRenderer backLeftShin;
private ModelRenderer backLeftHoof;
private ModelRenderer backRightLeg;
private ModelRenderer backRightShin;
private ModelRenderer backRightHoof;
private ModelRenderer frontRightLeg;
private ModelRenderer frontLeftShin;
private ModelRenderer frontLeftHoof;
private ModelRenderer field_110684_D;
private ModelRenderer frontRightShin;
private ModelRenderer frontRightHoof;
private ModelRenderer field_110687_G;
private ModelRenderer field_110695_H;
private ModelRenderer field_110696_I;
private ModelRenderer field_110697_J;
private ModelRenderer field_110698_K;
private ModelRenderer field_110691_L;
private ModelRenderer field_110692_M;
private ModelRenderer field_110693_N;
private ModelRenderer field_110694_O;
private ModelRenderer field_110700_P;
private ModelRenderer field_110699_Q;
private ModelRenderer field_110702_R;
private ModelRenderer field_110701_S;
public ModelSpiritHorse()
{
this.textureWidth = 128;
this.textureHeight = 128;
this.body = new ModelRenderer(this, 0, 34);
this.body.addBox(-5.0F, -8.0F, -19.0F, 10, 10, 24);
this.body.setRotationPoint(0.0F, 11.0F, 9.0F);
this.tailBase = new ModelRenderer(this, 44, 0);
this.tailBase.addBox(-1.0F, -1.0F, 0.0F, 2, 2, 3);
this.tailBase.setRotationPoint(0.0F, 3.0F, 14.0F);
this.func_110682_a(this.tailBase, -1.134464F, 0.0F, 0.0F);
this.tailMiddle = new ModelRenderer(this, 38, 7);
this.tailMiddle.addBox(-1.5F, -2.0F, 3.0F, 3, 4, 7);
this.tailMiddle.setRotationPoint(0.0F, 3.0F, 14.0F);
this.func_110682_a(this.tailMiddle, -1.134464F, 0.0F, 0.0F);
this.tailTip = new ModelRenderer(this, 24, 3);
this.tailTip.addBox(-1.5F, -4.5F, 9.0F, 3, 4, 7);
this.tailTip.setRotationPoint(0.0F, 3.0F, 14.0F);
this.func_110682_a(this.tailTip, -1.40215F, 0.0F, 0.0F);
this.backLeftLeg = new ModelRenderer(this, 78, 29);
this.backLeftLeg.addBox(-2.5F, -2.0F, -2.5F, 4, 9, 5);
this.backLeftLeg.setRotationPoint(4.0F, 9.0F, 11.0F);
this.backLeftShin = new ModelRenderer(this, 78, 43);
this.backLeftShin.addBox(-2.0F, 0.0F, -1.5F, 3, 5, 3);
this.backLeftShin.setRotationPoint(4.0F, 16.0F, 11.0F);
this.backLeftHoof = new ModelRenderer(this, 78, 51);
this.backLeftHoof.addBox(-2.5F, 5.1F, -2.0F, 4, 3, 4);
this.backLeftHoof.setRotationPoint(4.0F, 16.0F, 11.0F);
this.backRightLeg = new ModelRenderer(this, 96, 29);
this.backRightLeg.addBox(-1.5F, -2.0F, -2.5F, 4, 9, 5);
this.backRightLeg.setRotationPoint(-4.0F, 9.0F, 11.0F);
this.backRightShin = new ModelRenderer(this, 96, 43);
this.backRightShin.addBox(-1.0F, 0.0F, -1.5F, 3, 5, 3);
this.backRightShin.setRotationPoint(-4.0F, 16.0F, 11.0F);
this.backRightHoof = new ModelRenderer(this, 96, 51);
this.backRightHoof.addBox(-1.5F, 5.1F, -2.0F, 4, 3, 4);
this.backRightHoof.setRotationPoint(-4.0F, 16.0F, 11.0F);
this.frontRightLeg = new ModelRenderer(this, 44, 29);
this.frontRightLeg.addBox(-1.9F, -1.0F, -2.1F, 3, 8, 4);
this.frontRightLeg.setRotationPoint(4.0F, 9.0F, -8.0F);
this.frontLeftShin = new ModelRenderer(this, 44, 41);
this.frontLeftShin.addBox(-1.9F, 0.0F, -1.6F, 3, 5, 3);
this.frontLeftShin.setRotationPoint(4.0F, 16.0F, -8.0F);
this.frontLeftHoof = new ModelRenderer(this, 44, 51);
this.frontLeftHoof.addBox(-2.4F, 5.1F, -2.1F, 4, 3, 4);
this.frontLeftHoof.setRotationPoint(4.0F, 16.0F, -8.0F);
this.field_110684_D = new ModelRenderer(this, 60, 29);
this.field_110684_D.addBox(-1.1F, -1.0F, -2.1F, 3, 8, 4);
this.field_110684_D.setRotationPoint(-4.0F, 9.0F, -8.0F);
this.frontRightShin = new ModelRenderer(this, 60, 41);
this.frontRightShin.addBox(-1.1F, 0.0F, -1.6F, 3, 5, 3);
this.frontRightShin.setRotationPoint(-4.0F, 16.0F, -8.0F);
this.frontRightHoof = new ModelRenderer(this, 60, 51);
this.frontRightHoof.addBox(-1.6F, 5.1F, -2.1F, 4, 3, 4);
this.frontRightHoof.setRotationPoint(-4.0F, 16.0F, -8.0F);
this.head = new ModelRenderer(this, 0, 0);
this.head.addBox(-2.5F, -10.0F, -1.5F, 5, 5, 7);
this.head.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.head, 0.5235988F, 0.0F, 0.0F);
this.mouthTop = new ModelRenderer(this, 24, 18);
this.mouthTop.addBox(-2.0F, -10.0F, -7.0F, 4, 3, 6);
this.mouthTop.setRotationPoint(0.0F, 3.95F, -10.0F);
this.func_110682_a(this.mouthTop, 0.5235988F, 0.0F, 0.0F);
this.mouthBottom = new ModelRenderer(this, 24, 27);
this.mouthBottom.addBox(-2.0F, -7.0F, -6.5F, 4, 2, 5);
this.mouthBottom.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.mouthBottom, 0.5235988F, 0.0F, 0.0F);
this.head.addChild(this.mouthTop);
this.head.addChild(this.mouthBottom);
this.horseLeftEar = new ModelRenderer(this, 0, 0);
this.horseLeftEar.addBox(0.45F, -12.0F, 4.0F, 2, 3, 1);
this.horseLeftEar.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.horseLeftEar, 0.5235988F, 0.0F, 0.0F);
this.horseRightEar = new ModelRenderer(this, 0, 0);
this.horseRightEar.addBox(-2.45F, -12.0F, 4.0F, 2, 3, 1);
this.horseRightEar.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.horseRightEar, 0.5235988F, 0.0F, 0.0F);
this.field_110703_f = new ModelRenderer(this, 0, 12);
this.field_110703_f.addBox(-2.0F, -16.0F, 4.0F, 2, 7, 1);
this.field_110703_f.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.field_110703_f, 0.5235988F, 0.0F, 0.2617994F);
this.field_110704_g = new ModelRenderer(this, 0, 12);
this.field_110704_g.addBox(0.0F, -16.0F, 4.0F, 2, 7, 1);
this.field_110704_g.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.field_110704_g, 0.5235988F, 0.0F, -0.2617994F);
this.neck = new ModelRenderer(this, 0, 12);
this.neck.addBox(-2.05F, -9.8F, -2.0F, 4, 14, 8);
this.neck.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.neck, 0.5235988F, 0.0F, 0.0F);
this.field_110687_G = new ModelRenderer(this, 0, 34);
this.field_110687_G.addBox(-3.0F, 0.0F, 0.0F, 8, 8, 3);
this.field_110687_G.setRotationPoint(-7.5F, 3.0F, 10.0F);
this.func_110682_a(this.field_110687_G, 0.0F, ((float)Math.PI / 2F), 0.0F);
this.field_110695_H = new ModelRenderer(this, 0, 47);
this.field_110695_H.addBox(-3.0F, 0.0F, 0.0F, 8, 8, 3);
this.field_110695_H.setRotationPoint(4.5F, 3.0F, 10.0F);
this.func_110682_a(this.field_110695_H, 0.0F, ((float)Math.PI / 2F), 0.0F);
this.field_110696_I = new ModelRenderer(this, 80, 0);
this.field_110696_I.addBox(-5.0F, 0.0F, -3.0F, 10, 1, 8);
this.field_110696_I.setRotationPoint(0.0F, 2.0F, 2.0F);
this.field_110697_J = new ModelRenderer(this, 106, 9);
this.field_110697_J.addBox(-1.5F, -1.0F, -3.0F, 3, 1, 2);
this.field_110697_J.setRotationPoint(0.0F, 2.0F, 2.0F);
this.field_110698_K = new ModelRenderer(this, 80, 9);
this.field_110698_K.addBox(-4.0F, -1.0F, 3.0F, 8, 1, 2);
this.field_110698_K.setRotationPoint(0.0F, 2.0F, 2.0F);
this.field_110692_M = new ModelRenderer(this, 74, 0);
this.field_110692_M.addBox(-0.5F, 6.0F, -1.0F, 1, 2, 2);
this.field_110692_M.setRotationPoint(5.0F, 3.0F, 2.0F);
this.field_110691_L = new ModelRenderer(this, 70, 0);
this.field_110691_L.addBox(-0.5F, 0.0F, -0.5F, 1, 6, 1);
this.field_110691_L.setRotationPoint(5.0F, 3.0F, 2.0F);
this.field_110694_O = new ModelRenderer(this, 74, 4);
this.field_110694_O.addBox(-0.5F, 6.0F, -1.0F, 1, 2, 2);
this.field_110694_O.setRotationPoint(-5.0F, 3.0F, 2.0F);
this.field_110693_N = new ModelRenderer(this, 80, 0);
this.field_110693_N.addBox(-0.5F, 0.0F, -0.5F, 1, 6, 1);
this.field_110693_N.setRotationPoint(-5.0F, 3.0F, 2.0F);
this.field_110700_P = new ModelRenderer(this, 74, 13);
this.field_110700_P.addBox(1.5F, -8.0F, -4.0F, 1, 2, 2);
this.field_110700_P.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.field_110700_P, 0.5235988F, 0.0F, 0.0F);
this.field_110699_Q = new ModelRenderer(this, 74, 13);
this.field_110699_Q.addBox(-2.5F, -8.0F, -4.0F, 1, 2, 2);
this.field_110699_Q.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.field_110699_Q, 0.5235988F, 0.0F, 0.0F);
this.field_110702_R = new ModelRenderer(this, 44, 10);
this.field_110702_R.addBox(2.6F, -6.0F, -6.0F, 0, 3, 16);
this.field_110702_R.setRotationPoint(0.0F, 4.0F, -10.0F);
this.field_110701_S = new ModelRenderer(this, 44, 5);
this.field_110701_S.addBox(-2.6F, -6.0F, -6.0F, 0, 3, 16);
this.field_110701_S.setRotationPoint(0.0F, 4.0F, -10.0F);
this.mane = new ModelRenderer(this, 58, 0);
this.mane.addBox(-1.0F, -11.5F, 5.0F, 2, 16, 4);
this.mane.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.mane, 0.5235988F, 0.0F, 0.0F);
this.field_110717_i = new ModelRenderer(this, 80, 12);
this.field_110717_i.addBox(-2.5F, -10.1F, -7.0F, 5, 5, 12, 0.2F);
this.field_110717_i.setRotationPoint(0.0F, 4.0F, -10.0F);
this.func_110682_a(this.field_110717_i, 0.5235988F, 0.0F, 0.0F);
}
/**
* Sets the models various rotation angles then renders the model.
*/
public void render(Entity par1Entity, float par2, float par3, float par4, float par5, float par6, float par7)
{
EntitySpiritHorse entityhorse = (EntitySpiritHorse)par1Entity;
int i = entityhorse.getHorseType();
float f6 = entityhorse.getGrassEatingAmount(0.0F);
boolean flag = entityhorse.isAdultHorse();
boolean flag1 = flag && entityhorse.isHorseSaddled();
boolean flag2 = flag && entityhorse.isChested();
boolean flag3 = i == 1 || i == 2;
float f7 = entityhorse.getHorseSize();
boolean flag4 = entityhorse.riddenByEntity != null;
if (flag1)
{
this.field_110717_i.render(par7);
this.field_110696_I.render(par7);
this.field_110697_J.render(par7);
this.field_110698_K.render(par7);
this.field_110691_L.render(par7);
this.field_110692_M.render(par7);
this.field_110693_N.render(par7);
this.field_110694_O.render(par7);
this.field_110700_P.render(par7);
this.field_110699_Q.render(par7);
if (flag4)
{
this.field_110702_R.render(par7);
this.field_110701_S.render(par7);
}
}
if (!flag)
{
GL11.glPushMatrix();
GL11.glScalef(f7, 0.5F + f7 * 0.5F, f7);
GL11.glTranslatef(0.0F, 0.95F * (1.0F - f7), 0.0F);
}
this.backLeftLeg.render(par7);
this.backLeftShin.render(par7);
this.backLeftHoof.render(par7);
this.backRightLeg.render(par7);
this.backRightShin.render(par7);
this.backRightHoof.render(par7);
this.frontRightLeg.render(par7);
this.frontLeftShin.render(par7);
this.frontLeftHoof.render(par7);
this.field_110684_D.render(par7);
this.frontRightShin.render(par7);
this.frontRightHoof.render(par7);
if (!flag)
{
GL11.glPopMatrix();
GL11.glPushMatrix();
GL11.glScalef(f7, f7, f7);
GL11.glTranslatef(0.0F, 1.35F * (1.0F - f7), 0.0F);
}
this.body.render(par7);
this.tailBase.render(par7);
this.tailMiddle.render(par7);
this.tailTip.render(par7);
this.neck.render(par7);
this.mane.render(par7);
if (!flag)
{
GL11.glPopMatrix();
GL11.glPushMatrix();
float f8 = 0.5F + f7 * f7 * 0.5F;
GL11.glScalef(f8, f8, f8);
if (f6 <= 0.0F)
{
GL11.glTranslatef(0.0F, 1.35F * (1.0F - f7), 0.0F);
}
else
{
GL11.glTranslatef(0.0F, 0.9F * (1.0F - f7) * f6 + 1.35F * (1.0F - f7) * (1.0F - f6), 0.15F * (1.0F - f7) * f6);
}
}
if (flag3)
{
this.field_110703_f.render(par7);
this.field_110704_g.render(par7);
}
else
{
this.horseLeftEar.render(par7);
this.horseRightEar.render(par7);
}
this.head.render(par7);
if (!flag)
{
GL11.glPopMatrix();
}
if (flag2)
{
this.field_110687_G.render(par7);
this.field_110695_H.render(par7);
}
}
private void func_110682_a(ModelRenderer par1ModelRenderer, float par2, float par3, float par4)
{
par1ModelRenderer.rotateAngleX = par2;
par1ModelRenderer.rotateAngleY = par3;
par1ModelRenderer.rotateAngleZ = par4;
}
private float func_110683_a(float par1, float par2, float par3)
{
float f3;
for (f3 = par2 - par1; f3 < -180.0F; f3 += 360.0F)
{
;
}
while (f3 >= 180.0F)
{
f3 -= 360.0F;
}
return par1 + par3 * f3;
}
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4)
{
super.setLivingAnimations(par1EntityLivingBase, par2, par3, par4);
float f3 = this.func_110683_a(par1EntityLivingBase.prevRenderYawOffset, par1EntityLivingBase.renderYawOffset, par4);
float f4 = this.func_110683_a(par1EntityLivingBase.prevRotationYawHead, par1EntityLivingBase.rotationYawHead, par4);
float f5 = par1EntityLivingBase.prevRotationPitch + (par1EntityLivingBase.rotationPitch - par1EntityLivingBase.prevRotationPitch) * par4;
float f6 = f4 - f3;
float f7 = f5 / (180F / (float)Math.PI);
if (f6 > 20.0F)
{
f6 = 20.0F;
}
if (f6 < -20.0F)
{
f6 = -20.0F;
}
if (par3 > 0.2F)
{
f7 += MathHelper.cos(par2 * 0.4F) * 0.15F * par3;
}
EntitySpiritHorse entityhorse = (EntitySpiritHorse)par1EntityLivingBase;
float f8 = entityhorse.getGrassEatingAmount(par4);
float f9 = entityhorse.getRearingAmount(par4);
float f10 = 1.0F - f9;
float f11 = entityhorse.func_110201_q(par4);
boolean flag = entityhorse.field_110278_bp != 0;
boolean flag1 = entityhorse.isHorseSaddled();
boolean flag2 = entityhorse.riddenByEntity != null;
float f12 = (float)par1EntityLivingBase.ticksExisted + par4;
float f13 = MathHelper.cos(par2 * 0.6662F + (float)Math.PI);
float f14 = f13 * 0.8F * par3;
this.head.rotationPointY = 4.0F;
this.head.rotationPointZ = -10.0F;
this.tailBase.rotationPointY = 3.0F;
this.tailMiddle.rotationPointZ = 14.0F;
this.field_110695_H.rotationPointY = 3.0F;
this.field_110695_H.rotationPointZ = 10.0F;
this.body.rotateAngleX = 0.0F;
this.head.rotateAngleX = 0.5235988F + f7;
this.head.rotateAngleY = f6 / (180F / (float)Math.PI);
this.head.rotateAngleX = f9 * (0.2617994F + f7) + f8 * 2.18166F + (1.0F - Math.max(f9, f8)) * this.head.rotateAngleX;
this.head.rotateAngleY = f9 * (f6 / (180F / (float)Math.PI)) + (1.0F - Math.max(f9, f8)) * this.head.rotateAngleY;
this.head.rotationPointY = f9 * -6.0F + f8 * 11.0F + (1.0F - Math.max(f9, f8)) * this.head.rotationPointY;
this.head.rotationPointZ = f9 * -1.0F + f8 * -10.0F + (1.0F - Math.max(f9, f8)) * this.head.rotationPointZ;
this.tailBase.rotationPointY = f9 * 9.0F + f10 * this.tailBase.rotationPointY;
this.tailMiddle.rotationPointZ = f9 * 18.0F + f10 * this.tailMiddle.rotationPointZ;
this.field_110695_H.rotationPointY = f9 * 5.5F + f10 * this.field_110695_H.rotationPointY;
this.field_110695_H.rotationPointZ = f9 * 15.0F + f10 * this.field_110695_H.rotationPointZ;
this.body.rotateAngleX = f9 * -((float)Math.PI / 4F) + f10 * this.body.rotateAngleX;
this.horseLeftEar.rotationPointY = this.head.rotationPointY;
this.horseRightEar.rotationPointY = this.head.rotationPointY;
this.field_110703_f.rotationPointY = this.head.rotationPointY;
this.field_110704_g.rotationPointY = this.head.rotationPointY;
this.neck.rotationPointY = this.head.rotationPointY;
this.mouthTop.rotationPointY = 0.02F;
this.mouthBottom.rotationPointY = 0.0F;
this.mane.rotationPointY = this.head.rotationPointY;
this.horseLeftEar.rotationPointZ = this.head.rotationPointZ;
this.horseRightEar.rotationPointZ = this.head.rotationPointZ;
this.field_110703_f.rotationPointZ = this.head.rotationPointZ;
this.field_110704_g.rotationPointZ = this.head.rotationPointZ;
this.neck.rotationPointZ = this.head.rotationPointZ;
this.mouthTop.rotationPointZ = 0.02F - f11 * 1.0F;
this.mouthBottom.rotationPointZ = 0.0F + f11 * 1.0F;
this.mane.rotationPointZ = this.head.rotationPointZ;
this.horseLeftEar.rotateAngleX = this.head.rotateAngleX;
this.horseRightEar.rotateAngleX = this.head.rotateAngleX;
this.field_110703_f.rotateAngleX = this.head.rotateAngleX;
this.field_110704_g.rotateAngleX = this.head.rotateAngleX;
this.neck.rotateAngleX = this.head.rotateAngleX;
this.mouthTop.rotateAngleX = 0.0F - 0.09424778F * f11;
this.mouthBottom.rotateAngleX = 0.0F + 0.15707964F * f11;
this.mane.rotateAngleX = this.head.rotateAngleX;
this.horseLeftEar.rotateAngleY = this.head.rotateAngleY;
this.horseRightEar.rotateAngleY = this.head.rotateAngleY;
this.field_110703_f.rotateAngleY = this.head.rotateAngleY;
this.field_110704_g.rotateAngleY = this.head.rotateAngleY;
this.neck.rotateAngleY = this.head.rotateAngleY;
this.mouthTop.rotateAngleY = 0.0F;
this.mouthBottom.rotateAngleY = 0.0F;
this.mane.rotateAngleY = this.head.rotateAngleY;
this.field_110687_G.rotateAngleX = f14 / 5.0F;
this.field_110695_H.rotateAngleX = -f14 / 5.0F;
float f15 = ((float)Math.PI / 2F);
float f16 = ((float)Math.PI * 3F / 2F);
float f17 = -1.0471976F;
float f18 = 0.2617994F * f9;
float f19 = MathHelper.cos(f12 * 0.6F + (float)Math.PI);
this.frontRightLeg.rotationPointY = -2.0F * f9 + 9.0F * f10;
this.frontRightLeg.rotationPointZ = -2.0F * f9 + -8.0F * f10;
this.field_110684_D.rotationPointY = this.frontRightLeg.rotationPointY;
this.field_110684_D.rotationPointZ = this.frontRightLeg.rotationPointZ;
this.backLeftShin.rotationPointY = this.backLeftLeg.rotationPointY + MathHelper.sin(((float)Math.PI / 2F) + f18 + f10 * -f13 * 0.5F * par3) * 7.0F;
this.backLeftShin.rotationPointZ = this.backLeftLeg.rotationPointZ + MathHelper.cos(((float)Math.PI * 3F / 2F) + f18 + f10 * -f13 * 0.5F * par3) * 7.0F;
this.backRightShin.rotationPointY = this.backRightLeg.rotationPointY + MathHelper.sin(((float)Math.PI / 2F) + f18 + f10 * f13 * 0.5F * par3) * 7.0F;
this.backRightShin.rotationPointZ = this.backRightLeg.rotationPointZ + MathHelper.cos(((float)Math.PI * 3F / 2F) + f18 + f10 * f13 * 0.5F * par3) * 7.0F;
float f20 = (-1.0471976F + f19) * f9 + f14 * f10;
float f21 = (-1.0471976F + -f19) * f9 + -f14 * f10;
this.frontLeftShin.rotationPointY = this.frontRightLeg.rotationPointY + MathHelper.sin(((float)Math.PI / 2F) + f20) * 7.0F;
this.frontLeftShin.rotationPointZ = this.frontRightLeg.rotationPointZ + MathHelper.cos(((float)Math.PI * 3F / 2F) + f20) * 7.0F;
this.frontRightShin.rotationPointY = this.field_110684_D.rotationPointY + MathHelper.sin(((float)Math.PI / 2F) + f21) * 7.0F;
this.frontRightShin.rotationPointZ = this.field_110684_D.rotationPointZ + MathHelper.cos(((float)Math.PI * 3F / 2F) + f21) * 7.0F;
this.backLeftLeg.rotateAngleX = f18 + -f13 * 0.5F * par3 * f10;
this.backLeftShin.rotateAngleX = -0.08726646F * f9 + (-f13 * 0.5F * par3 - Math.max(0.0F, f13 * 0.5F * par3)) * f10;
this.backLeftHoof.rotateAngleX = this.backLeftShin.rotateAngleX;
this.backRightLeg.rotateAngleX = f18 + f13 * 0.5F * par3 * f10;
this.backRightShin.rotateAngleX = -0.08726646F * f9 + (f13 * 0.5F * par3 - Math.max(0.0F, -f13 * 0.5F * par3)) * f10;
this.backRightHoof.rotateAngleX = this.backRightShin.rotateAngleX;
this.frontRightLeg.rotateAngleX = f20;
this.frontLeftShin.rotateAngleX = (this.frontRightLeg.rotateAngleX + (float)Math.PI * Math.max(0.0F, 0.2F + f19 * 0.2F)) * f9 + (f14 + Math.max(0.0F, f13 * 0.5F * par3)) * f10;
this.frontLeftHoof.rotateAngleX = this.frontLeftShin.rotateAngleX;
this.field_110684_D.rotateAngleX = f21;
this.frontRightShin.rotateAngleX = (this.field_110684_D.rotateAngleX + (float)Math.PI * Math.max(0.0F, 0.2F - f19 * 0.2F)) * f9 + (-f14 + Math.max(0.0F, -f13 * 0.5F * par3)) * f10;
this.frontRightHoof.rotateAngleX = this.frontRightShin.rotateAngleX;
this.backLeftHoof.rotationPointY = this.backLeftShin.rotationPointY;
this.backLeftHoof.rotationPointZ = this.backLeftShin.rotationPointZ;
this.backRightHoof.rotationPointY = this.backRightShin.rotationPointY;
this.backRightHoof.rotationPointZ = this.backRightShin.rotationPointZ;
this.frontLeftHoof.rotationPointY = this.frontLeftShin.rotationPointY;
this.frontLeftHoof.rotationPointZ = this.frontLeftShin.rotationPointZ;
this.frontRightHoof.rotationPointY = this.frontRightShin.rotationPointY;
this.frontRightHoof.rotationPointZ = this.frontRightShin.rotationPointZ;
if (flag1)
{
this.field_110696_I.rotationPointY = f9 * 0.5F + f10 * 2.0F;
this.field_110696_I.rotationPointZ = f9 * 11.0F + f10 * 2.0F;
this.field_110697_J.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110698_K.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110691_L.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110693_N.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110692_M.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110694_O.rotationPointY = this.field_110696_I.rotationPointY;
this.field_110687_G.rotationPointY = this.field_110695_H.rotationPointY;
this.field_110697_J.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110698_K.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110691_L.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110693_N.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110692_M.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110694_O.rotationPointZ = this.field_110696_I.rotationPointZ;
this.field_110687_G.rotationPointZ = this.field_110695_H.rotationPointZ;
this.field_110696_I.rotateAngleX = this.body.rotateAngleX;
this.field_110697_J.rotateAngleX = this.body.rotateAngleX;
this.field_110698_K.rotateAngleX = this.body.rotateAngleX;
this.field_110702_R.rotationPointY = this.head.rotationPointY;
this.field_110701_S.rotationPointY = this.head.rotationPointY;
this.field_110717_i.rotationPointY = this.head.rotationPointY;
this.field_110700_P.rotationPointY = this.head.rotationPointY;
this.field_110699_Q.rotationPointY = this.head.rotationPointY;
this.field_110702_R.rotationPointZ = this.head.rotationPointZ;
this.field_110701_S.rotationPointZ = this.head.rotationPointZ;
this.field_110717_i.rotationPointZ = this.head.rotationPointZ;
this.field_110700_P.rotationPointZ = this.head.rotationPointZ;
this.field_110699_Q.rotationPointZ = this.head.rotationPointZ;
this.field_110702_R.rotateAngleX = f7;
this.field_110701_S.rotateAngleX = f7;
this.field_110717_i.rotateAngleX = this.head.rotateAngleX;
this.field_110700_P.rotateAngleX = this.head.rotateAngleX;
this.field_110699_Q.rotateAngleX = this.head.rotateAngleX;
this.field_110717_i.rotateAngleY = this.head.rotateAngleY;
this.field_110700_P.rotateAngleY = this.head.rotateAngleY;
this.field_110702_R.rotateAngleY = this.head.rotateAngleY;
this.field_110699_Q.rotateAngleY = this.head.rotateAngleY;
this.field_110701_S.rotateAngleY = this.head.rotateAngleY;
if (flag2)
{
this.field_110691_L.rotateAngleX = -1.0471976F;
this.field_110692_M.rotateAngleX = -1.0471976F;
this.field_110693_N.rotateAngleX = -1.0471976F;
this.field_110694_O.rotateAngleX = -1.0471976F;
this.field_110691_L.rotateAngleZ = 0.0F;
this.field_110692_M.rotateAngleZ = 0.0F;
this.field_110693_N.rotateAngleZ = 0.0F;
this.field_110694_O.rotateAngleZ = 0.0F;
}
else
{
this.field_110691_L.rotateAngleX = f14 / 3.0F;
this.field_110692_M.rotateAngleX = f14 / 3.0F;
this.field_110693_N.rotateAngleX = f14 / 3.0F;
this.field_110694_O.rotateAngleX = f14 / 3.0F;
this.field_110691_L.rotateAngleZ = f14 / 5.0F;
this.field_110692_M.rotateAngleZ = f14 / 5.0F;
this.field_110693_N.rotateAngleZ = -f14 / 5.0F;
this.field_110694_O.rotateAngleZ = -f14 / 5.0F;
}
}
f15 = -1.3089F + par3 * 1.5F;
if (f15 > 0.0F)
{
f15 = 0.0F;
}
if (flag)
{
this.tailBase.rotateAngleY = MathHelper.cos(f12 * 0.7F);
f15 = 0.0F;
}
else
{
this.tailBase.rotateAngleY = 0.0F;
}
this.tailMiddle.rotateAngleY = this.tailBase.rotateAngleY;
this.tailTip.rotateAngleY = this.tailBase.rotateAngleY;
this.tailMiddle.rotationPointY = this.tailBase.rotationPointY;
this.tailTip.rotationPointY = this.tailBase.rotationPointY;
this.tailMiddle.rotationPointZ = this.tailBase.rotationPointZ;
this.tailTip.rotationPointZ = this.tailBase.rotationPointZ;
this.tailBase.rotateAngleX = f15;
this.tailMiddle.rotateAngleX = f15;
this.tailTip.rotateAngleX = -0.2618F + f15;
}
}
@@ -0,0 +1,190 @@
package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.MathHelper;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.entity.living.EntitySpiritWolf;
@SideOnly(Side.CLIENT)
public class ModelSpiritWolf extends ModelBase
{
/** main box for the wolf head */
public ModelRenderer wolfHeadMain;
/** The wolf's body */
public ModelRenderer wolfBody;
/** Wolf'se first leg */
public ModelRenderer wolfLeg1;
/** Wolf's second leg */
public ModelRenderer wolfLeg2;
/** Wolf's third leg */
public ModelRenderer wolfLeg3;
/** Wolf's fourth leg */
public ModelRenderer wolfLeg4;
/** The wolf's tail */
ModelRenderer wolfTail;
/** The wolf's mane */
ModelRenderer wolfMane;
public ModelSpiritWolf()
{
float f = 0.0F;
float f1 = 13.5F;
this.wolfHeadMain = new ModelRenderer(this, 0, 0);
this.wolfHeadMain.addBox(-3.0F, -3.0F, -2.0F, 6, 6, 4, f);
this.wolfHeadMain.setRotationPoint(-1.0F, f1, -7.0F);
this.wolfBody = new ModelRenderer(this, 18, 14);
this.wolfBody.addBox(-4.0F, -2.0F, -3.0F, 6, 9, 6, f);
this.wolfBody.setRotationPoint(0.0F, 14.0F, 2.0F);
this.wolfMane = new ModelRenderer(this, 21, 0);
this.wolfMane.addBox(-4.0F, -3.0F, -3.0F, 8, 6, 7, f);
this.wolfMane.setRotationPoint(-1.0F, 14.0F, 2.0F);
this.wolfLeg1 = new ModelRenderer(this, 0, 18);
this.wolfLeg1.addBox(-1.0F, 0.0F, -1.0F, 2, 8, 2, f);
this.wolfLeg1.setRotationPoint(-2.5F, 16.0F, 7.0F);
this.wolfLeg2 = new ModelRenderer(this, 0, 18);
this.wolfLeg2.addBox(-1.0F, 0.0F, -1.0F, 2, 8, 2, f);
this.wolfLeg2.setRotationPoint(0.5F, 16.0F, 7.0F);
this.wolfLeg3 = new ModelRenderer(this, 0, 18);
this.wolfLeg3.addBox(-1.0F, 0.0F, -1.0F, 2, 8, 2, f);
this.wolfLeg3.setRotationPoint(-2.5F, 16.0F, -4.0F);
this.wolfLeg4 = new ModelRenderer(this, 0, 18);
this.wolfLeg4.addBox(-1.0F, 0.0F, -1.0F, 2, 8, 2, f);
this.wolfLeg4.setRotationPoint(0.5F, 16.0F, -4.0F);
this.wolfTail = new ModelRenderer(this, 9, 18);
this.wolfTail.addBox(-1.0F, 0.0F, -1.0F, 2, 8, 2, f);
this.wolfTail.setRotationPoint(-1.0F, 12.0F, 8.0F);
this.wolfHeadMain.setTextureOffset(16, 14).addBox(-3.0F, -5.0F, 0.0F, 2, 2, 1, f);
this.wolfHeadMain.setTextureOffset(16, 14).addBox(1.0F, -5.0F, 0.0F, 2, 2, 1, f);
this.wolfHeadMain.setTextureOffset(0, 10).addBox(-1.5F, 0.0F, -5.0F, 3, 3, 4, f);
}
/**
* Sets the models various rotation angles then renders the model.
*/
public void render(Entity par1Entity, float par2, float par3, float par4, float par5, float par6, float par7)
{
super.render(par1Entity, par2, par3, par4, par5, par6, par7);
this.setRotationAngles(par2, par3, par4, par5, par6, par7, par1Entity);
if (this.isChild)
{
float f6 = 2.0F;
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glTranslatef(0.0F, 5.0F * par7, 2.0F * par7);
this.wolfHeadMain.renderWithRotation(par7);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
GL11.glPushMatrix();
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glScalef(1.0F / f6, 1.0F / f6, 1.0F / f6);
GL11.glTranslatef(0.0F, 24.0F * par7, 0.0F);
this.wolfBody.render(par7);
this.wolfLeg1.render(par7);
this.wolfLeg2.render(par7);
this.wolfLeg3.render(par7);
this.wolfLeg4.render(par7);
this.wolfTail.renderWithRotation(par7);
this.wolfMane.render(par7);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
else
{
this.wolfHeadMain.renderWithRotation(par7);
this.wolfBody.render(par7);
this.wolfLeg1.render(par7);
this.wolfLeg2.render(par7);
this.wolfLeg3.render(par7);
this.wolfLeg4.render(par7);
this.wolfTail.renderWithRotation(par7);
this.wolfMane.render(par7);
}
}
/**
* Used for easily adding entity-dependent animations. The second and third float params here are the same second
* and third as in the setRotationAngles method.
*/
public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4)
{
EntitySpiritWolf EntitySpiritWolf = (EntitySpiritWolf)par1EntityLivingBase;
if (EntitySpiritWolf.isAngry())
{
this.wolfTail.rotateAngleY = 0.0F;
}
else
{
this.wolfTail.rotateAngleY = MathHelper.cos(par2 * 0.6662F) * 1.4F * par3;
}
if (EntitySpiritWolf.isSitting())
{
this.wolfMane.setRotationPoint(-1.0F, 16.0F, -3.0F);
this.wolfMane.rotateAngleX = ((float)Math.PI * 2F / 5F);
this.wolfMane.rotateAngleY = 0.0F;
this.wolfBody.setRotationPoint(0.0F, 18.0F, 0.0F);
this.wolfBody.rotateAngleX = ((float)Math.PI / 4F);
this.wolfTail.setRotationPoint(-1.0F, 21.0F, 6.0F);
this.wolfLeg1.setRotationPoint(-2.5F, 22.0F, 2.0F);
this.wolfLeg1.rotateAngleX = ((float)Math.PI * 3F / 2F);
this.wolfLeg2.setRotationPoint(0.5F, 22.0F, 2.0F);
this.wolfLeg2.rotateAngleX = ((float)Math.PI * 3F / 2F);
this.wolfLeg3.rotateAngleX = 5.811947F;
this.wolfLeg3.setRotationPoint(-2.49F, 17.0F, -4.0F);
this.wolfLeg4.rotateAngleX = 5.811947F;
this.wolfLeg4.setRotationPoint(0.51F, 17.0F, -4.0F);
}
else
{
this.wolfBody.setRotationPoint(0.0F, 14.0F, 2.0F);
this.wolfBody.rotateAngleX = ((float)Math.PI / 2F);
this.wolfMane.setRotationPoint(-1.0F, 14.0F, -3.0F);
this.wolfMane.rotateAngleX = this.wolfBody.rotateAngleX;
this.wolfTail.setRotationPoint(-1.0F, 12.0F, 8.0F);
this.wolfLeg1.setRotationPoint(-2.5F, 16.0F, 7.0F);
this.wolfLeg2.setRotationPoint(0.5F, 16.0F, 7.0F);
this.wolfLeg3.setRotationPoint(-2.5F, 16.0F, -4.0F);
this.wolfLeg4.setRotationPoint(0.5F, 16.0F, -4.0F);
this.wolfLeg1.rotateAngleX = MathHelper.cos(par2 * 0.6662F) * 1.4F * par3;
this.wolfLeg2.rotateAngleX = MathHelper.cos(par2 * 0.6662F + (float)Math.PI) * 1.4F * par3;
this.wolfLeg3.rotateAngleX = MathHelper.cos(par2 * 0.6662F + (float)Math.PI) * 1.4F * par3;
this.wolfLeg4.rotateAngleX = MathHelper.cos(par2 * 0.6662F) * 1.4F * par3;
}
this.wolfHeadMain.rotateAngleZ = EntitySpiritWolf.getInterestedAngle(par4) + EntitySpiritWolf.getShakeAngle(par4, 0.0F);
this.wolfMane.rotateAngleZ = EntitySpiritWolf.getShakeAngle(par4, -0.08F);
this.wolfBody.rotateAngleZ = EntitySpiritWolf.getShakeAngle(par4, -0.16F);
this.wolfTail.rotateAngleZ = EntitySpiritWolf.getShakeAngle(par4, -0.2F);
}
/**
* Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms
* and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how
* "far" arms and legs can swing at most.
*/
public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity)
{
super.setRotationAngles(par1, par2, par3, par4, par5, par6, par7Entity);
this.wolfHeadMain.rotateAngleX = par5 / (180F / (float)Math.PI);
this.wolfHeadMain.rotateAngleY = par4 / (180F / (float)Math.PI);
this.wolfTail.rotateAngleX = par3;
}
}
@@ -2,128 +2,174 @@ package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelWizard extends ModelBiped {
// fields
ModelRenderer Shape5;
ModelRenderer Shape8;
ModelRenderer Shape9;
ModelRenderer Shape10;
ModelRenderer Shape7;
ModelRenderer Shape11;
ModelRenderer Shape12;
ModelRenderer beard;
ModelRenderer Shape13;
public ModelWizard(){
// super(0, 0, 64, 32);
/* bipedRightLeg = new ModelRenderer(this, 32, 0); // 32 and 0 are the x and y texture offsets respectively.
* bipedRightLeg.addBox(-2F, 0F, -2F, 4, 12, 4); // x, y, z, u, v, w. bipedRightLeg.setRotationPoint(-2F, 12F,
* 0F); // Rotation point xyz (absolute, not relative) bipedRightLeg.setTextureSize(64, 64);
* bipedRightLeg.mirror = true; setRotation(bipedRightLeg, 0F, 0F, 0F);
*
* bipedLeftLeg.mirror = true; bipedLeftLeg = new ModelRenderer(this, 32, 0); bipedLeftLeg.addBox(-2F, 0F, -2F,
* 4, 12, 4); bipedLeftLeg.setRotationPoint(2F, 12F, 0F); bipedLeftLeg.setTextureSize(64, 64);
* bipedLeftLeg.mirror = true; setRotation(bipedLeftLeg, 0F, 0F, 0F); bipedLeftLeg.mirror = false;
*
* bipedBody = new ModelRenderer(this, 0, 16); bipedBody.addBox(0F, 0F, 0F, 8, 12, 4);
* bipedBody.setRotationPoint(-4F, 0F, -2F); bipedBody.setTextureSize(64, 64); bipedBody.mirror = true;
* setRotation(bipedBody, 0F, 0F, 0F);
*
* bipedLeftArm.mirror = true; bipedLeftArm = new ModelRenderer(this, 48, 0); bipedLeftArm.addBox(-1F, 0F, -2F,
* 4, 12, 4); bipedLeftArm.setRotationPoint(4F, 0F, 0F); bipedLeftArm.setTextureSize(64, 64);
* bipedLeftArm.mirror = true; setRotation(bipedLeftArm, 0F, 0F, 0F); bipedLeftArm.mirror = false;
*
* bipedRightArm = new ModelRenderer(this, 48, 0); bipedRightArm.addBox(-3F, 0F, -2F, 4, 12, 4);
* bipedRightArm.setRotationPoint(-4F, 0F, 0F); bipedRightArm.setTextureSize(64, 64); bipedRightArm.mirror =
* true; setRotation(bipedRightArm, 0F, 0F, 0F);
*
* bipedHead = new ModelRenderer(this, 0, 0); bipedHead.addBox(-4F, -8F, -4F, 8, 8, 8);
* bipedHead.setRotationPoint(0F, 0F, 0F); bipedHead.setTextureSize(64, 64); bipedHead.mirror = true;
* setRotation(bipedHead, 0F, 0F, 0F); */
Shape5 = new ModelRenderer(this, 0, 51);
Shape5.addBox(0F, 0F, 0F, 12, 1, 12);
Shape5.setRotationPoint(-6F, -7F, -6F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, 0F, 0F, 0F);
Shape8 = new ModelRenderer(this, 0, 32);
Shape8.addBox(0F, 0F, 0F, 6, 1, 6);
Shape8.setRotationPoint(-3F, -9F, -3F);
Shape8.setTextureSize(64, 64);
Shape8.mirror = true;
setRotation(Shape8, -0.0349066F, 0F, 0F);
Shape9 = new ModelRenderer(this, 24, 32);
Shape9.addBox(0F, 0F, 0F, 3, 3, 3);
Shape9.setRotationPoint(-1.5F, -13F, -0.5F);
Shape9.setTextureSize(64, 64);
Shape9.mirror = true;
setRotation(Shape9, -0.2511622F, 0F, 0F);
Shape10 = new ModelRenderer(this, 0, 39);
Shape10.addBox(0F, 0F, 0F, 5, 1, 5);
Shape10.setRotationPoint(-2.5F, -10F, -2.5F);
Shape10.setTextureSize(64, 64);
Shape10.mirror = true;
setRotation(Shape10, -0.0698132F, 0F, 0F);
Shape7 = new ModelRenderer(this, 0, 45);
Shape7.addBox(0F, 0F, 0F, 4, 2, 4);
Shape7.setRotationPoint(-2F, -11F, -1.5F);
Shape7.setTextureSize(64, 64);
Shape7.mirror = true;
setRotation(Shape7, -0.1396263F, 0F, 0F);
Shape11 = new ModelRenderer(this, 20, 39);
Shape11.addBox(0F, 0F, 0F, 2, 3, 2);
Shape11.setRotationPoint(-1F, -15F, 1F);
Shape11.setTextureSize(64, 64);
Shape11.mirror = true;
setRotation(Shape11, -0.4363323F, 0F, 0F);
Shape12 = new ModelRenderer(this, 28, 39);
Shape12.addBox(0F, 0F, 0F, 1, 2, 1);
Shape12.setRotationPoint(-0.5F, -16F, 2.5F);
Shape12.setTextureSize(64, 64);
Shape12.mirror = true;
setRotation(Shape12, -0.715585F, 0F, 0F);
beard = new ModelRenderer(this, 32, 0);
beard.addBox(0F, 0F, 0F, 8, 5, 0);
beard.setRotationPoint(-4F, 0F, -4F);
beard.setTextureSize(64, 64);
beard.mirror = true;
setRotation(beard, 0F, 0F, 0F);
Shape13 = new ModelRenderer(this, 36, 16);
Shape13.addBox(4F, 0F, 2F, 8, 20, 6);
Shape13.setRotationPoint(-4F, 0F, -3F);
Shape13.setTextureSize(64, 64);
Shape13.mirror = true;
setRotation(Shape13, 0F, 0F, 0F);
// Makes head bits move with head
// bipedHead.addChild(Shape5);
bipedHead.addChild(beard);
// bipedHead.addChild(Shape7);
// bipedHead.addChild(Shape8);
// bipedHead.addChild(Shape9);
// bipedHead.addChild(Shape10);
// bipedHead.addChild(Shape11);
// bipedHead.addChild(Shape12);
// Makes cloak attached to body
// bipedBody.addChild(Shape13);
// No outer head layer
this.bipedHeadwear.isHidden = true;
}
/* public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
* super.render(entity, f, f1, f2, f3, f4, f5); setRotationAngles(f, f1, f2, f3, f4, f5, entity);
* bipedRightLeg.render(f5); bipedLeftLeg.render(f5); bipedBody.render(f5); bipedLeftArm.render(f5);
* bipedRightArm.render(f5); bipedHead.render(f5); Shape5.render(f5); Shape8.render(f5); Shape9.render(f5);
* Shape10.render(f5); Shape7.render(f5); Shape11.render(f5); Shape12.render(f5); Shape6.render(f5);
* Shape13.render(f5); } */
private void setRotation(ModelRenderer model, float x, float y, float z){
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
/* public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity) {
* super.setRotationAngles(f, f1, f2, f3, f4, f5, entity); } */
public class ModelWizard extends ModelBiped
{
//fields
ModelRenderer Shape5;
ModelRenderer Shape8;
ModelRenderer Shape9;
ModelRenderer Shape10;
ModelRenderer Shape7;
ModelRenderer Shape11;
ModelRenderer Shape12;
ModelRenderer beard;
ModelRenderer Shape13;
public ModelWizard()
{
//super(0, 0, 64, 32);
/*
bipedRightLeg = new ModelRenderer(this, 32, 0); // 32 and 0 are the x and y texture offsets respectively.
bipedRightLeg.addBox(-2F, 0F, -2F, 4, 12, 4); // x, y, z, u, v, w.
bipedRightLeg.setRotationPoint(-2F, 12F, 0F); // Rotation point xyz (absolute, not relative)
bipedRightLeg.setTextureSize(64, 64);
bipedRightLeg.mirror = true;
setRotation(bipedRightLeg, 0F, 0F, 0F);
bipedLeftLeg.mirror = true;
bipedLeftLeg = new ModelRenderer(this, 32, 0);
bipedLeftLeg.addBox(-2F, 0F, -2F, 4, 12, 4);
bipedLeftLeg.setRotationPoint(2F, 12F, 0F);
bipedLeftLeg.setTextureSize(64, 64);
bipedLeftLeg.mirror = true;
setRotation(bipedLeftLeg, 0F, 0F, 0F);
bipedLeftLeg.mirror = false;
bipedBody = new ModelRenderer(this, 0, 16);
bipedBody.addBox(0F, 0F, 0F, 8, 12, 4);
bipedBody.setRotationPoint(-4F, 0F, -2F);
bipedBody.setTextureSize(64, 64);
bipedBody.mirror = true;
setRotation(bipedBody, 0F, 0F, 0F);
bipedLeftArm.mirror = true;
bipedLeftArm = new ModelRenderer(this, 48, 0);
bipedLeftArm.addBox(-1F, 0F, -2F, 4, 12, 4);
bipedLeftArm.setRotationPoint(4F, 0F, 0F);
bipedLeftArm.setTextureSize(64, 64);
bipedLeftArm.mirror = true;
setRotation(bipedLeftArm, 0F, 0F, 0F);
bipedLeftArm.mirror = false;
bipedRightArm = new ModelRenderer(this, 48, 0);
bipedRightArm.addBox(-3F, 0F, -2F, 4, 12, 4);
bipedRightArm.setRotationPoint(-4F, 0F, 0F);
bipedRightArm.setTextureSize(64, 64);
bipedRightArm.mirror = true;
setRotation(bipedRightArm, 0F, 0F, 0F);
bipedHead = new ModelRenderer(this, 0, 0);
bipedHead.addBox(-4F, -8F, -4F, 8, 8, 8);
bipedHead.setRotationPoint(0F, 0F, 0F);
bipedHead.setTextureSize(64, 64);
bipedHead.mirror = true;
setRotation(bipedHead, 0F, 0F, 0F);
*/
Shape5 = new ModelRenderer(this, 0, 51);
Shape5.addBox(0F, 0F, 0F, 12, 1, 12);
Shape5.setRotationPoint(-6F, -7F, -6F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, 0F, 0F, 0F);
Shape8 = new ModelRenderer(this, 0, 32);
Shape8.addBox(0F, 0F, 0F, 6, 1, 6);
Shape8.setRotationPoint(-3F, -9F, -3F);
Shape8.setTextureSize(64, 64);
Shape8.mirror = true;
setRotation(Shape8, -0.0349066F, 0F, 0F);
Shape9 = new ModelRenderer(this, 24, 32);
Shape9.addBox(0F, 0F, 0F, 3, 3, 3);
Shape9.setRotationPoint(-1.5F, -13F, -0.5F);
Shape9.setTextureSize(64, 64);
Shape9.mirror = true;
setRotation(Shape9, -0.2511622F, 0F, 0F);
Shape10 = new ModelRenderer(this, 0, 39);
Shape10.addBox(0F, 0F, 0F, 5, 1, 5);
Shape10.setRotationPoint(-2.5F, -10F, -2.5F);
Shape10.setTextureSize(64, 64);
Shape10.mirror = true;
setRotation(Shape10, -0.0698132F, 0F, 0F);
Shape7 = new ModelRenderer(this, 0, 45);
Shape7.addBox(0F, 0F, 0F, 4, 2, 4);
Shape7.setRotationPoint(-2F, -11F, -1.5F);
Shape7.setTextureSize(64, 64);
Shape7.mirror = true;
setRotation(Shape7, -0.1396263F, 0F, 0F);
Shape11 = new ModelRenderer(this, 20, 39);
Shape11.addBox(0F, 0F, 0F, 2, 3, 2);
Shape11.setRotationPoint(-1F, -15F, 1F);
Shape11.setTextureSize(64, 64);
Shape11.mirror = true;
setRotation(Shape11, -0.4363323F, 0F, 0F);
Shape12 = new ModelRenderer(this, 28, 39);
Shape12.addBox(0F, 0F, 0F, 1, 2, 1);
Shape12.setRotationPoint(-0.5F, -16F, 2.5F);
Shape12.setTextureSize(64, 64);
Shape12.mirror = true;
setRotation(Shape12, -0.715585F, 0F, 0F);
beard = new ModelRenderer(this, 32, 0);
beard.addBox(0F, 0F, 0F, 8, 5, 0);
beard.setRotationPoint(-4F, 0F, -4F);
beard.setTextureSize(64, 64);
beard.mirror = true;
setRotation(beard, 0F, 0F, 0F);
Shape13 = new ModelRenderer(this, 36, 16);
Shape13.addBox(4F, 0F, 2F, 8, 20, 6);
Shape13.setRotationPoint(-4F, 0F, -3F);
Shape13.setTextureSize(64, 64);
Shape13.mirror = true;
setRotation(Shape13, 0F, 0F, 0F);
// Makes head bits move with head
//bipedHead.addChild(Shape5);
bipedHead.addChild(beard);
//bipedHead.addChild(Shape7);
//bipedHead.addChild(Shape8);
//bipedHead.addChild(Shape9);
//bipedHead.addChild(Shape10);
//bipedHead.addChild(Shape11);
//bipedHead.addChild(Shape12);
// Makes cloak attached to body
//bipedBody.addChild(Shape13);
// No outer head layer
this.bipedHeadwear.isHidden = true;
}
/*
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
bipedRightLeg.render(f5);
bipedLeftLeg.render(f5);
bipedBody.render(f5);
bipedLeftArm.render(f5);
bipedRightArm.render(f5);
bipedHead.render(f5);
Shape5.render(f5);
Shape8.render(f5);
Shape9.render(f5);
Shape10.render(f5);
Shape7.render(f5);
Shape11.render(f5);
Shape12.render(f5);
Shape6.render(f5);
Shape13.render(f5);
}
*/
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
/*
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
*/
}
@@ -1,109 +1,113 @@
package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
public class ModelWizardArmour extends ModelWtfMojang {
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
ModelRenderer Shape4;
ModelRenderer Shape5;
ModelRenderer Shape6;
ModelRenderer Shape7;
ModelRenderer robe;
public ModelWizardArmour(float scale){
super(scale, 0, 64, 64);
// This is necessary to stop the head from scaling.
this.bipedHead = new ModelRenderer(this, 0, 0);
this.bipedHead.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.1f);
this.bipedHead.setRotationPoint(0.0F, 0.0F + 0, 0.0F);
Shape1 = new ModelRenderer(this, -16, 32);
Shape1.addBox(-8F, -7F, -8F, 16, 0, 16);
Shape1.setRotationPoint(0F, 0F, 0F);
Shape1.setTextureSize(64, 64);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 48);
Shape2.addBox(0F, 0F, 0F, 6, 2, 6);
Shape2.setRotationPoint(-3F, -10F, -3F);
Shape2.setTextureSize(64, 64);
Shape2.mirror = true;
setRotation(Shape2, -0.1396263F, 0F, 0F);
Shape3 = new ModelRenderer(this, 0, 56);
Shape3.addBox(0F, 0F, 0F, 5, 2, 5);
Shape3.setRotationPoint(-2.5F, -11.53333F, -2F);
Shape3.setTextureSize(64, 64);
Shape3.mirror = true;
setRotation(Shape3, -0.2443461F, 0F, 0F);
Shape4 = new ModelRenderer(this, 24, 48);
Shape4.addBox(0F, 0F, 0F, 4, 2, 4);
Shape4.setRotationPoint(-2F, -13F, -1F);
Shape4.setTextureSize(64, 64);
Shape4.mirror = true;
setRotation(Shape4, -0.4014257F, 0F, 0F);
Shape5 = new ModelRenderer(this, 24, 54);
Shape5.addBox(0F, 0F, 0F, 3, 2, 3);
Shape5.setRotationPoint(-1.5F, -14F, 0F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, -0.5759587F, 0F, 0F);
Shape6 = new ModelRenderer(this, 20, 59);
Shape6.addBox(0F, 0F, 0F, 2, 2, 2);
Shape6.setRotationPoint(-1F, -14F, 0F);
Shape6.setTextureSize(64, 64);
Shape6.mirror = true;
setRotation(Shape6, 0.3316126F, 0F, 0F);
Shape7 = new ModelRenderer(this, 28, 59);
Shape7.addBox(0F, 0F, 0F, 1, 1, 3);
Shape7.setRotationPoint(-0.5F, -14.5F, 2F);
Shape7.setTextureSize(64, 64);
Shape7.mirror = true;
setRotation(Shape7, -0.5585054F, 0F, 0F);
// The robe is now the body
bipedBody = new ModelRenderer(this, 40, 42);
bipedBody.addBox(-4F, 0F, -2F, 8, 18, 4, scale);
bipedBody.setRotationPoint(0F, 0F, 0F);
bipedBody.setTextureSize(64, 64);
bipedBody.mirror = true;
setRotation(bipedBody, 0F, 0F, 0F);
// Makes the hat rotate with the head.
bipedHead.addChild(Shape1);
bipedHead.addChild(Shape2);
bipedHead.addChild(Shape3);
bipedHead.addChild(Shape4);
bipedHead.addChild(Shape5);
bipedHead.addChild(Shape6);
bipedHead.addChild(Shape7);
// Makes the robe move with the body
// bipedBody.addChild(robe);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
private void setRotation(ModelRenderer model, float x, float y, float z){
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity){
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
public class ModelWizardArmour extends ModelBiped
{
ModelRenderer Shape1;
ModelRenderer Shape2;
ModelRenderer Shape3;
ModelRenderer Shape4;
ModelRenderer Shape5;
ModelRenderer Shape6;
ModelRenderer Shape7;
ModelRenderer robe;
public ModelWizardArmour(float scale){
super(scale, 0, 64, 64);
// This is necessary to stop the head from scaling.
this.bipedHead = new ModelRenderer(this, 0, 0);
this.bipedHead.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.1f);
this.bipedHead.setRotationPoint(0.0F, 0.0F + 0, 0.0F);
Shape1 = new ModelRenderer(this, -16, 32);
Shape1.addBox(-8F, -7F, -8F, 16, 0, 16);
Shape1.setRotationPoint(0F, 0F, 0F);
Shape1.setTextureSize(64, 64);
Shape1.mirror = true;
setRotation(Shape1, 0F, 0F, 0F);
Shape2 = new ModelRenderer(this, 0, 48);
Shape2.addBox(0F, 0F, 0F, 6, 2, 6);
Shape2.setRotationPoint(-3F, -10F, -3F);
Shape2.setTextureSize(64, 64);
Shape2.mirror = true;
setRotation(Shape2, -0.1396263F, 0F, 0F);
Shape3 = new ModelRenderer(this, 0, 56);
Shape3.addBox(0F, 0F, 0F, 5, 2, 5);
Shape3.setRotationPoint(-2.5F, -11.53333F, -2F);
Shape3.setTextureSize(64, 64);
Shape3.mirror = true;
setRotation(Shape3, -0.2443461F, 0F, 0F);
Shape4 = new ModelRenderer(this, 24, 48);
Shape4.addBox(0F, 0F, 0F, 4, 2, 4);
Shape4.setRotationPoint(-2F, -13F, -1F);
Shape4.setTextureSize(64, 64);
Shape4.mirror = true;
setRotation(Shape4, -0.4014257F, 0F, 0F);
Shape5 = new ModelRenderer(this, 24, 54);
Shape5.addBox(0F, 0F, 0F, 3, 2, 3);
Shape5.setRotationPoint(-1.5F, -14F, 0F);
Shape5.setTextureSize(64, 64);
Shape5.mirror = true;
setRotation(Shape5, -0.5759587F, 0F, 0F);
Shape6 = new ModelRenderer(this, 20, 59);
Shape6.addBox(0F, 0F, 0F, 2, 2, 2);
Shape6.setRotationPoint(-1F, -14F, 0F);
Shape6.setTextureSize(64, 64);
Shape6.mirror = true;
setRotation(Shape6, 0.3316126F, 0F, 0F);
Shape7 = new ModelRenderer(this, 28, 59);
Shape7.addBox(0F, 0F, 0F, 1, 1, 3);
Shape7.setRotationPoint(-0.5F, -14.5F, 2F);
Shape7.setTextureSize(64, 64);
Shape7.mirror = true;
setRotation(Shape7, -0.5585054F, 0F, 0F);
robe = new ModelRenderer(this, 40, 42);
robe.addBox(-4F, 0F, -2F, 8, 18, 4, scale);
robe.setRotationPoint(0F, 0F, 0F);
robe.setTextureSize(64, 64);
robe.mirror = true;
setRotation(robe, 0F, 0F, 0F);
// Makes the hat rotate with the head.
bipedHead.addChild(Shape1);
bipedHead.addChild(Shape2);
bipedHead.addChild(Shape3);
bipedHead.addChild(Shape4);
bipedHead.addChild(Shape5);
bipedHead.addChild(Shape6);
bipedHead.addChild(Shape7);
// Makes the robe move with the body
bipedBody.addChild(robe);
}
public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5)
{
super.render(entity, f, f1, f2, f3, f4, f5);
setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
private void setRotation(ModelRenderer model, float x, float y, float z)
{
model.rotateAngleX = x;
model.rotateAngleY = y;
model.rotateAngleZ = z;
}
public void setRotationAngles(float f, float f1, float f2, float f3, float f4, float f5, Entity entity)
{
super.setRotationAngles(f, f1, f2, f3, f4, f5, entity);
}
}
@@ -1,44 +0,0 @@
package electroblob.wizardry.client.model;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityArmorStand;
public class ModelWtfMojang extends ModelBiped {
public ModelWtfMojang(float modelSize, float rotationYOffset, int textureWidth, int textureHeight) {
super(modelSize, rotationYOffset, textureWidth, textureHeight);
}
@Override
public void setRotationAngles(float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, Entity entityIn) {
// [VanillaCopy] ModelArmorStandArmor
// this prevents helmets from always facing south, and the armor "breathing" on the stand
if (entityIn instanceof EntityArmorStand) {
EntityArmorStand entityarmorstand = (EntityArmorStand) entityIn;
this.bipedHead.rotateAngleX = 0.017453292F * entityarmorstand.getHeadRotation().getX();
this.bipedHead.rotateAngleY = 0.017453292F * entityarmorstand.getHeadRotation().getY();
this.bipedHead.rotateAngleZ = 0.017453292F * entityarmorstand.getHeadRotation().getZ();
this.bipedHead.setRotationPoint(0.0F, 1.0F, 0.0F);
this.bipedBody.rotateAngleX = 0.017453292F * entityarmorstand.getBodyRotation().getX();
this.bipedBody.rotateAngleY = 0.017453292F * entityarmorstand.getBodyRotation().getY();
this.bipedBody.rotateAngleZ = 0.017453292F * entityarmorstand.getBodyRotation().getZ();
this.bipedLeftArm.rotateAngleX = 0.017453292F * entityarmorstand.getLeftArmRotation().getX();
this.bipedLeftArm.rotateAngleY = 0.017453292F * entityarmorstand.getLeftArmRotation().getY();
this.bipedLeftArm.rotateAngleZ = 0.017453292F * entityarmorstand.getLeftArmRotation().getZ();
this.bipedRightArm.rotateAngleX = 0.017453292F * entityarmorstand.getRightArmRotation().getX();
this.bipedRightArm.rotateAngleY = 0.017453292F * entityarmorstand.getRightArmRotation().getY();
this.bipedRightArm.rotateAngleZ = 0.017453292F * entityarmorstand.getRightArmRotation().getZ();
this.bipedLeftLeg.rotateAngleX = 0.017453292F * entityarmorstand.getLeftLegRotation().getX();
this.bipedLeftLeg.rotateAngleY = 0.017453292F * entityarmorstand.getLeftLegRotation().getY();
this.bipedLeftLeg.rotateAngleZ = 0.017453292F * entityarmorstand.getLeftLegRotation().getZ();
this.bipedLeftLeg.setRotationPoint(1.9F, 11.0F, 0.0F);
this.bipedRightLeg.rotateAngleX = 0.017453292F * entityarmorstand.getRightLegRotation().getX();
this.bipedRightLeg.rotateAngleY = 0.017453292F * entityarmorstand.getRightLegRotation().getY();
this.bipedRightLeg.rotateAngleZ = 0.017453292F * entityarmorstand.getRightLegRotation().getZ();
this.bipedRightLeg.setRotationPoint(-1.9F, 11.0F, 0.0F);
copyModelAngles(this.bipedHead, this.bipedHeadwear);
} else super.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scaleFactor, entityIn);
}
}
@@ -1,198 +0,0 @@
package electroblob.wizardry.client.model;
import electroblob.wizardry.registry.WizardryBlocks;
import electroblob.wizardry.registry.WizardryItems;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.NonNullList;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
/**
* Class responsible for registering all of wizardry's item (and itemblock) models.
*
* @author Electroblob
* @since Wizardry 2.1
*/
@SideOnly(Side.CLIENT)
@Mod.EventBusSubscriber(Side.CLIENT)
public final class WizardryItemModels {
@SubscribeEvent
public static void register(ModelRegistryEvent event){
// ItemBlocks
registerItemModel(Item.getItemFromBlock(WizardryBlocks.arcane_workbench));
registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_ore));
registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_flower));
registerItemModel(Item.getItemFromBlock(WizardryBlocks.transportation_stone));
registerItemModel(Item.getItemFromBlock(WizardryBlocks.crystal_block));
// Items
registerItemModel(WizardryItems.magic_crystal);
registerItemModel(WizardryItems.magic_wand);
registerItemModel(WizardryItems.apprentice_wand);
registerItemModel(WizardryItems.advanced_wand);
registerItemModel(WizardryItems.master_wand);
registerItemModel(WizardryItems.spell_book);
// Wildcard registered for wizard trades.
registerItemModel(WizardryItems.spell_book, OreDictionary.WILDCARD_VALUE, "normal");
registerItemModel(WizardryItems.arcane_tome);
registerItemModel(WizardryItems.wizard_handbook);
registerItemModel(WizardryItems.basic_fire_wand);
registerItemModel(WizardryItems.basic_ice_wand);
registerItemModel(WizardryItems.basic_lightning_wand);
registerItemModel(WizardryItems.basic_necromancy_wand);
registerItemModel(WizardryItems.basic_earth_wand);
registerItemModel(WizardryItems.basic_sorcery_wand);
registerItemModel(WizardryItems.basic_healing_wand);
registerItemModel(WizardryItems.apprentice_fire_wand);
registerItemModel(WizardryItems.apprentice_ice_wand);
registerItemModel(WizardryItems.apprentice_lightning_wand);
registerItemModel(WizardryItems.apprentice_necromancy_wand);
registerItemModel(WizardryItems.apprentice_earth_wand);
registerItemModel(WizardryItems.apprentice_sorcery_wand);
registerItemModel(WizardryItems.apprentice_healing_wand);
registerItemModel(WizardryItems.advanced_fire_wand);
registerItemModel(WizardryItems.advanced_ice_wand);
registerItemModel(WizardryItems.advanced_lightning_wand);
registerItemModel(WizardryItems.advanced_necromancy_wand);
registerItemModel(WizardryItems.advanced_earth_wand);
registerItemModel(WizardryItems.advanced_sorcery_wand);
registerItemModel(WizardryItems.advanced_healing_wand);
registerItemModel(WizardryItems.master_fire_wand);
registerItemModel(WizardryItems.master_ice_wand);
registerItemModel(WizardryItems.master_lightning_wand);
registerItemModel(WizardryItems.master_necromancy_wand);
registerItemModel(WizardryItems.master_earth_wand);
registerItemModel(WizardryItems.master_sorcery_wand);
registerItemModel(WizardryItems.master_healing_wand);
registerItemModel(WizardryItems.spectral_sword);
registerItemModel(WizardryItems.spectral_pickaxe);
registerItemModel(WizardryItems.spectral_bow);
registerItemModel(WizardryItems.mana_flask);
registerItemModel(WizardryItems.storage_upgrade);
registerItemModel(WizardryItems.siphon_upgrade);
registerItemModel(WizardryItems.condenser_upgrade);
registerItemModel(WizardryItems.range_upgrade);
registerItemModel(WizardryItems.duration_upgrade);
registerItemModel(WizardryItems.cooldown_upgrade);
registerItemModel(WizardryItems.blast_upgrade);
registerItemModel(WizardryItems.attunement_upgrade);
registerItemModel(WizardryItems.flaming_axe);
registerItemModel(WizardryItems.frost_axe);
registerItemModel(WizardryItems.firebomb);
registerItemModel(WizardryItems.poison_bomb);
registerItemModel(WizardryItems.blank_scroll);
registerItemModel(WizardryItems.scroll);
registerItemModel(WizardryItems.armour_upgrade);
registerItemModel(WizardryItems.magic_silk);
registerItemModel(WizardryItems.wizard_hat);
registerItemModel(WizardryItems.wizard_robe);
registerItemModel(WizardryItems.wizard_leggings);
registerItemModel(WizardryItems.wizard_boots);
registerItemModel(WizardryItems.wizard_hat_fire);
registerItemModel(WizardryItems.wizard_robe_fire);
registerItemModel(WizardryItems.wizard_leggings_fire);
registerItemModel(WizardryItems.wizard_boots_fire);
registerItemModel(WizardryItems.wizard_hat_ice);
registerItemModel(WizardryItems.wizard_robe_ice);
registerItemModel(WizardryItems.wizard_leggings_ice);
registerItemModel(WizardryItems.wizard_boots_ice);
registerItemModel(WizardryItems.wizard_hat_lightning);
registerItemModel(WizardryItems.wizard_robe_lightning);
registerItemModel(WizardryItems.wizard_leggings_lightning);
registerItemModel(WizardryItems.wizard_boots_lightning);
registerItemModel(WizardryItems.wizard_hat_necromancy);
registerItemModel(WizardryItems.wizard_robe_necromancy);
registerItemModel(WizardryItems.wizard_leggings_necromancy);
registerItemModel(WizardryItems.wizard_boots_necromancy);
registerItemModel(WizardryItems.wizard_hat_earth);
registerItemModel(WizardryItems.wizard_robe_earth);
registerItemModel(WizardryItems.wizard_leggings_earth);
registerItemModel(WizardryItems.wizard_boots_earth);
registerItemModel(WizardryItems.wizard_hat_sorcery);
registerItemModel(WizardryItems.wizard_robe_sorcery);
registerItemModel(WizardryItems.wizard_leggings_sorcery);
registerItemModel(WizardryItems.wizard_boots_sorcery);
registerItemModel(WizardryItems.wizard_hat_healing);
registerItemModel(WizardryItems.wizard_robe_healing);
registerItemModel(WizardryItems.wizard_leggings_healing);
registerItemModel(WizardryItems.wizard_boots_healing);
registerItemModel(WizardryItems.spectral_helmet);
registerItemModel(WizardryItems.spectral_chestplate);
registerItemModel(WizardryItems.spectral_leggings);
registerItemModel(WizardryItems.spectral_boots);
registerItemModel(WizardryItems.smoke_bomb);
registerItemModel(WizardryItems.identification_scroll);
}
// Moved from the proxies
/**
* Registers an item model, using the item's registry name as the model name (this convention makes it easier to
* keep track of everything). Variant defaults to "normal". Registers the model for metadata 0 automatically, plus
* all the other metadata values that the item can take, as defined in
* {@link Item#getSubItems(Item, net.minecraft.creativetab.CreativeTabs, java.util.List)}. The passed in item
* <b>must</b> allow null to be passed in for the creative tab parameter in the aforementioned method, or a
* {@link NullPointerException} will result.
*/
private static void registerItemModel(Item item){
if(item.getHasSubtypes()){
NonNullList<ItemStack> items = NonNullList.create();
item.getSubItems(item.getCreativeTab(), items); // Client-only method, but we're client-side so this is OK.
for(ItemStack stack : items){
ModelLoader.setCustomModelResourceLocation(item, stack.getMetadata(),
new ModelResourceLocation(item.getRegistryName(), "inventory"));
}
}
// Changing the last parameter from null to "inventory" fixed the item/block model weirdness. No idea why!
ModelLoader.setCustomModelResourceLocation(item, 0,
new ModelResourceLocation(item.getRegistryName(), "inventory"));
}
/**
* Registers an item model for the given metadata, using the item's registry name as the model name (this convention
* makes it easier to keep track of everything). This is intended for registering additional metadata values which
* aren't displayed in the creative menu, for example the wildcard spell book used in wizard trades.
*/
private static void registerItemModel(Item item, int metadata, String variant){
ModelLoader.setCustomModelResourceLocation(item, metadata,
new ModelResourceLocation(item.getRegistryName(), variant));
}
}
@@ -0,0 +1,139 @@
package electroblob.wizardry.client.particle;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityBlizzardFX extends EntitySnowFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "blizzard";
private boolean gravity = false;
private double angle;
private double radius;
private double speed;
public EntityBlizzardFX(World world, float red, float green, float blue, int maxAge, double originX, double originZ, double radius, double yPos)
{
super(world, 0, 0, 0, 0, 0, 0, maxAge);
this.angle = this.rand.nextDouble() * Math.PI * 2;
double x = originX - Math.cos(angle)*radius;
double z = originZ + radius*Math.sin(angle);
this.radius = radius;
this.setPosition(x, yPos, z);
//this.particleScale *= 0.75F;
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
if(rand.nextBoolean()){
speed = rand.nextDouble()*2 + 1;
}else{
speed = rand.nextDouble()*-2 - 1;
}
}
public EntityBlizzardFX(World world, double x, double y, double z, double vx, double vy, double vz, float red, float green, float blue)
{
super(world, x, y, z, vx, vy, vz);
//this.particleScale *= 0.75F;
this.particleMaxAge = 48 + this.rand.nextInt(12);
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
}
public void setColour(int par1)
{
float f = (float)((par1 & 16711680) >> 16) / 255.0F;
float f1 = (float)((par1 & 65280) >> 8) / 255.0F;
float f2 = (float)((par1 & 255) >> 0) / 255.0F;
float f3 = 1.0F;
this.setRBGColorF(f * f3, f1 * f3, f2 * f3);
}
/**
* returns the bounding box for this entity
*/
public AxisAlignedBB getBoundingBox()
{
return null;
}
/**
* Returns true if this entity should push and be pushed by other entities when colliding.
*/
public boolean canBePushed()
{
return false;
}
public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7)
{
if (this.particleAge < this.particleMaxAge / 3 || (this.particleAge + this.particleMaxAge) / 3 % 2 == 0)
{
super.renderParticle(par1Tessellator, par2, par3, par4, par5, par6, par7);
}
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
// This is in radians per tick...
double omega = (Math.PI*2)/20 - speed/(20*radius);
if(speed < 0){
omega = -(Math.PI*2)/20 + speed/(20*radius);
}
// v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
this.angle += omega;
this.motionZ = radius * omega * Math.cos(angle);
this.motionX = radius * omega * Math.sin(angle);
this.moveEntity(motionX, motionY, motionZ);
if(this.gravity){
this.motionY -= 0.05d;
}
if (this.particleAge > this.particleMaxAge / 2)
{
this.setAlphaF(1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
}
/*
@Override
public int getBrightnessForRender(float par1)
{
return 15728880;
}
@Override
public float getBrightness(float par1)
{
return 1.0F;
}
*/
}
@@ -0,0 +1,93 @@
package electroblob.wizardry.client.particle;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityDarkMagicFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "darkmagic";
/** Base spell texture index */
private int baseSpellTextureIndex = 128;
public EntityDarkMagicFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float r, float g, float b)
{
super(par1World, par2, par4, par6, par8, par10, par12);
this.motionY *= 0.20000000298023224D;
this.particleRed = r;
this.particleGreen = g;
this.particleBlue = b;
this.particleScale *= 0.75F;
this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
this.noClip = true;
}
public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7)
{
float f6 = ((float)this.particleAge + par2) / (float)this.particleMaxAge * 32.0F;
if (f6 < 0.0F)
{
f6 = 0.0F;
}
if (f6 > 1.0F)
{
f6 = 1.0F;
}
super.renderParticle(par1Tessellator, par2, par3, par4, par5, par6, par7);
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.setParticleTextureIndex(this.baseSpellTextureIndex + (7 - this.particleAge * 8 / this.particleMaxAge));
this.motionY += 0.004D;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
/*
if (this.posY == this.prevPosY)
{
this.motionX *= 1.1D;
this.motionZ *= 1.1D;
}
*/
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
if (this.onGround)
{
this.motionX *= 0.699999988079071D;
this.motionZ *= 0.699999988079071D;
}
}
/**
* Sets the base spell texture index
*/
public void setBaseSpellTextureIndex(int par1)
{
this.baseSpellTextureIndex = par1;
}
}
@@ -0,0 +1,67 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.block.material.Material;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityDustFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "dust";
private final boolean shaded;
public EntityDustFX(World par1World, double x, double y, double z, double par8, double par10, double par12, float r, float g, float b, boolean shaded)
{
super(par1World, x, y, z, par8, par10, par12);
this.particleRed = r;
this.particleGreen = g;
this.particleBlue = b;
this.setParticleTextureIndex(0);
this.setSize(0.01F, 0.01F);
this.particleScale *= this.rand.nextFloat() + 0.2F;
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
this.particleMaxAge = (int)(16.0D / (Math.random() * 0.8D + 0.2D));
this.shaded = shaded;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
//this.moveEntity(this.motionX, this.motionY, this.motionZ);
if (this.particleMaxAge-- <= 0)
{
this.setDead();
}
}
@Override
public int getBrightnessForRender(float par1)
{
return shaded ? super.getBrightnessForRender(par1) : 15728880;
}
@Override
public float getBrightness(float par1)
{
return shaded ? super.getBrightness(par1) : 1.0F;
}
}
@@ -0,0 +1,199 @@
package electroblob.wizardry.client.particle;
import java.lang.reflect.Field;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityIceFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "ice";
private static final ResourceLocation iceTextures = new ResourceLocation("wizardry:textures/particle/ice_particles.png");
public EntityIceFX(World world, double x, double y, double z, double vx, double vy, double vz)
{
super(world, x, y, z, vx, vy, vz);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(rand.nextInt(8));
this.setSize(0.02F, 0.02F);
this.particleScale *= 0.75f;
this.motionX = vx;
this.motionY = vy;
this.motionZ = vz;
this.particleMaxAge = 40 + rand.nextInt(10);
this.noClip = true;
}
public EntityIceFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, int maxAge){
this(par1World, par2, par4, par6, par8, par10, par12);
this.particleMaxAge = maxAge;
this.noClip = true;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9800000190734863D;
this.motionY *= 0.9800000190734863D;
this.motionZ *= 0.9800000190734863D;
// Gravity
this.motionY -= 0.05d;
}
/* There are 4 layers of particles, specified as 0-3 by the method below.
* - Layer 0 causes the normal particles.png to be bound to the render engine for normal particles.
* - Layer 1 causes the block textures to be bound to the render engine for digging fx and falling fx.
* - Layer 2 causes the item textures to be bound to the render engine for tool breaking fx, snowballpoofs, slime particles, etc.
* - Layer 3 is not used in vanilla minecraft and was presumably added by forge for exactly this reason.
* This means no texture is bound by vanilla minecraft, meaning you are free to do as you wish without possibly
* overwriting vanilla particles. Mod particles won't be overwritten anyway since they bind their own textures.
* It is of course important to bind the texture every time you render a custom particle, but I don't see how
* you could do it any other way, since you don't have access to EffectRenderer.
*/
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
@Override
public void setParticleTextureIndex(int par1)
{
this.particleTextureIndexX = par1 % 4;
this.particleTextureIndexY = par1 / 4;
}
// Overwitten from entityfx to bind the new texture.
@Override
public void renderParticle(Tessellator tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7)
{
// Resets the tessellator and binds the new texture. Used to check if tessellator is drawing, but that field
// is no longer visible. If this results in an IllegalStateException (tessellator not drawing), look into this.
// Perhaps I could use reflection (ooooooh) to access it? Like this:
/*
Field f = null;
boolean isDrawing = false;
try {
f = tessellator.getClass().getDeclaredField("isDrawing");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
if(f != null){
f.setAccessible(true);
try {
isDrawing = (Boolean)f.get(tessellator);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if(isDrawing)*/
//tessellator.draw();
GL11.glPushMatrix();
// This stuff does the shading. The parameter does nothing apparently.
int j = this.getBrightnessForRender(0);
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)k / 1.0F, (float)l / 1.0F);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(iceTextures);
tessellator.startDrawingQuads();
float f6 = (float)this.particleTextureIndexX / 4.0F;
float f7 = f6 + 0.0624375F*4;
float f8 = (float)this.particleTextureIndexY / 4.0F;
float f9 = f8 + 0.0624375F*4;
float f10 = 0.1F * this.particleScale;
if (this.particleIcon != null)
{
f6 = this.particleIcon.getMinU();
f7 = this.particleIcon.getMaxU();
f8 = this.particleIcon.getMinV();
f9 = this.particleIcon.getMaxV();
}
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), (double)f7, (double)f9);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), (double)f7, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), (double)f6, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), (double)f6, (double)f9);
tessellator.draw();
GL11.glPopMatrix();
// Re-binds the normal particles so that the mod texture isn't on all of them
//Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation("textures/particle/particles.png"));
//tessellator.startDrawingQuads();
}
public int getBrightnessForRender(float par1)
{
return 15728880;
}
/**
* Gets how bright this entity is.
*/
public float getBrightness(float par1)
{
return 1.0F;
}
}
@@ -0,0 +1,180 @@
package electroblob.wizardry.client.particle;
import java.lang.reflect.Field;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityLeafFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "leaf";
private static final ResourceLocation leafTextures = new ResourceLocation("wizardry:textures/particle/leaf_particles.png");
public EntityLeafFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12)
{
super(par1World, par2, par4, par6, par8, par10, par12);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(rand.nextInt(16));
this.setSize(0.02F, 0.02F);
this.particleScale *= 1.4f;
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
this.particleMaxAge = 40 + rand.nextInt(10);
}
public EntityLeafFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, int maxAge){
this(par1World, par2, par4, par6, par8, par10, par12);
this.particleMaxAge = maxAge;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
if (this.particleMaxAge-- <= 0)
{
this.setDead();
}
}
/* There are 4 layers of particles, specified as 0-3 by the method below.
* - Layer 0 causes the normal particles.png to be bound to the render engine for normal particles.
* - Layer 1 causes the block textures to be bound to the render engine for digging fx and falling fx.
* - Layer 2 causes the item textures to be bound to the render engine for tool breaking fx, snowballpoofs, slime particles, etc.
* - Layer 3 is not used in vanilla minecraft and was presumably added by forge for exactly this reason.
* This means no texture is bound by vanilla minecraft, meaning you are free to do as you wish without possibly
* overwriting vanilla particles. Mod particles won't be overwritten anyway since they bind their own textures.
* It is of course important to bind the texture every time you render a custom particle, but I don't see how
* you could do it any other way, since you don't have access to EffectRenderer.
*/
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
/**
* Public method to set private field particleTextureIndex.
*/
public void setParticleTextureIndex(int par1)
{
this.particleTextureIndexX = par1 % 4;
this.particleTextureIndexY = par1 / 4;
}
// Overwitten from entityfx to bind the new texture.
@Override
public void renderParticle(Tessellator tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7)
{
// Resets the tessellator and binds the new texture. Used to check if tessellator is drawing, but that field
// is no longer visible. If this results in an IllegalStateException (tessellator not drawing), look into this.
// Perhaps I could use reflection (ooooooh) to access it? Like this:
/*
Field f = null;
boolean isDrawing = false;
try {
f = tessellator.getClass().getDeclaredField("isDrawing");
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
if(f != null){
f.setAccessible(true);
try {
isDrawing = (Boolean)f.get(tessellator);
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
if(isDrawing)*/
//tessellator.draw();
GL11.glPushMatrix();
// This stuff does the shading. The parameter does nothing apparently.
int j = this.getBrightnessForRender(0);
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)k / 1.0F, (float)l / 1.0F);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(leafTextures);
tessellator.startDrawingQuads();
float f6 = (float)this.particleTextureIndexX / 4.0F;
float f7 = f6 + 0.0624375F*4;
float f8 = (float)this.particleTextureIndexY / 4.0F;
float f9 = f8 + 0.0624375F*4;
float f10 = 0.1F * this.particleScale;
if (this.particleIcon != null)
{
f6 = this.particleIcon.getMinU();
f7 = this.particleIcon.getMaxU();
f8 = this.particleIcon.getMinV();
f9 = this.particleIcon.getMaxV();
}
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), (double)f7, (double)f9);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), (double)f7, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), (double)f6, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), (double)f6, (double)f9);
tessellator.draw();
GL11.glPopMatrix();
// Re-binds the normal particles so that the mod texture isn't on all of them
//Minecraft.getMinecraft().renderEngine.bindTexture(new ResourceLocation("textures/particle/particles.png"));
//tessellator.startDrawingQuads();
}
}
@@ -0,0 +1,52 @@
package electroblob.wizardry.client.particle;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.block.material.Material;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityMagicBubbleFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "magicbubble";
public EntityMagicBubbleFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12)
{
super(par1World, par2, par4, par6, par8, par10, par12);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(32);
this.setSize(0.02F, 0.02F);
this.particleScale *= this.rand.nextFloat() * 0.6F + 0.2F;
this.motionX = par8 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionY = par10 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionZ = par12 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.motionY += 0.002D;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.8500000238418579D;
this.motionY *= 0.8500000238418579D;
this.motionZ *= 0.8500000238418579D;
if (this.particleMaxAge-- <= 0)
{
this.setDead();
}
}
}
@@ -0,0 +1,108 @@
package electroblob.wizardry.client.particle;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityMagicFireFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "magicfire";
/** the scale of the flame FX */
private float flameScale;
public EntityMagicFireFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, int maxAge, float scale)
{
super(par1World, par2, par4, par6, par8, par10, par12);
this.motionX = this.motionX * 0.009999999776482582D + par8;
this.motionY = this.motionY * 0.009999999776482582D + par10;
this.motionZ = this.motionZ * 0.009999999776482582D + par12;
double d6 = par2 + (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.05F);
d6 = par4 + (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.05F);
d6 = par6 + (double)((this.rand.nextFloat() - this.rand.nextFloat()) * 0.05F);
this.flameScale = scale;
this.particleRed = this.particleGreen = this.particleBlue = 1.0F;
if(maxAge == 0){
this.particleMaxAge = (int)(2.0D / (Math.random() * 0.8D + 0.2D));
}else{
this.particleMaxAge = maxAge;
}
this.noClip = true;
this.setParticleTextureIndex(48);
}
public void renderParticle(Tessellator par1Tessellator, float par2, float par3, float par4, float par5, float par6, float par7)
{
float f6 = ((float)this.particleAge + par2) / (float)this.particleMaxAge;
this.particleScale = this.flameScale * (1.0F - f6 * f6 * 0.5F);
super.renderParticle(par1Tessellator, par2, par3, par4, par5, par6, par7);
}
public int getBrightnessForRender(float par1)
{
float f1 = ((float)this.particleAge + par1) / (float)this.particleMaxAge;
if (f1 < 0.0F)
{
f1 = 0.0F;
}
if (f1 > 1.0F)
{
f1 = 1.0F;
}
int i = super.getBrightnessForRender(par1);
int j = i & 255;
int k = i >> 16 & 255;
j += (int)(f1 * 15.0F * 16.0F);
if (j > 240)
{
j = 240;
}
//return j | k << 16;
return 256;
}
/**
* Gets how bright this entity is.
*/
public float getBrightness(float par1)
{
return 1.0f;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
if (this.onGround)
{
this.motionX *= 0.699999988079071D;
this.motionZ *= 0.699999988079071D;
}
}
}
@@ -0,0 +1,181 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.spell.Clairvoyance;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityPathFX extends EntityFX
{
/** The name used to identify this particle, without gravity. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "path";
private static final ResourceLocation pathTextures = new ResourceLocation("wizardry:textures/particle/path_particles.png");
private final double originX, originY, originZ;
public EntityPathFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue, int maxAge)
{
super(par1World, par2, par4, par6);
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
// Set to a constant to remove the randomness from EntityFX.
this.particleScale = 1.25F;
this.particleMaxAge = maxAge;
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
this.originX = par2;
this.originY = par4;
this.originZ = par6;
}
public EntityPathFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue)
{
super(par1World, par2, par4, par6);
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
// Set to a constant to remove the randomness from EntityFX.
this.particleScale = 1.25F;
this.particleMaxAge = 48 + this.rand.nextInt(12);
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
this.originX = par2;
this.originY = par4;
this.originZ = par6;
}
/**
* returns the bounding box for this entity
*/
public AxisAlignedBB getBoundingBox()
{
return null;
}
/**
* Returns true if this entity should push and be pushed by other entities when colliding.
*/
public boolean canBePushed()
{
return false;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
if (this.particleAge > this.particleMaxAge / 2)
{
this.setAlphaF(1.0F - 2 * (((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge));
}
if(this.particleAge % Clairvoyance.PARTICLE_MOVEMENT_INTERVAL == 0){
this.setPosition(this.originX, this.originY, this.originZ);
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
}
}
/* There are 4 layers of particles, specified as 0-3 by the method below.
* - Layer 0 causes the normal particles.png to be bound to the render engine for normal particles.
* - Layer 1 causes the block textures to be bound to the render engine for digging fx and falling fx.
* - Layer 2 causes the item textures to be bound to the render engine for tool breaking fx, snowballpoofs, slime particles, etc.
* - Layer 3 is not used in vanilla minecraft and was presumably added by forge for exactly this reason.
* This means no texture is bound by vanilla minecraft, meaning you are free to do as you wish without possibly
* overwriting vanilla particles. Mod particles won't be overwritten anyway since they bind their own textures.
* It is of course important to bind the texture every time you render a custom particle, but I don't see how
* you could do it any other way, since you don't have access to EffectRenderer.
*/
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
@Override
public void renderParticle(Tessellator tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7){
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(pathTextures);
tessellator.startDrawingQuads();
float f10 = 0.1F * this.particleScale;
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), 1, 1);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), 1, 0);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), 0, 0);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), 0, 1);
tessellator.draw();
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
@Override
public int getBrightnessForRender(float par1)
{
return 15728880;
}
@Override
public float getBrightness(float par1)
{
return 1.0F;
}
}
@@ -0,0 +1,131 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntitySnowFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "snow";
private static final ResourceLocation snowTextures = new ResourceLocation("wizardry:textures/particle/snow_particles.png");
public EntitySnowFX(World world, double x, double y, double z, double velX, double velY, double velZ)
{
super(world, x, y, z, velX, velY, velZ);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(rand.nextInt(8));
this.setSize(0.02F, 0.02F);
this.particleScale *= 0.6f;
this.motionX = velX;
this.motionY = velY;
this.motionZ = velZ;
this.particleMaxAge = 40 + rand.nextInt(10);
}
public EntitySnowFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, int maxAge){
this(par1World, par2, par4, par6, par8, par10, par12);
this.particleMaxAge = maxAge;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.moveEntity(this.motionX, this.motionY, this.motionZ);
if (this.particleMaxAge-- <= 0)
{
this.setDead();
}
}
/**
* Public method to set private field particleTextureIndex.
*/
public void setParticleTextureIndex(int par1)
{
this.particleTextureIndexX = par1 % 4;
this.particleTextureIndexY = par1 / 4;
}
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
// Overwitten from entityfx to bind the new texture.
@Override
public void renderParticle(Tessellator tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7)
{
GL11.glPushMatrix();
// This stuff does the shading. The parameter does nothing apparently.
int j = this.getBrightnessForRender(0);
int k = j % 65536;
int l = j / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)k / 1.0F, (float)l / 1.0F);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(snowTextures);
tessellator.startDrawingQuads();
float f6 = (float)this.particleTextureIndexX / 4.0F;
float f7 = f6 + 0.0624375F*4;
float f8 = (float)this.particleTextureIndexY / 4.0F;
float f9 = f8 + 0.0624375F*4;
float f10 = 0.1F * this.particleScale;
if (this.particleIcon != null)
{
f6 = this.particleIcon.getMinU();
f7 = this.particleIcon.getMaxU();
f8 = this.particleIcon.getMinV();
f9 = this.particleIcon.getMaxV();
}
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), (double)f7, (double)f9);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), (double)f7, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), (double)f6, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), (double)f6, (double)f9);
tessellator.draw();
GL11.glPopMatrix();
}
}
@@ -0,0 +1,117 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntitySparkFX extends EntityFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "spark";
private static final ResourceLocation sparkTextures = new ResourceLocation("wizardry:textures/particle/lightning_particles.png");
public EntitySparkFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12)
{
super(par1World, par2, par4, par6, par8, par10, par12);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(rand.nextInt(8));
this.setSize(0.02F, 0.02F);
this.particleScale *= 1.4f;
this.motionX = par8 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionY = par10 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionZ = par12 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.particleMaxAge = 3;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
}
/**
* Public method to set private field particleTextureIndex.
*/
public void setParticleTextureIndex(int par1)
{
this.particleTextureIndexY = par1;
}
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
// Overwitten from entityfx to bind the new texture.
@Override
public void renderParticle(Tessellator par1Tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7)
{
GL11.glPushMatrix();
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240f, 240f);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(sparkTextures);
par1Tessellator.startDrawingQuads();
// Particles are now animated using a strip of 4 from left to right.
float f6 = (float)this.particleAge / 4.0F;
float f7 = f6 + 0.0624375F*4;
float f8 = (float)this.particleTextureIndexY / 8.0f;
float f9 = f8 + 0.0624375F*2;
float f10 = 0.1F * this.particleScale;
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
par1Tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
par1Tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), (double)f7, (double)f9);
par1Tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), (double)f7, (double)f8);
par1Tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), (double)f6, (double)f8);
par1Tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), (double)f6, (double)f9);
par1Tessellator.draw();
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_BLEND);
GL11.glPopMatrix();
}
}
@@ -0,0 +1,203 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.entity.Entity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntitySparkleFX extends EntityFX
{
/** The name used to identify this particle, without gravity. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "sparkle";
/** The name used to identify this particle, with gravity. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME_GRAVITY = Wizardry.MODID + "sparkleGravity";
private static final ResourceLocation sparkleTextures = new ResourceLocation("wizardry:textures/particle/sparkle_particles.png");
private boolean gravity = false;
public EntitySparkleFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue, int maxAge)
{
super(par1World, par2, par4, par6);
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
this.particleScale *= 0.75F;
this.particleMaxAge = maxAge;
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
}
public EntitySparkleFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue)
{
super(par1World, par2, par4, par6);
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
this.particleScale *= 0.75F;
this.particleMaxAge = 48 + this.rand.nextInt(12);
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
}
public EntitySparkleFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue, boolean doGravity){
this(par1World, par2, par4, par6, par8, par10, par12, red, green, blue);
this.gravity = doGravity;
}
public EntitySparkleFX(World par1World, double par2, double par4, double par6, double par8, double par10, double par12, float red, float green, float blue, int maxAge, boolean doGravity){
this(par1World, par2, par4, par6, par8, par10, par12, red, green, blue, maxAge);
this.gravity = doGravity;
}
/**
* returns the bounding box for this entity
*/
public AxisAlignedBB getBoundingBox()
{
return null;
}
/**
* Returns true if this entity should push and be pushed by other entities when colliding.
*/
public boolean canBePushed()
{
return false;
}
@Override
public void setParticleTextureIndex(int par1)
{
this.particleTextureIndexX = par1 % 4;
this.particleTextureIndexY = par1 / 4;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
this.moveEntity(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.9800000190734863D;
this.motionY *= 0.9800000190734863D;
this.motionZ *= 0.9800000190734863D;
if(this.gravity){
this.motionY -= 0.05d;
}
if (this.particleAge > this.particleMaxAge / 2)
{
this.setAlphaF(1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
this.setParticleTextureIndex((this.particleAge * 11)/this.particleMaxAge);
}
/* There are 4 layers of particles, specified as 0-3 by the method below.
* - Layer 0 causes the normal particles.png to be bound to the render engine for normal particles.
* - Layer 1 causes the block textures to be bound to the render engine for digging fx and falling fx.
* - Layer 2 causes the item textures to be bound to the render engine for tool breaking fx, snowballpoofs, slime particles, etc.
* - Layer 3 is not used in vanilla minecraft and was presumably added by forge for exactly this reason.
* This means no texture is bound by vanilla minecraft, meaning you are free to do as you wish without possibly
* overwriting vanilla particles. Mod particles won't be overwritten anyway since they bind their own textures.
* It is of course important to bind the texture every time you render a custom particle, but I don't see how
* you could do it any other way, since you don't have access to EffectRenderer.
*/
@Override
public int getFXLayer() {
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
@Override
public void renderParticle(Tessellator tessellator, float partialTicks, float par3, float par4, float par5, float par6, float par7){
GL11.glPushMatrix();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().renderEngine.bindTexture(sparkleTextures);
tessellator.startDrawingQuads();
float f6 = (float)this.particleTextureIndexX / 4.0F;
float f7 = f6 + 0.0624375F*4;
float f8 = (float)this.particleTextureIndexY / 4.0F;
float f9 = f8 + 0.0624375F*4;
float f10 = 0.1F * this.particleScale;
if (this.particleIcon != null)
{
f6 = this.particleIcon.getMinU();
f7 = this.particleIcon.getMaxU();
f8 = this.particleIcon.getMinV();
f9 = this.particleIcon.getMaxV();
}
// Fix which gets proper values for interpPos so the particles don't appear to move.
Entity player = Minecraft.getMinecraft().thePlayer;
this.interpPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
this.interpPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
this.interpPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
float f11 = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float f12 = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float f13 = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
float f14 = 1.0F;
tessellator.setColorRGBA_F(this.particleRed * f14, this.particleGreen * f14, this.particleBlue * f14, this.particleAlpha);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 - par5 * f10 - par7 * f10), (double)f7, (double)f9);
tessellator.addVertexWithUV((double)(f11 - par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 - par5 * f10 + par7 * f10), (double)f7, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 + par6 * f10), (double)(f12 + par4 * f10), (double)(f13 + par5 * f10 + par7 * f10), (double)f6, (double)f8);
tessellator.addVertexWithUV((double)(f11 + par3 * f10 - par6 * f10), (double)(f12 - par4 * f10), (double)(f13 + par5 * f10 - par7 * f10), (double)f6, (double)f9);
tessellator.draw();
GL11.glPopMatrix();
}
@Override
public int getBrightnessForRender(float par1)
{
return 15728880;
}
@Override
public float getBrightness(float par1)
{
return 1.0F;
}
}
@@ -0,0 +1,135 @@
package electroblob.wizardry.client.particle;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import electroblob.wizardry.Wizardry;
import net.minecraft.block.Block;
import net.minecraft.client.particle.EntityDiggingFX;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.init.Blocks;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
@SideOnly(Side.CLIENT)
public class EntityTornadoFX extends EntityDiggingFX
{
/** The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would
* be any, but I may as well.) */
public static final String NAME = Wizardry.MODID + "tornado";
private boolean gravity = false;
private double angle;
private double radius;
private double speed;
private double velX, velZ;
private boolean fullBrightness = false;
public EntityTornadoFX(World world, int maxAge, double originX, double originZ, double radius, double yPos, double velX, double velZ, Block block, int metadata, int side)
{
super(world, 0, 0, 0, 0, 0, 0, block, metadata, side);
this.angle = this.rand.nextDouble() * Math.PI * 2;
double x = originX - Math.cos(angle)*radius;
double z = originZ + radius*Math.sin(angle);
this.radius = radius;
this.setPosition(x, yPos, z);
//this.particleScale *= 0.75F;
this.particleMaxAge = maxAge;
this.noClip = true;
// Grass has special treatment, since it has a colourised top but the rest is normal.
if(block != Blocks.grass || side == 1) this.setColour(block.getRenderColor(side));
if(block.getLightValue() == 0){
this.particleRed *= 0.75;
this.particleGreen *= 0.75;
this.particleBlue *= 0.75;
}else{
this.fullBrightness = true;
}
speed = rand.nextDouble()*2 + 1;
this.velX = velX;
this.velZ = velZ;
}
public EntityTornadoFX(World world, double x, double y, double z, double vx, double vy, double vz, float red, float green, float blue)
{
super(world, x, y, z, vx, vy, vz, Blocks.dirt, 0);
//this.particleScale *= 0.75F;
this.particleMaxAge = 48 + this.rand.nextInt(12);
this.noClip = true;
particleRed = red;
particleGreen = green;
particleBlue = blue;
}
public void setColour(int par1)
{
float f = (float)((par1 & 16711680) >> 16) / 255.0F;
float f1 = (float)((par1 & 65280) >> 8) / 255.0F;
float f2 = (float)((par1 & 255) >> 0) / 255.0F;
float f3 = 1.0F;
this.setRBGColorF(f * f3, f1 * f3, f2 * f3);
}
/**
* returns the bounding box for this entity
*/
public AxisAlignedBB getBoundingBox()
{
return null;
}
/**
* Returns true if this entity should push and be pushed by other entities when colliding.
*/
public boolean canBePushed()
{
return false;
}
@Override
public void onUpdate()
{
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if (this.particleAge++ >= this.particleMaxAge)
{
this.setDead();
}
// This is in radians per tick...
double omega = Math.signum(speed) * ((Math.PI*2)/20 - speed/(20*radius));
// v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
this.angle += omega;
this.motionZ = radius * omega * Math.cos(angle);
this.motionX = radius * omega * Math.sin(angle);
this.moveEntity(motionX + velX, 0, motionZ + velZ);
if(this.gravity){
this.motionY -= 0.05d;
}
if (this.particleAge > this.particleMaxAge / 2)
{
this.setAlphaF(1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
}
@Override
public int getBrightnessForRender(float par1)
{
return fullBrightness ? 15728880 : super.getBrightnessForRender(par1);
}
@Override
public float getBrightness(float par1)
{
return fullBrightness ? 1.0F : super.getBrightness(par1);
}
}
@@ -1,74 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleBlizzard extends ParticleSnow {
private double angle;
private double radius;
private double speed;
public ParticleBlizzard(World world, int maxAge, double originX, double originZ, double radius, double yPos){
super(world, 0, 0, 0, 0, 0, 0, maxAge);
this.angle = this.rand.nextDouble() * Math.PI * 2;
double x = originX - Math.cos(angle) * radius;
double z = originZ + radius * Math.sin(angle);
this.radius = radius;
this.setPosition(x, yPos, z);
this.prevPosX = x;
this.prevPosY = yPos;
this.prevPosZ = z;
if(rand.nextBoolean()){
speed = rand.nextDouble() * 2 + 1;
}else{
speed = rand.nextDouble() * -2 - 1;
}
this.multipleParticleScaleBy(1.5f);
}
@Override
public void init(){
super.init();
this.fullBrightness = true;
}
// @Override
// public void renderParticle(VertexBuffer buffer, Entity entity, float partialTicks, float rotationX, float
// rotationZ, float rotationYZ, float rotationXY, float rotationXZ){
// if(this.particleAge < this.particleMaxAge / 3 || (this.particleAge + this.particleMaxAge) / 3 % 2 == 0){
// super.renderParticle(buffer, entity, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
// }
// }
@Override
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge){
this.setExpired();
}
// This is in radians per tick...
double omega = Math.signum(speed) * ((Math.PI * 2) / 20 - speed / (20 * radius));
// v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
this.angle += omega;
this.motionY -= 0.04D * (double)this.particleGravity;
this.motionZ = radius * omega * Math.cos(angle);
this.motionX = radius * omega * Math.sin(angle);
this.move(motionX, motionY, motionZ);
if(this.particleAge > this.particleMaxAge / 2){
this.setAlphaF(
1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
}
}
@@ -1,217 +0,0 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.Minecraft;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
/**
* Abstract superclass for all particles that use custom textures. This is intended to centralise as much code as
* possible; all subclasses need to do is to define the texture to use, how the frames are arranged (and which to
* choose), and any properties like gravity and collisions.
*
* @author Electroblob
* @since Wizardry 1.2
*/
@SideOnly(Side.CLIENT)
public abstract class ParticleCustomTexture extends Particle {
/** True if the particle always renders at full brightness. Defaults to false. */
protected boolean fullBrightness = false;
public ParticleCustomTexture(World world, double x, double y, double z, double vx, double vy, double vz){
super(world, x, y, z, vx, vy, vz);
this.motionX = vx;
this.motionY = vy;
this.motionZ = vz;
this.init();
}
public ParticleCustomTexture(World world, double x, double y, double z, double vx, double vy, double vz,
int maxAge){
this(world, x, y, z, vx, vy, vz);
this.particleMaxAge = maxAge;
}
/**
* Called from both constructors to set constants, avoiding duplicate code. Common fields to set here include:
* particleScale, particleGravity, canCollide, fullBrightness and setting the texture index.
*/
public abstract void init();
/**
* Returns a ResourceLocation for the particle's texture sheet. Do not create a new ResourceLocation in this method,
* only return a constant.
*/
public abstract ResourceLocation getTexture();
/** Returns how many 'frames' there are in the x direction on the texture. */
protected abstract int getXFrames();
/** Returns how many 'frames' there are in the y direction on the texture. */
protected abstract int getYFrames();
/* There are 4 layers of particles, specified as 0-3 by the method below. - Layer 0 causes the normal particles.png
* to be bound to the render engine for normal particles. - Layer 1 causes the block textures to be bound to the
* render engine for digging fx and falling fx. - Layer 2 causes the item textures to be bound to the render engine
* for tool breaking fx, snowballpoofs, slime particles, etc. - Layer 3 is not used in vanilla minecraft and was
* presumably added by forge for exactly this reason. This means no texture is bound by vanilla minecraft, meaning
* you are free to do as you wish without possibly overwriting vanilla particles. Mod particles won't be overwritten
* anyway since they bind their own textures. It is of course important to bind the texture every time you render a
* custom particle, but I don't see how you could do it any other way, since you don't have access to
* EffectRenderer. */
@Override
public int getFXLayer(){
// This can only be 0-3 or it will cause an ArrayIndexOutOfBoundsException in EffectRenderer.
return 3;
}
@Override
public void setParticleTextureIndex(int index){
this.particleTextureIndexX = index % getXFrames();
this.particleTextureIndexY = index / getYFrames();
}
// Overridden to fix the bug with vanilla that makes particles frictionless. (y != y... seriously, Mojang?)
// TESTME: Probably no longer necessary.
// @Override
// public void move(double x, double y, double z){
//
// double d0 = y;
//
// if (this.canCollide)
// {
// List<AxisAlignedBB> list = this.world.getCollisionBoxes((Entity)null, this.getBoundingBox().addCoord(x, y, z));
//
// for (AxisAlignedBB axisalignedbb : list)
// {
// y = axisalignedbb.calculateYOffset(this.getBoundingBox(), y);
// }
//
// this.setBoundingBox(this.getBoundingBox().offset(0.0D, y, 0.0D));
//
// for (AxisAlignedBB axisalignedbb1 : list)
// {
// x = axisalignedbb1.calculateXOffset(this.getBoundingBox(), x);
// }
//
// this.setBoundingBox(this.getBoundingBox().offset(x, 0.0D, 0.0D));
//
// for (AxisAlignedBB axisalignedbb2 : list)
// {
// z = axisalignedbb2.calculateZOffset(this.getBoundingBox(), z);
// }
//
// this.setBoundingBox(this.getBoundingBox().offset(0.0D, 0.0D, z));
// }
// else
// {
// this.setBoundingBox(this.getBoundingBox().offset(x, y, z));
// }
//
// this.resetPositionToBB();
// this.onGround = d0 != y && d0 < 0.0D;
//
// /* Can never be true! - But this doesn't seem to make any difference anyway.
// if (x != x)
// {
// this.motionX = 0.0D;
// }
//
// if (z != z)
// {
// this.motionZ = 0.0D;
// }
// */
// }
// Overridden to bind the new texture. I think this can be done with TextureAtlasSprite, but this works as it is
// so I'm not changing it for the time being.
@Override
public void renderParticle(BufferBuilder buffer, Entity viewer, float partialTicks, float rotationX, float rotationZ,
float rotationYZ, float rotationXY, float rotationXZ){
GlStateManager.pushMatrix();
this.applyGLStateChanges();
// This stuff does the shading. It vanilla does this later on for each point, but this also seems to work.
int brightness = this.getBrightnessForRender(partialTicks);
int lightmapX = brightness % 65536;
int lightmapY = brightness / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)lightmapX / 1.0F,
(float)lightmapY / 1.0F);
RenderHelper.disableStandardItemLighting();
Minecraft.getMinecraft().getTextureManager().bindTexture(getTexture());
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
float u1 = (float)this.particleTextureIndexX / (float)getXFrames();
float u2 = u1 + 1.0f / getXFrames();
float v1 = (float)this.particleTextureIndexY / (float)getYFrames();
float v2 = v1 + 1.0f / getYFrames();
float scale = 0.1F * this.particleScale;
// I'm pretty sure these were always static.
Particle.interpPosX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * (double)partialTicks;
Particle.interpPosY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * (double)partialTicks;
Particle.interpPosZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * (double)partialTicks;
float x = (float)(this.prevPosX + (this.posX - this.prevPosX) * (double)partialTicks - interpPosX);
float y = (float)(this.prevPosY + (this.posY - this.prevPosY) * (double)partialTicks - interpPosY);
float z = (float)(this.prevPosZ + (this.posZ - this.prevPosZ) * (double)partialTicks - interpPosZ);
buffer.pos((double)(x - rotationX * scale - rotationXY * scale), (double)(y - rotationZ * scale),
(double)(z - rotationYZ * scale - rotationXZ * scale)).tex(u2, v2)
.color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
buffer.pos((double)(x - rotationX * scale + rotationXY * scale), (double)(y + rotationZ * scale),
(double)(z - rotationYZ * scale + rotationXZ * scale)).tex(u2, v1)
.color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
buffer.pos((double)(x + rotationX * scale + rotationXY * scale), (double)(y + rotationZ * scale),
(double)(z + rotationYZ * scale + rotationXZ * scale)).tex(u1, v1)
.color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
buffer.pos((double)(x + rotationX * scale - rotationXY * scale), (double)(y - rotationZ * scale),
(double)(z + rotationYZ * scale - rotationXZ * scale)).tex(u1, v2)
.color(particleRed, particleGreen, particleBlue, particleAlpha).endVertex();
;
Tessellator.getInstance().draw();
this.undoGLStateChanges();
GlStateManager.popMatrix();
}
/**
* Override to add any GL state changes, like blending. Does nothing by default. <b>State changes should be done
* using GLStateManager, not using GL11 directly</b> (as is the case with all rendering code now).
*/
public void applyGLStateChanges(){
}
/**
* Override to undo any GL state changes, like blending. Does nothing by default. <b>State changes should be done
* using GLStateManager, not using GL11 directly</b> (as is the case with all rendering code now).
*/
public void undoGLStateChanges(){
}
@Override
public int getBrightnessForRender(float partialTick){
return fullBrightness ? 15728880 : super.getBrightnessForRender(partialTick);
}
}
@@ -1,78 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleDarkMagic extends Particle {
/** Base spell texture index */
private int baseSpellTextureIndex = 128;
public ParticleDarkMagic(World par1World, double par2, double par4, double par6, double par8, double par10,
double par12, float r, float g, float b){
super(par1World, par2, par4, par6, par8, par10, par12);
this.motionY *= 0.20000000298023224D;
this.particleRed = r;
this.particleGreen = g;
this.particleBlue = b;
this.particleScale *= 0.75F;
this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
this.canCollide = true;
}
@Override
public void renderParticle(BufferBuilder buffer, Entity entity, float partialTicks, float rotationX, float rotationZ,
float rotationYZ, float rotationXY, float rotationXZ){
float f6 = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge * 32.0F;
if(f6 < 0.0F){
f6 = 0.0F;
}
if(f6 > 1.0F){
f6 = 1.0F;
}
super.renderParticle(buffer, entity, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge){
this.setExpired();
}
this.setParticleTextureIndex(this.baseSpellTextureIndex + (7 - this.particleAge * 8 / this.particleMaxAge));
this.motionY += 0.004D;
this.move(this.motionX, this.motionY, this.motionZ);
/* if (this.posY == this.prevPosY) { this.motionX *= 1.1D; this.motionZ *= 1.1D; } */
this.motionX *= 0.9599999785423279D;
this.motionY *= 0.9599999785423279D;
this.motionZ *= 0.9599999785423279D;
if(this.onGround){
this.motionX *= 0.699999988079071D;
this.motionZ *= 0.699999988079071D;
}
}
/**
* Sets the base spell texture index
*/
public void setBaseSpellTextureIndex(int par1){
this.baseSpellTextureIndex = par1;
}
}
@@ -1,48 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.client.particle.Particle;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleDust extends Particle {
private final boolean shaded;
public ParticleDust(World par1World, double x, double y, double z, double par8, double par10, double par12, float r,
float g, float b, boolean shaded){
super(par1World, x, y, z, par8, par10, par12);
this.particleRed = r;
this.particleGreen = g;
this.particleBlue = b;
this.setParticleTextureIndex(0);
this.setSize(0.01F, 0.01F);
this.particleScale *= this.rand.nextFloat() + 0.2F;
this.motionX = par8;
this.motionY = par10;
this.motionZ = par12;
this.particleMaxAge = (int)(16.0D / (Math.random() * 0.8D + 0.2D));
this.shaded = shaded;
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
// this.moveEntity(this.motionX, this.motionY, this.motionZ);
if(this.particleMaxAge-- <= 0){
this.setExpired();
}
}
@Override
public int getBrightnessForRender(float par1){
return shaded ? super.getBrightnessForRender(par1) : 15728880;
}
/* @Override public float getBrightness(float par1) { return shaded ? super.getBrightness(par1) : 1.0F; } */
}
@@ -1,49 +0,0 @@
package electroblob.wizardry.client.particle;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.particle.Particle;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleGiantBubble extends Particle {
/**
* The name used to identify this particle. Uses the mod id to avoid any possible conflicts (Not that there would be
* any, but I may as well.)
*/
public static final String NAME = Wizardry.MODID + "magicbubble";
public ParticleGiantBubble(World par1World, double par2, double par4, double par6, double par8, double par10,
double par12){
super(par1World, par2, par4, par6, par8, par10, par12);
this.particleRed = 1.0F;
this.particleGreen = 1.0F;
this.particleBlue = 1.0F;
this.setParticleTextureIndex(32);
this.setSize(0.02F, 0.02F);
this.particleScale *= this.rand.nextFloat() * 0.6F + 0.2F;
this.motionX = par8 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionY = par10 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.motionZ = par12 * 0.20000000298023224D + (double)((float)(Math.random() * 2.0D - 1.0D) * 0.02F);
this.particleMaxAge = (int)(8.0D / (Math.random() * 0.8D + 0.2D));
}
/**
* Called to update the entity's position/logic.
*/
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
this.motionY += 0.002D;
this.move(this.motionX, this.motionY, this.motionZ);
this.motionX *= 0.8500000238418579D;
this.motionY *= 0.8500000238418579D;
this.motionZ *= 0.8500000238418579D;
if(this.particleMaxAge-- <= 0){
this.setExpired();
}
}
}
@@ -1,46 +0,0 @@
package electroblob.wizardry.client.particle;
import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleIce extends ParticleCustomTexture {
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/ice_particles.png");
public ParticleIce(World world, double x, double y, double z, double vx, double vy, double vz){
super(world, x, y, z, vx, vy, vz);
}
public ParticleIce(World world, double x, double y, double z, double vx, double vy, double vz, int maxAge){
super(world, x, y, z, vx, vy, vz, maxAge);
}
@Override
public void init(){
this.setParticleTextureIndex(rand.nextInt(8));
this.particleScale *= 0.75f;
this.particleGravity = 1;
this.canCollide = true;
this.fullBrightness = true;
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 4;
}
@Override
protected int getYFrames(){
return 4;
}
}
@@ -1,45 +0,0 @@
package electroblob.wizardry.client.particle;
import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleLeaf extends ParticleCustomTexture {
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/leaf_particles.png");
public ParticleLeaf(World world, double x, double y, double z, double vx, double vy, double vz){
super(world, x, y, z, vx, vy, vz);
}
public ParticleLeaf(World world, double x, double y, double z, double vx, double vy, double vz, int maxAge){
super(world, x, y, z, vx, vy, vz, maxAge);
}
@Override
public void init(){
this.setParticleTextureIndex(rand.nextInt(16));
this.particleScale *= 1.4f;
this.particleGravity = 0;
this.canCollide = true;
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 4;
}
@Override
protected int getYFrames(){
return 4;
}
}
@@ -1,46 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.client.particle.Particle;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.entity.Entity;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleMagicFlame extends Particle {
/** The scale of the flame particle */
private float flameScale;
public ParticleMagicFlame(World par1World, double par2, double par4, double par6, double par8, double par10,
double par12, int maxAge, float scale){
super(par1World, par2, par4, par6, par8, par10, par12);
this.motionX = this.motionX * 0.009999999776482582D + par8;
this.motionY = this.motionY * 0.009999999776482582D + par10;
this.motionZ = this.motionZ * 0.009999999776482582D + par12;
this.flameScale = scale;
this.particleRed = this.particleGreen = this.particleBlue = 1.0F;
if(maxAge == 0){
this.particleMaxAge = (int)(2.0D / (Math.random() * 0.8D + 0.2D));
}else{
this.particleMaxAge = maxAge;
}
// IDEA: Make the particles for ray spells collide properly and not spawn on the other side of stuff.
this.canCollide = false;
this.setParticleTextureIndex(48);
}
@Override
public void renderParticle(BufferBuilder buffer, Entity entity, float partialTicks, float rotationX, float rotationZ,
float rotationYZ, float rotationXY, float rotationXZ){
float f6 = ((float)this.particleAge + partialTicks) / (float)this.particleMaxAge;
this.particleScale = this.flameScale * (1.0F - f6 * f6 * 0.5F);
super.renderParticle(buffer, entity, partialTicks, rotationX, rotationZ, rotationYZ, rotationXY, rotationXZ);
}
@Override
public int getBrightnessForRender(float par1){
return 256;
}
}
@@ -1,107 +0,0 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import electroblob.wizardry.Wizardry;
import electroblob.wizardry.spell.Clairvoyance;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticlePath extends ParticleCustomTexture {
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/path_particles.png");
private final double originX, originY, originZ;
public ParticlePath(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b){
super(world, x, y, z, vx, vy, vz);
this.setRBGColorF(r, g, b);
this.originX = x;
this.originY = y;
this.originZ = z;
}
public ParticlePath(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b, int maxAge){
super(world, x, y, z, vx, vy, vz, maxAge);
this.setRBGColorF(r, g, b);
this.originX = x;
this.originY = y;
this.originZ = z;
}
@Override
public void init(){
this.setParticleTextureIndex(0);
// Set to a constant to remove the randomness from Particle.
this.particleScale = 1.25f;
this.particleGravity = 0;
this.fullBrightness = true;
this.canCollide = false;
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 1;
}
@Override
protected int getYFrames(){
return 1;
}
@Override
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge){
this.setExpired();
}
this.move(this.motionX, this.motionY, this.motionZ);
// Fading
if(this.particleAge > this.particleMaxAge / 2){
this.setAlphaF(1.0F
- 2 * (((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge));
}
if(this.particleAge % Clairvoyance.PARTICLE_MOVEMENT_INTERVAL == 0){
this.setPosition(this.originX, this.originY, this.originZ);
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
}
}
@Override
public void applyGLStateChanges(){
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// TESTME: Are these two actually necessary?
GlStateManager.disableLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
}
@Override
public void undoGLStateChanges(){
GlStateManager.disableBlend();
GlStateManager.enableLighting();
}
}
@@ -1,61 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleRotatingSparkle extends ParticleSparkle {
private double angle;
private double radius;
private double speed;
public ParticleRotatingSparkle(World world, int maxAge, double originX, double originZ, double radius, double yPos,
float r, float g, float b){
super(world, 0, 0, 0, 0, 0, 0, r, g, b, maxAge);
this.angle = this.rand.nextDouble() * Math.PI * 2;
double x = originX - Math.cos(angle) * radius;
double z = originZ + radius * Math.sin(angle);
this.radius = radius;
this.setPosition(x, yPos, z);
this.prevPosX = x;
this.prevPosY = yPos;
this.prevPosZ = z;
if(rand.nextBoolean()){
speed = rand.nextDouble() * 2 + 1;
}else{
speed = rand.nextDouble() * -2 - 1;
}
this.multipleParticleScaleBy(1.5f);
}
@Override
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge){
this.setExpired();
}
// This is in radians per tick...
double omega = Math.signum(speed) * ((Math.PI * 2) / 20 - speed / (20 * radius));
// v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
this.angle += omega;
this.motionY -= 0.04D * (double)this.particleGravity;
this.motionZ = radius * omega * Math.cos(angle);
this.motionX = radius * omega * Math.sin(angle);
this.move(motionX, motionY, motionZ);
if(this.particleAge > this.particleMaxAge / 2){
this.setAlphaF(
1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
}
}
@@ -1,45 +0,0 @@
package electroblob.wizardry.client.particle;
import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleSnow extends ParticleCustomTexture {
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/snow_particles.png");
public ParticleSnow(World world, double x, double y, double z, double vx, double vy, double vz){
super(world, x, y, z, vx, vy, vz);
}
public ParticleSnow(World world, double x, double y, double z, double vx, double vy, double vz, int maxAge){
super(world, x, y, z, vx, vy, vz, maxAge);
}
@Override
public void init(){
this.setParticleTextureIndex(rand.nextInt(8));
this.particleScale *= 0.6f;
this.particleGravity = 0;
this.canCollide = true;
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 4;
}
@Override
protected int getYFrames(){
return 4;
}
}
@@ -1,70 +0,0 @@
package electroblob.wizardry.client.particle;
import org.lwjgl.opengl.GL11;
import electroblob.wizardry.Wizardry;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleSpark extends ParticleCustomTexture {
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/lightning_particles.png");
public ParticleSpark(World world, double x, double y, double z, double vx, double vy, double vz){
// Max age is always 3.
super(world, x, y, z, vx, vy, vz, 3);
}
@Override
public void init(){
// Multiplied by 4 because the index works slightly differently for spark particles.
this.setParticleTextureIndex(rand.nextInt(8) * 4);
this.particleScale *= 1.4f;
this.fullBrightness = true;
this.canCollide = false;
}
@Override
public void onUpdate(){
super.onUpdate();
// Well this is handy! Looks like vanilla uses the texture index like this too.
this.nextTextureIndexX();
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 4;
}
@Override
protected int getYFrames(){
return 8;
}
@Override
public void applyGLStateChanges(){
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// TESTME: Are these two actually necessary?
GlStateManager.disableLighting();
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, 240, 240);
}
@Override
public void undoGLStateChanges(){
GlStateManager.disableBlend();
GlStateManager.enableLighting();
}
}
@@ -1,111 +0,0 @@
package electroblob.wizardry.client.particle;
import electroblob.wizardry.Wizardry;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleSparkle extends ParticleCustomTexture {
/* I have now figured out what particle factories are for: they separate out the individual uses of the varargs
* parameter in spawnParticle so they are kept with the particle class. For my purposes, it would be easier to do
* that in the particle spawning method itself. */
private static final ResourceLocation TEXTURE = new ResourceLocation(Wizardry.MODID,
"textures/particle/sparkle_particles.png");
// NOTE: Uncomment once 2.1.0 is released
// private final float initialRed;
// private final float initialGreen;
// private final float initialBlue;
// TODO: Assign these via the constructors, as part of the refactoring for particle parameters.
// NOTE: Uncomment once 2.1.0 is released
// private final float fadeRed = 1;
// private final float fadeGreen = 1;
// private final float fadeBlue = 0;
public ParticleSparkle(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b){
super(world, x, y, z, vx, vy, vz);
this.setRBGColorF(r, g, b);
// NOTE: Uncomment once 2.1.0 is released
// initialRed = r;
// initialGreen = g;
// initialBlue = b;
this.particleMaxAge = 48 + this.rand.nextInt(12);
}
public ParticleSparkle(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b, int maxAge){
super(world, x, y, z, vx, vy, vz, maxAge);
this.setRBGColorF(r, g, b);
// NOTE: Uncomment once 2.1.0 is released
// initialRed = r;
// initialGreen = g;
// initialBlue = b;
}
public ParticleSparkle(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b, boolean doGravity){
this(world, x, y, z, vx, vy, vz, r, g, b);
this.particleGravity = doGravity ? 1 : 0;
}
public ParticleSparkle(World world, double x, double y, double z, double vx, double vy, double vz, float r, float g,
float b, int maxAge, boolean doGravity){
this(world, x, y, z, vx, vy, vz, r, g, b, maxAge);
this.particleGravity = doGravity ? 1 : 0;
}
@Override
public void init(){
this.setParticleTextureIndex(rand.nextInt(16));
this.particleScale *= 0.75f;
this.particleGravity = 0;
this.canCollide = false;
this.fullBrightness = true;
}
@Override
public ResourceLocation getTexture(){
return TEXTURE;
}
@Override
protected int getXFrames(){
return 4;
}
@Override
protected int getYFrames(){
return 4;
}
@Override
public void onUpdate(){
super.onUpdate();
// Fading
if(this.particleAge > this.particleMaxAge / 2){
this.setAlphaF(
1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
// Colour fading TODO Uncomment once 2.1.0 is released
// float ageFraction = (float)this.particleAge / (float)this.particleMaxAge;
// this.setRBGColorF(this.initialRed + (this.fadeRed - this.initialRed)*ageFraction,
// this.initialGreen + (this.fadeGreen - this.initialGreen)*ageFraction,
// this.initialBlue + (this.fadeBlue - this.initialBlue)*ageFraction);
this.setParticleTextureIndex((this.particleAge * 11)/this.particleMaxAge);
}
/* As a side note, I see a lot of magic mods with fancy-looking particle effects that really seem to 'glow'. It's
* actually not that hard - you simply create a reasonably high-res texture with translucency and then set the
* OpenGL blend function to something like SRC_ALPHA, SRC_ALPHA or ONE, ONE. The thing is... they're not very
* Minecraft-y. I still maintain that part of wizardry's appeal is that it stays true to the game's pixelated charm,
* rather than trying to make it something it's not. Still, the newer textures are much better than the defaults I
* used to use. */
}
@@ -1,85 +0,0 @@
package electroblob.wizardry.client.particle;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.particle.ParticleDigging;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
@SideOnly(Side.CLIENT)
public class ParticleTornado extends ParticleDigging {
private double angle;
private double radius;
private double speed;
/** Velocity of the tornado itself; in other words the velocity of the point the particle circles around. */
private double velX, velZ;
private boolean fullBrightness = false;
public ParticleTornado(World world, int maxAge, double originX, double originZ, double radius, double yPos,
double velX, double velZ, IBlockState block){
super(world, 0, 0, 0, 0, 0, 0, block);
this.angle = this.rand.nextDouble() * Math.PI * 2;
double x = originX - Math.cos(angle) * radius;
double z = originZ + radius * Math.sin(angle);
this.radius = radius;
this.setPosition(x, yPos, z);
this.prevPosX = x;
this.prevPosY = yPos;
this.prevPosZ = z;
// this.particleScale *= 0.75F;
this.particleMaxAge = maxAge;
this.canCollide = false;
// Grass has special treatment, since it has a colourised top but the rest is normal.
// Commented out for now since vanilla does something about this now, but I'm not sure what exactly
// if(block.getBlock() != Blocks.GRASS || side == 1) this.setColour(block.getRenderColor(side));
// Blocks that emit light are rendered with full brightness.
if(block.getLightValue(world, new BlockPos(this.posX, this.posY, this.posZ)) == 0){
this.particleRed *= 0.75;
this.particleGreen *= 0.75;
this.particleBlue *= 0.75;
}else{
this.fullBrightness = true;
}
speed = rand.nextDouble() * 2 + 1;
this.velX = velX;
this.velZ = velZ;
}
@Override
public void onUpdate(){
this.prevPosX = this.posX;
this.prevPosY = this.posY;
this.prevPosZ = this.posZ;
if(this.particleAge++ >= this.particleMaxAge){
this.setExpired();
}
// This is in radians per tick...
double omega = Math.signum(speed) * ((Math.PI * 2) / 20 - speed / (20 * radius));
// v = r times omega; therefore the normalised velocity vector needs to be r times the angle increment / 2 pi.
this.angle += omega;
this.motionZ = radius * omega * Math.cos(angle);
this.motionX = radius * omega * Math.sin(angle);
this.move(motionX + velX, 0, motionZ + velZ);
if(this.particleAge > this.particleMaxAge / 2){
this.setAlphaF(
1.0F - ((float)this.particleAge - (float)(this.particleMaxAge / 2)) / (float)this.particleMaxAge);
}
}
@Override
public int getBrightnessForRender(float partialTicks){
return fullBrightness ? 15728880 : super.getBrightnessForRender(partialTicks);
}
}
@@ -1,154 +0,0 @@
package electroblob.wizardry.client.renderer;
import java.util.Map.Entry;
import org.lwjgl.opengl.GL11;
import electroblob.wizardry.client.ClientProxy;
import electroblob.wizardry.spell.Petrify;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.GlStateManager.DestFactor;
import net.minecraft.client.renderer.GlStateManager.SourceFactor;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
/**
* Layer used to render the stone texture on a petrified creature. Handles dynamic tiling of the stone texture.
*
* @author Electroblob
* @since Wizardry 1.2
*/
public class LayerStone implements LayerRenderer<EntityLivingBase> {
protected ModelBase model;
private final RenderLivingBase<?> renderer;
private static final ResourceLocation texture = new ResourceLocation("textures/blocks/stone.png");
public static void initialiseLayers(){
for(Entry<Class<? extends Entity>, Render<? extends Entity>> entry : Minecraft.getMinecraft()
.getRenderManager().entityRenderMap.entrySet()){
// Because the zombie classes are now split properly, their renderers play nicely like everything else.
if(entry.getValue() instanceof RenderLivingBase){
// Adds a stone layer to all the living entity renderers in the game. Whether it is actually rendered
// is decided in doRenderLayer below on a per-entity basis.
((RenderLivingBase<?>)entry.getValue()).addLayer(new LayerStone((RenderLivingBase<?>)entry.getValue()));
}
// NOTE: May have to do some special stuff for players if they are to be added; see
// Minecraft.getMinecraft().getRenderManager().getSkinMap()
}
}
public LayerStone(RenderLivingBase<?> renderer){
this.renderer = renderer;
this.model = renderer.getMainModel();
}
@Override
public void doRenderLayer(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
float ageInTicks, float netHeadYaw, float headPitch, float scale){
if(entity.getEntityData().getBoolean(Petrify.NBT_KEY)){
GlStateManager.enableLighting();
int i = this.getBlockBrightnessForEntity(entity, partialTicks);
int j = i % 65536;
int k = i / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F);
ResourceLocation breakingTexture = ClientProxy.renderStatue.getBlockBreakingTexture();
if(breakingTexture != null){
// Block breaking animation
// TODO: Spider eyes and enderman eyes (any others?) show through the stone when the block is being
// broken...
GlStateManager.enableBlend();
GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA);
this.renderer.bindTexture(breakingTexture);
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw,
headPitch, scale);
GlStateManager.disableBlend();
}else{
// Stone texture
this.renderer.bindTexture(texture);
this.renderEntityModel(entity, limbSwing, limbSwingAmount, partialTicks, ageInTicks, netHeadYaw,
headPitch, scale);
}
}
}
private int getBlockBrightnessForEntity(Entity entity, float partialTicks){
BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(MathHelper.floor(entity.posX), 0,
MathHelper.floor(entity.posZ));
if(entity.world.isBlockLoaded(pos)){
pos.setY(MathHelper.floor(entity.posY + (double)entity.getEyeHeight()));
return entity.world.getCombinedLight(pos, 0);
}else{
return 0;
}
}
private void renderEntityModel(EntityLivingBase entity, float limbSwing, float limbSwingAmount, float partialTicks,
float ageInTicks, float netHeadYaw, float headPitch, float scale){
GlStateManager.pushMatrix();
// Enables tiling (Also used for guardian beam, beacon beam and ender crystal beam)
// TODO: Backport this improvement
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
GlStateManager.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
GlStateManager.depthMask(true); // Some entities set depth mask to false (i.e. no sorting of faces by depth)
// In particular, LayerSpiderEyes sets it to false when the spider is invisible, for some reason.
// Changes the scale at which the texture is applied to the model. See LayerCreeper for a similar example,
// but with translation instead of scaling.
// NOTE: You can do all sorts of fun stuff with this, just by applying transformations in the 2D texture space.
GlStateManager.matrixMode(GL11.GL_TEXTURE);
GlStateManager.loadIdentity();
double scaleX = 1, scaleY = 1;
// It's more logical to use the model's texture size, but some classes don't bother setting it properly
// (e.g. ModelVillager), so to get the correct dimensions I'm getting them from the first box instead.
if(model.boxList != null && model.boxList.get(0) != null){
scaleX = (double)model.boxList.get(0).textureWidth / 16d;
scaleY = (double)model.boxList.get(0).textureHeight / 16d;
}else{ // Fallback to model fields; should never be needed
scaleX = (double)model.textureWidth / 16d;
scaleY = (double)model.textureHeight / 16d;
}
GlStateManager.scale(scaleX, scaleY, 1);
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
// Hides the hat layer for bipeds
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = true;
this.model.setLivingAnimations(entity, limbSwing, limbSwingAmount, partialTicks);
this.model.render(entity, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale);
if(this.model instanceof ModelBiped) ((ModelBiped)this.model).bipedHeadwear.isHidden = false;
// Undoes the texture scaling
GlStateManager.matrixMode(GL11.GL_TEXTURE);
GlStateManager.loadIdentity();
GlStateManager.matrixMode(GL11.GL_MODELVIEW);
GlStateManager.popMatrix();
}
@Override
public boolean shouldCombineTextures(){
return false;
}
}

Some files were not shown because too many files have changed in this diff Show More