2 Commits

Author SHA1 Message Date
Christian Knaapen
346fc6d533 Fixed mouse clicks in Modifier Settings sometimes being in the wrong place.
Fixed typing in multiple text fields at once.
2019-02-28 18:25:39 +01:00
Christian Knaapen
6678405c75 Settings are saved across dimensions (including reach upgrades, issue #12).
Fixed silk touch, shearing leaves, dropping bed etc. (issue #15)
Items dont drop directly to inventory anymore because of above fix, might be re-added later.
Can no longer place blocks in entities (including the player).
Added support for changing config ingame.
Added preliminary ArchitectureCraft compatibility (places right type, not rotation yet).
Updated forge.
2019-02-14 14:57:28 +01:00
134 changed files with 2322 additions and 7373 deletions

58
.gitignore vendored
View File

@@ -1,25 +1,43 @@
# eclipse ## Based on GitHub's Eclipse .gitignore
bin
*.launch
.settings
.metadata
.classpath
.project
# idea classes/
out run/
*.ipr .gradle/
*.iws build/
gradle-app.setting
## IntelliJ IDEA
.idea/
*.iml *.iml
.idea *.iws
*.ipr
# gradle ## Eclipse
build
.gradle
# other eclipse/
eclipse *.pydevproject
run .project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# Files from Forge MDK # External tool builders
forge*changelog.txt .externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath

View File

@@ -1 +0,0 @@
The 1.12 repository can be found here: https://bitbucket.org/Requios/effortless-building/src/master/

View File

@@ -1,53 +0,0 @@
-------------------------------------------
Source installation information for modders
-------------------------------------------
This code follows the Minecraft Forge installation methodology. It will apply
some small patches to the vanilla MCP source code, giving you and it access
to some of the data and functions you need to build a successful mod.
Note also that the patches are built against "unrenamed" MCP source code (aka
srgnames) - this means that you will not be able to read them directly against
normal code.
Source pack installation information:
Standalone source installation
==============================
See the Forge Documentation online for more detailed instructions:
http://mcforge.readthedocs.io/en/latest/gettingstarted/
Step 1: Open your command-line and browse to the folder where you extracted the zip file.
Step 2: You're left with a choice.
If you prefer to use Eclipse:
1. Run the following command: "gradlew genEclipseRuns" (./gradlew genEclipseRuns if you are on Mac/Linux)
2. Open Eclipse, Import > Existing Gradle Project > Select Folder
or run "gradlew eclipse" to generate the project.
(Current Issue)
4. Open Project > Run/Debug Settings > Edit runClient and runServer > Environment
5. Edit MOD_CLASSES to show [modid]%%[Path]; 2 times rather then the generated 4.
If you prefer to use IntelliJ:
1. Open IDEA, and import project.
2. Select your build.gradle file and have it import.
3. Run the following command: "gradlew genIntellijRuns" (./gradlew genIntellijRuns if you are on Mac/Linux)
4. Refresh the Gradle Project in IDEA if required.
If at any point you are missing libraries in your IDE, or you've run into problems you can run "gradlew --refresh-dependencies" to refresh the local cache. "gradlew clean" to reset everything {this does not affect your code} and then start the processs again.
Should it still not work,
Refer to #ForgeGradle on EsperNet for more information about the gradle environment.
or the Forge Project Discord discord.gg/UvedJ9m
Forge source installation
=========================
MinecraftForge ships with this code and installs it as part of the forge
installation process, no further action is required on your part.
LexManos' Install Video
=======================
https://www.youtube.com/watch?v=8VEdtQLuLO0&feature=youtu.be
For more details update more often refer to the Forge Forums:
http://www.minecraftforge.net/forum/index.php/topic,14048.0.html

View File

@@ -1,131 +1,77 @@
buildscript { buildscript {
repositories { repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
jcenter() jcenter()
mavenCentral() maven { url = "http://files.minecraftforge.net/maven" }
} }
dependencies { dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
} }
} }
apply plugin: 'net.minecraftforge.gradle' 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. //Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = '1.13.2-2.16'
group = 'nl.requios.effortlessbuilding' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'effortlessbuilding'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. version = "1.0.3"
group = "nl.requios.effortlessbuilding" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "effortlessbuilding"
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
compileJava {
sourceCompatibility = targetCompatibility = '1.8'
}
minecraft { minecraft {
// The mappings can be changed at any time, and must be in the following format. version = "1.12.2-14.23.5.2768"
// snapshot_YYYYMMDD Snapshot are built nightly. runDir = "run"
// 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 channel: 'snapshot', version: '20180921-1.13'
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
// accessTransformer = file('build/resources/main/META-INF/accesstransformer.cfg') // the mappings can be changed at any time, and must be in the following format.
// snapshot_YYYYMMDD snapshot are built nightly.
// Default run configurations. // stable_# stables are built at the discretion of the MCP team.
// These can be tweaked, removed, or duplicated as needed. // Use non-default mappings at your own risk. they may not always work.
runs { // simply re-run your setup task after changing the mappings to update your workspace.
client { mappings = "stable_39"
workingDirectory project.file('run') // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
// Recommended logging data for a userdev environment (SCAN,REGISTRIES,REGISTRYDUMP)
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
mods {
effortlessbuilding {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment (SCAN,REGISTRIES,REGISTRYDUMP)
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
mods {
effortlessbuilding {
source sourceSets.main
}
}
}
}
} }
dependencies { dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed // you may put jars on which you depend on in ./libs
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // or you may define them like so..
// The userdev artifact is a special name and will get all sorts of transformations applied to it. //compile "some.group:artifact:version:classifier"
minecraft 'net.minecraftforge:forge:1.13.2-25.0.219' //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
// You may put jars on which you depend on in ./libs or you may define them like so.. // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
// compile "some.group:artifact:version:classifier" //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// compile "some.group:artifact:version"
// Real examples // the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env // except that these dependencies get remapped to your current MCP mappings
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
//deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. // for more info...
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// These dependencies get remapped to your current MCP mappings
// deobf '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/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html // http://www.gradle.org/docs/current/userguide/dependency_management.html
} }
// Example for how to get properties into the manifest for reading by the runtime.. processResources {
jar { // this will ensure that this task is redone when the versions change.
manifest { inputs.property "version", project.version
attributes([ inputs.property "mcversion", project.minecraft.version
"Specification-Title": "effortlessbuilding",
"Specification-Vendor": "requios",
"Specification-Version": "1", // We are version 1 of ourselves
"Implementation-Title": project.name,
"Implementation-Version": "${version}",
"Implementation-Vendor" :"requios",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
// Example configuration to allow publishing using the maven-publish task // replace stuff in mcmod.info, nothing else
// we define a custom artifact that is sourced from the reobfJar output task from(sourceSets.main.resources.srcDirs) {
// and then declare that to be published include 'mcmod.info'
// Note you'll need to add a repository here
def reobfFile = file("$buildDir/reobfJar/output.jar") // replace version and mcversion
def reobfArtifact = artifacts.add('default', reobfFile) { expand 'version':project.version, 'mcversion':project.minecraft.version
type 'jar' }
builtBy 'reobfJar'
// copy everything else except the mcmod.info
from(sourceSets.main.resources.srcDirs) {
exclude 'mcmod.info'
}
} }
publishing {
publications {
mavenJava(MavenPublication) {
artifact reobfArtifact
}
}
repositories {
maven {
url "file:///${project.projectDir}/mcmodsrepo"
}
}
}

View File

@@ -1,4 +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
org.gradle.daemon=false

Binary file not shown.

View File

@@ -1,5 +1,6 @@
#Mon Sep 14 12:28:28 PDT 2015
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip

110
gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env sh #!/usr/bin/env bash
############################################################################## ##############################################################################
## ##
@@ -6,6 +6,47 @@
## ##
############################################################################## ##############################################################################
# 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 # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" PRG="$0"
@@ -20,49 +61,9 @@ while [ -h "$PRG" ] ; do
fi fi
done done
SAVED="`pwd`" SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`" APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null cd "$SAVED" >&-
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 CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@@ -89,7 +90,7 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n` MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -113,7 +114,6 @@ fi
if $cygwin ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
@@ -154,19 +154,11 @@ if $cygwin ; then
esac esac
fi fi
# Escape application args # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
save () { function splitJvmOpts() {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done JVM_OPTS=("$@")
echo " "
} }
APP_ARGS=$(save "$@") eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# Collect all arguments for the java command, following the shell quoting and substitution rules exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
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" "$@"

14
gradlew.bat vendored
View File

@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal 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 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% 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 @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,9 +46,10 @@ echo location of your Java installation.
goto fail goto fail
:init :init
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
@@ -59,6 +60,11 @@ set _SKIP=2
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute :execute
@rem Setup the command line @rem Setup the command line

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -45,7 +45,7 @@ public class Array {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find arraysettings for the player //find arraysettings for the player
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings(); ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates; if (!isEnabled(a)) return coordinates;
BlockPos pos = startPos; BlockPos pos = startPos;
@@ -63,7 +63,7 @@ public class Array {
List<IBlockState> blockStates = new ArrayList<>(); List<IBlockState> blockStates = new ArrayList<>();
//find arraysettings for the player that placed the block //find arraysettings for the player that placed the block
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings(); ArraySettings a = BuildSettingsManager.getBuildSettings(player).getArraySettings();
if (!isEnabled(a)) return blockStates; if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos; BlockPos pos = startPos;
@@ -81,8 +81,7 @@ public class Array {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
blockState = BuildModifiers blockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
} }
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, ) //blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )

View File

@@ -1,134 +1,62 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.config.Config;
import static net.minecraftforge.common.config.Config.*;
@Config(modid = EffortlessBuilding.MODID, name = "EffortlessBuilding", type = Type.INSTANCE, category = "")
public class BuildConfig { public class BuildConfig {
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); public static Reach reach = new Reach();
public static final Reach reach = new Reach(builder); public static SurvivalBalancers survivalBalancers = new SurvivalBalancers();
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder); public static Visuals visuals = new Visuals();
public static final Visuals visuals = new Visuals(builder);
public static final ForgeConfigSpec spec = builder.build();
public static class Reach { public static class Reach {
public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades; @Comment({"Reach: how far away the player can place blocks using mirror/array etc.",
public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative; "Enable the crafting of reach upgrades to increase reach.",
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0; "If disabled, reach is set to level 3 for survival players."})
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1; public boolean enableReachUpgrades = true;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3;
public Reach(ForgeConfigSpec.Builder builder) { @Comment({"Maximum reach in creative",
builder.push("Reach"); "Keep in mind that chunks need to be loaded to be able to place blocks inside."})
enableReachUpgrades = builder public int maxReachCreative = 200;
.comment("Reach: how far away the player can place blocks using mirror/array etc.",
"Enable the crafting of reach upgrades to increase reach.",
"If disabled, reach is set to level 3 for survival players.")
.define("enableReachUpgrades", true);
maxReachCreative = builder @Comment({"Maximum reach in survival without upgrades",
.comment("Maximum reach in creative", "Reach upgrades are craftable consumables that permanently increase reach.",
"Keep in mind that chunks need to be loaded to be able to place blocks inside.") "Set to 0 to disable Effortless Building until the player has consumed a reach upgrade."})
.define("maxReachCreative", 200); public int maxReachLevel0 = 20;
maxReachLevel0 = builder @Comment("Maximum reach in survival with one upgrade")
.comment("Maximum reach in survival without upgrades", public int maxReachLevel1 = 50;
"Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
.define("maxReachLevel0", 20);
maxReachLevel1 = builder @Comment("Maximum reach in survival with two upgrades")
.comment("Maximum reach in survival with one upgrade") public int maxReachLevel2 = 100;
.define("maxReachLevel1", 50);
maxReachLevel2 = builder @Comment("Maximum reach in survival with three upgrades")
.comment("Maximum reach in survival with two upgrades") public int maxReachLevel3 = 200;
.define("maxReachLevel2", 100);
maxReachLevel3 = builder
.comment("Maximum reach in survival with three upgrades")
.define("maxReachLevel3", 200);
builder.pop();
}
} }
public static class SurvivalBalancers { public static class SurvivalBalancers {
public final ForgeConfigSpec.ConfigValue<Boolean> breakFar; @Comment({"Allows a survival player to break blocks that are far away, in addition to placing blocks.",
public final ForgeConfigSpec.ConfigValue<Boolean> increasedMiningTime; "Note: this allows insta-breaking of blocks in survival."})
public final ForgeConfigSpec.ConfigValue<Integer> miningTimePercentage; public boolean breakFar = false;
public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
public SurvivalBalancers(ForgeConfigSpec.Builder builder) { @Comment({"Increases the time to mine a block when breaking multiple at once.",
builder.push("SurvivalBalancers"); "Mining time depends on how many blocks, what type of blocks, and the percentage below.",
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian."})
public boolean increasedMiningTime = true;
breakFar = builder @Comment({"How much the mining time of each additional block counts towards an increased mining time.",
.comment("Allows a survival player to break blocks that are far away, in addition to placing blocks.", "A percentage between 0% and 100%, where 0% is the same as disabling it,",
"Note: this allows insta-breaking of blocks in survival.") "and 100% takes as much time as breaking each block individually.",
.define("breakFar", false); "The block in front of you always counts as 100%."})
@RangeInt(min = 0, max = 100)
increasedMiningTime = builder public int miningTimePercentage = 50;
.comment("Increases the time to mine a block when breaking multiple at once.",
"Mining time depends on how many blocks, what type of blocks, and the percentage below.",
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian.")
.define("increasedMiningTime", true);
miningTimePercentage = builder
.comment("How much the mining time of each additional block counts towards an increased mining time.",
"A percentage between 0% and 100%, where 0% is the same as disabling it,",
"and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%.")
.defineInRange("miningTimePercentage", 50, 0, 200);
quickReplaceMiningLevel = builder
.comment("Determines what blocks can be replaced in survival.",
"-1: only blocks that can be harvested by hand (default)",
"0: blocks that can be harvested with wooden or gold tools",
"1: blocks that can be harvested with stone tools",
"2: blocks that can be harvested with iron tools",
"3: blocks that can be harvested with diamond tools")
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
undoStackSize = builder
.comment("How many placements are remembered for the undo functionality.")
.worldRestart()
.define("undoStackSize", 10);
builder.pop();
}
} }
public static class Visuals { public static class Visuals {
public final ForgeConfigSpec.ConfigValue<Boolean> alwaysShowBlockPreview; @Comment({"Show a block preview if you have a block in hand,",
public final ForgeConfigSpec.ConfigValue<Double> dissolveTimeMultiplier; "even when mirror and array are off."})
public final ForgeConfigSpec.ConfigValue<Integer> shaderTreshold; public boolean alwaysShowBlockPreview = false;
public final ForgeConfigSpec.ConfigValue<Boolean> useShaders;
public Visuals(ForgeConfigSpec.Builder builder) {
builder.push("Visuals");
alwaysShowBlockPreview = builder
.comment("Show a block preview if you have a block in hand even in the 'Normal' build mode")
.define("alwaysShowBlockPreview", false);
dissolveTimeMultiplier = builder
.comment("How long the dissolve effect takes when placing blocks.",
"Default between 30 and 60 ticks, you can multiply that here.",
"Recommended values:",
"Snappy: 0.7",
"Relaxing: 1.5")
.define("dissolveTimeMultiplier", 1.0);
shaderTreshold = builder
.comment("Switch to using the simple performance shader when placing more than this many blocks.")
.define("shaderTreshold", 1500);
useShaders = builder
.comment("Use fancy shaders while placing blocks")
.define("useShaders", true);
builder.pop();
}
} }
} }

View File

@@ -0,0 +1,216 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.ArrayList;
import java.util.List;
public class BuildModifiers {
//Uses a network message to get the previous raytraceresult from the player
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) {
if (!message.isBlockHit() || message.getBlockPos() == null) return;
World world = player.world;
ItemRandomizerBag.renewRandomness();
BlockPos startPos = message.getBlockPos();
//Offset in direction of sidehit if not quickreplace and not replaceable
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
boolean replaceable = world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !replaceable) {
startPos = startPos.offset(message.getSideHit());
}
//Get under tall grass and other replaceable blocks
if (buildSettings.doQuickReplace() && replaceable) {
startPos = startPos.down();
}
//Check if player reach does not exceed startpos
int maxReach = ReachHelper.getMaxReach(player);
if (player.getPosition().distanceSq(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
//Format hitvec to 0.x
Vec3d hitVec = message.getHitVec();
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startPos);
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, startPos, hitVec, message.getSideHit(), itemStacks);
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//place blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) continue;
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false);
}
}
}
public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
if (event.getWorld().isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own place event if anything is enabled
if (isEnabled(buildSettings, event.getPos())) {
//EffortlessBuilding.packetHandler.sendTo(new BlockPlacedMessage(), (EntityPlayerMP) event.getPlayer());
event.setCanceled(true);
}
}
//Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos blockPos = message.getBlockPos();
if (ReachHelper.canBreakFar(player) && message.isBlockHit()) {
BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(player.world, blockPos, player.world.getBlockState(blockPos), player);
onBlockBroken(event);
}
}
public static void onBlockBroken(BlockEvent.BreakEvent event) {
World world = event.getWorld();
BlockPos pos = event.getPos();
if (world.isRemote) return;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer());
//Only use own break event if anything is enabled
if (isEnabled(buildSettings, pos)) {
//get coordinates
List<BlockPos> coordinates = findCoordinates(event.getPlayer(), pos);
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = world.getBlockState(pos).getBlockHardness(
world, pos) == 0f;
//break all those blocks
for (BlockPos coordinate : coordinates) {
if (world.isBlockLoaded(coordinate, false)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, event.getPlayer(), coordinate);
}
}
}
}
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current block being placed too
coordinates.add(startPos);
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, startPos));
coordinates.addAll(RadialMirror.findCoordinates(player, startPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
}
return coordinates;
}
public static List<IBlockState> findBlockStates(EntityPlayer player, BlockPos startPos, Vec3d hitVec, EnumFacing facing, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
itemStacks.clear();
//Get itemstack
ItemStack itemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (itemStack.isEmpty() || !(itemStack.getItem() instanceof ItemBlock || itemStack.getItem() instanceof ItemRandomizerBag)) {
itemStack = player.getHeldItem(EnumHand.OFF_HAND);
}
if (itemStack.isEmpty() || !(itemStack.getItem() instanceof ItemBlock || itemStack.getItem() instanceof ItemRandomizerBag)) {
return blockStates;
}
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
ItemRandomizerBag.resetRandomness();
if (itemStack.getItem() instanceof ItemRandomizerBag) itemBlock = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack));
IBlockState blockState = getBlockStateFromItem(itemBlock, player, startPos, facing, hitVec, EnumHand.MAIN_HAND);
//Add current block being placed too
blockStates.add(blockState);
itemStacks.add(itemStack);
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, startPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, startPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, startPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
IBlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// }
return blockStates;
}
public static boolean isEnabled(BuildSettingsManager.BuildSettings buildSettings, BlockPos startPos) {
return Mirror.isEnabled(buildSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(buildSettings.getArraySettings()) ||
RadialMirror.isEnabled(buildSettings.getRadialMirrorSettings(), startPos) ||
buildSettings.doQuickReplace();
}
public static IBlockState getBlockStateFromItem(ItemStack itemStack, EntityPlayer player, BlockPos blockPos, EnumFacing facing, Vec3d hitVec, EnumHand hand) {
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(player.world, blockPos, facing,
((float) hitVec.x), ((float) hitVec.y), ((float) hitVec.z), itemStack.getMetadata(), player, hand);
}
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
return coordinates1.equals(coordinates2);
}
}

View File

@@ -1,69 +1,51 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.BuildConfig; import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.UUID;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class ModifierSettingsManager { public class BuildSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability //Retrieves the buildsettings of a player through the buildModifierCapability capability
//Never returns null //Never returns null
@Nonnull public static BuildSettings getBuildSettings(EntityPlayer player){
public static ModifierSettings getModifierSettings(EntityPlayer player){ if (player.hasCapability(BuildModifierCapabilityManager.buildModifierCapability, null)) {
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability = BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability(
player.getCapability(ModifierCapabilityManager.modifierCapability, null); BuildModifierCapabilityManager.buildModifierCapability, null);
if (capability.getBuildModifierData() == null) {
if (modifierCapability.isPresent()) { capability.setBuildModifierData(new BuildSettings());
ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null);
if (capability.getModifierData() == null) {
capability.setModifierData(new ModifierSettings());
} }
return capability.getModifierData(); return capability.getBuildModifierData();
} }
throw new IllegalArgumentException("Player does not have buildModifierCapability capability");
//Player does not have modifierCapability capability
//Return dummy settings
return new ModifierSettings();
// throw new IllegalArgumentException("Player does not have modifierCapability capability");
} }
public static void setModifierSettings(EntityPlayer player, ModifierSettings modifierSettings) { public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) {
if (player == null) { if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null"); EffortlessBuilding.log("Cannot set buildsettings, player is null");
return; return;
} }
if (player.hasCapability(BuildModifierCapabilityManager.buildModifierCapability, null)) {
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability = BuildModifierCapabilityManager.IBuildModifierCapability capability = player.getCapability(
player.getCapability(ModifierCapabilityManager.modifierCapability, null); BuildModifierCapabilityManager.buildModifierCapability, null);
capability.setBuildModifierData(buildSettings);
modifierCapability.ifPresent((capability) -> { } else {
capability.setModifierData(modifierSettings);
});
if (!modifierCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildsettings failed."); EffortlessBuilding.log(player, "Saving buildsettings failed.");
} }
} }
public static String sanitize(ModifierSettings modifierSettings, EntityPlayer player) { public static String sanitize(BuildSettings buildSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player); int maxReach = ReachHelper.getMaxReach(player);
String error = ""; String error = "";
//Mirror settings //Mirror settings
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m.radius < 1) { if (m.radius < 1) {
m.radius = 1; m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. "; error += "Mirror size has to be at least 1. This has been corrected. ";
@@ -74,7 +56,7 @@ public class ModifierSettingsManager {
} }
//Array settings //Array settings
Array.ArraySettings a = modifierSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
if (a.count < 0) { if (a.count < 0) {
a.count = 0; a.count = 0;
error += "Array count may not be negative. It has been reset to 0."; error += "Array count may not be negative. It has been reset to 0.";
@@ -86,7 +68,7 @@ public class ModifierSettingsManager {
} }
//Radial mirror settings //Radial mirror settings
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r.slices < 2) { if (r.slices < 2) {
r.slices = 2; r.slices = 2;
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2."; error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
@@ -102,31 +84,31 @@ public class ModifierSettingsManager {
} }
//Other //Other
if (modifierSettings.reachUpgrade < 0) { if (buildSettings.reachUpgrade < 0) {
modifierSettings.reachUpgrade = 0; buildSettings.reachUpgrade = 0;
} }
if (modifierSettings.reachUpgrade > 3) { if (buildSettings.reachUpgrade > 3) {
modifierSettings.reachUpgrade = 3; buildSettings.reachUpgrade = 3;
} }
return error; return error;
} }
public static class ModifierSettings { public static class BuildSettings {
private Mirror.MirrorSettings mirrorSettings; private Mirror.MirrorSettings mirrorSettings;
private Array.ArraySettings arraySettings; private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings; private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false; private boolean quickReplace = false;
private int reachUpgrade = 0; private int reachUpgrade = 0;
public ModifierSettings() { public BuildSettings() {
mirrorSettings = new Mirror.MirrorSettings(); mirrorSettings = new Mirror.MirrorSettings();
arraySettings = new Array.ArraySettings(); arraySettings = new Array.ArraySettings();
radialMirrorSettings = new RadialMirror.RadialMirrorSettings(); radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
} }
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) { RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
this.mirrorSettings = mirrorSettings; this.mirrorSettings = mirrorSettings;
this.arraySettings = arraySettings; this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings; this.radialMirrorSettings = radialMirrorSettings;
@@ -178,31 +160,37 @@ public class ModifierSettingsManager {
public void setReachUpgrade(int reachUpgrade) { public void setReachUpgrade(int reachUpgrade) {
this.reachUpgrade = reachUpgrade; this.reachUpgrade = reachUpgrade;
//Set mirror radius to max
int reach = 10;
switch (reachUpgrade) {
case 0: reach = BuildConfig.reach.maxReachLevel0.get(); break;
case 1: reach = BuildConfig.reach.maxReachLevel1.get(); break;
case 2: reach = BuildConfig.reach.maxReachLevel2.get(); break;
case 3: reach = BuildConfig.reach.maxReachLevel3.get(); break;
}
if (this.mirrorSettings != null)
this.mirrorSettings.radius = reach / 2;
if (this.radialMirrorSettings != null)
this.radialMirrorSettings.radius = reach / 2;
} }
} }
public static void handleNewPlayer(EntityPlayer player){ @SubscribeEvent
//Makes sure player has modifier settings (if it doesnt it will create it) public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
getModifierSettings(player); EntityPlayer player = event.player;
handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
EntityPlayer player = event.player;
handleNewPlayer(player);
}
private static void handleNewPlayer(EntityPlayer player){
if (getBuildSettings(player) == null) {
setBuildSettings(player, new BuildSettings());
}
//Only on server //Only on server
if (!player.world.isRemote) { if (!player.world.isRemote) {
//Send to client //Send to client
ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player)); BuildSettingsMessage msg = new BuildSettingsMessage(getBuildSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), msg); EffortlessBuilding.packetHandler.sendTo(msg, (EntityPlayerMP) player);
} }
} }
} }

View File

@@ -3,56 +3,53 @@ package nl.requios.effortlessbuilding;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.common.config.Config;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent; import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.network.NetworkRegistry; import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach; import nl.requios.effortlessbuilding.command.CommandReach;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler; import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler;
import nl.requios.effortlessbuilding.helper.ReachConditionFactory;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade1; import nl.requios.effortlessbuilding.item.ItemReachUpgrade1;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade2; import nl.requios.effortlessbuilding.item.ItemReachUpgrade2;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade3; import nl.requios.effortlessbuilding.item.ItemReachUpgrade3;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.proxy.IProxy; import nl.requios.effortlessbuilding.proxy.IProxy;
import nl.requios.effortlessbuilding.proxy.ServerProxy;
import nl.requios.effortlessbuilding.render.ShaderHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file @Mod(modid = EffortlessBuilding.MODID, name = EffortlessBuilding.NAME, version = EffortlessBuilding.VERSION)
@Mod(EffortlessBuilding.MODID) @Mod.EventBusSubscriber
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public class EffortlessBuilding public class EffortlessBuilding
{ {
public static final String MODID = "effortlessbuilding"; public static final String MODID = "effortlessbuilding";
public static final String NAME = "Effortless Building"; public static final String NAME = "Effortless Building";
public static final String VERSION = "1.13.2-2.16"; public static final String VERSION = "1.0.3";
@Mod.Instance(EffortlessBuilding.MODID)
public static EffortlessBuilding instance; public static EffortlessBuilding instance;
public static final Logger logger = LogManager.getLogger(); public static Logger logger;
public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new); @SidedProxy(
clientSide="nl.requios.effortlessbuilding.proxy.ClientProxy",
serverSide="nl.requios.effortlessbuilding.proxy.ServerProxy"
)
public static IProxy proxy;
public static final SimpleNetworkWrapper packetHandler = NetworkRegistry.INSTANCE.newSimpleChannel(EffortlessBuilding.MODID);
public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag(); public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag();
public static final ItemReachUpgrade1 ITEM_REACH_UPGRADE_1 = new ItemReachUpgrade1(); public static final ItemReachUpgrade1 ITEM_REACH_UPGRADE_1 = new ItemReachUpgrade1();
@@ -69,76 +66,53 @@ public class EffortlessBuilding
ITEM_REACH_UPGRADE_3 ITEM_REACH_UPGRADE_3
}; };
public static final ResourceLocation RANDOMIZER_BAG_GUI = new ResourceLocation(EffortlessBuilding.MODID, "randomizer_bag"); public static final int RANDOMIZER_BAG_GUI = 0;
public EffortlessBuilding() { @EventHandler
instance = this; // preInit "Run before anything else. Read your config, create blocks, items, etc, and register them with the GameRegistry."
public void preInit(FMLPreInitializationEvent event)
// Register the setup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
// Register the enqueueIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC);
// Register the processIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
// Register the clientSetup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
//Register config
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
@SubscribeEvent
public void setup(final FMLCommonSetupEvent event)
{ {
CapabilityManager.INSTANCE.register(ModifierCapabilityManager.IModifierCapability.class, new ModifierCapabilityManager.Storage(), ModifierCapabilityManager.ModifierCapability::new); logger = event.getModLog();
CapabilityManager.INSTANCE.register(ModeCapabilityManager.IModeCapability.class, new ModeCapabilityManager.Storage(), ModeCapabilityManager.ModeCapability::new);
PacketHandler.register(); CapabilityManager.INSTANCE.register(
BuildModifierCapabilityManager.IBuildModifierCapability.class, new BuildModifierCapabilityManager.Storage(), BuildModifierCapabilityManager.BuildModifierCapability.class);
//Register recipe condition EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.SERVER);
CraftingHelper.register(new ResourceLocation(MODID, "enable_reach_upgrades"), new ReachConditionFactory()); EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.CLIENT);
//TODO 1.13 config EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.SERVER);
// ConfigManager.sync(MODID, Config.Type.INSTANCE); EffortlessBuilding.packetHandler.registerMessage(BlockPlacedMessage.MessageHandler.class, BlockPlacedMessage.class, 1, Side.CLIENT);
ModLoadingContext.get().registerExtensionPoint(ExtensionPoint.GUIFACTORY, () -> RandomizerBagGuiHandler::openGui); EffortlessBuilding.packetHandler.registerMessage(BlockBrokenMessage.MessageHandler.class, BlockBrokenMessage.class, 2, Side.SERVER);
proxy.setup(event); proxy.preInit(event);
CompatHelper.setup();
} }
@SubscribeEvent @EventHandler
public void clientSetup(final FMLClientSetupEvent event) { // Do your mod setup. Build whatever data structures you care about.
// Register network handlers
public void init(FMLInitializationEvent event)
{
ConfigManager.sync(MODID, Config.Type.INSTANCE);
NetworkRegistry.INSTANCE.registerGuiHandler(EffortlessBuilding.instance, new RandomizerBagGuiHandler());
proxy.clientSetup(event); proxy.init(event);
} }
@SubscribeEvent @EventHandler
public void enqueueIMC(final InterModEnqueueEvent event) { // postInit "Handle interaction with other mods, complete your setup based on this."
public void postInit(FMLPostInitializationEvent event)
// some example code to dispatch IMC to another mod {
// InterModComms.sendTo("examplemod", "helloworld", () -> { logger.info("Hello world from the MDK"); return "Hello world";}); proxy.postInit(event);
} }
@SubscribeEvent @EventHandler
public void processIMC(final InterModProcessEvent event) { public void serverStarting(FMLServerStartingEvent event)
{
// some example code to receive and process InterModComms from other mods event.registerServerCommand(new CommandReach());
// logger.info("Got IMC {}", event.getIMCStream(). proxy.serverStarting(event);
// map(m->m.getMessageSupplier().get()).
// collect(Collectors.toList()));
} }
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
CommandReach.register(event.getCommandDispatcher());
}
public static void log(String msg){ public static void log(String msg){
logger.info(msg); logger.info(msg);
} }

View File

@@ -1,61 +1,64 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item;
import net.minecraft.init.Blocks; import net.minecraft.item.ItemBlock;
import net.minecraft.stats.Stat;
import net.minecraft.stats.StatList;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.config.Config;
import net.minecraftforge.common.config.ConfigManager;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.capability.BuildModifierCapabilityManager;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.AddUndoMessage;
import nl.requios.effortlessbuilding.network.ClearUndoMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
import java.util.List; import java.util.List;
import static net.minecraftforge.fml.common.gameevent.PlayerEvent.*;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class EventHandler public class EventHandler
{ {
@SubscribeEvent @SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) { public static void registerBlocks(RegistryEvent.Register<Block> event)
if (event.getObject() instanceof EntityPlayer) { {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider()); event.getRegistry().registerAll(EffortlessBuilding.BLOCKS);
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider()); }
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event)
{
event.getRegistry().registerAll(EffortlessBuilding.ITEMS);
for (Block block : EffortlessBuilding.BLOCKS)
{
event.getRegistry().register(new ItemBlock(block).setRegistryName(block.getRegistryName()));
} }
} }
//TODO 1.13 config @SubscribeEvent
// @SubscribeEvent public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
// public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event) if (event.getObject() instanceof EntityPlayer) {
// { event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildModifier"), new BuildModifierCapabilityManager.Provider());
// if (event.getModID().equals(EffortlessBuilding.MODID)) }
// { }
// ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
// } @SubscribeEvent
// } public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
{
if (event.getModID().equals(EffortlessBuilding.MODID))
{
ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
}
}
// @SubscribeEvent // @SubscribeEvent
// public static void onServerTick(TickEvent.ServerTickEvent event) { // public static void onServerTick(TickEvent.ServerTickEvent event) {
@@ -63,63 +66,20 @@ public class EventHandler
// } // }
@SubscribeEvent @SubscribeEvent
//Only called serverside (except with lilypads...) public static void onBlockPlaced(BlockEvent.PlaceEvent event) {
public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) { //Still call it to cancel event
if (event.getWorld().isRemote()) return; BuildModifiers.onBlockPlaced(event);
if (!(event.getEntity() instanceof EntityPlayer)) return;
//Cancel event if necessary
EntityPlayerMP player = ((EntityPlayerMP) event.getEntity());
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL) {
event.setCanceled(true);
} else if (modifierSettings.doQuickReplace()) {
//Cancel event and send message if QuickReplace
event.setCanceled(true);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(true));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
} else {
//NORMAL mode, let vanilla handle block placing
//But modifiers should still work
//Send message to client, which sends message back with raytrace info
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(false));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
}
// Stat<ResourceLocation> blocksPlacedStat = StatList.CUSTOM.get(new ResourceLocation(EffortlessBuilding.MODID, "blocks_placed"));
// player.getStats().increment(player, blocksPlacedStat, 1);
//
// System.out.println(player.getStats().getValue(blocksPlacedStat));
} }
@SubscribeEvent @SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote()) return; BuildModifiers.onBlockBroken(event);
//Cancel event if necessary
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
//Add to undo stack in client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) event.getPlayer()), new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.getDefaultState()));
}
} }
@SubscribeEvent @SubscribeEvent
public static void breakSpeed(PlayerEvent.BreakSpeed event) { public static void breakSpeed(PlayerEvent.BreakSpeed event) {
//Disable if config says so //Disable if config says so
if (!BuildConfig.survivalBalancers.increasedMiningTime.get()) return; if (!BuildConfig.survivalBalancers.increasedMiningTime) return;
EntityPlayer player = event.getEntityPlayer(); EntityPlayer player = event.getEntityPlayer();
World world = player.world; World world = player.world;
@@ -142,7 +102,7 @@ public class EventHandler
} }
//Grabbing percentage from config //Grabbing percentage from config
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage.get() / 100; float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage / 100;
totalBlockHardness *= percentage; totalBlockHardness *= percentage;
totalBlockHardness += originalBlockHardness; totalBlockHardness += originalBlockHardness;
@@ -152,62 +112,4 @@ public class EventHandler
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed())); //EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed()));
} }
@SubscribeEvent
public static void onPlayerLoggedIn(PlayerLoggedInEvent event) {
EntityPlayer player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerLoggedOut(PlayerLoggedOutEvent event) {
EntityPlayer player = event.getPlayer();
if (player.getEntityWorld().isRemote) return;
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), new ClearUndoMessage());
}
@SubscribeEvent
public static void onPlayerRespawn(PlayerRespawnEvent event) {
EntityPlayer player = event.getPlayer();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
@SubscribeEvent
public static void onPlayerChangedDimension(PlayerChangedDimensionEvent event) {
EntityPlayer player = event.getPlayer();
if (player.getEntityWorld().isRemote) return;
//Set build mode to normal
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL);
ModeSettingsManager.setModeSettings(player, modeSettings);
//Disable modifiers
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.getMirrorSettings().enabled = false;
modifierSettings.getRadialMirrorSettings().enabled = false;
modifierSettings.getArraySettings().enabled = false;
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), new ClearUndoMessage());
}
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
//Attach capabilities on death, otherwise crash
EntityPlayer oldPlayer = event.getOriginal();
oldPlayer.revive();
EntityPlayer newPlayer = event.getEntityPlayer();
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
}
} }

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding;
import net.minecraft.block.BlockDirectional; import net.minecraft.block.BlockDirectional;
import net.minecraft.block.BlockDispenser; import net.minecraft.block.BlockDispenser;
@@ -7,8 +7,6 @@ import net.minecraft.block.BlockStairs;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -25,7 +23,7 @@ public class Mirror {
public boolean enabled = false; public boolean enabled = false;
public Vec3d position = new Vec3d(0.5, 64.5, 0.5); public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false; public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 10; public int radius = 20;
public boolean drawLines = true, drawPlanes = true; public boolean drawLines = true, drawPlanes = true;
public MirrorSettings() { public MirrorSettings() {
@@ -43,7 +41,7 @@ public class Mirror {
} }
public int getReach() { public int getReach() {
return radius * 2; //Change ModifierSettings#setReachUpgrade too return radius * 2;
} }
} }
@@ -51,7 +49,7 @@ public class Mirror {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find mirrorsettings for the player //find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings(); MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates; if (!isEnabled(m, startPos)) return coordinates;
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates); if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
@@ -91,7 +89,7 @@ public class Mirror {
List<IBlockState> blockStates = new ArrayList<>(); List<IBlockState> blockStates = new ArrayList<>();
//find mirrorsettings for the player //find mirrorsettings for the player
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings(); MirrorSettings m = BuildSettingsManager.getBuildSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates; if (!isEnabled(m, startPos)) return blockStates;
//Randomizer bag synergy //Randomizer bag synergy
@@ -120,7 +118,7 @@ public class Mirror {
} }
//Find blockstate //Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.FRONT_BACK); IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK);
//Store blockstate and itemstack //Store blockstate and itemstack
blockStates.add(newBlockState); blockStates.add(newBlockState);
@@ -165,7 +163,7 @@ public class Mirror {
} }
//Find blockstate //Find blockstate
IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.LEFT_RIGHT); IBlockState newBlockState = oldBlockState == null ? null : oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT);
//Store blockstate and itemstack //Store blockstate and itemstack
blockStates.add(newBlockState); blockStates.add(newBlockState);
@@ -187,39 +185,38 @@ public class Mirror {
private static IBlockState getVerticalMirror(IBlockState blockState) { private static IBlockState getVerticalMirror(IBlockState blockState) {
//Stairs //Stairs
if (blockState.getBlock() instanceof BlockStairs) { if (blockState.getBlock() instanceof BlockStairs) {
if (blockState.get(BlockStairs.HALF) == Half.BOTTOM) { if (blockState.getValue(BlockStairs.HALF) == BlockStairs.EnumHalf.BOTTOM) {
return blockState.with(BlockStairs.HALF, Half.TOP); return blockState.withProperty(BlockStairs.HALF, BlockStairs.EnumHalf.TOP);
} else { } else {
return blockState.with(BlockStairs.HALF, Half.BOTTOM); return blockState.withProperty(BlockStairs.HALF, BlockStairs.EnumHalf.BOTTOM);
} }
} }
//Slabs //Slabs
if (blockState.getBlock() instanceof BlockSlab) { if (blockState.getBlock() instanceof BlockSlab) {
if (blockState.get(BlockSlab.TYPE) == SlabType.DOUBLE) { if (((BlockSlab) blockState.getBlock()).isDouble()) return blockState;
return blockState; if (blockState.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
} else if (blockState.get(BlockSlab.TYPE) == SlabType.BOTTOM) { return blockState.withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.TOP);
return blockState.with(BlockSlab.TYPE, SlabType.TOP);
} else { } else {
return blockState.with(BlockSlab.TYPE, SlabType.BOTTOM); return blockState.withProperty(BlockSlab.HALF, BlockSlab.EnumBlockHalf.BOTTOM);
} }
} }
//Buttons, endrod, observer, piston //Buttons, endrod, observer, piston
if (blockState.getBlock() instanceof BlockDirectional) { if (blockState.getBlock() instanceof BlockDirectional) {
if (blockState.get(BlockDirectional.FACING) == EnumFacing.DOWN) { if (blockState.getValue(BlockDirectional.FACING) == EnumFacing.DOWN) {
return blockState.with(BlockDirectional.FACING, EnumFacing.UP); return blockState.withProperty(BlockDirectional.FACING, EnumFacing.UP);
} else if (blockState.get(BlockDirectional.FACING) == EnumFacing.UP) { } else if (blockState.getValue(BlockDirectional.FACING) == EnumFacing.UP) {
return blockState.with(BlockDirectional.FACING, EnumFacing.DOWN); return blockState.withProperty(BlockDirectional.FACING, EnumFacing.DOWN);
} }
} }
//Dispenser, dropper //Dispenser, dropper
if (blockState.getBlock() instanceof BlockDispenser) { if (blockState.getBlock() instanceof BlockDispenser) {
if (blockState.get(BlockDispenser.FACING) == EnumFacing.DOWN) { if (blockState.getValue(BlockDispenser.FACING) == EnumFacing.DOWN) {
return blockState.with(BlockDispenser.FACING, EnumFacing.UP); return blockState.withProperty(BlockDispenser.FACING, EnumFacing.UP);
} else if (blockState.get(BlockDispenser.FACING) == EnumFacing.UP) { } else if (blockState.getValue(BlockDispenser.FACING) == EnumFacing.UP) {
return blockState.with(BlockDispenser.FACING, EnumFacing.DOWN); return blockState.withProperty(BlockDispenser.FACING, EnumFacing.DOWN);
} }
} }

View File

@@ -1,30 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
// You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
// Event bus for receiving Registry Events)
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public class ModEventHandler {
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
event.getRegistry().registerAll(EffortlessBuilding.BLOCKS);
}
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event)
{
event.getRegistry().registerAll(EffortlessBuilding.ITEMS);
for (Block block : EffortlessBuilding.BLOCKS)
{
event.getRegistry().register(new ItemBlock(block, new Item.Properties()).setRegistryName(block.getRegistryName()));
}
}
}

View File

@@ -1,4 +1,4 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -48,7 +48,7 @@ public class RadialMirror {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//find radial mirror settings for the player //find radial mirror settings for the player
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings(); RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates; if (!isEnabled(r, startPos)) return coordinates;
//get angle between slices //get angle between slices
@@ -82,7 +82,7 @@ public class RadialMirror {
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block //find radial mirror settings for the player that placed the block
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings(); RadialMirrorSettings r = BuildSettingsManager.getBuildSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates; if (!isEnabled(r, startPos)) return blockStates;
@@ -123,8 +123,7 @@ public class RadialMirror {
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (bagInventory != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
newBlockState = BuildModifiers newBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
.getBlockStateFromItem(itemStack, player, startPos, EnumFacing.UP, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState); newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState);
} }
@@ -143,11 +142,11 @@ public class RadialMirror {
IBlockState newBlockState = blockState; IBlockState newBlockState = blockState;
if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) { if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180); newBlockState = blockState.withRotation(Rotation.CLOCKWISE_180);
} else if (startAngleToCenter < -0.251 * Math.PI) { } else if (startAngleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90); newBlockState = blockState.withRotation(Rotation.COUNTERCLOCKWISE_90);
} else if (startAngleToCenter > 0.249 * Math.PI) { } else if (startAngleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90); newBlockState = blockState.withRotation(Rotation.CLOCKWISE_90);
} }
return newBlockState; return newBlockState;
@@ -158,24 +157,24 @@ public class RadialMirror {
double angleToCenter = MathHelper.atan2(relVec.x, relVec.z); //between -PI and PI double angleToCenter = MathHelper.atan2(relVec.x, relVec.z); //between -PI and PI
if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) { if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180); newBlockState = blockState.withRotation(Rotation.CLOCKWISE_180);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK); newBlockState = newBlockState.withMirror(Mirror.FRONT_BACK);
} }
} else if (angleToCenter < -0.251 * Math.PI) { } else if (angleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90); newBlockState = blockState.withRotation(Rotation.CLOCKWISE_90);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT); newBlockState = newBlockState.withMirror(Mirror.LEFT_RIGHT);
} }
} else if (angleToCenter > 0.249 * Math.PI) { } else if (angleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90); newBlockState = blockState.withRotation(Rotation.COUNTERCLOCKWISE_90);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT); newBlockState = newBlockState.withMirror(Mirror.LEFT_RIGHT);
} }
} else { } else {
newBlockState = blockState; newBlockState = blockState;
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK); newBlockState = newBlockState.withMirror(Mirror.FRONT_BACK);
} }
} }

View File

@@ -1,40 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import java.util.UUID;
public abstract class BaseBuildMode implements IBuildMode {
//In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click
protected Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
protected Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
protected Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
protected Dictionary<UUID, EnumFacing> sideHitTable = new Hashtable<>();
protected Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>();
@Override
public void initialize(EntityPlayer player) {
rightClickClientTable.put(player.getUniqueID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
sideHitTable.put(player.getUniqueID(), EnumFacing.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO);
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return sideHitTable.get(player.getUniqueID());
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return hitVecTable.get(player.getUniqueID());
}
}

View File

@@ -1,245 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceFluidMode;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.buildmodes.*;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
public class BuildModes {
//Static variables are shared between client and server in singleplayer
//We need them separate
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<EntityPlayer, Boolean> currentlyBreakingServer = new Hashtable<>();
public enum BuildModeEnum {
NORMAL("effortlessbuilding.mode.normal", new Normal()),
NORMAL_PLUS("effortlessbuilding.mode.normal_plus", new NormalPlus(), OptionEnum.BUILD_SPEED),
LINE("effortlessbuilding.mode.line", new Line() /*, OptionEnum.THICKNESS*/),
WALL("effortlessbuilding.mode.wall", new Wall(), OptionEnum.FILL),
FLOOR("effortlessbuilding.mode.floor", new Floor(), OptionEnum.FILL),
DIAGONAL_LINE("effortlessbuilding.mode.diagonal_line", new DiagonalLine() /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("effortlessbuilding.mode.diagonal_wall", new DiagonalWall() /*, OptionEnum.FILL*/),
SLOPE_FLOOR("effortlessbuilding.mode.slope_floor", new SlopeFloor(), OptionEnum.RAISED_EDGE),
CIRCLE("effortlessbuilding.mode.circle", new Circle(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CYLINDER("effortlessbuilding.mode.cylinder", new Cylinder(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
SPHERE("effortlessbuilding.mode.sphere", new Sphere(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CUBE("effortlessbuilding.mode.cube", new Cube(), OptionEnum.CUBE_FILL);
public String name;
public IBuildMode instance;
public OptionEnum[] options;
BuildModeEnum(String name, IBuildMode instance, OptionEnum... options) {
this.name = name;
this.instance = instance;
this.options = options;
}
}
//Uses a network message to get the previous raytraceresult from the player
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(EntityPlayer player, BlockPlacedMessage message) {
//Check if not in the middle of breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModeEnum buildMode = modeSettings.getBuildMode();
BlockPos startPos = null;
if (message.isBlockHit() && message.getBlockPos() != null) {
startPos = message.getBlockPos();
//Offset in direction of sidehit if not quickreplace and not replaceable
//TODO 1.13 replaceable
boolean replaceable = player.world.getBlockState(startPos).getMaterial().isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, message.getSideHit());
if (!modifierSettings.doQuickReplace() && !replaceable && !becomesDoubleSlab) {
startPos = startPos.offset(message.getSideHit());
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && replaceable) {
startPos = startPos.down();
}
//Check if player reach does not exceed startpos
int maxReach = ReachHelper.getMaxReach(player);
if (buildMode != BuildModeEnum.NORMAL && player.getPosition().distanceSq(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
}
//Even when no starting block is found, call buildmode instance
//We might want to place things in the air
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, false);
return;
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (coordinates.size() > limit) {
coordinates = coordinates.subList(0, limit);
}
EnumFacing sideHit = buildMode.instance.getSideHit(player);
if (sideHit == null) sideHit = message.getSideHit();
Vec3d hitVec = buildMode.instance.getHitVec(player);
if (hitVec == null) hitVec = message.getHitVec();
BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec, message.getPlaceStartPos());
//Only works when finishing a buildmode is equal to placing some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
}
//Use a network message to break blocks in the distance using clientside mouse input
public static void onBlockBrokenMessage(EntityPlayer player, BlockBrokenMessage message) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
onBlockBroken(player, startPos, true);
}
public static void onBlockBroken(EntityPlayer player, BlockPos startPos, boolean breakStartPos) {
//Check if not in the middle of placing
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
//If first click
if (currentlyBreaking.get(player) == null) {
//If startpos is null, dont do anything
if (startPos == null) return;
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Get coordinates
BuildModeEnum buildMode = modeSettings.getBuildMode();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, EnumFacing.UP, Vec3d.ZERO, true);
if (coordinates.isEmpty()) {
currentlyBreaking.put(player, true);
return;
}
//Let buildmodifiers break blocks
BuildModifiers.onBlockBroken(player, coordinates, breakStartPos);
//Only works when finishing a buildmode is equal to breaking some blocks
//No intermediate blocks allowed
currentlyBreaking.remove(player);
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos startPos, boolean skipRaytrace) {
List<BlockPos> coordinates = new ArrayList<>();
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace));
return coordinates;
}
public static void initializeMode(EntityPlayer player) {
//Resetting mode, so not placing or breaking
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
}
public static boolean isCurrentlyPlacing(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player);
}
public static boolean isCurrentlyBreaking(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
}
//Either placing or breaking
public static boolean isActive(EntityPlayer player) {
Dictionary<EntityPlayer, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
//-- Common build mode functionality --//
//Find coordinates on a line bound by a plane
public static Vec3d findXBound(double x, Vec3d start, Vec3d look) {
//then y and z are
double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
return new Vec3d(x, y, z);
}
public static Vec3d findYBound(double y, Vec3d start, Vec3d look) {
//then x and z are
double x = (y - start.y) / look.y * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z;
return new Vec3d(x, y, z);
}
public static Vec3d findZBound(double z, Vec3d start, Vec3d look) {
//then x and y are
double x = (z - start.z) / look.z * look.x + start.x;
double y = (z - start.z) / look.z * look.y + start.y;
return new Vec3d(x, y, z);
}
public static boolean isCriteriaValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace, Vec3d lineBound, Vec3d planeBound, double distToPlayerSq) {
boolean intersects = false;
if (!skipRaytrace) {
//collision within a 1 block radius to selected is fine
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(start, lineBound, RayTraceFluidMode.NEVER, true, false);
intersects = rayTraceResult != null && rayTraceResult.type == RayTraceResult.Type.BLOCK &&
planeBound.subtract(rayTraceResult.hitVec).lengthSquared() > 4;
}
return planeBound.subtract(start).dotProduct(look) > 0 &&
distToPlayerSq > 2 && distToPlayerSq < reach * reach &&
!intersects;
}
}

View File

@@ -1,25 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.List;
public interface IBuildMode {
//Fired when a player selects a buildmode and when it needs to initializeMode
void initialize(EntityPlayer player);
//Fired when a block would be placed
//Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace);
//Fired continuously for visualization purposes
List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace);
EnumFacing getSideHit(EntityPlayer player);
Vec3d getHitVec(EntityPlayer player);
}

View File

@@ -1,182 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.text.TextFormatting;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
public class ModeOptions {
public enum ActionEnum {
UNDO("effortlessbuilding.action.undo"),
REDO("effortlessbuilding.action.redo"),
REPLACE("effortlessbuilding.action.replace"),
OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"),
NORMAL_SPEED("effortlessbuilding.action.normal_speed"),
FAST_SPEED("effortlessbuilding.action.fast_speed"),
FULL("effortlessbuilding.action.full"),
HOLLOW("effortlessbuilding.action.hollow"),
CUBE_FULL("effortlessbuilding.action.full"),
CUBE_HOLLOW("effortlessbuilding.action.hollow"),
CUBE_SKELETON("effortlessbuilding.action.skeleton"),
SHORT_EDGE("effortlessbuilding.action.short_edge"),
LONG_EDGE("effortlessbuilding.action.long_edge"),
THICKNESS_1("effortlessbuilding.action.thickness_1"),
THICKNESS_3("effortlessbuilding.action.thickness_3"),
THICKNESS_5("effortlessbuilding.action.thickness_5"),
CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"),
CIRCLE_START_CENTER("effortlessbuilding.action.start_center");
public String name;
ActionEnum(String name) {
this.name = name;
}
}
public enum OptionEnum {
BUILD_SPEED("effortlessbuilding.action.build_speed", ActionEnum.NORMAL_SPEED, ActionEnum.FAST_SPEED),
FILL("effortlessbuilding.action.filling", ActionEnum.FULL, ActionEnum.HOLLOW),
CUBE_FILL("effortlessbuilding.action.filling", ActionEnum.CUBE_FULL, ActionEnum.CUBE_HOLLOW, ActionEnum.CUBE_SKELETON),
RAISED_EDGE("effortlessbuilding.action.raised_edge", ActionEnum.SHORT_EDGE, ActionEnum.LONG_EDGE),
LINE_THICKNESS("effortlessbuilding.action.thickness", ActionEnum.THICKNESS_1, ActionEnum.THICKNESS_3, ActionEnum.THICKNESS_5),
CIRCLE_START("effortlessbuilding.action.circle_start", ActionEnum.CIRCLE_START_CORNER, ActionEnum.CIRCLE_START_CENTER);
public String name;
public ActionEnum[] actions;
OptionEnum(String name, ActionEnum... actions){
this.name = name;
this.actions = actions;
}
}
private static ActionEnum buildSpeed = ActionEnum.NORMAL_SPEED;
private static ActionEnum fill = ActionEnum.FULL;
private static ActionEnum cubeFill = ActionEnum.CUBE_FULL;
private static ActionEnum raisedEdge = ActionEnum.SHORT_EDGE;
private static ActionEnum lineThickness = ActionEnum.THICKNESS_1;
private static ActionEnum circleStart = ActionEnum.CIRCLE_START_CORNER;
public static ActionEnum getOptionSetting(OptionEnum option) {
switch (option) {
case BUILD_SPEED:
return getBuildSpeed();
case FILL:
return getFill();
case CUBE_FILL:
return getCubeFill();
case RAISED_EDGE:
return getRaisedEdge();
case LINE_THICKNESS:
return getLineThickness();
case CIRCLE_START:
return getCircleStart();
default:
return null;
}
}
public static ActionEnum getBuildSpeed() {
return buildSpeed;
}
public static ActionEnum getFill() {
return fill;
}
public static ActionEnum getCubeFill() {
return cubeFill;
}
public static ActionEnum getRaisedEdge() {
return raisedEdge;
}
public static ActionEnum getLineThickness() {
return lineThickness;
}
public static ActionEnum getCircleStart() {
return circleStart;
}
//Called on both client and server
public static void performAction(EntityPlayer player, ActionEnum action) {
if (action == null) return;
switch (action) {
case UNDO:
UndoRedo.undo(player);
break;
case REDO:
UndoRedo.redo(player);
break;
case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"), true);
break;
case OPEN_MODIFIER_SETTINGS:
if (player.world.isRemote)
ClientProxy.openModifierSettings();
break;
case NORMAL_SPEED:
buildSpeed = ActionEnum.NORMAL_SPEED;
break;
case FAST_SPEED:
buildSpeed = ActionEnum.FAST_SPEED;
break;
case FULL:
fill = ActionEnum.FULL;
break;
case HOLLOW:
fill = ActionEnum.HOLLOW;
break;
case CUBE_FULL:
cubeFill = ActionEnum.CUBE_FULL;
break;
case CUBE_HOLLOW:
cubeFill = ActionEnum.CUBE_HOLLOW;
break;
case CUBE_SKELETON:
cubeFill = ActionEnum.CUBE_SKELETON;
break;
case SHORT_EDGE:
raisedEdge = ActionEnum.SHORT_EDGE;
break;
case LONG_EDGE:
raisedEdge = ActionEnum.LONG_EDGE;
break;
case THICKNESS_1:
lineThickness = ActionEnum.THICKNESS_1;
break;
case THICKNESS_3:
lineThickness = ActionEnum.THICKNESS_3;
break;
case THICKNESS_5:
lineThickness = ActionEnum.THICKNESS_5;
break;
case CIRCLE_START_CENTER:
circleStart = ActionEnum.CIRCLE_START_CENTER;
break;
case CIRCLE_START_CORNER:
circleStart = ActionEnum.CIRCLE_START_CORNER;
break;
}
if (player.world.isRemote && action != ActionEnum.REPLACE && action != ActionEnum.OPEN_MODIFIER_SETTINGS) {
ClientProxy.logTranslate(action.name);
}
}
}

View File

@@ -1,98 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import javax.annotation.Nonnull;
@Mod.EventBusSubscriber
public class ModeSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null
@Nonnull
public static ModeSettings getModeSettings(EntityPlayer player) {
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null);
if (modeCapability.isPresent()) {
ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null);
if (capability.getModeData() == null) {
capability.setModeData(new ModeSettings());
}
return capability.getModeData();
}
//Player does not have modeCapability capability
//Return dummy settings
return new ModeSettings();
// throw new IllegalArgumentException("Player does not have modeCapability capability");
}
public static void setModeSettings(EntityPlayer player, ModeSettings modeSettings) {
if (player == null) {
EffortlessBuilding.log("Cannot set buildmode settings, player is null");
return;
}
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null);
modeCapability.ifPresent((capability) -> {
capability.setModeData(modeSettings);
BuildModes.initializeMode(player);
});
if (!modeCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildmode settings failed.");
}
}
public static String sanitize(ModeSettings modeSettings, EntityPlayer player) {
int maxReach = ReachHelper.getMaxReach(player);
String error = "";
//TODO sanitize
return error;
}
public static class ModeSettings {
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL;
public ModeSettings() {
}
public ModeSettings(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
public BuildModes.BuildModeEnum getBuildMode() {
return this.buildMode;
}
public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode;
}
}
public static void handleNewPlayer(EntityPlayer player){
//Makes sure player has mode settings (if it doesnt it will create it)
getModeSettings(player);
//Only on server
if (!player.world.isRemote) {
//Send to client
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (EntityPlayerMP) player), msg);
}
}
}

View File

@@ -1,215 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.buildmodes.DiagonalLine;
import nl.requios.effortlessbuilding.buildmode.buildmodes.Floor;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public abstract class ThreeClicksBuildMode extends BaseBuildMode {
protected Dictionary<UUID, BlockPos> secondPosTable = new Hashtable<>();
static class HeightCriteria {
Vec3d planeBound;
Vec3d lineBound;
double distToLineSq;
double distToPlayerSq;
HeightCriteria(Vec3d planeBound, BlockPos secondPos, Vec3d start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, secondPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//Make it from a plane into a line, on y axis only
private Vec3d toLongestLine(Vec3d boundVec, BlockPos secondPos) {
BlockPos bound = new BlockPos(boundVec);
return new Vec3d(secondPos.getX(), bound.getY(), secondPos.getZ());
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
}
@Override
public void initialize(EntityPlayer player) {
super.initialize(player);
secondPosTable.put(player.getUniqueID(), BlockPos.ORIGIN);
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else if (rightClickNr == 2) {
//Second click, find other floor point
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
if (secondPos == null) {
rightClickTable.put(player.getUniqueID(), 1);
return list;
}
secondPosTable.put(player.getUniqueID(), secondPos);
} else {
//Third click, place diagonal wall with height
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else if (rightClickNr == 1) {
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
if (secondPos == null) return list;
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Add diagonal line from first to second
list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2));
} else {
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = secondPosTable.get(player.getUniqueID());
BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace);
if (thirdPos == null) return list;
//Limit amount of blocks you can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX(), x3 = thirdPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(), y3 = thirdPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(), z3 = thirdPos.getZ();
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
if (x3 - x1 >= axisLimit) x3 = x1 + axisLimit - 1;
if (x1 - x3 >= axisLimit) x3 = x1 - axisLimit + 1;
if (y3 - y1 >= axisLimit) y3 = y1 + axisLimit - 1;
if (y1 - y3 >= axisLimit) y3 = y1 - axisLimit + 1;
if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1;
if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1;
//Add diagonal line from first to third
list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3));
}
return list;
}
//Finds the place of the second block pos
protected abstract BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace);
//Finds the place of the third block pos
protected abstract BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace);
//After first and second pos are known, we want to visualize the blocks in a way (like floor for cube)
protected abstract List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2);
//After first, second and third pos are known, we want all the blocks
protected abstract List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3);
//Finds height after floor has been chosen in buildmodes with 3 clicks
public static BlockPos findHeight(EntityPlayer player, BlockPos secondPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
List<HeightCriteria> criteriaList = new ArrayList<>(3);
//X
Vec3d xBound = BuildModes.findXBound(secondPos.getX(), start, look);
criteriaList.add(new HeightCriteria(xBound, secondPos, start));
//Z
Vec3d zBound = BuildModes.findZBound(secondPos.getZ(), start, look);
criteriaList.add(new HeightCriteria(zBound, secondPos, start));
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
//If only 1 is valid, choose that one
HeightCriteria selected = criteriaList.get(0);
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
HeightCriteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
}

View File

@@ -1,86 +0,0 @@
package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.UUID;
public abstract class TwoClicksBuildMode extends BaseBuildMode {
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr);
if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0);
return list;
}
//First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else {
//Second click, place blocks
list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0);
}
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
if (rightClickNr == 0) {
if (blockPos != null)
list.add(blockPos);
} else {
BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace);
if (secondPos == null) return list;
//Limit amount of blocks we can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ();
//limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2));
}
return list;
}
//Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc)
protected abstract BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace);
//After first and second pos are known, we want all the blocks
protected abstract List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2);
}

View File

@@ -1,88 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import java.util.*;
public class Circle extends TwoClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getCircleBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
float centerX = x1;
float centerZ = z1;
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
z1 = (int) (centerZ - (z2 - centerZ));
}
float radiusX = MathHelper.abs(x2 - centerX);
float radiusZ = MathHelper.abs(z2 - centerZ);
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
else
addHollowCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
return list;
}
public static void addCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, y1, n));
}
}
}
public static void addHollowCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, y1, n));
}
}
}
private static float distance(float x1, float z1, float x2, float z2) {
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1));
}
public static float calculateEllipseRadius(float centerX, float centerZ, float radiusX, float radiusZ, int x, int z) {
//https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo
float theta = (float) MathHelper.atan2(z - centerZ, x - centerX);
float part1 = radiusX * radiusX * MathHelper.sin(theta) * MathHelper.sin(theta);
float part2 = radiusZ * radiusZ * MathHelper.cos(theta) * MathHelper.cos(theta);
return radiusX * radiusZ / MathHelper.sqrt(part1 + part2);
}
}

View File

@@ -1,104 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Cube extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocksUsingCubeFill(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCubeBlocks(player, x1, y1, z1, x3, y3, z3);
}
public static List<BlockPos> getFloorBlocksUsingCubeFill(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
if (ModeOptions.getCubeFill() == ModeOptions.ActionEnum.CUBE_SKELETON)
Floor.addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
else
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
return list;
}
public static List<BlockPos> getCubeBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
switch (ModeOptions.getCubeFill()) {
case CUBE_FULL:
addCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_HOLLOW:
addHollowCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_SKELETON:
addSkeletonCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
}
return list;
}
public static void addCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addHollowCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Wall.addXWallBlocks(list, x1, y1, y2, z1, z2);
Wall.addXWallBlocks(list, x2, y1, y2, z1, z2);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z1);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z2);
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
Floor.addFloorBlocks(list, x1, x2, y2, z1, z2);
}
public static void addSkeletonCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y1, z1);
Line.addXLineBlocks(list, x1, x2, y1, z2);
Line.addXLineBlocks(list, x1, x2, y2, z1);
Line.addXLineBlocks(list, x1, x2, y2, z2);
Line.addYLineBlocks(list, y1, y2, x1, z1);
Line.addYLineBlocks(list, y1, y2, x1, z2);
Line.addYLineBlocks(list, y1, y2, x2, z1);
Line.addYLineBlocks(list, y1, y2, x2, z2);
Line.addZLineBlocks(list, z1, z2, x1, y1);
Line.addZLineBlocks(list, z1, z2, x1, y2);
Line.addZLineBlocks(list, z1, z2, x2, y1);
Line.addZLineBlocks(list, z1, z2, x2, y2);
}
}

View File

@@ -1,50 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList;
import java.util.List;
public class Cylinder extends ThreeClicksBuildMode {
@Override
public BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
public BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
public List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
public List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCylinderBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
public static List<BlockPos> getCylinderBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
//Get circle blocks (using CIRCLE_START and FILL options built-in)
List<BlockPos> circleBlocks = Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
//Copy circle on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : circleBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
return list;
}
}

View File

@@ -1,54 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class DiagonalLine extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
//Add diagonal line from first to second
return getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 10);
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//Add diagonal line from first to third
return getDiagonalLineBlocks(player, x1, y1, z1, x3, y3, z3, 10);
}
//Add diagonal line from first to second
public static List<BlockPos> getDiagonalLineBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, float sampleMultiplier) {
List<BlockPos> list = new ArrayList<>();
Vec3d first = new Vec3d(x1, y1, z1).add(0.5, 0.5, 0.5);
Vec3d second = new Vec3d(x2, y2, z2).add(0.5, 0.5, 0.5);
int iterations = (int) Math.ceil(first.distanceTo(second) * sampleMultiplier);
for (double t = 0; t <= 1.0; t += 1.0/iterations) {
Vec3d lerp = first.add(second.subtract(first).scale(t));
BlockPos candidate = new BlockPos(lerp);
//Only add if not equal to the last in the list
if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate))
list.add(candidate);
}
return list;
}
}

View File

@@ -1,52 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class DiagonalWall extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getDiagonalWallBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
//Add diagonal wall from first to second
public static List<BlockPos> getDiagonalWallBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
int lowest = Math.min(y1, y3);
int highest = Math.max(y1, y3);
//Copy diagonal line on y axis
for (int y = lowest; y <= highest; y++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
return list;
}
}

View File

@@ -1,93 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Floor extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
double distToPlayerSq;
Criteria(Vec3d planeBound, Vec3d start) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findFloor(player, firstPos, skipRaytrace);
}
public static BlockPos findFloor(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
List<Criteria> criteriaList = new ArrayList<>(3);
//Y
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, start));
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
//Then only 1 can be valid, return that one
Criteria selected = criteriaList.get(0);
return new BlockPos(selected.planeBound);
}
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getFloorBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addFloorBlocks(list, x1, x2, y1, z1, z2);
else
addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
return list;
}
public static void addFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
list.add(new BlockPos(l, y, n));
}
}
}
public static void addHollowFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
Line.addXLineBlocks(list, x1, x2, y, z1);
Line.addXLineBlocks(list, x1, x2, y, z2);
Line.addZLineBlocks(list, z1, z2, x1, y);
Line.addZLineBlocks(list, z1, z2, x2, y);
}
}

View File

@@ -1,147 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class Line extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
Vec3d lineBound;
double distToLineSq;
double distToPlayerSq;
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start) {
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, firstPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//Make it from a plane into a line
//Select the axis that is longest
private Vec3d toLongestLine(Vec3d boundVec, BlockPos firstPos) {
BlockPos bound = new BlockPos(boundVec);
BlockPos firstToSecond = bound.subtract(firstPos);
firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ()));
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ()));
if (longest == firstToSecond.getX()) {
return new Vec3d(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3d(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3d(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
}
}
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findLine(player, firstPos, skipRaytrace);
}
public static BlockPos findLine(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
List<Criteria> criteriaList = new ArrayList<>(3);
//X
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start));
//Y
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look);
criteriaList.add(new Criteria(yBound, firstPos, start));
//Z
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start));
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getLineBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getLineBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
if (x1 != x2) {
addXLineBlocks(list, x1, x2, y1, z1);
} else if (y1 != y2) {
addYLineBlocks(list, y1, y2, x1, z1);
} else {
addZLineBlocks(list, z1, z2, x1, y1);
}
return list;
}
public static void addXLineBlocks(List<BlockPos> list, int x1, int x2, int y, int z) {
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
public static void addYLineBlocks(List<BlockPos> list, int y1, int y2, int x, int z) {
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
public static void addZLineBlocks(List<BlockPos> list, int z1, int z2, int x, int y) {
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}

View File

@@ -1,41 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList;
import java.util.List;
public class Normal implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -1,41 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList;
import java.util.List;
public class NormalPlus implements IBuildMode {
@Override
public void initialize(EntityPlayer player) {
}
@Override
public List<BlockPos> onRightClick(EntityPlayer player, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos);
return list;
}
@Override
public EnumFacing getSideHit(EntityPlayer player) {
return null;
}
@Override
public Vec3d getHitVec(EntityPlayer player) {
return null;
}
}

View File

@@ -1,95 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class SlopeFloor extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
//Add slope floor from first to second
public static List<BlockPos> getSlopeFloorBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
//Determine whether to use x or z axis to slope up
boolean onXAxis = true;
int xLength = Math.abs(x2 - x1);
int zLength = Math.abs(z2 - z1);
if (ModeOptions.getRaisedEdge() == ModeOptions.ActionEnum.SHORT_EDGE) {
//Slope along short edge
if (zLength > xLength) onXAxis = false;
} else {
//Slope along long edge
if (zLength <= xLength) onXAxis = false;
}
if (onXAxis) {
//Along X goes up
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y3, z1, 1f);
//Limit amount of blocks we can place
int lowest = Math.min(z1, z2);
int highest = Math.max(z1, z2);
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
//Copy diagonal line on x axis
for (int z = lowest; z <= highest; z++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z));
}
}
} else {
//Along Z goes up
//Get diagonal line blocks
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x1, y3, z2, 1f);
//Limit amount of blocks we can place
int lowest = Math.min(x1, x2);
int highest = Math.max(x1, x2);
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
//Copy diagonal line on x axis
for (int x = lowest; x <= highest; x++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ()));
}
}
}
return list;
}
}

View File

@@ -1,110 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList;
import java.util.List;
public class Sphere extends ThreeClicksBuildMode {
@Override
public BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
public BlockPos findThirdPos(EntityPlayer player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
public List<BlockPos> getIntermediateBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
public List<BlockPos> getFinalBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSphereBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
public static List<BlockPos> getSphereBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
List<BlockPos> list = new ArrayList<>();
float centerX = x1;
float centerY = y1;
float centerZ = z1;
//Adjust for CIRCLE_START
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerY = y1 + (y3 - y1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
y1 = (int) (centerY - (y3 - centerY));
z1 = (int) (centerZ - (z2 - centerZ));
}
float radiusX = MathHelper.abs(x2 - centerX);
float radiusY = MathHelper.abs(y3 - centerY);
float radiusZ = MathHelper.abs(z2 - centerZ);
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
else
addHollowSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
return list;
}
public static void addSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addHollowSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, m, n));
}
}
}
}
private static float distance(float x1, float y1, float z1, float x2, float y2, float z2) {
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
}
public static float calculateSpheroidRadius(float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ, int x, int y, int z) {
//Twice ellipse radius
float radiusXZ = Circle.calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, x, z);
//TODO project x to plane
return Circle.calculateEllipseRadius(centerX, centerY, radiusXZ, radiusY, x, y);
}
}

View File

@@ -1,134 +0,0 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*;
public class Wall extends TwoClicksBuildMode {
static class Criteria {
Vec3d planeBound;
double distToPlayerSq;
double angle;
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start, Vec3d look) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
Vec3d wall = this.planeBound.subtract(new Vec3d(firstPos));
this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle)
}
//check if its not behind the player and its not too close and not too far
//also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3d start, Vec3d look, int reach, EntityPlayer player, boolean skipRaytrace) {
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
}
}
@Override
protected BlockPos findSecondPos(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
return findWall(player, firstPos, skipRaytrace);
}
public static BlockPos findWall(EntityPlayer player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
List<Criteria> criteriaList = new ArrayList<>(3);
//X
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look);
criteriaList.add(new Criteria(xBound, firstPos, start, look));
//Z
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
criteriaList.add(new Criteria(zBound, firstPos, start, look));
//Remove invalid criteria
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
//If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
//If multiple are valid, choose based on criteria
if (criteriaList.size() > 1) {
//Select the one that is closest
//Limit the angle to not be too extreme
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToPlayerSq < selected.distToPlayerSq && Math.abs(criteria.angle) - Math.abs(selected.angle) < 3)
selected = criteria;
}
}
return new BlockPos(selected.planeBound);
}
@Override
protected List<BlockPos> getAllBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getWallBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getWallBlocks(EntityPlayer player, int x1, int y1, int z1, int x2, int y2, int z2) {
List<BlockPos> list = new ArrayList<>();
if (x1 == x2) {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addXWallBlocks(list, x1, y1, y2, z1, z2);
else
addXHollowWallBlocks(list, x1, y1, y2, z1, z2);
} else {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addZWallBlocks(list, x1, x2, y1, y2, z1);
else
addZHollowWallBlocks(list, x1, x2, y1, y2, z1);
}
return list;
}
public static void addXWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
public static void addZWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
}
public static void addXHollowWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
Line.addZLineBlocks(list, z1, z2, x, y1);
Line.addZLineBlocks(list, z1, z2, x, y2);
Line.addYLineBlocks(list, y1, y2, x, z1);
Line.addYLineBlocks(list, y1, y2, x, z2);
}
public static void addZHollowWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
Line.addXLineBlocks(list, x1, x2, y1, z);
Line.addXLineBlocks(list, x1, x2, y2, z);
Line.addYLineBlocks(list, y1, y2, x1, z);
Line.addYLineBlocks(list, y1, y2, x2, z);
}
}

View File

@@ -1,50 +0,0 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.List;
public class BlockSet {
private List<BlockPos> coordinates;
private List<IBlockState> previousBlockStates;
private List<IBlockState> newBlockStates;
private Vec3d hitVec;
private BlockPos firstPos;
private BlockPos secondPos;
public BlockSet(List<BlockPos> coordinates, List<IBlockState> previousBlockStates, List<IBlockState> newBlockStates, Vec3d hitVec,
BlockPos firstPos, BlockPos secondPos) {
this.coordinates = coordinates;
this.previousBlockStates = previousBlockStates;
this.newBlockStates = newBlockStates;
this.hitVec = hitVec;
this.firstPos = firstPos;
this.secondPos = secondPos;
}
public List<BlockPos> getCoordinates() {
return coordinates;
}
public List<IBlockState> getPreviousBlockStates() {
return previousBlockStates;
}
public List<IBlockState> getNewBlockStates() {
return newBlockStates;
}
public Vec3d getHitVec() {
return hitVec;
}
public BlockPos getFirstPos() {
return firstPos;
}
public BlockPos getSecondPos() {
return secondPos;
}
}

View File

@@ -1,260 +0,0 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.*;
public class BuildModifiers {
//Called from BuildModes
public static void onBlockPlaced(EntityPlayer player, List<BlockPos> startCoordinates, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) {
World world = player.world;
ItemRandomizerBag.renewRandomness();
//Format hitvec to 0.x
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//remember previous blockstates for undo
List<IBlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<IBlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
if (world.isRemote) {
BlockPreviewRenderer.onBlocksPlaced();
newBlockStates = blockStates;
} else {
//place blocks
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (world.isBlockLoaded(blockPos, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
if (itemStack.isEmpty()) continue;
}
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, EnumFacing.UP, hitVec, false, false, false);
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block is placed by the time it gets here, and unplaced after this)
if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.getDefaultState());
//If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.getDefaultState()) != newBlockStates.size()) {
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
}
public static void onBlockBroken(EntityPlayer player, List<BlockPos> startCoordinates, boolean breakStartPos) {
World world = player.world;
List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
if (coordinates.isEmpty()) return;
//remember previous blockstates for undo
List<IBlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<IBlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate));
}
if (world.isRemote) {
BlockPreviewRenderer.onBlocksBroken();
//list of air blockstates
for (int i = 0; i < coordinates.size(); i++) {
newBlockStates.add(Blocks.AIR.getDefaultState());
}
} else {
//If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(startCoordinates.get(0)).getBlockHardness(world, startCoordinates.get(0)) == 0f;
//break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (world.isBlockLoaded(coordinate, false)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, player, coordinate, false);
}
}
}
//find actual new blockstates for undo
for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate));
}
}
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.getDefaultState());
//add to undo stack
BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
Vec3d hitVec = new Vec3d(0.5, 0.5, 0.5);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
}
public static List<BlockPos> findCoordinates(EntityPlayer player, List<BlockPos> posList) {
List<BlockPos> coordinates = new ArrayList<>();
//Add current blocks being placed too
coordinates.addAll(posList);
//Find mirror/array/radial mirror coordinates for each blockpos
for (BlockPos blockPos : posList) {
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
}
}
return coordinates;
}
public static List<BlockPos> findCoordinates(EntityPlayer player, BlockPos blockPos) {
return findCoordinates(player, new ArrayList<>(Arrays.asList(blockPos)));
}
public static List<IBlockState> findBlockStates(EntityPlayer player, List<BlockPos> posList, Vec3d hitVec, EnumFacing facing, List<ItemStack> itemStacks) {
List<IBlockState> blockStates = new ArrayList<>();
itemStacks.clear();
//Get itemstack
ItemStack itemStack = player.getHeldItem(EnumHand.MAIN_HAND);
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
itemStack = player.getHeldItem(EnumHand.OFF_HAND);
}
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
return blockStates;
}
//Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof ItemBlock) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
ItemRandomizerBag.resetRandomness();
//Add blocks in posList first
for (BlockPos blockPos : posList) {
if (!(itemStack.getItem() instanceof ItemBlock)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
blockStates.add(blockState);
itemStacks.add(itemBlock);
}
for (BlockPos blockPos : posList) {
IBlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, EnumHand.MAIN_HAND);
List<IBlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks);
blockStates.addAll(arrayBlockStates);
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
IBlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// }
}
return blockStates;
}
public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(modifierSettings.getArraySettings()) ||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
modifierSettings.doQuickReplace();
}
public static IBlockState getBlockStateFromItem(ItemStack itemStack, EntityPlayer player, BlockPos blockPos, EnumFacing facing, Vec3d hitVec, EnumHand hand) {
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(new BlockItemUseContext(player.world, player, itemStack, blockPos, facing,
((float) hitVec.x), ((float) hitVec.y), ((float) hitVec.z)));
}
//Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false;
//Check count, not actual values
if (coordinates1.size() == coordinates2.size()){
if (coordinates1.size() == 1){
return coordinates1.get(0).equals(coordinates2.get(0));
}
return true;
} else {
return false;
}
// return coordinates1.equals(coordinates2);
}
}

View File

@@ -1,229 +0,0 @@
package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.FixedStack;
import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.*;
public class UndoRedo {
//Undo and redo stacks per player
//Gets added to twice in singleplayer (server and client) if not careful. So separate stacks.
private static Map<UUID, FixedStack<BlockSet>> undoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> undoStacksServer = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksServer = new HashMap<>();
//add to undo stack
public static void addUndo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
//Assert coordinates is as long as previous and new blockstate lists
if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() ||
blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) {
EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.",
blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size());
}
//Warn if previous and new blockstate are equal
//Can happen in a lot of valid cases
// for (int i = 0; i < blockSet.getCoordinates().size(); i++) {
// if (blockSet.getPreviousBlockStates().get(i).equals(blockSet.getNewBlockStates().get(i))) {
// EffortlessBuilding.logger.warn("Previous and new blockstates are equal at index {}. Blockstate: {}.",
// i, blockSet.getPreviousBlockStates().get(i));
// }
// }
//If no stack exists, make one
if (!undoStacks.containsKey(player.getUniqueID())) {
undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
undoStacks.get(player.getUniqueID()).push(blockSet);
}
private static void addRedo(EntityPlayer player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
//(No asserts necessary, it's private)
//If no stack exists, make one
if (!redoStacks.containsKey(player.getUniqueID())) {
redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
}
redoStacks.get(player.getUniqueID()).push(blockSet);
}
public static boolean undo(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
if (!undoStacks.containsKey(player.getUniqueID())) return false;
FixedStack<BlockSet> undoStack = undoStacks.get(player.getUniqueID());
if (undoStack.isEmpty()) return false;
BlockSet blockSet = undoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<IBlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates);
if (player.world.isRemote) {
BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
} else {
//break all those blocks, reset to what they were
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack
IBlockState previousBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) {
previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
}
if (player.world.isBlockLoaded(coordinate, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, previousBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
previousBlockState = previousBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
previousBlockState = Blocks.AIR.getDefaultState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
//if previousBlockState is air, placeBlock will set it to air
SurvivalHelper.placeBlock(player.world, player, coordinate, previousBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false);
}
}
}
//add to redo
addRedo(player, blockSet);
return true;
}
public static boolean redo(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
if (!redoStacks.containsKey(player.getUniqueID())) return false;
FixedStack<BlockSet> redoStack = redoStacks.get(player.getUniqueID());
if (redoStack.isEmpty()) return false;
BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates();
List<IBlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<IBlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates);
if (player.world.isRemote) {
BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
} else {
//place blocks
for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack
IBlockState newBlockState = Blocks.AIR.getDefaultState();
if (itemStack.getItem() instanceof ItemBlock) {
newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
}
if (player.world.isBlockLoaded(coordinate, true)) {
//check itemstack empty
if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, newBlockStates.get(i));
//get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemBlock) {
newBlockState = newBlockStates.get(i);//((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
} else {
newBlockState = Blocks.AIR.getDefaultState();
}
}
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true);
SurvivalHelper.placeBlock(player.world, player, coordinate, newBlockState, itemStack, EnumFacing.UP, hitVec, true, false, false);
}
}
}
//add to undo
addUndo(player, blockSet);
return true;
}
public static void clear(EntityPlayer player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer;
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer;
if (undoStacks.containsKey(player.getUniqueID())) {
undoStacks.get(player.getUniqueID()).clear();
}
if (redoStacks.containsKey(player.getUniqueID())) {
redoStacks.get(player.getUniqueID()).clear();
}
}
private static List<ItemStack> findItemStacksInInventory(EntityPlayer player, List<IBlockState> blockStates) {
List<ItemStack> itemStacks = new ArrayList<>(blockStates.size());
for (IBlockState blockState : blockStates) {
itemStacks.add(findItemStackInInventory(player, blockState));
}
return itemStacks;
}
private static ItemStack findItemStackInInventory(EntityPlayer player, IBlockState blockState) {
ItemStack itemStack = ItemStack.EMPTY;
if (blockState == null) return itemStack;
//First try previousBlockStates
//TODO try to find itemstack with right blockstate first
// then change line 103 back (get state from item)
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
//then anything it drops
if (itemStack.isEmpty()) {
Item itemDropped = blockState.getBlock().getItemDropped(blockState, player.world, BlockPos.ORIGIN, 10).asItem();
if (itemDropped instanceof ItemBlock) {
Block block = ((ItemBlock) itemDropped).getBlock();
itemStack = InventoryHelper.findItemStackInInventory(player, block);
}
}
//then air
//(already empty)
return itemStack;
}
}

View File

@@ -0,0 +1,171 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings;
import nl.requios.effortlessbuilding.Mirror;
import nl.requios.effortlessbuilding.RadialMirror;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@Mod.EventBusSubscriber
public class BuildModifierCapabilityManager {
@CapabilityInject(IBuildModifierCapability.class)
public final static Capability<IBuildModifierCapability> buildModifierCapability = null;
public interface IBuildModifierCapability {
BuildSettings getBuildModifierData();
void setBuildModifierData(BuildSettings buildSettings);
}
public static class BuildModifierCapability implements IBuildModifierCapability {
private BuildSettings buildSettings;
@Override
public BuildSettings getBuildModifierData() {
return buildSettings;
}
@Override
public void setBuildModifierData(BuildSettings buildSettings) {
this.buildSettings = buildSettings;
}
}
public static class Storage implements Capability.IStorage<IBuildModifierCapability> {
@Override
public NBTBase writeNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
BuildSettings buildSettings = instance.getBuildModifierData();
if (buildSettings == null) buildSettings = new BuildSettings();
//MIRROR
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.setBoolean("mirrorEnabled", m.enabled);
compound.setDouble("mirrorPosX", m.position.x);
compound.setDouble("mirrorPosY", m.position.y);
compound.setDouble("mirrorPosZ", m.position.z);
compound.setBoolean("mirrorX", m.mirrorX);
compound.setBoolean("mirrorY", m.mirrorY);
compound.setBoolean("mirrorZ", m.mirrorZ);
compound.setInteger("mirrorRadius", m.radius);
compound.setBoolean("mirrorDrawLines", m.drawLines);
compound.setBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY
Array.ArraySettings a = buildSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.setBoolean("arrayEnabled", a.enabled);
compound.setInteger("arrayOffsetX", a.offset.getX());
compound.setInteger("arrayOffsetY", a.offset.getY());
compound.setInteger("arrayOffsetZ", a.offset.getZ());
compound.setInteger("arrayCount", a.count);
compound.setInteger("reachUpgrade", buildSettings.getReachUpgrade());
//compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.setBoolean("radialMirrorEnabled", r.enabled);
compound.setDouble("radialMirrorPosX", r.position.x);
compound.setDouble("radialMirrorPosY", r.position.y);
compound.setDouble("radialMirrorPosZ", r.position.z);
compound.setInteger("radialMirrorSlices", r.slices);
compound.setBoolean("radialMirrorAlternate", r.alternate);
compound.setInteger("radialMirrorRadius", r.radius);
compound.setBoolean("radialMirrorDrawLines", r.drawLines);
compound.setBoolean("radialMirrorDrawPlanes", r.drawPlanes);
return compound;
}
@Override
public void readNBT(Capability<IBuildModifierCapability> capability, IBuildModifierCapability instance, EnumFacing side, NBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
//MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3d mirrorPosition = new Vec3d(compound.getDouble("mirrorPosX"), compound.getDouble("mirrorPosY"), compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInteger("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
//ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled");
BlockPos arrayOffset = new BlockPos(compound.getInteger("arrayOffsetX"), compound.getInteger("arrayOffsetY"), compound.getInteger("arrayOffsetZ"));
int arrayCount = compound.getInteger("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
int reachUpgrade = compound.getInteger("reachUpgrade");
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
//RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3d radialMirrorPosition = new Vec3d(compound.getDouble("radialMirrorPosX"), compound.getDouble("radialMirrorPosY"), compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInteger("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInteger("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setBuildModifierData(buildSettings);
}
}
public static class Provider implements ICapabilitySerializable<NBTBase> {
IBuildModifierCapability inst = buildModifierCapability.getDefaultInstance();
@Override
public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return capability == buildModifierCapability;
}
@Override
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == buildModifierCapability) return buildModifierCapability.<T>cast(inst);
return null;
}
@Override
public NBTBase serializeNBT() {
return buildModifierCapability.getStorage().writeNBT(buildModifierCapability, inst, null);
}
@Override
public void deserializeNBT(NBTBase nbt) {
buildModifierCapability.getStorage().readNBT(buildModifierCapability, inst, null, nbt);
}
}
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
IBuildModifierCapability original = event.getOriginal().getCapability(buildModifierCapability, null);
IBuildModifierCapability clone = event.getEntity().getCapability(buildModifierCapability, null);
clone.setBuildModifierData(original.getBuildModifierData());
}
}

View File

@@ -3,9 +3,7 @@ package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
@@ -17,10 +15,19 @@ import javax.annotation.Nullable;
public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<NBTTagCompound> { public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<NBTTagCompound> {
IItemHandler itemHandler = new ItemStackHandler(ItemRandomizerBag.INV_SIZE); IItemHandler itemHandler = new ItemStackHandler(ItemRandomizerBag.INV_SIZE);
@Nonnull
@Override @Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) { public boolean hasCapability(@Nonnull Capability<?> capability, @Nullable EnumFacing facing) {
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> itemHandler)); if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return true;
return false;
}
@Nullable
@Override
public <T> T getCapability(@Nonnull Capability<T> capability, @Nullable EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return (T) itemHandler;
return null;
} }
@Override @Override

View File

@@ -1,103 +0,0 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
@Mod.EventBusSubscriber
public class ModeCapabilityManager {
@CapabilityInject(IModeCapability.class)
public final static Capability<IModeCapability> modeCapability = null;
public interface IModeCapability {
ModeSettings getModeData();
void setModeData(ModeSettings modeSettings);
}
public static class ModeCapability implements IModeCapability {
private ModeSettings modeSettings;
@Override
public ModeSettings getModeData() {
return modeSettings;
}
@Override
public void setModeData(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
}
public static class Storage implements Capability.IStorage<IModeCapability> {
@Override
public INBTBase writeNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
ModeSettings modeSettings = instance.getModeData();
if (modeSettings == null) modeSettings = new ModeSettings();
//compound.setInteger("buildMode", modeSettings.getBuildMode().ordinal());
//TODO add mode settings
return compound;
}
@Override
public void readNBT(Capability<IModeCapability> capability, IModeCapability instance, EnumFacing side, INBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
//TODO add mode settings
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL);
instance.setModeData(modeSettings);
}
}
public static class Provider implements ICapabilitySerializable<INBTBase> {
IModeCapability inst = modeCapability.getDefaultInstance();
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) {
return modeCapability.orEmpty(cap, LazyOptional.of(() -> inst));
}
@Override
public INBTBase serializeNBT() {
return modeCapability.getStorage().writeNBT(modeCapability, inst, null);
}
@Override
public void deserializeNBT(INBTBase nbt) {
modeCapability.getStorage().readNBT(modeCapability, inst, null, nbt);
}
}
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(modeCapability, null);
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(modeCapability, null);
clone.ifPresent(cloneModeCapability ->
original.ifPresent(originalModeCapability ->
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
}
}

View File

@@ -1,185 +0,0 @@
package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.INBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*;
@Mod.EventBusSubscriber
public class ModifierCapabilityManager {
@CapabilityInject(IModifierCapability.class)
public final static Capability<IModifierCapability> modifierCapability = null;
public interface IModifierCapability {
ModifierSettings getModifierData();
void setModifierData(ModifierSettings modifierSettings);
}
public static class ModifierCapability implements IModifierCapability {
private ModifierSettings modifierSettings;
@Override
public ModifierSettings getModifierData() {
return modifierSettings;
}
@Override
public void setModifierData(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings;
}
}
public static class Storage implements Capability.IStorage<IModifierCapability> {
@Override
public INBTBase writeNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side) {
NBTTagCompound compound = new NBTTagCompound();
ModifierSettings modifierSettings = instance.getModifierData();
if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.setBoolean("mirrorEnabled", m.enabled);
compound.setDouble("mirrorPosX", m.position.x);
compound.setDouble("mirrorPosY", m.position.y);
compound.setDouble("mirrorPosZ", m.position.z);
compound.setBoolean("mirrorX", m.mirrorX);
compound.setBoolean("mirrorY", m.mirrorY);
compound.setBoolean("mirrorZ", m.mirrorZ);
compound.setInt("mirrorRadius", m.radius);
compound.setBoolean("mirrorDrawLines", m.drawLines);
compound.setBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY
Array.ArraySettings a = modifierSettings.getArraySettings();
if (a == null) a = new Array.ArraySettings();
compound.setBoolean("arrayEnabled", a.enabled);
compound.setInt("arrayOffsetX", a.offset.getX());
compound.setInt("arrayOffsetY", a.offset.getY());
compound.setInt("arrayOffsetZ", a.offset.getZ());
compound.setInt("arrayCount", a.count);
compound.setInt("reachUpgrade", modifierSettings.getReachUpgrade());
//compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.setBoolean("radialMirrorEnabled", r.enabled);
compound.setDouble("radialMirrorPosX", r.position.x);
compound.setDouble("radialMirrorPosY", r.position.y);
compound.setDouble("radialMirrorPosZ", r.position.z);
compound.setInt("radialMirrorSlices", r.slices);
compound.setBoolean("radialMirrorAlternate", r.alternate);
compound.setInt("radialMirrorRadius", r.radius);
compound.setBoolean("radialMirrorDrawLines", r.drawLines);
compound.setBoolean("radialMirrorDrawPlanes", r.drawPlanes);
return compound;
}
@Override
public void readNBT(Capability<IModifierCapability> capability, IModifierCapability instance, EnumFacing side, INBTBase nbt) {
NBTTagCompound compound = (NBTTagCompound) nbt;
//MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3d mirrorPosition = new Vec3d(
compound.getDouble("mirrorPosX"),
compound.getDouble("mirrorPosY"),
compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInt("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
//ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled");
BlockPos arrayOffset = new BlockPos(
compound.getInt("arrayOffsetX"),
compound.getInt("arrayOffsetY"),
compound.getInt("arrayOffsetZ"));
int arrayCount = compound.getInt("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
int reachUpgrade = compound.getInt("reachUpgrade");
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
//RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3d radialMirrorPosition = new Vec3d(
compound.getDouble("radialMirrorPosX"),
compound.getDouble("radialMirrorPosY"),
compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInt("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInt("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setModifierData(modifierSettings);
}
}
public static class Provider implements ICapabilitySerializable<INBTBase> {
IModifierCapability inst = modifierCapability.getDefaultInstance();
@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable EnumFacing side) {
return modifierCapability.orEmpty(cap, LazyOptional.of(() -> inst));
}
@Override
public INBTBase serializeNBT() {
return modifierCapability.getStorage().writeNBT(modifierCapability, inst, null);
}
@Override
public void deserializeNBT(INBTBase nbt) {
modifierCapability.getStorage().readNBT(modifierCapability, inst, null, nbt);
}
}
// Allows for the capability to persist after death.
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(modifierCapability, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(modifierCapability, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
}

View File

@@ -1,44 +1,43 @@
package nl.requios.effortlessbuilding.command; package nl.requios.effortlessbuilding.command;
import com.mojang.brigadier.CommandDispatcher; import net.minecraft.command.CommandBase;
import com.mojang.brigadier.arguments.IntegerArgumentType; import net.minecraft.command.CommandException;
import net.minecraft.command.CommandSource; import net.minecraft.command.ICommandSender;
import net.minecraft.command.Commands; import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentString;
import net.minecraftforge.fml.network.PacketDistributor; import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
public class CommandReach { public class CommandReach extends CommandBase {
@Override
public static void register(CommandDispatcher<CommandSource> dispatcher) { public String getName() {
dispatcher.register(Commands.literal("reach").then(Commands.literal("set").then(Commands.argument("level", IntegerArgumentType.integer(0, 3)).executes((context) -> { return "reach";
return setReachLevel(context.getSource().asPlayer(), IntegerArgumentType.getInteger(context, "level"));
}))).then(Commands.literal("get").executes((context -> {
return getReachLevel(context.getSource().asPlayer());
}))));
} }
private static int setReachLevel(EntityPlayerMP player, int level){ @Override
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); public String getUsage(ICommandSender sender) {
modifierSettings.setReachUpgrade(level); return "commands.reach.usage";
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
//Send to client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new ModifierSettingsMessage(modifierSettings));
player.sendMessage(new TextComponentString("Reach level of " + player.getName().getString() + " set to " + modifierSettings.getReachUpgrade()));
return 1;
} }
private static int getReachLevel(EntityPlayerMP player){ @Override
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade(); public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
EffortlessBuilding.log(player, "Current reach: level "+reachUpgrade); if (args.length != 1) {
throw new WrongUsageException("commands.reach.usage");
}
return 1; if (sender instanceof EntityPlayerMP) {
EntityPlayerMP player = (EntityPlayerMP) sender;
//Set reach level to args[0]
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
buildSettings.setReachUpgrade(Integer.valueOf(args[0]));
BuildSettingsManager.setBuildSettings(player, buildSettings);
//Send to client
EffortlessBuilding.packetHandler.sendTo(new BuildSettingsMessage(buildSettings), player);
sender.sendMessage(new TextComponentString("Reach level of " + sender.getName() + " set to " + buildSettings.getReachUpgrade()));
}
} }
} }

View File

@@ -1,133 +0,0 @@
package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
public class CompatHelper {
//TODO 1.13 compatibility
// // Get a handle to the dank null item instance. This will remain null if the mod doesn't load
// // and all checks will fail, so it works.
// @GameRegistry.ObjectHolder("danknull:dank_null")
// public static final Item dankNullItem = null;
//
// public static IChiselsAndBitsProxy chiselsAndBitsProxy;
//
public static void setup() {
//TODO 1.13 compatibility
// if (Loader.isModLoaded("chiselsandbits")) {
// // reflection to avoid hard dependency
// try {
// chiselsAndBitsProxy = Class.forName("nl.requios.effortlessbuilding.compatibility.ActiveChiselsAndBitsProxy").asSubclass(ActiveChiselsAndBitsProxy.class).newInstance();
// } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
// e.printStackTrace();
// }
// } else {
// chiselsAndBitsProxy = new DummyChiselsAndBitsProxy();
// }
}
// Check if the item given is a proxy for blocks. For now, we check for the randomizer bag,
// /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof ItemBlock)
return true;
if ((item instanceof ItemRandomizerBag))
return true;
//TODO 1.13 compatibility
// if (item == dankNullItem)
// return true;
return false;
}
// Get the block to be placed by this proxy. For the /dank/null, it's the slot stack
// pointed to by nbt integer selectedIndex.
public static ItemStack getItemBlockFromStack(ItemStack proxy) {
Item proxyItem = proxy.getItem();
if (proxyItem instanceof ItemBlock)
return proxy;
//Randomizer Bag
if (proxyItem instanceof ItemRandomizerBag) {
ItemStack itemStack = proxy;
while (!(itemStack.getItem() instanceof ItemBlock || itemStack.isEmpty())) {
if (itemStack.getItem() instanceof ItemRandomizerBag)
itemStack = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack));
}
return itemStack;
}
//TODO 1.13 compatibility
//Dank Null
// if (proxyItem == dankNullItem) {
// int index = 0;
// if (proxy.hasTagCompound() && proxy.getTagCompound().hasKey("selectedIndex"))
// index = proxy.getTagCompound().getInteger("selectedIndex");
// return proxy.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
return ItemStack.EMPTY;
}
public static ItemStack getItemBlockByState(ItemStack stack, IBlockState state) {
if (state == null) return ItemStack.EMPTY;
Item blockItem = Item.getItemFromBlock(state.getBlock());
if (stack.getItem() instanceof ItemBlock)
return stack;
else if (stack.getItem() instanceof ItemRandomizerBag) {
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(stack);
return ItemRandomizerBag.findStack(bagInventory, blockItem);
}
//TODO 1.13 compatibility
// else if (stack.getItem() == dankNullItem) {
// int index = itemHandlerSlotForItem(stack, blockItem);
// if (index >= 0)
// return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
return ItemStack.EMPTY;
}
// Handle IItemHandler slot stacks not being modifiable. We must call IItemHandler#extractItem,
// because the ItemStack returned by IItemHandler#getStackInSlot isn't modifiable.
public static void shrinkStack(ItemStack origStack, ItemStack curStack, EntityPlayer player) {
//TODO 1.13 compatibility, offhand support
//Hacky way to get the origstack, because given origStack is itemblock stack and never proxy
// origStack = player.getHeldItem(EnumHand.MAIN_HAND);
// if (origStack.getItem() == dankNullItem) {
// int index = itemHandlerSlotForItem(origStack, curStack.getItem());
// origStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).extractItem(index, 1, false);
// } else
curStack.shrink(1);
}
private static int itemHandlerSlotForItem(ItemStack stack, Item blockItem) {
LazyOptional<IItemHandler> itemHandlerLazyOptional = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
IItemHandler handler = itemHandlerLazyOptional.orElse(null);
if (handler == null) {
EffortlessBuilding.logger.warn("Itemblock proxy has no item handler capability!");
return -1;
}
for (int i = 0; i < handler.getSlots(); i++) {
ItemStack ref = handler.getStackInSlot(i);
if (ref.getItem() instanceof ItemBlock)
if (ref.getItem() == blockItem)
return i;
}
return -1;
}
}

View File

@@ -1,25 +1,19 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.Array;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT)
public class ArraySettingsGui extends GuiCollapsibleScrollEntry { public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>(); protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
@@ -32,44 +26,38 @@ public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
} }
@Override @Override
public int initGui(int id, List<GuiButton> buttons) { public int initGui(int id, List<GuiButton> buttonList) {
id = super.initGui(id, buttons); id = super.initGui(id, buttonList);
int y = top; int y = top;
buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) { buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
@Override buttonList.add(buttonArrayEnabled);
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonArrayEnabled.isChecked());
}
};
buttons.add(buttonArrayEnabled);
y = top + 20; y = top + 20;
textArrayOffsetX = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 70, y, 50, 18); textArrayOffsetX = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0); textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip("How much each copy is shifted."); textArrayOffsetX.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetX); arrayNumberFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 140, y, 50, 18); textArrayOffsetY = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0); textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip("How much each copy is shifted."); textArrayOffsetY.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetY); arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 210, y, 50, 18); textArrayOffsetZ = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0); textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip("How much each copy is shifted."); textArrayOffsetZ.setTooltip("How much each copy is shifted.");
arrayNumberFieldList.add(textArrayOffsetZ); arrayNumberFieldList.add(textArrayOffsetZ);
y = top + 50; y = top + 50;
textArrayCount = new GuiNumberField(id++, id++, id++, fontRenderer, buttons, left + 55, y, 50, 18); textArrayCount = new GuiNumberField(id++, id++, id++, fontRenderer, buttonList, left + 55, y, 50, 18);
textArrayCount.setNumber(5); textArrayCount.setNumber(5);
textArrayCount.setTooltip("How many copies should be made."); textArrayCount.setTooltip("How many copies should be made.");
arrayNumberFieldList.add(textArrayCount); arrayNumberFieldList.add(textArrayCount);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (modifierSettings != null) { if (buildSettings != null) {
Array.ArraySettings a = modifierSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled); buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX()); textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY()); textArrayOffsetY.setNumber(a.offset.getY());
@@ -82,44 +70,48 @@ public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
return id; return id;
} }
@Override
public void updateScreen() { public void updateScreen() {
super.updateScreen();
arrayNumberFieldList.forEach(GuiNumberField::update); arrayNumberFieldList.forEach(GuiNumberField::update);
} }
@Override @Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) { boolean isSelected, float partialTicks) {
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partialTicks);
int yy = y; int yy = y;
int offset = 8; int offset = 8;
buttonArrayEnabled.render(mouseX, mouseY, partialTicks); buttonArrayEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) { if (buttonArrayEnabled.isChecked()) {
buttonArrayEnabled.y = yy; buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array enabled", left + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Array enabled", left + offset, yy + 2, 0xFFFFFF, true);
yy = y + 20; yy = y + 20;
fontRenderer.drawString("Offset", left + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Offset", left + offset, yy + 5, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 50 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("X", left + 50 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetX.y = yy; textArrayOffsetX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetY.y = yy; textArrayOffsetY.y = yy;
fontRenderer.drawString("Z", left + 190 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Z", left + 190 + offset, yy + 5, 0xFFFFFF, true);
textArrayOffsetZ.y = yy; textArrayOffsetZ.y = yy;
yy = y + 50; yy = y + 50;
fontRenderer.drawString("Count", left + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Count", left + offset, yy + 5, 0xFFFFFF, true);
textArrayCount.y = yy; textArrayCount.y = yy;
int currentReach = Math.max(-1, getArrayReach()); int currentReach = Math.max(-1, getArrayReach());
int maxReach = ReachHelper.getMaxReach(mc.player); int maxReach = ReachHelper.getMaxReach(mc.player);
TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED; TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach; String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach;
fontRenderer.drawString(reachText, left + 176 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString(reachText, left + 176 + offset, yy + 5, 0xFFFFFF, true);
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks)); arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else { } else {
buttonArrayEnabled.y = yy; buttonArrayEnabled.y = yy;
fontRenderer.drawString("Array disabled", left + offset, yy + 2, 0x999999); fontRenderer.drawString("Array disabled", left + offset, yy + 2, 0x999999, true);
} }
} }
@@ -133,28 +125,43 @@ public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
} }
@Override @Override
public boolean charTyped(char typedChar, int keyCode) { public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
super.charTyped(typedChar, keyCode); super.updatePosition(slotIndex, x, y, partialTicks);
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : arrayNumberFieldList) { for (GuiNumberField numberField : arrayNumberFieldList) {
numberField.charTyped(typedChar, keyCode); numberField.keyTyped(typedChar, keyCode);
} }
return true;
} }
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
super.mousePressed(slotIndex, mouseX, mouseY, mouseEvent, relativeX, relativeY);
arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideArrayEnabledLabel) { if (insideArrayEnabledLabel) {
buttonArrayEnabled.setIsChecked(!buttonArrayEnabled.isChecked());
buttonArrayEnabled.playPressSound(this.mc.getSoundHandler()); buttonArrayEnabled.playPressSound(this.mc.getSoundHandler());
buttonArrayEnabled.onClick(mouseX, mouseY); actionPerformed(buttonArrayEnabled);
} }
return true; return true;
} }
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonArrayEnabled) {
setCollapsed(!buttonArrayEnabled.isChecked());
}
arrayNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public Array.ArraySettings getArraySettings() { public Array.ArraySettings getArraySettings() {
boolean arrayEnabled = buttonArrayEnabled.isChecked(); boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0); BlockPos arrayOffset = new BlockPos(0, 0, 0);

View File

@@ -1,17 +1,13 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.IGuiEventListener;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT)
public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry { public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry {
public GuiScrollPane scrollPane; public GuiScrollPane scrollPane;
@@ -40,10 +36,18 @@ public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScroll
@Override @Override
public void updateScreen() { public void updateScreen() {
}
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
} }
@Override @Override
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) { public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
} }
@Override @Override
@@ -52,8 +56,8 @@ public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScroll
} }
@Override @Override
public boolean charTyped(char eventChar, int eventKey) { public void keyTyped(char eventChar, int eventKey) throws IOException {
return false;
} }
@Override @Override
@@ -66,8 +70,14 @@ public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScroll
} }
@Override
public void actionPerformed(GuiButton button) {
}
@Override @Override
public void onGuiClosed() { public void onGuiClosed() {
} }
@Override @Override

View File

@@ -1,17 +1,14 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT)
public class GuiIconButton extends GuiButton { public class GuiIconButton extends GuiButton {
private final ResourceLocation resourceLocation; private final ResourceLocation resourceLocation;
@@ -47,12 +44,12 @@ public class GuiIconButton extends GuiButton {
} }
@Override @Override
public void render(int mouseX, int mouseY, float partialTicks) { public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
super.render(mouseX, mouseY, partialTicks); super.drawButton(mc, mouseX, mouseY, partialTicks);
if (this.visible) if (this.visible)
{ {
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
Minecraft.getInstance().getTextureManager().bindTexture(this.resourceLocation); mc.getTextureManager().bindTexture(this.resourceLocation);
int currentIconX = this.iconX; int currentIconX = this.iconX;
int currentIconY = this.iconY; int currentIconY = this.iconY;

View File

@@ -1,23 +1,19 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*; import net.minecraft.client.gui.*;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.io.IOException; import java.io.IOException;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT)
public class GuiNumberField extends Gui { public class GuiNumberField extends Gui {
public int x, y, width, height; int x, y, width, height;
public int buttonWidth = 10; int buttonWidth = 10;
protected GuiTextField textField; protected GuiTextField textField;
protected GuiButton minusButton, plusButton; protected GuiButton minusButton, plusButton;
@@ -32,42 +28,21 @@ public class GuiNumberField extends Gui {
this.height = height; this.height = height;
textField = new GuiTextField(id1, fontRenderer, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2); textField = new GuiTextField(id1, fontRenderer, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2);
minusButton = new GuiButton(id2, x, y - 1, buttonWidth, height + 2, "-") { minusButton = new GuiButton(id2, x, y - 1, buttonWidth, height + 2, "-");
@Override plusButton = new GuiButton(id3, x + width - buttonWidth, y - 1, buttonWidth, height + 2, "+");
public void onClick(double mouseX, double mouseY) {
float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
setNumber(getNumber() - valueChanged);
}
};
plusButton = new GuiButton(id3, x + width - buttonWidth, y - 1, buttonWidth, height + 2, "+") {
@Override
public void onClick(double mouseX, double mouseY) {
float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
setNumber(getNumber() + valueChanged);
}
};
buttonList.add(minusButton); buttonList.add(minusButton);
buttonList.add(plusButton); buttonList.add(plusButton);
} }
public void setNumber(double number) { public void setNumber(double number) {
textField.setText(DecimalFormat.getInstance().format(number)); DecimalFormat format = new DecimalFormat("0.#");
textField.setText(format.format(number));
} }
public double getNumber() { public double getNumber() {
if (textField.getText().isEmpty()) return 0; if (textField.getText().isEmpty()) return 0;
try { return Double.parseDouble(textField.getText());
return DecimalFormat.getInstance().parse(textField.getText()).doubleValue();
} catch (ParseException e) {
return 0;
}
} }
public void setTooltip(String tooltip) { public void setTooltip(String tooltip) {
@@ -78,7 +53,7 @@ public class GuiNumberField extends Gui {
this.tooltip = tooltip; this.tooltip = tooltip;
} }
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) {
boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton); boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton);
//Check if clicked inside textfield //Check if clicked inside textfield
@@ -94,14 +69,14 @@ public class GuiNumberField extends Gui {
return result; return result;
} }
public void drawNumberField(int mouseX, int mouseY, float partialTicks) { public void drawNumberField(Minecraft mc, int mouseX, int mouseY, float partialTicks) {
textField.y = y + 1; textField.y = y + 1;
minusButton.y = y - 1; minusButton.y = y - 1;
plusButton.y = y - 1; plusButton.y = y - 1;
textField.drawTextField(mouseX, mouseY, partialTicks); textField.drawTextBox();
minusButton.render(mouseX, mouseY, partialTicks); minusButton.drawButton(mc, mouseX, mouseY, partialTicks);
plusButton.render(mouseX, mouseY, partialTicks); plusButton.drawButton(mc, mouseX, mouseY, partialTicks);
} }
public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) { public void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY) {
@@ -131,21 +106,33 @@ public class GuiNumberField extends Gui {
} }
public void update() { protected void actionPerformed(GuiButton button) {
textField.tick(); float valueChanged = 1f;
if (GuiScreen.isCtrlKeyDown()) valueChanged = 5f;
if (GuiScreen.isShiftKeyDown()) valueChanged = 10f;
if (button == minusButton) {
setNumber(getNumber() - valueChanged);
}
if (button == plusButton) {
setNumber(getNumber() + valueChanged);
}
} }
public boolean charTyped(char typedChar, int keyCode) { public void update() {
if (!textField.isFocused()) return false; textField.updateCursorCounter();
}
protected void keyTyped(char typedChar, int keyCode) throws IOException {
if (!textField.isFocused()) return;
// if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK // if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK
// || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT // || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT
// || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) { // || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) {
return textField.charTyped(typedChar, keyCode); textField.textboxKeyTyped(typedChar, keyCode);
// } // }
} }
//Scroll inside textfield to change number //Scroll inside textfield to change number
//Disabled because entire screen can be scrolled
// public void handleMouseInput(int mouseX, int mouseY) { // public void handleMouseInput(int mouseX, int mouseY) {
// boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height; // boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
// //

View File

@@ -1,37 +1,29 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.MouseHelper; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*; import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiListExtended;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.Util;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.client.event.GuiScreenEvent; import org.lwjgl.input.Mouse;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.glfw.GLFW;
import sun.security.ssl.Debug;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT) @SideOnly(Side.CLIENT)
public class GuiScrollPane extends GuiSlot { public class GuiScrollPane extends GuiListExtended {
public GuiScreen parent; public GuiScreen parent;
public FontRenderer fontRenderer; public FontRenderer fontRenderer;
private List<IScrollEntry> listEntries; public List<IScrollEntry> listEntries;
private float scrollMultiplier = 1f;
private int mouseX;
private int mouseY;
public GuiScrollPane(GuiScreen parent, FontRenderer fontRenderer, int top, int bottom) { public GuiScrollPane(GuiScreen parent, FontRenderer fontRenderer, int top, int bottom) {
super(parent.mc, parent.width, parent.height, top, bottom, 100); super(parent.mc, parent.width, parent.height, top, bottom, 100);
@@ -39,27 +31,18 @@ public class GuiScrollPane extends GuiSlot {
this.fontRenderer = fontRenderer; this.fontRenderer = fontRenderer;
this.setShowSelectionBox(false); this.setShowSelectionBox(false);
listEntries = new ArrayList<>(); listEntries = new ArrayList<>();
MinecraftForge.EVENT_BUS.register(this);
} }
public IScrollEntry getListEntry(int index) { @Override
public IGuiListEntry getListEntry(int index) {
return listEntries.get(index); return listEntries.get(index);
} }
public void AddListEntry(IScrollEntry listEntry){
listEntries.add(listEntry);
}
@Override @Override
protected int getSize() { protected int getSize() {
return listEntries.size(); return listEntries.size();
} }
@Override
protected boolean isSelected(int slotIndex) {
return false;
}
@Override @Override
protected int getScrollBarX() { protected int getScrollBarX() {
//return width / 2 + 140 + 10; //return width / 2 + 140 + 10;
@@ -96,15 +79,15 @@ public class GuiScrollPane extends GuiSlot {
//All entries //All entries
this.drawSelectionBox(insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks); this.drawSelectionBox(insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks);
GlStateManager.disableDepthTest(); GlStateManager.disableDepth();
//Dirt overlays on top and bottom //Dirt overlays on top and bottom
// this.overlayBackground(0, this.top, 255, 255); // this.overlayBackground(0, this.top, 255, 255);
// this.overlayBackground(this.bottom, this.height, 255, 255); // this.overlayBackground(this.bottom, this.height, 255, 255);
GlStateManager.enableBlend(); GlStateManager.enableBlend();
GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
GlStateManager.disableAlphaTest(); GlStateManager.disableAlpha();
GlStateManager.shadeModel(7425); GlStateManager.shadeModel(7425);
GlStateManager.disableTexture2D(); GlStateManager.disableTexture2D();
@@ -177,7 +160,7 @@ public class GuiScrollPane extends GuiSlot {
GlStateManager.enableTexture2D(); GlStateManager.enableTexture2D();
GlStateManager.shadeModel(7424); GlStateManager.shadeModel(7424);
GlStateManager.enableAlphaTest(); GlStateManager.enableAlpha();
GlStateManager.disableBlend(); GlStateManager.disableBlend();
} }
} }
@@ -194,17 +177,6 @@ public class GuiScrollPane extends GuiSlot {
return height; return height;
} }
@Override
protected void drawBackground() {
}
@Override
protected void drawSlot(int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) {
this.getListEntry(slotIndex).drawEntry(slotIndex, xPos, yPos, this.getListWidth(), heightIn, mouseXIn, mouseYIn,
this.getSlotIndexFromScreenCoords(mouseXIn, mouseYIn) == slotIndex, partialTicks);
}
public int getContentHeight(int count) { public int getContentHeight(int count) {
//Add all count entry heights //Add all count entry heights
int height = this.headerPadding; int height = this.headerPadding;
@@ -215,10 +187,11 @@ public class GuiScrollPane extends GuiSlot {
return height; return height;
} }
public int getSlotIndexFromScreenCoords(double posX, double posY) { @Override
public int getSlotIndexFromScreenCoords(int posX, int posY) {
int left = this.left + (this.width - this.getListWidth()) / 2; int left = this.left + (this.width - this.getListWidth()) / 2;
int right = this.left + (this.width + this.getListWidth()) / 2; int right = this.left + (this.width + this.getListWidth()) / 2;
double relativeMouseY = getRelativeMouseY(mouseY, 0); int relativeMouseY = getRelativeMouseY(mouseY, 0);
//Iterate over every entry until relativeMouseY falls within its height //Iterate over every entry until relativeMouseY falls within its height
for (int i = 0; i < listEntries.size(); i++) { for (int i = 0; i < listEntries.size(); i++) {
@@ -232,14 +205,15 @@ public class GuiScrollPane extends GuiSlot {
} }
@Override @Override
protected boolean mouseClicked(int index, int button, double mouseX, double mouseY) { public boolean mouseClicked(int mouseX, int mouseY, int mouseEvent)
{
int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY); int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
double relativeX = getRelativeMouseX(mouseX); int relativeX = getRelativeMouseX(mouseX);
//Always pass through mouseclicked, to be able to unfocus textfields //Always pass through mouseclicked, to be able to unfocus textfields
for (int i = 0; i < this.listEntries.size(); i++) { for (int i = 0; i < this.listEntries.size(); i++) {
double relativeY = getRelativeMouseY(mouseY, i); int relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mousePressed(selectedSlot, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY); this.getListEntry(i).mousePressed(selectedSlot, mouseX, mouseY, mouseEvent, relativeX, relativeY);
} }
@@ -264,36 +238,38 @@ public class GuiScrollPane extends GuiSlot {
} }
@Override @Override
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) { public boolean mouseReleased(int x, int y, int mouseEvent)
{
for (int i = 0; i < this.getSize(); ++i) for (int i = 0; i < this.getSize(); ++i)
{ {
double relativeX = getRelativeMouseX(mouseX); int relativeX = getRelativeMouseX(mouseX);
double relativeY = getRelativeMouseY(mouseY, i); int relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mouseReleased(i, (int) p_mouseReleased_1_, (int) p_mouseReleased_3_, p_mouseReleased_5_, (int) relativeX, (int) relativeY); this.getListEntry(i).mouseReleased(i, x, y, mouseEvent, relativeX, relativeY);
} }
this.visible = true; this.setEnabled(true);
return false; return false;
} }
@Override
public void handleMouseInput() { public void handleMouseInput() {
if (this.isMouseInList(this.mouseX, this.mouseY)) { if (this.isMouseYWithinSlotBounds(this.mouseY)) {
if (mc.mouseHelper.isLeftDown() && this.mouseY >= this.top && if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState() && this.mouseY >= this.top &&
this.mouseY <= this.bottom) { this.mouseY <= this.bottom) {
int i = this.left + (this.width - this.getListWidth()) / 2; int i = this.left + (this.width - this.getListWidth()) / 2;
int j = this.left + (this.width + this.getListWidth()) / 2; int j = this.left + (this.width + this.getListWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY); int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex); int relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) { if (slotIndex > -1) {
this.mouseClicked(slotIndex, 0, this.mouseX, this.mouseY); this.elementClicked(slotIndex, false, this.mouseX, this.mouseY);
this.selectedElement = slotIndex; this.selectedElement = slotIndex;
} else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) { } else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i, this.mouseY - this.top + (int) this.amountScrolled - 4); this.clickedHeader(this.mouseX - i, this.mouseY - this.top + (int) this.amountScrolled - 4);
} }
} }
if (mc.mouseHelper.isLeftDown() && this.isVisible()) { if (Mouse.isButtonDown(0) && this.getEnabled()) {
if (this.initialClickY == -1) { if (this.initialClickY == -1) {
boolean flag1 = true; boolean flag1 = true;
@@ -301,15 +277,14 @@ public class GuiScrollPane extends GuiSlot {
int i2 = this.left + (this.width - this.getListWidth()) / 2; int i2 = this.left + (this.width - this.getListWidth()) / 2;
int j2 = this.left + (this.width + this.getListWidth()) / 2; int j2 = this.left + (this.width + this.getListWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY); int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex); int relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) { if (slotIndex > -1) {
//TODO 1.13 use flag
boolean flag = slotIndex == this.selectedElement && boolean flag = slotIndex == this.selectedElement &&
Util.milliTime() - this.lastClicked < 250L; Minecraft.getSystemTime() - this.lastClicked < 250L;
this.mouseClicked(slotIndex, this.mouseX, this.mouseY); this.elementClicked(slotIndex, flag, this.mouseX, this.mouseY);
this.selectedElement = slotIndex; this.selectedElement = slotIndex;
this.lastClicked = Util.milliTime(); this.lastClicked = Minecraft.getSystemTime();
} else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) { } else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i2, this.clickedHeader(this.mouseX - i2,
this.mouseY - this.top + (int) this.amountScrolled - 4); this.mouseY - this.top + (int) this.amountScrolled - 4);
@@ -351,21 +326,17 @@ public class GuiScrollPane extends GuiSlot {
this.initialClickY = -1; this.initialClickY = -1;
} }
} int i2 = Mouse.getEventDWheel();
}
//Through forge event instead of through the parent, because the parent no longer has scroll functionality in 1.13 if (i2 != 0) {
@SubscribeEvent if (i2 > 0) {
public void mouseScrolled(GuiScreenEvent.MouseScrollEvent.Pre event) { i2 = -1;
double scrollDelta = event.getScrollDelta(); } else if (i2 < 0) {
if (scrollDelta != 0) { i2 = 1;
if (scrollDelta > 0) { }
scrollDelta = -1;
} else if (scrollDelta < 0) { this.amountScrolled += (float) (i2 * this.slotHeight / 2);
scrollDelta = 1;
} }
this.amountScrolled += (float) (scrollDelta * this.slotHeight / 2);
} }
} }
@@ -402,7 +373,7 @@ public class GuiScrollPane extends GuiSlot {
{ {
int i1 = this.left + this.width / 2 - this.getListWidth() / 2; int i1 = this.left + this.width / 2 - this.getListWidth() / 2;
int j1 = this.left + this.width / 2 + this.getListWidth() / 2; int j1 = this.left + this.width / 2 + this.getListWidth() / 2;
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableTexture2D(); GlStateManager.disableTexture2D();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i1, (double)(y + entryHeight2 + 2), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex(); bufferbuilder.pos((double)i1, (double)(y + entryHeight2 + 2), 0.0D).tex(0.0D, 1.0D).color(128, 128, 128, 255).endVertex();
@@ -422,14 +393,14 @@ public class GuiScrollPane extends GuiSlot {
} }
} }
private double getRelativeMouseX(double mouseX) { private int getRelativeMouseX(int mouseX) {
int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2; int j = this.left + this.width / 2 - this.getListWidth() / 2 + 2;
return mouseX - j; return mouseX - j;
} }
private double getRelativeMouseY(double mouseY, int contentIndex) { private int getRelativeMouseY(int mouseY, int contentIndex) {
int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(contentIndex) + this.headerPadding; int k = this.top + 4 - this.getAmountScrolled() + getContentHeight(contentIndex) + this.headerPadding;
double relativeMouseY = mouseY - k; int relativeMouseY = mouseY - k;
//Content might be centered, adjust relative mouse y accordingly //Content might be centered, adjust relative mouse y accordingly
int contentHeight = getContentHeight(); int contentHeight = getContentHeight();
@@ -447,6 +418,7 @@ public class GuiScrollPane extends GuiSlot {
for (IScrollEntry entry : this.listEntries) { for (IScrollEntry entry : this.listEntries) {
id = entry.initGui(id, buttonList); id = entry.initGui(id, buttonList);
} }
registerScrollButtons(id++, id++);
return id; return id;
} }
@@ -460,11 +432,14 @@ public class GuiScrollPane extends GuiSlot {
entry.drawTooltip(guiScreen, mouseX, mouseY); entry.drawTooltip(guiScreen, mouseX, mouseY);
} }
@Override public void keyTyped(char eventChar, int eventKey) throws IOException {
public boolean charTyped(char eventChar, int eventKey) {
for (IScrollEntry entry : this.listEntries) for (IScrollEntry entry : this.listEntries)
entry.charTyped(eventChar, eventKey); entry.keyTyped(eventChar, eventKey);
return false; }
public void actionPerformed(GuiButton button) {
for (IScrollEntry entry : this.listEntries)
entry.actionPerformed(button);
} }
public void onGuiClosed() { public void onGuiClosed() {
@@ -472,32 +447,19 @@ public class GuiScrollPane extends GuiSlot {
entry.onGuiClosed(); entry.onGuiClosed();
} }
public interface IScrollEntry { public interface IScrollEntry extends GuiListExtended.IGuiListEntry {
int initGui(int id, List<GuiButton> buttonList); int initGui(int id, List<GuiButton> buttonList);
void updateScreen(); void updateScreen();
void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY); void drawTooltip(GuiScreen guiScreen, int mouseX, int mouseY);
boolean charTyped(char eventChar, int eventKey); void keyTyped(char eventChar, int eventKey) throws IOException;
void actionPerformed(GuiButton button);
void onGuiClosed(); void onGuiClosed();
int getHeight(); int getHeight();
void updatePosition(int slotIndex, int x, int y, float partialTicks);
void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks);
/**
* Called when the mouse is clicked within this entry. Returning true means that something within this entry was
* clicked and the list should not be dragged.
*/
boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY);
/**
* Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY
*/
void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY);
} }
} }

View File

@@ -1,20 +1,14 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
@@ -22,8 +16,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT)
public class MirrorSettingsGui extends GuiCollapsibleScrollEntry { public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
@@ -46,13 +38,7 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
id = super.initGui(id, buttonList); id = super.initGui(id, buttonList);
int y = top - 2; int y = top - 2;
buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) { buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonMirrorEnabled.isChecked());
}
};
buttonList.add(buttonMirrorEnabled); buttonList.add(buttonMirrorEnabled);
y = top + 18; y = top + 18;
@@ -92,68 +78,25 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
mirrorNumberFieldList.add(textMirrorRadius); mirrorNumberFieldList.add(textMirrorRadius);
y = top + 72; y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS) { buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
}
};
buttonCurrentPosition.setTooltip("Set mirror position to current player position"); buttonCurrentPosition.setTooltip("Set mirror position to current player position");
mirrorIconButtonList.add(buttonCurrentPosition); mirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS) { buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
}
};
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
mirrorIconButtonList.add(buttonToggleOdd); mirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS) { buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
};
buttonDrawLines.setTooltip("Show lines"); buttonDrawLines.setTooltip("Show lines");
mirrorIconButtonList.add(buttonDrawLines); mirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS) { buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
};
buttonDrawPlanes.setTooltip("Show area"); buttonDrawPlanes.setTooltip("Show area");
mirrorIconButtonList.add(buttonDrawPlanes); mirrorIconButtonList.add(buttonDrawPlanes);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (modifierSettings != null) { if (buildSettings != null) {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled); buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x); textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y); textMirrorPosY.setNumber(m.position.y);
@@ -195,30 +138,31 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
@Override @Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) { boolean isSelected, float partialTicks) {
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partialTicks);
int yy = y; int yy = y;
int offset = 8; int offset = 8;
buttonMirrorEnabled.render(mouseX, mouseY, partialTicks); buttonMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonMirrorEnabled.isChecked()) { if (buttonMirrorEnabled.isChecked()) {
buttonMirrorEnabled.y = yy; buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror enabled", left + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Mirror enabled", left + offset, yy + 2, 0xFFFFFF, true);
yy = y + 18; yy = y + 18;
fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosX.y = yy; textMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosY.y = yy; textMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF, true);
textMirrorPosZ.y = yy; textMirrorPosZ.y = yy;
yy = y + 50; yy = y + 50;
fontRenderer.drawString("Direction", left + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Direction", left + offset, yy + 2, 0xFFFFFF, true);
buttonMirrorX.y = yy; buttonMirrorX.y = yy;
buttonMirrorY.y = yy; buttonMirrorY.y = yy;
buttonMirrorZ.y = yy; buttonMirrorZ.y = yy;
fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF, true);
textMirrorRadius.y = yy - 3; textMirrorRadius.y = yy - 3;
yy = y + 72; yy = y + 72;
@@ -227,12 +171,12 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
buttonDrawLines.y = yy; buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy; buttonDrawPlanes.y = yy;
mirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); mirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); mirrorIconButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks)); mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else { } else {
buttonMirrorEnabled.y = yy; buttonMirrorEnabled.y = yy;
fontRenderer.drawString("Mirror disabled", left + offset, yy + 2, 0x999999); fontRenderer.drawString("Mirror disabled", left + offset, yy + 2, 0x999999, true);
} }
} }
@@ -247,28 +191,74 @@ public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
} }
@Override @Override
public boolean charTyped(char typedChar, int keyCode) { public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
super.charTyped(typedChar, keyCode); super.updatePosition(slotIndex, x, y, partialTicks);
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : mirrorNumberFieldList) { for (GuiNumberField numberField : mirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode); numberField.keyTyped(typedChar, keyCode);
} }
return true;
} }
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
super.mousePressed(slotIndex, mouseX, mouseY, mouseEvent, relativeX, relativeY);
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideMirrorEnabledLabel) { if (insideMirrorEnabledLabel) {
buttonMirrorEnabled.setIsChecked(!buttonMirrorEnabled.isChecked());
buttonMirrorEnabled.playPressSound(this.mc.getSoundHandler()); buttonMirrorEnabled.playPressSound(this.mc.getSoundHandler());
buttonMirrorEnabled.onClick(mouseX, mouseY); actionPerformed(buttonMirrorEnabled);
} }
return true; return true;
} }
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonMirrorEnabled) {
setCollapsed(!buttonMirrorEnabled.isChecked());
}
if (button == buttonCurrentPosition) {
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z);
}
if (button == buttonToggleOdd) {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
}
}
if (button == buttonDrawLines) {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
if (button == buttonDrawPlanes) {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
mirrorNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public Mirror.MirrorSettings getMirrorSettings() { public Mirror.MirrorSettings getMirrorSettings() {
boolean mirrorEnabled = buttonMirrorEnabled.isChecked(); boolean mirrorEnabled = buttonMirrorEnabled.isChecked();

View File

@@ -1,20 +1,14 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiScreen;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.config.GuiCheckBox; import net.minecraftforge.fml.client.config.GuiCheckBox;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.RadialMirror;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiCollapsibleScrollEntry;
import nl.requios.effortlessbuilding.gui.elements.GuiIconButton;
import nl.requios.effortlessbuilding.gui.elements.GuiNumberField;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.io.IOException; import java.io.IOException;
@@ -22,8 +16,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@SuppressWarnings("Duplicates")
@OnlyIn(Dist.CLIENT)
public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry { public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
@@ -46,13 +38,7 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
id = super.initGui(id, buttonList); id = super.initGui(id, buttonList);
int y = top - 2; int y = top - 2;
buttonRadialMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false) { buttonRadialMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
}
};
buttonList.add(buttonRadialMirrorEnabled); buttonList.add(buttonRadialMirrorEnabled);
y = top + 18; y = top + 18;
@@ -86,63 +72,21 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades.")); TextFormatting.GRAY + "Upgradeable in survival with reach upgrades."));
radialMirrorNumberFieldList.add(textRadialMirrorRadius); radialMirrorNumberFieldList.add(textRadialMirrorRadius);
y = top + 72; y = top + 72;
buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS) { buttonCurrentPosition = new GuiIconButton(id++, left + 5, y, 0, 0, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.setNumber(pos.z);
}
};
buttonCurrentPosition.setTooltip("Set radial mirror position to current player position"); buttonCurrentPosition.setTooltip("Set radial mirror position to current player position");
radialMirrorIconButtonList.add(buttonCurrentPosition); radialMirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS) { buttonToggleOdd = new GuiIconButton(id++, left + 35, y, 0, 20, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber()));
}
}
};
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds"));
radialMirrorIconButtonList.add(buttonToggleOdd); radialMirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS) { buttonDrawLines = new GuiIconButton(id++, left + 65, y, 0, 40, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
};
buttonDrawLines.setTooltip("Show lines"); buttonDrawLines.setTooltip("Show lines");
radialMirrorIconButtonList.add(buttonDrawLines); radialMirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS) { buttonDrawPlanes = new GuiIconButton(id++, left + 95, y, 0, 60, BUILDING_ICONS);
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
};
buttonDrawPlanes.setTooltip("Show area"); buttonDrawPlanes.setTooltip("Show area");
radialMirrorIconButtonList.add(buttonDrawPlanes); radialMirrorIconButtonList.add(buttonDrawPlanes);
@@ -150,9 +94,9 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false); buttonRadialMirrorAlternate = new GuiCheckBox(id++, left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate); radialMirrorButtonList.add(buttonRadialMirrorAlternate);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (modifierSettings != null) { if (buildSettings != null) {
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled); buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x); textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y); textRadialMirrorPosY.setNumber(r.position.y);
@@ -184,36 +128,38 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
return id; return id;
} }
@Override
public void updateScreen() { public void updateScreen() {
super.updateScreen();
radialMirrorNumberFieldList.forEach(GuiNumberField::update); radialMirrorNumberFieldList.forEach(GuiNumberField::update);
} }
@Override @Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) { boolean isSelected, float partialTicks) {
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partialTicks);
int yy = y; int yy = y;
int offset = 8; int offset = 8;
buttonRadialMirrorEnabled.render(mouseX, mouseY, partialTicks); buttonRadialMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks);
if (buttonRadialMirrorEnabled.isChecked()) { if (buttonRadialMirrorEnabled.isChecked()) {
buttonRadialMirrorEnabled.y = yy; buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF, true);
yy = y + 18; yy = y + 18;
fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Position", left + offset, yy + 5, 0xFFFFFF, true);
fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF, true);
textRadialMirrorPosX.y = yy; textRadialMirrorPosX.y = yy;
fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF, true);
textRadialMirrorPosY.y = yy; textRadialMirrorPosY.y = yy;
fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF); fontRenderer.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF, true);
textRadialMirrorPosZ.y = yy; textRadialMirrorPosZ.y = yy;
yy = y + 50; yy = y + 50;
fontRenderer.drawString("Slices", left + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Slices", left + offset, yy + 2, 0xFFFFFF, true);
textRadialMirrorSlices.y = yy - 3; textRadialMirrorSlices.y = yy - 3;
fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF); fontRenderer.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF, true);
textRadialMirrorRadius.y = yy - 3; textRadialMirrorRadius.y = yy - 3;
yy = y + 72; yy = y + 72;
@@ -225,13 +171,13 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
yy = y + 76; yy = y + 76;
buttonRadialMirrorAlternate.y = yy; buttonRadialMirrorAlternate.y = yy;
radialMirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); radialMirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
radialMirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); radialMirrorIconButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks));
radialMirrorNumberFieldList radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks)); .forEach(numberField -> numberField.drawNumberField(this.mc, mouseX, mouseY, partialTicks));
} else { } else {
buttonRadialMirrorEnabled.y = yy; buttonRadialMirrorEnabled.y = yy;
fontRenderer.drawString("Radial mirror disabled", left + offset, yy + 2, 0x999999); fontRenderer.drawString("Radial mirror disabled", left + offset, yy + 2, 0x999999, true);
} }
} }
@@ -246,28 +192,74 @@ public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
} }
@Override @Override
public boolean charTyped(char typedChar, int keyCode) { public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
super.charTyped(typedChar, keyCode); super.updatePosition(slotIndex, x, y, partialTicks);
}
@Override
public void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (GuiNumberField numberField : radialMirrorNumberFieldList) { for (GuiNumberField numberField : radialMirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode); numberField.keyTyped(typedChar, keyCode);
} }
return true;
} }
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
super.mousePressed(slotIndex, mouseX, mouseY, mouseEvent, relativeX, relativeY);
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideRadialMirrorEnabledLabel) { if (insideRadialMirrorEnabledLabel) {
buttonRadialMirrorEnabled.setIsChecked(!buttonRadialMirrorEnabled.isChecked());
buttonRadialMirrorEnabled.playPressSound(this.mc.getSoundHandler()); buttonRadialMirrorEnabled.playPressSound(this.mc.getSoundHandler());
buttonRadialMirrorEnabled.onClick(mouseX, mouseY); actionPerformed(buttonRadialMirrorEnabled);
} }
return true; return true;
} }
@Override
public void actionPerformed(GuiButton button) {
super.actionPerformed(button);
if (button == buttonRadialMirrorEnabled) {
setCollapsed(!buttonRadialMirrorEnabled.isChecked());
}
if (button == buttonCurrentPosition) {
Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5);
textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.setNumber(pos.z);
}
if (button == buttonToggleOdd) {
toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds"));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds"));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber()));
}
}
if (button == buttonDrawLines) {
drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines");
}
if (button == buttonDrawPlanes) {
drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area");
}
radialMirrorNumberFieldList.forEach(numberField -> numberField.actionPerformed(button));
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() { public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked(); boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked();

View File

@@ -23,20 +23,20 @@ public class RandomizerBagContainer extends Container {
bagInventory = parIInventory; bagInventory = parIInventory;
sizeInventory = bagInventory.getSlots(); sizeInventory = bagInventory.getSlots();
for (int i = 0; i < sizeInventory; ++i) { for (int i = 0; i < sizeInventory; ++i) {
this.addSlot(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20)); this.addSlotToContainer(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20));
} }
// add player inventory slots // add player inventory slots
int i; int i;
for (i = 0; i < 3; ++i) { for (i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) { for (int j = 0; j < 9; ++j) {
addSlot(new Slot(parInventoryPlayer, j + i * 9 + 9, 8 + j * 18, 51 + i * 18)); addSlotToContainer(new Slot(parInventoryPlayer, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
} }
} }
// add hotbar slots // add hotbar slots
for (i = 0; i < 9; ++i) { for (i = 0; i < 9; ++i) {
addSlot(new Slot(parInventoryPlayer, i, 8 + i * 18, 109)); addSlotToContainer(new Slot(parInventoryPlayer, i, 8 + i * 18, 109));
} }
} }
@@ -109,22 +109,26 @@ public class RandomizerBagContainer extends Container {
@Override @Override
public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) { public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, EntityPlayer player) {
// this will prevent the player from interacting with the item that opened the inventory: // this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack().equals(player.getHeldItem(EnumHand.MAIN_HAND))) { ItemStack clickItemStack = super.slotClick(slot, dragType, clickTypeIn, player);
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack() == player.getHeldItem(EnumHand.MAIN_HAND)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
return super.slotClick(slot, dragType, clickTypeIn, player); return clickItemStack;
} }
/** /**
* Callback for when the crafting gui is closed. * Callback for when the crafting gui is closed.
*/ */
@Override // @Override
public void onContainerClosed(EntityPlayer player) // public void onContainerClosed(EntityPlayer player)
{ // {
super.onContainerClosed(player); // if(player.inventory.getItemStack() != null)
if(!player.world.isRemote) // {
{ // player.entityDropItem(player.inventory.getItemStack(), 0.5f);
detectAndSendChanges(); // }
} // if(!player.world.isRemote)
} // {
// detectAndSendChanges();
// }
// }
} }

View File

@@ -4,15 +4,15 @@ import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
@OnlyIn(Dist.CLIENT) @SideOnly(Side.CLIENT)
public class RandomizerBagGuiContainer extends GuiContainer { public class RandomizerBagGuiContainer extends GuiContainer {
private static final ResourceLocation guiTextures = private static final ResourceLocation guiTextures =
new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png"); new ResourceLocation(EffortlessBuilding.MODID + ":textures/gui/container/randomizerbag.png");
private final InventoryPlayer inventoryPlayer; private final InventoryPlayer inventoryPlayer;
private final IItemHandler inventoryBag; private final IItemHandler inventoryBag;
@@ -25,9 +25,9 @@ public class RandomizerBagGuiContainer extends GuiContainer {
} }
@Override @Override
public void render(int mouseX, int mouseY, float partialTicks) { public void drawScreen(int mouseX, int mouseY, float partialTicks) {
drawDefaultBackground(); drawDefaultBackground();
super.render(mouseX, mouseY, partialTicks); super.drawScreen(mouseX, mouseY, partialTicks);
this.renderHoveredToolTip(mouseX, mouseY); this.renderHoveredToolTip(mouseX, mouseY);
} }
@@ -35,12 +35,12 @@ public class RandomizerBagGuiContainer extends GuiContainer {
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) {
String s = "Randomizer Bag"; String s = "Randomizer Bag";
fontRenderer.drawString(s, 8, 6, 0x404040); fontRenderer.drawString(s, 8, 6, 0x404040);
fontRenderer.drawString(inventoryPlayer.getDisplayName().getUnformattedComponentText(), 8, ySize - 96 + 2, 0x404040); fontRenderer.drawString(inventoryPlayer.getDisplayName().getUnformattedText(), 8, ySize - 96 + 2, 0x404040);
} }
@Override @Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
GlStateManager.color3f(1.0F, 1.0F, 1.0F); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
mc.getTextureManager().bindTexture(guiTextures); mc.getTextureManager().bindTexture(guiTextures);
int marginHorizontal = (width - xSize) / 2; int marginHorizontal = (width - xSize) / 2;
int marginVertical = (height - ySize) / 2; int marginVertical = (height - ySize) / 2;

View File

@@ -1,112 +1,41 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.network.FMLPlayMessages; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class RandomizerBagGuiHandler implements /*IGuiHandler, */IInteractionObject { public class RandomizerBagGuiHandler implements IGuiHandler {
// @Nullable @Nullable
// @Override @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 == EffortlessBuilding.RANDOMIZER_BAG_GUI) { if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// // Use the player's held item to create the container // Use the player's held item to create the container
// LazyOptional<IItemHandler> capabilityOptional = player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); IItemHandler capability = player.getHeldItemMainhand().hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) ?
// player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) :
// if (!capabilityOptional.isPresent()) { player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
// capabilityOptional = player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); return new RandomizerBagContainer(player.inventory, capability);
// }
//
// return new RandomizerBagContainer(player.inventory, capabilityOptional.orElse(null));
// }
// return null;
// }
//
// @Nullable
// @Override
// @OnlyIn(Dist.CLIENT)
// public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
// if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// // Use the player's held item to create the client-side gui container
// LazyOptional<IItemHandler> capabilityOptional = player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
//
// if (!capabilityOptional.isPresent()) {
// capabilityOptional = player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
// }
//
// return new RandomizerBagGuiContainer(player.inventory, capabilityOptional.orElse(null));
// }
// return null;
// }
@OnlyIn(Dist.CLIENT)
public static GuiScreen openGui(FMLPlayMessages.OpenContainer openContainer) {
if (openContainer.getId().equals(EffortlessBuilding.RANDOMIZER_BAG_GUI)) {
EntityPlayerSP player = Minecraft.getInstance().player;
if (player.getHeldItem(EnumHand.MAIN_HAND).getItem() instanceof ItemRandomizerBag) {
IItemHandler itemHandler = player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (itemHandler != null) {
return new RandomizerBagGuiContainer(player.inventory, itemHandler);
}
}
} }
return null; return null;
} }
@Override
public Container createContainer(InventoryPlayer inventory, EntityPlayer player) {
if (player.getHeldItem(EnumHand.MAIN_HAND).getItem() instanceof ItemRandomizerBag) {
IItemHandler itemHandler = player.getHeldItem(EnumHand.MAIN_HAND).getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (itemHandler != null) {
return new RandomizerBagContainer(inventory, itemHandler);
}
}
return null;
}
@Override
public String getGuiID() {
return EffortlessBuilding.RANDOMIZER_BAG_GUI.toString();
}
@Override
public ITextComponent getName() {
return new TextComponentString("Randomizer Bag");
}
@Override
public boolean hasCustomName() {
return false;
}
@Override
public ITextComponent getDisplayName() {
return new TextComponentString("Randomizer Bag");
}
@Nullable @Nullable
@Override @Override
public ITextComponent getCustomName() { @SideOnly(Side.CLIENT)
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) {
// Use the player's held item to create the client-side gui container
IItemHandler capability = player.getHeldItemMainhand().hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) ?
player.getHeldItemMainhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null) :
player.getHeldItemOffhand().getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
return new RandomizerBagGuiContainer(player.inventory, capability);
}
return null; return null;
} }
} }

View File

@@ -0,0 +1,132 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.io.IOException;
public class SettingsGui extends GuiScreen {
private GuiScrollPane scrollPane;
private GuiButton buttonClose;
private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui;
@Override
//Create buttons and labels and add them to buttonList/labelList
public void initGui() {
int id = 0;
scrollPane = new GuiScrollPane(this, fontRenderer, 8, height - 30);
mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
scrollPane.listEntries.add(mirrorSettingsGui);
arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.listEntries.add(arraySettingsGui);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.listEntries.add(radialMirrorSettingsGui);
id = scrollPane.initGui(id, buttonList);
//Close button
int y = height - 26;
buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close");
buttonList.add(buttonClose);
}
@Override
//Process general logic, i.e. hide buttons
public void updateScreen() {
scrollPane.updateScreen();
}
@Override
//Set colors using GL11, use the fontRendererObj field to display text
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
this.drawDefaultBackground();
scrollPane.drawScreen(mouseX, mouseY, partialTicks);
buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks);
scrollPane.drawTooltip(this, mouseX, mouseY);
}
@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
scrollPane.keyTyped(typedChar, keyCode);
if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) {
mc.player.closeScreen();
}
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override
protected void mouseReleased(int mouseX, int mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
{
super.mouseReleased(mouseX, mouseY, state);
}
}
@Override
public void handleMouseInput() throws IOException {
super.handleMouseInput();
scrollPane.handleMouseInput();
//Scrolling numbers
// int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
// int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
// numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY));
}
@Override
protected void actionPerformed(GuiButton button) {
//check what button and action type (left/right click)
if (button == buttonClose) {
mc.player.closeScreen();
}
scrollPane.actionPerformed(button);
}
@Override
public void onGuiClosed() {
scrollPane.onGuiClosed();
//save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (buildSettings == null) buildSettings = new BuildSettingsManager.BuildSettings();
buildSettings.setMirrorSettings(m);
buildSettings.setArraySettings(a);
buildSettings.setRadialMirrorSettings(r);
//Sanitize
String error = BuildSettingsManager.sanitize(buildSettings, mc.player);
if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error);
BuildSettingsManager.setBuildSettings(mc.player, buildSettings);
//Send to server
EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings));
}
}

View File

@@ -1,478 +0,0 @@
package nl.requios.effortlessbuilding.gui.buildmode;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.text.TextFormatting;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.opengl.GL11;
import com.google.common.base.Stopwatch;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.client.model.ModelLoader;
import static nl.requios.effortlessbuilding.buildmode.BuildModes.*;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
/**
* From Chisels and Bits by AlgorithmX2
* https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java
*/
public class RadialMenu extends GuiScreen {
private final float TIME_SCALE = 0.01f;
public static final RadialMenu instance = new RadialMenu();
private float visibility = 0.0f;
private Stopwatch lastChange = Stopwatch.createStarted();
public BuildModeEnum switchTo = null;
public ActionEnum doAction = null;
public boolean actionUsed = false;
private float clampVis(final float f) {
return Math.max( 0.0f, Math.min( 1.0f, f ) );
}
public void raiseVisibility() {
visibility = clampVis( visibility + lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
public void decreaseVisibility() {
visibility = clampVis( visibility - lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE );
lastChange = Stopwatch.createStarted();
}
public void setVisibility(float visibility) {
this.visibility = visibility;
}
public boolean isVisible() {
return visibility > 0.001;
}
public void configure(final int scaledWidth, final int scaledHeight ) {
mc = Minecraft.getInstance();
fontRenderer = mc.fontRenderer;
width = scaledWidth;
height = scaledHeight;
}
private static class MenuButton {
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public final ActionEnum action;
public String name;
public EnumFacing textSide;
public MenuButton(final String name, final ActionEnum action, final double x, final double y,
final EnumFacing textSide) {
this.name = I18n.format(name);
this.action = action;
x1 = x - 10;
x2 = x + 10;
y1 = y - 10;
y2 = y + 10;
this.textSide = textSide;
}
}
static class MenuRegion {
public final BuildModeEnum mode;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode;
}
}
@Override
public void render(final int mouseX, final int mouseY, final float partialTicks) {
if (!isVisible()) return;
BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(Minecraft.getInstance().player).getBuildMode();
GlStateManager.pushMatrix();
GlStateManager.translatef( 0.0F, 0.0F, 200.0F );
final int startColor = (int) ( visibility * 98 ) << 24;
final int endColor = (int) ( visibility * 128 ) << 24;
drawGradientRect(0, 0, width, height, startColor, endColor);
GlStateManager.disableTexture2D();
GlStateManager.enableBlend();
GlStateManager.disableAlphaTest();
GlStateManager.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
GlStateManager.shadeModel(GL11.GL_SMOOTH);
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder buffer = tessellator.getBuffer();
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
final double middleX = width / 2.0;
final double middleY = height / 2.0;
final double mouseXCenter = mouseX - middleX;
final double mouseYCenter = -mouseY + middleY;
double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter);
final double ringInnerEdge = 30;
final double ringOuterEdge = 65;
final double textDistance = 75;
final double buttonDistance = 105;
final double quarterCircle = Math.PI / 2.0;
if ( mouseRadians < -quarterCircle ) {
mouseRadians = mouseRadians + Math.PI * 2;
}
final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>();
final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
//Add build modes
for (final BuildModeEnum mode : BuildModeEnum.values()) {
modes.add(new MenuRegion(mode));
}
//Add actions
buttons.add(new MenuButton(ActionEnum.UNDO.name, ActionEnum.UNDO, -buttonDistance - 26, -13, EnumFacing.UP));
buttons.add(new MenuButton(ActionEnum.REDO.name, ActionEnum.REDO, -buttonDistance, -13, EnumFacing.UP));
buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS.name, ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 26, 13, EnumFacing.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE.name, ActionEnum.REPLACE, -buttonDistance, 13, EnumFacing.DOWN));
//Add buildmode dependent options
OptionEnum[] options = currentBuildMode.options;
for (int i = 0; i < options.length; i++) {
for (int j = 0; j < options[i].actions.length; j++) {
ActionEnum action = options[i].actions[j];
buttons.add(new MenuButton(action.name, action, buttonDistance + j * 26, -13 + i * 39, EnumFacing.DOWN));
}
}
switchTo = null;
doAction = null;
//Draw buildmode backgrounds
if (!modes.isEmpty()) {
final int totalModes = Math.max( 3, modes.size() );
int currentMode = 0;
final double fragment = Math.PI * 0.005;
final double fragment2 = Math.PI * 0.0025;
final double perObject = 2.0 * Math.PI / totalModes;
for (int i = 0; i < modes.size(); i++) {
MenuRegion menuRegion = modes.get(i);
final double beginRadians = currentMode * perObject - quarterCircle;
final double endRadians = (currentMode + 1) * perObject - quarterCircle;
menuRegion.x1 = Math.cos(beginRadians);
menuRegion.x2 = Math.cos(endRadians);
menuRegion.y1 = Math.sin(beginRadians);
menuRegion.y2 = Math.sin(endRadians);
final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge;
final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge;
final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge;
final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge;
float r = 0.0f;
float g = 0.0f;
float b = 0.0f;
float a = 0.5f;
//check if current mode
int buildMode = currentBuildMode.ordinal();
if (buildMode == i) {
r = 0f;
g = 0.5f;
b = 1f;
a = 0.5f;
//menuRegion.highlighted = true; //draw text
}
//check if mouse is over this region
final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter)
|| inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter);
if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
menuRegion.highlighted = true;
switchTo = menuRegion.mode;
}
buffer.pos(middleX + x1m1, middleY + y1m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m1, middleY + y2m1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x2m2, middleY + y2m2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + x1m2, middleY + y1m2, zLevel).color(r, g, b, a).endVertex();
currentMode++;
}
}
//Draw action backgrounds
for (final MenuButton btn : buttons) {
float r = 0.5f;
float g = 0.5f;
float b = 0.5f;
float a = 0.5f;
//highlight when active option
if (btn.action == getBuildSpeed() ||
btn.action == getFill() ||
btn.action == getCubeFill() ||
btn.action == getRaisedEdge() ||
btn.action == getLineThickness() ||
btn.action == getCircleStart()) {
r = 0.0f;
g = 0.5f;
b = 1f;
a = 0.6f;
}
//highlight when mouse over
if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) {
r = 0.6f;
g = 0.8f;
b = 1f;
a = 0.6f;
btn.highlighted = true;
doAction = btn.action;
}
buffer.pos(middleX + btn.x1, middleY + btn.y1, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x1, middleY + btn.y2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y2, zLevel).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y1, zLevel).color(r, g, b, a).endVertex();
}
tessellator.draw();
GlStateManager.shadeModel(GL11.GL_FLAT);
GlStateManager.translatef(0f, 0f, 5f);
GlStateManager.enableTexture2D();
GlStateManager.color3f(1f, 1f, 1f);
GlStateManager.disableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.bindTexture(Minecraft.getInstance().getTextureMap().getGlTextureId());
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
//Draw buildmode icons
for (final MenuRegion menuRegion : modes) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge);
final TextureAtlasSprite sprite = ClientProxy.getBuildModeIcon(menuRegion.mode);
final double x1 = x - 8;
final double x2 = x + 8;
final double y1 = y - 8;
final double y2 = y + 8;
final float f = 1f;
final float a = 1f;
final double u1 = 0;
final double u2 = 16;
final double v1 = 0;
final double v2 = 16;
buffer.pos(middleX + x1, middleY + y1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x1, middleY + y2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + x2, middleY + y1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
}
//Draw action icons
for (final MenuButton button : buttons) {
final float f = 1f;
final float a = 1f;
final double u1 = 0;
final double u2 = 16;
final double v1 = 0;
final double v2 = 16;
final TextureAtlasSprite sprite = ClientProxy.getModeOptionIcon(button.action);
final double btnmiddleX = (button.x1 + button.x2) / 2 + 0.01;
final double btnmiddleY = (button.y1 + button.y2) / 2 + 0.01;
final double btnx1 = btnmiddleX - 8;
final double btnx2 = btnmiddleX + 8;
final double btny1 = btnmiddleY - 8;
final double btny2 = btnmiddleY + 8;
buffer.pos(middleX + btnx1, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx1, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny2, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny1, zLevel).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex();
}
tessellator.draw();
//Draw strings
//fontRenderer.drawStringWithShadow("Actions", (int) (middleX - buttonDistance - 13) - fontRenderer.getStringWidth("Actions") * 0.5f, (int) middleY - 38, 0xffffffff);
//Draw option strings
for (int i = 0; i < currentBuildMode.options.length; i++) {
OptionEnum option = options[i];
fontRenderer.drawStringWithShadow(I18n.format(option.name), (int) (middleX + buttonDistance - 9), (int) middleY - 37 + i * 39, 0xeeeeeeff);
}
String credits = "Effortless Building";
fontRenderer.drawStringWithShadow(credits, width - fontRenderer.getStringWidth(credits) - 4, height - 10, 0x88888888);
//Draw buildmode text
for (final MenuRegion menuRegion : modes) {
if (menuRegion.highlighted) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5;
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5;
int fixed_x = (int) (x * textDistance);
final int fixed_y = (int) (y * textDistance) - fontRenderer.FONT_HEIGHT / 2;
final String text = I18n.format(menuRegion.mode.name);
if ( x <= -0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text);
} else if ( -0.2 <= x && x <= 0.2 ) {
fixed_x -= fontRenderer.getStringWidth(text) / 2;
}
fontRenderer.drawStringWithShadow(text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff);
}
}
//Draw action text
for (final MenuButton button : buttons) {
if (button.highlighted) {
String text = TextFormatting.AQUA + button.name;
int wrap = 120;
String keybind = "";
String keybindFormatted = "";
//Add keybind in brackets
if (button.action == ActionEnum.UNDO) {
keybind = ClientProxy.keyBindings[4].getKey().getName();
}
if (button.action == ActionEnum.REDO) {
keybind = ClientProxy.keyBindings[5].getKey().getName();
}
if (button.action == ActionEnum.REPLACE) {
keybind = ClientProxy.keyBindings[1].getKey().getName();
}
if (button.action == ActionEnum.OPEN_MODIFIER_SETTINGS) {
keybind = ClientProxy.keyBindings[0].getKey().getName();
}
if (currentBuildMode.options.length > 0) {
//Add (ctrl) to first two actions of first option
if (button.action == currentBuildMode.options[0].actions[0]
|| button.action == currentBuildMode.options[0].actions[1]) {
keybind = ClientProxy.keyBindings[6].getKey().getName();
if (keybind.equals("Left Control")) keybind = "Ctrl";
}
}
if (!keybind.isEmpty()) keybindFormatted = TextFormatting.GRAY + "(" + WordUtils.capitalizeFully(keybind) + ")";
if (button.textSide == EnumFacing.WEST) {
fontRenderer.drawSplitString( text, (int) (middleX + button.x1 - 8 ) - fontRenderer.getStringWidth(text),
(int) (middleY + button.y1 + 6), wrap, 0xffffffff);
} else if (button.textSide == EnumFacing.EAST) {
fontRenderer.drawSplitString(text, (int) (middleX + button.x2 + 8),
(int) (middleY + button.y1 + 6 ), wrap, 0xffffffff);
} else if (button.textSide == EnumFacing.UP || button.textSide == EnumFacing.NORTH) {
fontRenderer.drawSplitString( keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 - 26), wrap,0xffffffff);
fontRenderer.drawSplitString( text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 - 14), wrap,0xffffffff);
} else if (button.textSide == EnumFacing.DOWN || button.textSide == EnumFacing.SOUTH) {
fontRenderer.drawSplitString(text, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(text) * 0.5),
(int) (middleY + button.y1 + 26), wrap, 0xffffffff);
fontRenderer.drawSplitString(keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - fontRenderer.getStringWidth(keybindFormatted) * 0.5),
(int) (middleY + button.y1 + 38), wrap, 0xffffffff);
}
}
}
GlStateManager.popMatrix();
}
private boolean inTriangle(final double x1, final double y1, final double x2, final double y2,
final double x3, final double y3, final double x, final double y ) {
final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y);
final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y);
final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
return sign(ab) == sign(bc) && sign(bc) == sign(ca);
}
private int sign(final double n) {
return n > 0 ? 1 : -1;
}
/**
* Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton
*/
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
EffortlessBuilding.log("mouse clicked");
// KeyBinding.updateKeyBindState();
// KeyBinding.setKeyBindState(ClientProxy.keyBindings[3].getKeyCode(), true);
// if (mouseButton == 0) {
// this.mc.displayGuiScreen(null);
//
// if (this.mc.currentScreen == null) {
// this.mc.setIngameFocus();
// }
// }
return super.mouseClicked(mouseX, mouseY, mouseButton);
}
}

View File

@@ -1,147 +0,0 @@
package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import nl.requios.effortlessbuilding.gui.elements.GuiScrollPane;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.io.IOException;
@OnlyIn(Dist.CLIENT)
public class ModifierSettingsGui extends GuiScreen {
private GuiScrollPane scrollPane;
private GuiButton buttonClose;
private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui;
@Override
//Create buttons and labels and add them to buttonList/labelList
public void initGui() {
int id = 0;
scrollPane = new GuiScrollPane(this, fontRenderer, 8, height - 30);
mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(mirrorSettingsGui);
arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.AddListEntry(arraySettingsGui);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui);
id = scrollPane.initGui(id, buttons);
//Close button
int y = height - 26;
buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close") {
@Override
public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY);
mc.player.closeScreen();
}
};
buttons.add(buttonClose);
}
@Override
//Process general logic, i.e. hide buttons
public void tick() {
scrollPane.updateScreen();
handleMouseInput();
}
@Override
//Set colors using GL11, use the fontRendererObj field to display text
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void render(int mouseX, int mouseY, float partialTicks) {
this.drawDefaultBackground();
scrollPane.drawScreen(mouseX, mouseY, partialTicks);
buttonClose.render(mouseX, mouseY, partialTicks);
scrollPane.drawTooltip(this, mouseX, mouseY);
}
@Override
public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode);
scrollPane.charTyped(typedChar, keyCode);
if (keyCode == ClientProxy.keyBindings[0].getKey().getKeyCode()) {
mc.player.closeScreen();
}
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
super.mouseClicked(mouseX, mouseY, mouseButton);
buttons.forEach(button -> button.mouseClicked(mouseX, mouseY, mouseButton));
return scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
{
return super.mouseReleased(mouseX, mouseY, state);
}
return false;
}
public void handleMouseInput() {
//super.handleMouseInput();
scrollPane.handleMouseInput();
//Scrolling numbers
// int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
// int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
// numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY));
}
@Override
public void onGuiClosed() {
scrollPane.onGuiClosed();
//save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();
modifierSettings.setMirrorSettings(m);
modifierSettings.setArraySettings(a);
modifierSettings.setRadialMirrorSettings(r);
//Sanitize
String error = ModifierSettingsManager.sanitize(modifierSettings, mc.player);
if (!error.isEmpty()) EffortlessBuilding.log(mc.player, error);
ModifierSettingsManager.setModifierSettings(mc.player, modifierSettings);
//Send to server
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
//TODO fix not being able to scroll after this gui has opened
Minecraft.getInstance().mouseHelper.grabMouse();
}
}

View File

@@ -1,54 +0,0 @@
package nl.requios.effortlessbuilding.helper;
import nl.requios.effortlessbuilding.EffortlessBuilding;
//Stack with fixed size. Removes (overwrites) oldest element on push.
public class FixedStack<T> {
private T[] stack;
private int size;
private int top;
private int filled = 0; //how many valid items are in the stack
public FixedStack(T[] stack) {
this.stack = stack;
this.top = 0;
this.size = stack.length;
}
public void push(T object) {
if (top == stack.length)
top = 0;
stack[top] = object;
top++;
if (filled < size)
filled++;
}
public T pop() {
if (filled <= 0) return null;
if (top - 1 < 0)
top = size;
top--;
T object = stack[top];
filled--;
return object;
}
public void clear() {
top = 0;
filled = 0;
}
public int size() {
return size;
}
public boolean isEmpty() {
return filled <= 0;
}
}

View File

@@ -1,31 +0,0 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
public class InventoryHelper {
public static ItemStack findItemStackInInventory(EntityPlayer player, Block block) {
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(block)) {
return invStack;
}
}
return ItemStack.EMPTY;
}
public static int findTotalBlocksInInventory(EntityPlayer player, Block block) {
int total = 0;
for (ItemStack invStack : player.inventory.mainInventory) {
if (!invStack.isEmpty() && invStack.getItem() instanceof ItemBlock &&
((ItemBlock) invStack.getItem()).getBlock().equals(block)) {
total += invStack.getCount();
}
}
return total;
}
}

View File

@@ -1,14 +1,15 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraftforge.common.crafting.IConditionSerializer; import net.minecraftforge.common.crafting.IConditionFactory;
import net.minecraftforge.common.crafting.JsonContext;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import java.util.function.BooleanSupplier; import java.util.function.BooleanSupplier;
public class ReachConditionFactory implements IConditionSerializer { public class ReachConditionFactory implements IConditionFactory {
@Override @Override
public BooleanSupplier parse(JsonObject json) { public BooleanSupplier parse(JsonContext context, JsonObject json) {
return () -> BuildConfig.reach.enableReachUpgrades.get(); return () -> BuildConfig.reach.enableReachUpgrades;
} }
} }

View File

@@ -1,50 +1,27 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.math.MathHelper;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.BuildSettingsManager;
public class ReachHelper { public class ReachHelper {
public static int getMaxReach(EntityPlayer player) { public static int getMaxReach(EntityPlayer player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get(); if (player.isCreative()) return BuildConfig.reach.maxReachCreative;
if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get(); if (!BuildConfig.reach.enableReachUpgrades) return BuildConfig.reach.maxReachLevel3;
//Check buildsettings for reachUpgrade //Check buildsettings for reachUpgrade
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade(); int reachUpgrade = BuildSettingsManager.getBuildSettings(player).getReachUpgrade();
switch (reachUpgrade) { switch (reachUpgrade) {
case 0: return BuildConfig.reach.maxReachLevel0.get(); case 0: return BuildConfig.reach.maxReachLevel0;
case 1: return BuildConfig.reach.maxReachLevel1.get(); case 1: return BuildConfig.reach.maxReachLevel1;
case 2: return BuildConfig.reach.maxReachLevel2.get(); case 2: return BuildConfig.reach.maxReachLevel2;
case 3: return BuildConfig.reach.maxReachLevel3.get(); case 3: return BuildConfig.reach.maxReachLevel3;
} }
return BuildConfig.reach.maxReachLevel0.get(); return BuildConfig.reach.maxReachLevel0;
}
public static int getPlacementReach(EntityPlayer player) {
return getMaxReach(player) / 4;
}
public static int getMaxBlocksPlacedAtOnce(EntityPlayer player) {
if (player.isCreative()) return 1000000;
return MathHelper.ceil(Math.pow(getMaxReach(player), 1.6));
//Level 0: 121
//Level 1: 523
//Level 2: 1585
//Level 3: 4805
}
public static int getMaxBlocksPerAxis(EntityPlayer player) {
if (player.isCreative()) return 2000;
return MathHelper.ceil(getMaxReach(player) * 0.3);
//Level 0: 6
//Level 1: 15
//Level 2: 30
//Level 3: 60
} }
public static boolean canBreakFar(EntityPlayer player) { public static boolean canBreakFar(EntityPlayer player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar.get(); return player.isCreative() || BuildConfig.survivalBalancers.breakFar;
} }
} }

View File

@@ -0,0 +1,435 @@
package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.*;
import net.minecraft.world.IWorldEventListener;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.Color;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@Mod.EventBusSubscriber(Side.CLIENT)
public class RenderHelper implements IWorldEventListener {
private static final Color colorX = new Color(255, 72, 52);
private static final Color colorY = new Color(67, 204, 51);
private static final Color colorZ = new Color(52, 247, 255);
private static final Color colorRadial = new Color(52, 247, 255);
private static final int lineAlpha = 200;
private static final int planeAlpha = 75;
private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
private static List<BlockPos> previousCoordinates;
private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getMinecraft().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushMatrix();
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glDepthMask(false);
}
private static void beginLines() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLineWidth(2);
}
private static void endLines() {
GL11.glPopAttrib();
}
private static void beginBlockPreviews() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_TEXTURE_2D);
Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_CONSTANT_ALPHA, GL11.GL_ONE_MINUS_CONSTANT_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
}
private static void endBlockPreviews() {
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.disableBlend();
GL11.glPopAttrib();
}
private static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
}
private static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) {
GlStateManager.pushMatrix();
GlStateManager.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F);
GlStateManager.translate(-0.005f, -0.005f, 0.005f);
GlStateManager.scale(1.01f, 1.01f, 1.01f);
dispatcher.renderBlockBrightness(blockState, 0.85f);
GlStateManager.popMatrix();
}
public static void renderBlockOutline(BlockPos pos) {
renderBlockOutline(pos, pos);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
public static void renderBlockOutline(BlockPos pos1, BlockPos pos2) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
RenderGlobal.drawSelectionBoundingBox(aabb, 0f, 0f, 0f, 0.4f);
}
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getMinecraft().player;
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
begin(event.getPartialTicks());
beginLines();
//Mirror lines and areas
Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ))
{
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
if (m.mirrorX)
{
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes, true);
}
if (m.mirrorY)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes, true);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ)))
{
drawMirrorLines(m);
}
}
//Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
if (r != null && r.enabled)
{
Vec3d pos = r.position.add(epsilon);
int radius = r.radius;
float angle = 2f * ((float) Math.PI) / r.slices;
Vec3d relStartVec = new Vec3d(radius, 0, 0);
if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f);
for (int i = 0; i < r.slices; i++) {
Vec3d relNewVec = relStartVec.rotateYaw(angle * i);
Vec3d newVec = pos.add(relNewVec);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
}
}
endLines();
//Render block previews
RayTraceResult lookingAt = ClientProxy.getLookingAt(player);
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK)
{
beginBlockPreviews();
BlockRendererDispatcher dispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
BlockPos startPos = lookingAt.getBlockPos();
//Check if tool (or none) in hand
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = !(!mainhand.isEmpty() && (mainhand.getItem() instanceof ItemBlock || mainhand.getItem() instanceof ItemRandomizerBag));
boolean replaceable =
player.world.getBlockState(startPos).getBlock().isReplaceable(player.world, startPos);
if (!buildSettings.doQuickReplace() && !toolInHand && !replaceable) {
startPos = startPos.offset(lookingAt.sideHit);
}
//Get under tall grass and other replaceable blocks
if (buildSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
if (BuildModifiers.isEnabled(buildSettings, startPos) || BuildConfig.visuals.alwaysShowBlockPreview) {
//get coordinates
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startPos);
//check if they are different from previous
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness();
}
Vec3d hitVec = lookingAt.hitVec;
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = BuildModifiers.findBlockStates(player, startPos, hitVec, lookingAt.sideHit, itemStacks);
//check if valid blockstates
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = newCoordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.get(i);
//Check if can place
if (!itemstack.isEmpty() && SurvivalHelper.canPlayerEdit(player, player.world, blockPos, itemstack) &&
SurvivalHelper.mayPlace(player.world, Block.getBlockFromItem(itemstack.getItem()), blockState, blockPos, false, EnumFacing.UP, player) &&
SurvivalHelper.canReplace(player.world, player, blockPos)) {
renderBlockPreview(dispatcher, blockPos, blockState);
}
}
}
}
endBlockPreviews();
beginLines();
//Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar
RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
if (toolInHand && breakingRaytrace != null && breakingRaytrace.typeOfHit == RayTraceResult.Type.BLOCK) {
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos());
//Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) {
renderBlockOutline(coordinate);
}
}
}
}
endLines();
}
end();
}
//----Mirror----
public static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
if (drawVerticalLines) {
bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
}
tessellator.draw();
}
}
public static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
public static void drawMirrorLines(Mirror.MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
//IWORLDEVENTLISTENER IMPLEMENTATION
@Override
public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
}
@Override
public void notifyLightSet(BlockPos pos) {
}
@Override
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
}
@Override
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category,
double x, double y, double z, float volume, float pitch) {
}
@Override
public void playRecord(SoundEvent soundIn, BlockPos pos) {
}
@Override
public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord,
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
}
@Override
public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z,
double xSpeed, double ySpeed, double zSpeed, int... parameters) {
}
@Override
public void onEntityAdded(Entity entityIn) {
}
@Override
public void onEntityRemoved(Entity entityIn) {
}
@Override
public void broadcastSound(int soundID, BlockPos pos, int data) {
}
@Override
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) {
}
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
Minecraft mc = Minecraft.getMinecraft();
BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player);
if (!BuildModifiers.isEnabled(buildSettings, pos)) return;
List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
//Send i as entity id because only one block can be broken per id
//Unless i happens to be the player id, then take something else
int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
}
}
}
}

View File

@@ -1,144 +1,172 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockSlab; import net.minecraft.block.BlockLiquid;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.block.state.BlockWorldState;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.init.Enchantments;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult; import net.minecraft.stats.StatList;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.ToolType; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.BuildConfig; import net.minecraftforge.items.ItemHandlerHelper;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public class SurvivalHelper { public class SurvivalHelper {
//Used for all placing of blocks in this mod. //Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack. //Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse //Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, public static boolean placeBlock(World world, EntityPlayer player, BlockPos pos, IBlockState blockState, ItemStack itemstack, EnumFacing facing, Vec3d hitVec, boolean skipCollisionCheck, boolean playSound) {
ItemStack origstack, EnumFacing facing, Vec3d hitVec, boolean skipPlaceCheck,
boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockLoaded(pos, true)) return false; if (!world.isBlockLoaded(pos, true)) return false;
ItemStack itemstack = origstack;
if (blockState.getBlock().isAir(blockState, world, pos) || itemstack.isEmpty()) { //Randomizer bag synergy
dropBlock(world, player, pos); //Find itemstack that belongs to the blockstate
world.removeBlock(pos); if (itemstack.getItem() == EffortlessBuilding.ITEM_RANDOMIZER_BAG) {
return true; IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(itemstack);
itemstack = ItemRandomizerBag.findStack(bagInventory, Item.getItemFromBlock(blockState.getBlock()));
} }
//Randomizer bag, other proxy item synergy //Check if itemstack is correct
//Preliminary compatibility code for other items that hold blocks if (!(itemstack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemstack.getItem()) != blockState.getBlock()) {
if (CompatHelper.isItemBlockProxy(itemstack)) EffortlessBuilding.log(player, "Cannot (re)place block", true);
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); EffortlessBuilding.log("SurvivalHelper#placeBlock: itemstack " + itemstack.toString() + " does not match blockstate " + blockState.toString());
if (!(itemstack.getItem() instanceof ItemBlock))
return false; return false;
}
Block block = ((ItemBlock) itemstack.getItem()).getBlock(); Block block = ((ItemBlock) itemstack.getItem()).getBlock();
if (!itemstack.isEmpty() && canPlayerEdit(player, world, pos, itemstack) &&
mayPlace(world, block, blockState, pos, skipCollisionCheck, facing.getOpposite(), player) &&
canReplace(world, player, pos)) {
//More manual with ItemBlock#placeBlockAt
if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
//TryPlace sets block with offset, so we only do world.setBlockState now boolean placed = ((ItemBlock) itemstack.getItem()).placeBlockAt(itemstack, player, world, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, blockState);
//Remember count of itemstack before tryPlace, and set it back after. if (!placed) return false;
//TryPlace reduces stack even in creative so it is not usable here.
// int origCount = itemstack.getCount();
// BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, itemstack, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z);
// EnumActionResult result = ((ItemBlock) itemstack.getItem()).tryPlace(blockItemUseContext);
// itemstack.setCount(origCount);
//Set our (rotated) blockstate //From ItemBlock#placeBlockAt
world.setBlockState(pos, blockState, 3); // if (!world.setBlockState(pos, blockState, 11)) return false;
// blockState.onBlockAdded(world, pos, blockState); //
// block.onBlockPlacedBy(world, pos, blockState, player, itemstack); IBlockState state = world.getBlockState(pos);
// world.notifyBlockUpdate(pos, blockState, world.getBlockState(pos), 3); // if (state.getBlock() == block)
// {
// if (result != EnumActionResult.SUCCESS) return false; // ((ItemBlock) itemstack.getItem()).setTileEntityNBT(world, player, pos, itemstack);
// block.onBlockPlacedBy(world, pos, state, player, itemstack);
IBlockState afterState = world.getBlockState(pos); //
//// if (player instanceof EntityPlayerMP)
//// CriteriaTriggers.PLACED_BLOCK.trigger((EntityPlayerMP)player, pos, itemstack);
// }
if (playSound) { if (playSound) {
SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player); SoundType soundtype = state.getBlock().getSoundType(state, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
} }
if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) { if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) {
CompatHelper.shrinkStack(origstack, itemstack, player); itemstack.shrink(1);
} }
return true; return true;
} }
return false; return false;
//Using ItemBlock#onItemUse
// EnumActionResult result;
// PlayerInteractEvent.RightClickBlock event = ForgeHooks.onRightClickBlock(player, EnumHand.MAIN_HAND, pos, facing, net.minecraftforge.common.ForgeHooks.rayTraceEyeHitVec(player, ReachHelper.getPlacementReach(player)));
// if (player.isCreative())
// {
// int i = itemstack.getMetadata();
// int j = itemstack.getCount();
// if (event.getUseItem() != net.minecraftforge.fml.common.eventhandler.Event.Result.DENY) {
// EnumActionResult enumactionresult = itemstack.getItem().onItemUse(player, world, pos, EnumHand.MAIN_HAND, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z);
// itemstack.setItemDamage(i);
// itemstack.setCount(j);
// return enumactionresult == EnumActionResult.SUCCESS;
// } else return false;
// }
// else
// {
// ItemStack copyForUse = itemstack.copy();
// if (event.getUseItem() != net.minecraftforge.fml.common.eventhandler.Event.Result.DENY)
// result = itemstack.getItem().onItemUse(player, world, pos, EnumHand.MAIN_HAND, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z);
// if (itemstack.isEmpty()) net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(player, copyForUse, EnumHand.MAIN_HAND);
// return false;
// }
} }
//Used for all breaking of blocks in this mod. //Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory //Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos, boolean skipChecks) { public static boolean breakBlock(World world, EntityPlayer player, BlockPos pos) {
if (!world.isBlockLoaded(pos, false)) return false; if (!world.isBlockLoaded(pos, false)) return false;
//Check if can break //Check if can break
if (skipChecks || canBreak(world, player, pos)) { if (canBreak(world, player, pos))
// player.addStat(StatList.getBlockStats(world.getNewBlockState(pos).getBlock())); {
// player.addExhaustion(0.005F);
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
//Damage tool //Damage tool
player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player); player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player);
world.removeBlock(pos); world.setBlockToAir(pos);
return true; return true;
} }
return false; return false;
} }
//Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
IBlockState blockState = world.getBlockState(pos);
if (blockState.getBlock() instanceof BlockLiquid) return false;
if (player.isCreative()) return true;
return canHarvestBlock(blockState.getBlock(), player, world, pos);
}
//From ForgeHooks#canHarvestBlock
public static boolean canHarvestBlock(@Nonnull Block block, @Nonnull EntityPlayer player, @Nonnull IBlockAccess world, @Nonnull BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
//Dont break bedrock
if (state.getBlockHardness((World) world, pos) < 0) {
return false;
}
if (state.getMaterial().isToolNotRequired())
{
return true;
}
ItemStack stack = player.getHeldItemMainhand();
String tool = block.getHarvestTool(state);
if (stack.isEmpty() || tool == null)
{
return player.canHarvestBlock(state);
}
if (stack.getItemDamage() >= stack.getMaxDamage()) return false;
int toolLevel = stack.getItem().getHarvestLevel(stack, tool, player, state);
if (toolLevel < 0)
{
return player.canHarvestBlock(state);
}
return toolLevel >= block.getHarvestLevel(state);
}
//Can be harvested with hand? (or in creative)
public static boolean canReplace(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return true;
IBlockState state = world.getBlockState(pos);
state = state.getBlock().getActualState(state, world, pos);
if (state.getMaterial().isToolNotRequired()) return true;
return false;
}
//Gives items directly to player //Gives items directly to player
public static void dropBlock(World world, EntityPlayer player, BlockPos pos){ public static void dropBlock(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return; if (player.isCreative()) return;
@@ -148,88 +176,18 @@ public class SurvivalHelper {
block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand()); block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand());
//TODO drop items in inventory instead of world
// List<ItemStack> drops = new ArrayList<>();
//
// //From Block#harvestBlock
// int silktouch = EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, player.getHeldItemMainhand());
// if (block.canSilkHarvest(world, pos, blockState, player) && silktouch > 0) {
//
// //From Block#getSilkTouchDrop (protected)
// Item item = Item.getItemFromBlock(block);
// int i = 0;
//
// if (item.getHasSubtypes())
// {
// i = block.getMetaFromState(blockState);
// }
//
// drops.add(new ItemStack(item, 1, i));
//
// net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(drops, world, pos, blockState, 0, 1.0f, true, player);
// }
//
// int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand()); // int fortune = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, player.getHeldItemMainhand());
// drops.addAll(block.getDrops(world, pos, blockState, fortune)); // List<ItemStack> drops = blockState.getBlock().getDrops(world, pos, blockState, fortune);
// for (ItemStack drop : drops) // for (ItemStack drop : drops)
// { // {
// ItemHandlerHelper.giveItemToPlayer(player, drop); // ItemHandlerHelper.giveItemToPlayer(player, drop);
// } // }
} }
/**
* Check if player can place a block.
* Turn randomizer bag into itemstack inside before.
* @param world
* @param player
* @param pos
* @param newBlockState the blockstate that is going to be placed
* @param itemStack the itemstack used for placing
* @param skipCollisionCheck skips collision check with entities
* @param sidePlacedOn
* @return Whether the player may place the block at pos with itemstack
*/
public static boolean canPlace(World world, EntityPlayer player, BlockPos pos, IBlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, EnumFacing sidePlacedOn) {
//Check if itemstack is correct
if (!(itemStack.getItem() instanceof ItemBlock) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) {
// EffortlessBuilding.log(player, "Cannot (re)place block", true);
// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString());
//Happens when breaking blocks, no need to notify in that case
return false;
}
Block block = ((ItemBlock) itemStack.getItem()).getBlock();
return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) &&
mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) &&
canReplace(world, player, pos);
}
//Can be harvested with hand? (or in creative)
private static boolean canReplace(World world, EntityPlayer player, BlockPos pos){
if (player.isCreative()) return true;
IBlockState state = world.getBlockState(pos);
switch (BuildConfig.survivalBalancers.quickReplaceMiningLevel.get()) {
case -1: return state.getMaterial().isToolNotRequired();
case 0: return state.getBlock().getHarvestLevel(state) <= 0;
case 1: return state.getBlock().getHarvestLevel(state) <= 1;
case 2: return state.getBlock().getHarvestLevel(state) <= 2;
case 3: return state.getBlock().getHarvestLevel(state) <= 3;
}
return false;
}
//From EntityPlayer#canPlayerEdit //From EntityPlayer#canPlayerEdit
private static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack) public static boolean canPlayerEdit(EntityPlayer player, World world, BlockPos pos, ItemStack stack)
{ {
if (!world.isBlockModifiable(player, pos)) return false; if (player.capabilities.allowEdit)
if (player.abilities.allowEdit)
{ {
//True in creative and survival mode //True in creative and survival mode
return true; return true;
@@ -237,28 +195,22 @@ public class SurvivalHelper {
else else
{ {
//Adventure mode //Adventure mode
BlockWorldState blockworldstate = new BlockWorldState(world, pos, false); Block block = world.getBlockState(pos).getBlock();
return stack.canPlaceOn(world.getTags(), blockworldstate); return stack.canPlaceOn(block) || stack.canEditBlocks();
} }
} }
//From World#mayPlace //From World#mayPlace
private static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer) public static boolean mayPlace(World world, Block blockIn, IBlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, EnumFacing sidePlacedOn, @Nullable Entity placer)
{ {
IBlockState iblockstate1 = world.getBlockState(pos); IBlockState iblockstate1 = world.getBlockState(pos);
VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionShape(world, pos); AxisAlignedBB axisalignedbb = skipCollisionCheck ? Block.NULL_AABB : blockIn.getDefaultState().getCollisionBoundingBox(world, pos);
if (voxelShape != null && !world.checkNoEntityCollision(iblockstate1, pos)) if (axisalignedbb != Block.NULL_AABB && !world.checkNoEntityCollision(axisalignedbb.offset(pos)))
{ {
return false; return false;
} }
//Check if double slab
if (placer != null && doesBecomeDoubleSlab(((EntityPlayer) placer), pos, sidePlacedOn)) {
return true;
}
//Check if same block //Check if same block
//Necessary otherwise extra items will be dropped //Necessary otherwise extra items will be dropped
if (iblockstate1 == newBlockState) { if (iblockstate1 == newBlockState) {
@@ -271,82 +223,10 @@ public class SurvivalHelper {
} }
//Check quickreplace //Check quickreplace
if (placer instanceof EntityPlayer && ModifierSettingsManager.getModifierSettings(((EntityPlayer) placer)).doQuickReplace()) { if (placer instanceof EntityPlayer && BuildSettingsManager.getBuildSettings(((EntityPlayer) placer)).doQuickReplace()) {
return true; return true;
} }
//TODO 1.13 replaceable return iblockstate1.getBlock().isReplaceable(world, pos) && blockIn.canPlaceBlockOnSide(world, pos, sidePlacedOn);
return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
}
//Can break using held tool? (or in creative)
public static boolean canBreak(World world, EntityPlayer player, BlockPos pos) {
IBlockState blockState = world.getBlockState(pos);
if (!world.getFluidState(pos).isEmpty()) return false;
if (player.isCreative()) return true;
return canHarvestBlock(blockState.getBlock(), player, world, pos);
}
//From ForgeHooks#canHarvestBlock
public static boolean canHarvestBlock(@Nonnull Block block, @Nonnull EntityPlayer player, @Nonnull World world, @Nonnull BlockPos pos)
{
IBlockState state = world.getBlockState(pos);
//Dont break bedrock
if (state.getBlockHardness(world, pos) < 0) {
return false;
}
if (state.getMaterial().isToolNotRequired())
{
return true;
}
ItemStack stack = player.getHeldItemMainhand();
ToolType tool = block.getHarvestTool(state);
if (stack.isEmpty() || tool == null)
{
return player.canHarvestBlock(state);
}
if (stack.getDamage() >= stack.getMaxDamage()) return false;
int toolLevel = stack.getItem().getHarvestLevel(stack, tool, player, state);
if (toolLevel < 0)
{
return player.canHarvestBlock(state);
}
return toolLevel >= block.getHarvestLevel(state);
}
public static boolean doesBecomeDoubleSlab(EntityPlayer player, BlockPos pos, EnumFacing facing) {
IBlockState placedBlockState = player.world.getBlockState(pos);
ItemStack itemstack = player.getHeldItem(EnumHand.MAIN_HAND);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockFromStack(itemstack);
if (itemstack.isEmpty() || !(itemstack.getItem() instanceof ItemBlock) || !(((ItemBlock) itemstack.getItem()).getBlock() instanceof BlockSlab)) return false;
BlockSlab heldSlab = (BlockSlab) ((ItemBlock) itemstack.getItem()).getBlock();
if (placedBlockState.getBlock() == heldSlab) {
//TODO 1.13
// IProperty<?> variantProperty = heldSlab.getVariantProperty();
// Comparable<?> placedVariant = placedBlockState.getValue(variantProperty);
// BlockSlab.EnumBlockHalf placedHalf = placedBlockState.getValue(BlockSlab.HALF);
//
// Comparable<?> heldVariant = heldSlab.getTypeForItem(itemstack);
//
// if ((facing == EnumFacing.UP && placedHalf == BlockSlab.EnumBlockHalf.BOTTOM || facing == EnumFacing.DOWN && placedHalf == BlockSlab.EnumBlockHalf.TOP) && placedVariant == heldVariant)
// {
// return true;
// }
}
return false;
} }
} }

View File

@@ -3,9 +3,10 @@ package nl.requios.effortlessbuilding.item;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item;
import net.minecraft.item.*; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ActionResult; import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumActionResult;
@@ -13,21 +14,13 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider; import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.RandomizerBagGuiHandler;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -43,39 +36,25 @@ public class ItemRandomizerBag extends Item {
private static Random rand = new Random(currentSeed); private static Random rand = new Random(currentSeed);
public ItemRandomizerBag() { public ItemRandomizerBag() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag"); this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
} }
@Override @Override
public EnumActionResult onItemUse(ItemUseContext ctx) { public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) {
EntityPlayer player = ctx.getPlayer();
World world = ctx.getWorld();
BlockPos pos = ctx.getPos();
EnumFacing facing = ctx.getFace();
ItemStack item = ctx.getItem();
if (player == null) return EnumActionResult.FAIL; if (player.isSneaking()) {
if (ctx.isPlacerSneaking()) {
if (world.isRemote) return EnumActionResult.SUCCESS; if (world.isRemote) return EnumActionResult.SUCCESS;
//Open inventory //Open inventory
NetworkHooks.openGui((EntityPlayerMP) player, new RandomizerBagGuiHandler()); player.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, world, 0, 0, 0);
} else { } else {
if (world.isRemote) return EnumActionResult.SUCCESS; if (world.isRemote) return EnumActionResult.SUCCESS;
//Only place manually if in normal vanilla mode
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) {
return EnumActionResult.FAIL;
}
//Use item //Use item
//Get bag inventory //Get bag inventory
//TODO offhand support ItemStack bag = player.getHeldItem(hand);
ItemStack bag = player.getHeldItem(EnumHand.MAIN_HAND);
IItemHandler bagInventory = getBagInventory(bag); IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null) if (bagInventory == null)
return EnumActionResult.FAIL; return EnumActionResult.FAIL;
@@ -87,22 +66,15 @@ public class ItemRandomizerBag extends Item {
//bag.setItemDamage(toPlace.getMetadata()); //bag.setItemDamage(toPlace.getMetadata());
//toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ); //toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
//TODO replaceable if (!world.getBlockState(pos).getBlock().isReplaceable(world, pos)) {
if (!world.getBlockState(pos).getBlock().getMaterial(world.getBlockState(pos)).isReplaceable()) {
pos = pos.offset(facing); pos = pos.offset(facing);
} }
BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, item, pos, facing, ctx.getHitX(), ctx.getHitY(), ctx.getHitZ()); IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(world, pos, facing,
IBlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(blockItemUseContext); hitX, hitY, hitZ, toPlace.getMetadata(), player, hand);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(ctx.getHitX(), ctx.getHitY(), ctx.getHitZ()), false, false, true); SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, new Vec3d(hitX, hitY, hitZ), false, true);
//Synergy
//Works without calling
// BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
// BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
// Mirror.onBlockPlaced(placeEvent);
// Array.onBlockPlaced(placeEvent);
} }
return EnumActionResult.SUCCESS; return EnumActionResult.SUCCESS;
} }
@@ -114,7 +86,7 @@ public class ItemRandomizerBag extends Item {
if (player.isSneaking()) { if (player.isSneaking()) {
if (world.isRemote) return new ActionResult<>(EnumActionResult.SUCCESS, bag); if (world.isRemote) return new ActionResult<>(EnumActionResult.SUCCESS, bag);
//Open inventory //Open inventory
NetworkHooks.openGui((EntityPlayerMP) player, new RandomizerBagGuiHandler()); player.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, world, 0, 0, 0);
} else { } else {
//Use item //Use item
//Get bag inventory //Get bag inventory
@@ -137,7 +109,8 @@ public class ItemRandomizerBag extends Item {
* @return * @return
*/ */
public static IItemHandler getBagInventory(ItemStack bag) { public static IItemHandler getBagInventory(ItemStack bag) {
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).orElse(null); if (!bag.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)) return null;
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
} }
/** /**
@@ -186,7 +159,7 @@ public class ItemRandomizerBag extends Item {
} }
@Override @Override
public int getUseDuration(ItemStack p_77626_1_) { public int getMaxItemUseDuration(ItemStack stack) {
return 1; return 1;
} }
@@ -197,14 +170,14 @@ public class ItemRandomizerBag extends Item {
} }
@Override @Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) { public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block")); tooltip.add(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block");
tooltip.add(new TextComponentString(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory")); tooltip.add(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory");
} }
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return this.getRegistryName().toString(); return super.getTranslationKey();
} }
public static void resetRandomness() { public static void resetRandomness() {

View File

@@ -1,18 +1,17 @@
package nl.requios.effortlessbuilding.item; package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -21,8 +20,11 @@ import java.util.List;
public class ItemReachUpgrade1 extends Item { public class ItemReachUpgrade1 extends Item {
public ItemReachUpgrade1() { public ItemReachUpgrade1() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
} }
@Override @Override
@@ -33,12 +35,12 @@ public class ItemReachUpgrade1 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = modifierSettings.getReachUpgrade(); int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 0) { if (currentLevel == 0) {
modifierSettings.setReachUpgrade(1); buildSettings.setReachUpgrade(1);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -54,12 +56,18 @@ public class ItemReachUpgrade1 extends Item {
} }
@Override @Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) { public ItemStack onItemUseFinish(ItemStack stack, World worldIn, EntityLivingBase entityLiving) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get())); EffortlessBuilding.log("used");
return ItemStack.EMPTY;
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel1);
} }
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return this.getRegistryName().toString(); return super.getTranslationKey();
} }
} }

View File

@@ -1,18 +1,16 @@
package nl.requios.effortlessbuilding.item; package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -21,8 +19,11 @@ import java.util.List;
public class ItemReachUpgrade2 extends Item { public class ItemReachUpgrade2 extends Item {
public ItemReachUpgrade2() { public ItemReachUpgrade2() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
} }
@Override @Override
@@ -33,11 +34,11 @@ public class ItemReachUpgrade2 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = modifierSettings.getReachUpgrade(); int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 1) { if (currentLevel == 1) {
modifierSettings.setReachUpgrade(2); buildSettings.setReachUpgrade(2);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -58,13 +59,13 @@ public class ItemReachUpgrade2 extends Item {
} }
@Override @Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) { public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get())); tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel2);
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Previous upgrades need to be consumed first")); tooltip.add(TextFormatting.GRAY + "Previous upgrades need to be consumed first");
} }
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return this.getRegistryName().toString(); return super.getTranslationKey();
} }
} }

View File

@@ -1,18 +1,16 @@
package nl.requios.effortlessbuilding.item; package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.*; import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World; import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -21,8 +19,11 @@ import java.util.List;
public class ItemReachUpgrade3 extends Item { public class ItemReachUpgrade3 extends Item {
public ItemReachUpgrade3() { public ItemReachUpgrade3() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3"); this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3");
this.setTranslationKey(this.getRegistryName().toString());
this.maxStackSize = 1;
this.setCreativeTab(CreativeTabs.TOOLS);
} }
@Override @Override
@@ -33,11 +34,11 @@ public class ItemReachUpgrade3 extends Item {
return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand)); return new ActionResult<>(EnumActionResult.PASS, player.getHeldItem(hand));
} }
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
int currentLevel = modifierSettings.getReachUpgrade(); int currentLevel = buildSettings.getReachUpgrade();
if (currentLevel == 2) { if (currentLevel == 2) {
modifierSettings.setReachUpgrade(3); buildSettings.setReachUpgrade(3);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player)); if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to level " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY); player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup")); SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
@@ -61,13 +62,13 @@ public class ItemReachUpgrade3 extends Item {
} }
@Override @Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) { public void addInformation(ItemStack stack, @Nullable World world, List<String> tooltip, ITooltipFlag flag) {
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get())); tooltip.add(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel3);
tooltip.add(new TextComponentString(TextFormatting.GRAY + "Previous upgrades need to be consumed first")); tooltip.add(TextFormatting.GRAY + "Previous upgrades need to be consumed first");
} }
@Override @Override
public String getTranslationKey() { public String getTranslationKey() {
return this.getRegistryName().toString(); return super.getTranslationKey();
} }
} }

View File

@@ -1,86 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import java.util.ArrayList;
import java.util.function.Supplier;
/***
* Sends a message to the client asking to add a block to the undo stack.
*/
public class AddUndoMessage {
private BlockPos coordinate;
private IBlockState previousBlockState;
private IBlockState newBlockState;
public AddUndoMessage() {
coordinate = BlockPos.ORIGIN;
previousBlockState = null;
newBlockState = null;
}
public AddUndoMessage(BlockPos coordinate, IBlockState previousBlockState, IBlockState newBlockState) {
this.coordinate = coordinate;
this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState;
}
public BlockPos getCoordinate() {
return coordinate;
}
public IBlockState getPreviousBlockState() {
return previousBlockState;
}
public IBlockState getNewBlockState() {
return newBlockState;
}
public static void encode(AddUndoMessage message, PacketBuffer buf) {
buf.writeInt(message.coordinate.getX());
buf.writeInt(message.coordinate.getY());
buf.writeInt(message.coordinate.getZ());
buf.writeInt(Block.getStateId(message.previousBlockState));
buf.writeInt(Block.getStateId(message.newBlockState));
}
public static AddUndoMessage decode(PacketBuffer buf) {
BlockPos coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
IBlockState previousBlockState = Block.getStateById(buf.readInt());
IBlockState newBlockState = Block.getStateById(buf.readInt());
return new AddUndoMessage(coordinate, previousBlockState, newBlockState);
}
public static class Handler
{
public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.addUndo(ctx.get().getSender(), new BlockSet(
new ArrayList<BlockPos>() {{add(message.getCoordinate());}},
new ArrayList<IBlockState>() {{add(message.getPreviousBlockState());}},
new ArrayList<IBlockState>() {{add(message.getNewBlockState());}},
new Vec3d(0,0,0),
message.getCoordinate(), message.getCoordinate()));
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,21 +1,18 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.network.PacketBuffer; import io.netty.buffer.ByteBuf;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.BuildModifiers;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import java.util.function.Supplier; public class BlockBrokenMessage implements IMessage {
/***
* Sends a message to the server indicating that a player wants to break a block
*/
public class BlockBrokenMessage {
private boolean blockHit; private boolean blockHit;
private BlockPos blockPos; private BlockPos blockPos;
@@ -30,19 +27,12 @@ public class BlockBrokenMessage {
} }
public BlockBrokenMessage(RayTraceResult result) { public BlockBrokenMessage(RayTraceResult result) {
this.blockHit = result.type == RayTraceResult.Type.BLOCK; this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos(); this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit; this.sideHit = result.sideHit;
this.hitVec = result.hitVec; this.hitVec = result.hitVec;
} }
public BlockBrokenMessage(boolean blockHit, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
}
public boolean isBlockHit() { public boolean isBlockHit() {
return blockHit; return blockHit;
} }
@@ -59,36 +49,43 @@ public class BlockBrokenMessage {
return hitVec; return hitVec;
} }
public static void encode(BlockBrokenMessage message, PacketBuffer buf) { @Override
buf.writeBoolean(message.blockHit); public void toBytes(ByteBuf buf) {
buf.writeInt(message.blockPos.getX()); buf.writeBoolean(blockHit);
buf.writeInt(message.blockPos.getY()); buf.writeInt(blockPos.getX());
buf.writeInt(message.blockPos.getZ()); buf.writeInt(blockPos.getY());
buf.writeInt(message.sideHit.getIndex()); buf.writeInt(blockPos.getZ());
buf.writeDouble(message.hitVec.x); buf.writeInt(sideHit.getIndex());
buf.writeDouble(message.hitVec.y); buf.writeDouble(hitVec.x);
buf.writeDouble(message.hitVec.z); buf.writeDouble(hitVec.y);
buf.writeDouble(hitVec.z);
} }
public static BlockBrokenMessage decode(PacketBuffer buf) { @Override
boolean blockHit = buf.readBoolean(); public void fromBytes(ByteBuf buf) {
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); blockHit = buf.readBoolean();
EnumFacing sideHit = EnumFacing.byIndex(buf.readInt()); blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); sideHit = EnumFacing.byIndex(buf.readInt());
return new BlockBrokenMessage(blockHit, blockPos, sideHit, hitVec); hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
} }
public static class Handler // The params of the IMessageHandler are <REQ, REPLY>
{ public static class MessageHandler implements IMessageHandler<BlockBrokenMessage, IMessage> {
public static void handle(BlockBrokenMessage message, Supplier<NetworkEvent.Context> ctx) // Do note that the default constructor is required, but implicitly defined in this case
{
ctx.get().enqueueWork(() -> { @Override
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.SERVER) { public IMessage onMessage(BlockBrokenMessage message, MessageContext ctx) {
//Received serverside //EffortlessBuilding.log("message received on " + ctx.side + " side");
BuildModes.onBlockBrokenMessage(ctx.get().getSender(), message);
} if (ctx.side == Side.SERVER) {
}); //Received serverside
ctx.get().setPacketHandled(true); EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
BuildModifiers.onBlockBrokenMessage(ctx.getServerHandler().player, message);
});
}
// No response packet
return null;
} }
} }
} }

View File

@@ -1,52 +1,37 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.network.PacketBuffer; import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import nl.requios.effortlessbuilding.BuildModifiers;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.function.Supplier; public class BlockPlacedMessage implements IMessage {
/***
* Sends a message to the server indicating that a player wants to place a block.
* Received clientside: server has placed blocks and its letting the client know.
*/
public class BlockPlacedMessage {
private boolean blockHit; private boolean blockHit;
private BlockPos blockPos; private BlockPos blockPos;
private EnumFacing sideHit; private EnumFacing sideHit;
private Vec3d hitVec; private Vec3d hitVec;
private boolean placeStartPos; //prevent double placing in normal mode
public BlockPlacedMessage() { public BlockPlacedMessage() {
this.blockHit = false; this.blockHit = false;
this.blockPos = BlockPos.ORIGIN; this.blockPos = BlockPos.ORIGIN;
this.sideHit = EnumFacing.UP; this.sideHit = EnumFacing.UP;
this.hitVec = new Vec3d(0, 0, 0); this.hitVec = new Vec3d(0, 0, 0);
this.placeStartPos = true;
} }
public BlockPlacedMessage(RayTraceResult result, boolean placeStartPos) { public BlockPlacedMessage(RayTraceResult result) {
this.blockHit = result.type == RayTraceResult.Type.BLOCK; this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK;
this.blockPos = result.getBlockPos(); this.blockPos = result.getBlockPos();
this.sideHit = result.sideHit; this.sideHit = result.sideHit;
this.hitVec = result.hitVec; this.hitVec = result.hitVec;
this.placeStartPos = placeStartPos;
}
public BlockPlacedMessage(boolean blockHit, BlockPos blockPos, EnumFacing sideHit, Vec3d hitVec, boolean placeStartPos) {
this.blockHit = blockHit;
this.blockPos = blockPos;
this.sideHit = sideHit;
this.hitVec = hitVec;
this.placeStartPos = placeStartPos;
} }
public boolean isBlockHit() { public boolean isBlockHit() {
@@ -65,46 +50,46 @@ public class BlockPlacedMessage {
return hitVec; return hitVec;
} }
public boolean getPlaceStartPos() { @Override
return placeStartPos; public void toBytes(ByteBuf buf) {
buf.writeBoolean(blockHit);
buf.writeInt(blockPos.getX());
buf.writeInt(blockPos.getY());
buf.writeInt(blockPos.getZ());
buf.writeInt(sideHit.getIndex());
buf.writeDouble(hitVec.x);
buf.writeDouble(hitVec.y);
buf.writeDouble(hitVec.z);
} }
public static void encode(BlockPlacedMessage message, PacketBuffer buf) { @Override
buf.writeBoolean(message.blockHit); public void fromBytes(ByteBuf buf) {
buf.writeInt(message.blockPos.getX()); blockHit = buf.readBoolean();
buf.writeInt(message.blockPos.getY()); blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
buf.writeInt(message.blockPos.getZ()); sideHit = EnumFacing.byIndex(buf.readInt());
buf.writeInt(message.sideHit.getIndex()); hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
buf.writeBoolean(message.placeStartPos);
} }
public static BlockPlacedMessage decode(PacketBuffer buf) { // The params of the IMessageHandler are <REQ, REPLY>
boolean blockHit = buf.readBoolean(); public static class MessageHandler implements IMessageHandler<BlockPlacedMessage, IMessage> {
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); // Do note that the default constructor is required, but implicitly defined in this case
EnumFacing sideHit = EnumFacing.byIndex(buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean placeStartPos = buf.readBoolean();
return new BlockPlacedMessage(blockHit, blockPos, sideHit, hitVec, placeStartPos);
}
public static class Handler @Override
{ public IMessage onMessage(BlockPlacedMessage message, MessageContext ctx) {
public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) //EffortlessBuilding.log("message received on " + ctx.side + " side");
{
ctx.get().enqueueWork(() -> { if (ctx.side == Side.CLIENT){
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { //Received clientside
//Received clientside //Send back your info
//Nod RenderHandler to do the dissolve shader effect return new BlockPlacedMessage(ClientProxy.previousLookAt);
BlockPreviewRenderer.onBlocksPlaced(); } else {
} else { //Received serverside
//Received serverside EffortlessBuilding.proxy.getThreadListenerFromContext(ctx).addScheduledTask(() -> {
BuildModes.onBlockPlacedMessage(ctx.get().getSender(), message); BuildModifiers.onBlockPlacedMessage(ctx.getServerHandler().player, message);
} });
}); // No response packet
ctx.get().setPacketHandled(true); return null;
}
} }
} }
} }

View File

@@ -1,37 +1,31 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer; import net.minecraft.util.IThreadListener;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import nl.requios.effortlessbuilding.EffortlessBuilding; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import nl.requios.effortlessbuilding.buildmodifier.Array; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.*;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import java.util.function.Supplier; public class BuildSettingsMessage implements IMessage {
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; private BuildSettings buildSettings;
/** public BuildSettingsMessage() {
* Shares modifier settings (see ModifierSettingsManager) between server and client
*/
public class ModifierSettingsMessage {
private ModifierSettings modifierSettings;
public ModifierSettingsMessage() {
} }
public ModifierSettingsMessage(ModifierSettings modifierSettings) { public BuildSettingsMessage(BuildSettings buildSettings) {
this.modifierSettings = modifierSettings; this.buildSettings = buildSettings;
} }
public static void encode(ModifierSettingsMessage message, PacketBuffer buf) { @Override
public void toBytes(ByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = buildSettings.getMirrorSettings();
buf.writeBoolean(m != null); buf.writeBoolean(m != null);
if (m != null) { if (m != null) {
buf.writeBoolean(m.enabled); buf.writeBoolean(m.enabled);
@@ -47,7 +41,7 @@ public class ModifierSettingsMessage {
} }
//ARRAY //ARRAY
Array.ArraySettings a = message.modifierSettings.getArraySettings(); Array.ArraySettings a = buildSettings.getArraySettings();
buf.writeBoolean(a != null); buf.writeBoolean(a != null);
if (a != null) { if (a != null) {
buf.writeBoolean(a.enabled); buf.writeBoolean(a.enabled);
@@ -57,12 +51,12 @@ public class ModifierSettingsMessage {
buf.writeInt(a.count); buf.writeInt(a.count);
} }
buf.writeBoolean(message.modifierSettings.doQuickReplace()); buf.writeBoolean(buildSettings.doQuickReplace());
buf.writeInt(message.modifierSettings.getReachUpgrade()); buf.writeInt(buildSettings.getReachUpgrade());
//RADIAL MIRROR //RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = buildSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null); buf.writeBoolean(r != null);
if (r != null) { if (r != null) {
buf.writeBoolean(r.enabled); buf.writeBoolean(r.enabled);
@@ -77,7 +71,8 @@ public class ModifierSettingsMessage {
} }
} }
public static ModifierSettingsMessage decode(PacketBuffer buf) { @Override
public void fromBytes(ByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = new Mirror.MirrorSettings(); Mirror.MirrorSettings m = new Mirror.MirrorSettings();
if (buf.readBoolean()) { if (buf.readBoolean()) {
@@ -90,7 +85,7 @@ public class ModifierSettingsMessage {
boolean mirrorDrawLines = buf.readBoolean(); boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean(); boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes); mirrorDrawLines, mirrorDrawPlanes);
} }
//ARRAY //ARRAY
@@ -117,26 +112,35 @@ public class ModifierSettingsMessage {
boolean radialMirrorDrawLines = buf.readBoolean(); boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean(); boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices, r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes); radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
} }
ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade); buildSettings = new BuildSettings(m, a, r, quickReplace, reachUpgrade);
return new ModifierSettingsMessage(modifierSettings);
} }
public static class Handler // The params of the IMessageHandler are <REQ, REPLY>
{ public static class MessageHandler implements IMessageHandler<BuildSettingsMessage, IMessage> {
public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx) // Do note that the default constructor is required, but implicitly defined in this case
{
ctx.get().enqueueWork(() -> { @Override
public IMessage onMessage(BuildSettingsMessage message, MessageContext ctx) {
//EffortlessBuilding.log("message received on " + ctx.side + " side");
// The value that was sent
BuildSettings buildSettings = message.buildSettings;
// Execute the action on the main server thread by adding it as a scheduled task
IThreadListener threadListener = EffortlessBuilding.proxy.getThreadListenerFromContext(ctx);
threadListener.addScheduledTask(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize // Sanitize
ModifierSettingsManager.sanitize(message.modifierSettings, player); BuildSettingsManager.sanitize(buildSettings, player);
ModifierSettingsManager.setModifierSettings(player, message.modifierSettings); BuildSettingsManager.setBuildSettings(player, buildSettings);
}); });
ctx.get().setPacketHandled(true); // No response packet
return null;
} }
} }
} }

View File

@@ -1,35 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import java.util.function.Supplier;
/**
* Sends a message to the server indicating that a buildmode needs to be canceled for a player
*/
public class CancelModeMessage {
public static void encode(CancelModeMessage message, PacketBuffer buf) {
}
public static CancelModeMessage decode(PacketBuffer buf) {
return new CancelModeMessage();
}
public static class Handler
{
public static void handle(CancelModeMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
BuildModes.initializeMode(player);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,44 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import java.util.function.Supplier;
/***
* Sends a message to the client asking to clear the undo and redo stacks.
*/
public class ClearUndoMessage {
public ClearUndoMessage() {
}
public static void encode(ClearUndoMessage message, PacketBuffer buf) {
}
public static ClearUndoMessage decode(PacketBuffer buf) {
return new ClearUndoMessage();
}
public static class Handler
{
public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Add to undo stack clientside
UndoRedo.clear(player);
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,46 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import java.util.function.Supplier;
/**
* Shares mode settings (see ModeSettingsManager) between server and client
*/
public class ModeActionMessage {
private ModeOptions.ActionEnum action;
public ModeActionMessage() {
}
public ModeActionMessage(ModeOptions.ActionEnum action) {
this.action = action;
}
public static void encode(ModeActionMessage message, PacketBuffer buf) {
buf.writeInt(message.action.ordinal());
}
public static ModeActionMessage decode(PacketBuffer buf) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.values()[buf.readInt()];
return new ModeActionMessage(action);
}
public static class Handler
{
public static void handle(ModeActionMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ModeOptions.performAction(player, message.action);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,54 +0,0 @@
package nl.requios.effortlessbuilding.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
import java.util.function.Supplier;
/**
* Shares mode settings (see ModeSettingsManager) between server and client
*/
public class ModeSettingsMessage {
private ModeSettings modeSettings;
public ModeSettingsMessage() {
}
public ModeSettingsMessage(ModeSettings modeSettings) {
this.modeSettings = modeSettings;
}
public static void encode(ModeSettingsMessage message, PacketBuffer buf) {
buf.writeInt(message.modeSettings.getBuildMode().ordinal());
}
public static ModeSettingsMessage decode(PacketBuffer buf) {
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
return new ModeSettingsMessage(new ModeSettings(buildMode));
}
public static class Handler
{
public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize
ModeSettingsManager.sanitize(message.modeSettings, player);
ModeSettingsManager.setModeSettings(player, message.modeSettings);
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,32 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
import nl.requios.effortlessbuilding.EffortlessBuilding;
public class PacketHandler {
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.ChannelBuilder
.named(new ResourceLocation(EffortlessBuilding.MODID, "main_channel"))
.clientAcceptedVersions(PROTOCOL_VERSION::equals)
.serverAcceptedVersions(PROTOCOL_VERSION::equals)
.networkProtocolVersion(() -> PROTOCOL_VERSION)
.simpleChannel();
public static void register() {
int id = 0;
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockPlacedMessage.class, BlockPlacedMessage::encode, BlockPlacedMessage::decode, BlockPlacedMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockBrokenMessage.class, BlockBrokenMessage::encode, BlockBrokenMessage::decode, BlockBrokenMessage.Handler::handle);
INSTANCE.registerMessage(id++, CancelModeMessage.class, CancelModeMessage::encode, CancelModeMessage::decode, CancelModeMessage.Handler::handle);
INSTANCE.registerMessage(id++, RequestLookAtMessage.class, RequestLookAtMessage::encode, RequestLookAtMessage::decode, RequestLookAtMessage.Handler::handle);
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle);
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle);
}
}

View File

@@ -1,65 +0,0 @@
package nl.requios.effortlessbuilding.network;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import java.util.ArrayList;
import java.util.function.Supplier;
/***
* Sends a message to the client asking for its lookat (objectmouseover) data.
* This is then sent back with a BlockPlacedMessage.
*/
public class RequestLookAtMessage {
private boolean placeStartPos;
public RequestLookAtMessage() {
placeStartPos = false;
}
public RequestLookAtMessage(boolean placeStartPos) {
this.placeStartPos = placeStartPos;
}
public boolean getPlaceStartPos() {
return placeStartPos;
}
public static void encode(RequestLookAtMessage message, PacketBuffer buf) {
buf.writeBoolean(message.placeStartPos);
}
public static RequestLookAtMessage decode(PacketBuffer buf) {
boolean placeStartPos = buf.readBoolean();
return new RequestLookAtMessage(placeStartPos);
}
public static class Handler
{
public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx)
{
ctx.get().enqueueWork(() -> {
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
//Send back your info
EntityPlayer player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
//Prevent double placing in normal mode with placeStartPos false
//Unless QuickReplace is on, then we do need to place start pos.
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage(ClientProxy.previousLookAt, message.getPlaceStartPos()));
}
});
ctx.get().setPacketHandled(true);
}
}
}

View File

@@ -1,393 +1,250 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.KeyboardListener;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.IThreadListener;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceFluidMode;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.client.settings.KeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier;
import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.network.NetworkEvent; import nl.requios.effortlessbuilding.BuildModifiers;
import nl.requios.effortlessbuilding.BuildSettingsManager;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.gui.SettingsGui;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.*; import nl.requios.effortlessbuilding.helper.RenderHelper;
import nl.requios.effortlessbuilding.render.RenderHandler; import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.render.ShaderHandler; import nl.requios.effortlessbuilding.network.BlockBrokenMessage;
import org.lwjgl.glfw.GLFW; import nl.requios.effortlessbuilding.network.BlockPlacedMessage;
import nl.requios.effortlessbuilding.network.BuildSettingsMessage;
import org.lwjgl.input.Keyboard;
import javax.annotation.Nullable; @Mod.EventBusSubscriber(Side.CLIENT)
import java.util.HashMap;
import java.util.function.Supplier;
@Mod.EventBusSubscriber(value = {Dist.CLIENT})
public class ClientProxy implements IProxy { public class ClientProxy implements IProxy {
public static KeyBinding[] keyBindings; public static KeyBinding[] keyBindings;
public static RayTraceResult previousLookAt; public static RayTraceResult previousLookAt;
public static RayTraceResult currentLookAt; public static RayTraceResult currentLookAt;
private static int placeCooldown = 0;
private static int breakCooldown = 0; private static int breakCooldown = 0;
private static boolean shadersInitialized = false;
public static int ticksInGame = 0;
private static final HashMap<BuildModes.BuildModeEnum, ResourceLocation> buildModeIcons = new HashMap<>();
private static final HashMap<ModeOptions.ActionEnum, ResourceLocation> modeOptionIcons = new HashMap<>();
@Override @Override
public void setup(FMLCommonSetupEvent event) {} public void preInit(FMLPreInitializationEvent event) {
}
@Override @Override
public void clientSetup(FMLClientSetupEvent event) { public void init(FMLInitializationEvent event) {
//Crashes in 1.13, do it elsewhere
// ShaderHandler.init();
// register key bindings // register key bindings
keyBindings = new KeyBinding[7]; keyBindings = new KeyBinding[3];
// instantiate the key bindings // instantiate the key bindings
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category"); keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", Keyboard.KEY_ADD, "key.effortlessbuilding.category");
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_SUBTRACT, 0), "key.effortlessbuilding.category"); keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", Keyboard.KEY_SUBTRACT, "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_F4, 0), "key.effortlessbuilding.category"); keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", Keyboard.KEY_F4, "key.effortlessbuilding.category");
keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category") {
@Override
public boolean func_197983_b(KeyBinding other) {
//Does not conflict with Chisels and Bits radial menu
if (other.getKey().getKeyCode() == getKey().getKeyCode() && other.getKeyDescription().equals("mod.chiselsandbits.other.mode")) return false;
return super.func_197983_b(other);
}
};
keyBindings[4] = new KeyBinding("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");
keyBindings[5] = new KeyBinding("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category");
keyBindings[6] = new KeyBinding("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category");
//keyBindings[7] = new KeyBinding("Reload shaders", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_TAB, 0), "key.effortlessbuilding.category");
// register all the key bindings // register all the key bindings
for (int i = 0; i < keyBindings.length; ++i) { for (int i = 0; i < keyBindings.length; ++i) {
ClientRegistry.registerKeyBinding(keyBindings[i]); ClientRegistry.registerKeyBinding(keyBindings[i]);
} }
}
@Override
public void postInit(FMLPostInitializationEvent event) {
} }
public EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){ @Override
return (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT ? Minecraft.getInstance().player : ctx.get().getSender()); public EntityPlayer getPlayerEntityFromContext(MessageContext ctx) {
return (ctx.side.isClient() ? Minecraft.getMinecraft().player : ctx.getServerHandler().player);
}
@Override
public IThreadListener getThreadListenerFromContext(MessageContext ctx) {
return (ctx.side.isClient() ? Minecraft.getMinecraft() : ((EntityPlayerMP) getPlayerEntityFromContext(ctx)).getServerWorld());
}
@Override
public void serverStarting(FMLServerStartingEvent event) {
//This will get called clientside
}
@SubscribeEvent
public static void registerModels(ModelRegistryEvent event) {
for (Block block : EffortlessBuilding.BLOCKS) {
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory"));
}
for (Item item : EffortlessBuilding.ITEMS) {
ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory"));
}
} }
@SubscribeEvent @SubscribeEvent
public static void onEntityJoinWorld(EntityJoinWorldEvent event) { public static void onEntityJoinWorld(EntityJoinWorldEvent event) {
if (event.getEntity() == Minecraft.getInstance().player) { if (event.getEntity() == Minecraft.getMinecraft().player) {
event.getWorld().addEventListener(new RenderHandler()); event.getWorld().addEventListener(new RenderHelper());
} }
} }
@SubscribeEvent @SubscribeEvent
public static void onTextureStitch(final TextureStitchEvent.Pre event) { public static void onMouseInput(InputEvent.MouseInputEvent event) {
//register icon textures Minecraft mc = Minecraft.getMinecraft();
final TextureMap map = event.getMap();
for ( final BuildModes.BuildModeEnum mode : BuildModes.BuildModeEnum.values() )
{
final ResourceLocation sprite = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + mode.name().toLowerCase());
map.registerSprite(Minecraft.getInstance().getResourceManager(), sprite);
buildModeIcons.put(mode, sprite);
}
for ( final ModeOptions.ActionEnum action : ModeOptions.ActionEnum.values() )
{
final ResourceLocation sprite = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + action.name().toLowerCase());
map.registerSprite(Minecraft.getInstance().getResourceManager(), sprite);
modeOptionIcons.put(action, sprite);
}
}
public static TextureAtlasSprite getBuildModeIcon(BuildModes.BuildModeEnum mode) {
return Minecraft.getInstance().getTextureMap().getSprite(buildModeIcons.get(mode));
}
public static TextureAtlasSprite getModeOptionIcon(ModeOptions.ActionEnum action) {
return Minecraft.getInstance().getTextureMap().getSprite(modeOptionIcons.get(action));
}
@SubscribeEvent
public static void onClientTick(TickEvent.ClientTickEvent event) {
if (event.phase == TickEvent.Phase.START) {
onMouseInput();
//Update previousLookAt
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return;
if (currentLookAt == null) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
return;
}
if (objectMouseOver.type == RayTraceResult.Type.BLOCK) {
if (currentLookAt.type != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
}
} else if (event.phase == TickEvent.Phase.END){
GuiScreen gui = Minecraft.getInstance().currentScreen;
if(gui == null || !gui.doesGuiPauseGame()) {
ticksInGame++;
}
//Init shaders in the first tick. Doing it anywhere before this seems to crash the game.
if (!shadersInitialized) {
ShaderHandler.init();
shadersInitialized = true;
}
}
}
private static void onMouseInput() {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player; EntityPlayerSP player = mc.player;
if (player == null) return;
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (Minecraft.getInstance().currentScreen != null || if (!BuildModifiers.isEnabled(BuildSettingsManager.getBuildSettings(player), player.getPosition())) return;
buildMode == BuildModes.BuildModeEnum.NORMAL ||
RadialMenu.instance.isVisible()) {
return;
}
if (mc.gameSettings.keyBindUseItem.isKeyDown()) {
if (mc.gameSettings.keyBindUseItem.isPressed()) {
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); //KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
if (placeCooldown <= 0) { ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND);
placeCooldown = 4; if (currentItemStack.getItem() instanceof ItemBlock ||
(currentItemStack.getItem() instanceof ItemRandomizerBag && !player.isSneaking())) {
ItemStack currentItemStack = player.getHeldItem(EnumHand.MAIN_HAND); //find position in distance
if (currentItemStack.getItem() instanceof ItemBlock || RayTraceResult lookingAt = getLookingAt(player);
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isSneaking())) { if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
EffortlessBuilding.packetHandler.sendToServer(new BlockPlacedMessage(lookingAt));
ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack);
//find position in distance
RayTraceResult lookingAt = getLookingAt(player);
BuildModes.onBlockPlacedMessage(player, lookingAt == null ? new BlockPlacedMessage() : new BlockPlacedMessage(lookingAt, true));
PacketHandler.INSTANCE.sendToServer(lookingAt == null ? new BlockPlacedMessage() : new BlockPlacedMessage(lookingAt, true));
//play sound if further than normal //play sound if further than normal
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK && if ((lookingAt.hitVec.subtract(player.getPositionEyes(1f))).lengthSquared() > 25f) {
(lookingAt.hitVec.subtract(player.getEyePosition(1f))).lengthSquared() > 25f &&
itemStack.getItem() instanceof ItemBlock) {
IBlockState state = ((ItemBlock) itemStack.getItem()).getBlock().getDefaultState();
BlockPos blockPos = lookingAt.getBlockPos(); BlockPos blockPos = lookingAt.getBlockPos();
SoundType soundType = state.getBlock().getSoundType(state, player.world, blockPos, player); IBlockState state = player.world.getBlockState(blockPos);
player.world.playSound(player, player.getPosition(), soundType.getPlaceSound(), SoundCategory.BLOCKS, SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
0.4f, soundType.getPitch() * 1f); player.world.playSound(player, blockPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS,
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.swingArm(EnumHand.MAIN_HAND); player.swingArm(EnumHand.MAIN_HAND);
} }
} }
} }
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
placeCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
}
} else {
placeCooldown = 0;
} }
if (mc.gameSettings.keyBindAttack.isKeyDown()) { if (mc.gameSettings.keyBindAttack.isKeyDown()) {
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindAttack.getKeyCode(), false);
//Break block in distance in creative (or survival if enabled in config) //Break block in distance in creative (or survival if enabled in config)
if (breakCooldown <= 0) { if (ReachHelper.canBreakFar(player)) {
breakCooldown = 4; if (breakCooldown <= 0) {
breakCooldown = 6;
RayTraceResult lookingAt = getLookingAt(player);
if (lookingAt != null && lookingAt.typeOfHit == RayTraceResult.Type.BLOCK) {
EffortlessBuilding.packetHandler.sendToServer(new BlockBrokenMessage(lookingAt));
//Early out if cant break far, coming from own mouse event (not block broken event) //play sound
//To make breaking blocks in survival possible like array BlockPos blockPos = lookingAt.getBlockPos();
//TODO this causes not being able to cancel placement in survival IBlockState state = player.world.getBlockState(blockPos);
// moving it to after buildmodes fixes that, but introduces this bug SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
if (!ReachHelper.canBreakFar(player)) return; player.world.playSound(player, blockPos, soundtype.getBreakSound(), SoundCategory.BLOCKS,
(soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
RayTraceResult lookingAt = getLookingAt(player); player.swingArm(EnumHand.MAIN_HAND);
BuildModes.onBlockBrokenMessage(player, lookingAt == null ? new BlockBrokenMessage() : new BlockBrokenMessage(lookingAt)); }
PacketHandler.INSTANCE.sendToServer(lookingAt == null ? new BlockBrokenMessage() : new BlockBrokenMessage(lookingAt)); } else {
breakCooldown--;
//play sound if further than normal
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK &&
(lookingAt.hitVec.subtract(player.getEyePosition(1f))).lengthSquared() > 25f) {
BlockPos blockPos = lookingAt.getBlockPos();
IBlockState state = player.world.getBlockState(blockPos);
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player);
player.world.playSound(player, player.getPosition(), soundtype.getBreakSound(), SoundCategory.BLOCKS,
0.4f, soundtype.getPitch() * 1f);
player.swingArm(EnumHand.MAIN_HAND);
} }
} }
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
breakCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
}
//EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage());
} else { } else {
breakCooldown = 0; breakCooldown = 0;
} }
event.setResult(Event.Result.ALLOW);
} }
@SubscribeEvent(receiveCanceled = true) @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true)
public static void onKeyPress(InputEvent.KeyInputEvent event) { public static void onKeyPress(InputEvent.KeyInputEvent event) {
EntityPlayerSP player = Minecraft.getInstance().player; EntityPlayerSP player = Minecraft.getMinecraft().player;
//Remember to send packet to server if necessary //Remember to send packet to server if necessary
//Show Modifier Settings GUI //Show HUD
if (keyBindings[0].isPressed()) { if (keyBindings[0].isPressed()) {
openModifierSettings(); //Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Effortless Building is disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
if (Minecraft.getMinecraft().currentScreen == null) {
Minecraft.getMinecraft().displayGuiScreen(new SettingsGui());
} else {
player.closeScreen();
}
}
} }
//QuickReplace toggle //QuickReplace toggle
if (keyBindings[1].isPressed()) { if (keyBindings[1].isPressed()) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace()); buildSettings.setQuickReplace(!buildSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + ( EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (buildSettings.doQuickReplace() ? "on" : "off"));
modifierSettings.doQuickReplace() ? "on" : "off")); EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings));
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
} }
//Creative/survival mode toggle //Creative/survival mode toggle
if (keyBindings[2].isPressed()) { if (keyBindings[2].isPressed()) {
if (player.isCreative()) { if (player.isCreative()) {
player.sendChatMessage("/gamemode survival"); player.sendChatMessage("/gamemode 0");
} else { } else {
player.sendChatMessage("/gamemode creative"); player.sendChatMessage("/gamemode 1");
}
}
//Undo (Ctrl+Z)
if (keyBindings[4].isPressed()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
//Redo (Ctrl+Y)
if (keyBindings[5].isPressed()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.REDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
//Change placement mode
if (keyBindings[6].isPressed()) {
//Toggle between first two actions of the first option of the current build mode
BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentBuildMode.options.length > 0) {
ModeOptions.OptionEnum option = currentBuildMode.options[0];
if (option.actions.length >= 2) {
if (ModeOptions.getOptionSetting(option) == option.actions[0]) {
ModeOptions.performAction(player, option.actions[1]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[1]));
} else {
ModeOptions.performAction(player, option.actions[0]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[0]));
}
}
}
}
//For shader development
if (keyBindings.length >= 8 && keyBindings[7].isPressed()) {
ShaderHandler.init();
EffortlessBuilding.log(player, "Reloaded shaders");
}
}
public static void openModifierSettings() {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player;
RadialMenu.instance.setVisibility(0f);
//Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
if (mc.currentScreen == null) {
mc.displayGuiScreen(new ModifierSettingsGui());
} else {
player.closeScreen();
} }
} }
} }
@SubscribeEvent @SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) { public static void onClientTick(TickEvent.ClientTickEvent event) {
EntityPlayer player = Minecraft.getInstance().player; if (event.phase != TickEvent.Phase.START) return;
if (player != null) {
BuildModes.initializeMode(player); RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return;
if (currentLookAt == null) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
return;
}
if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) {
if (currentLookAt.typeOfHit != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()){
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
} }
} }
@Nullable
public static RayTraceResult getLookingAt(EntityPlayer player) { public static RayTraceResult getLookingAt(EntityPlayer player) {
// World world = player.world; // World world = player.world;
//base distance off of player ability (config) //base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player); float raytraceRange = ReachHelper.getMaxReach(player) / 4f;
// Vec3d look = player.getLookVec(); // Vec3d look = player.getLookVec();
// Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ); // Vec3d start = new Vec3d(player.posX, player.posY + player.getEyeHeight(), player.posZ);
// Vec3d end = new Vec3d(player.posX + look.x * raytraceRange, player.posY + player.getEyeHeight() + look.y * raytraceRange, player.posZ + look.z * raytraceRange); // Vec3d end = new Vec3d(player.posX + look.x * raytraceRange, player.posY + player.getEyeHeight() + look.y * raytraceRange, player.posZ + look.z * raytraceRange);
return player.rayTrace(raytraceRange, 1f, RayTraceFluidMode.NEVER); return player.rayTrace(raytraceRange, 1f);
// return world.rayTraceBlocks(start, end, false, false, false); // return world.rayTraceBlocks(start, end, false, false, false);
} }
public static void logTranslate(String key) {
EffortlessBuilding.log(Minecraft.getInstance().player, I18n.format(key), true);
}
} }

View File

@@ -1,16 +1,43 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import java.util.function.Supplier; public interface IProxy
{
/**
* Register entities and networking.
*/
void preInit(FMLPreInitializationEvent event);
public interface IProxy { /**
void setup(final FMLCommonSetupEvent event); * Register event listeners, recipes and advancements.
*/
void init(FMLInitializationEvent event);
void clientSetup(final FMLClientSetupEvent event); /**
* For doing inter-mod stuff like checking which mods are loaded or if you want a complete view of things across
* mods like having a list of all registered items to aid random item generation.
*/
void postInit(FMLPostInitializationEvent event);
EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx); /**
* Server commands should be registered here.
*/
void serverStarting(FMLServerStartingEvent event);
/**
* Returns a side-appropriate EntityPlayer for use during message handling.
*
* @param ctx the context
* @return the player entity from context
*/
EntityPlayer getPlayerEntityFromContext(MessageContext ctx);
IThreadListener getThreadListenerFromContext(MessageContext ctx);
} }

View File

@@ -1,23 +1,45 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import java.util.function.Supplier; public class ServerProxy implements IProxy
{
public class ServerProxy implements IProxy {
//Only physical server! Singleplayer server is seen as clientproxy //Only physical server! Singleplayer server is seen as clientproxy
@Override @Override
public void setup(FMLCommonSetupEvent event) { public void preInit(FMLPreInitializationEvent event)
{
} }
@Override @Override
public void clientSetup(FMLClientSetupEvent event) {} public void init(FMLInitializationEvent event)
{
}
public EntityPlayer getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){ @Override
return ctx.get().getSender(); public void postInit(FMLPostInitializationEvent event)
{
}
@Override
public void serverStarting(FMLServerStartingEvent event)
{
}
@Override
public EntityPlayer getPlayerEntityFromContext(MessageContext ctx)
{
return ctx.getServerHandler().player;
}
@Override
public IThreadListener getThreadListenerFromContext(MessageContext ctx) {
return ((EntityPlayerMP) getPlayerEntityFromContext(ctx)).getServerWorld();
} }
} }

View File

@@ -1,439 +0,0 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.SoundType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.ARBMultitexture;
import org.lwjgl.opengl.ARBShaderObjects;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
@OnlyIn(Dist.CLIENT)
public class BlockPreviewRenderer {
private static List<BlockPos> previousCoordinates;
private static List<IBlockState> previousBlockStates;
private static List<ItemStack> previousItemStacks;
private static BlockPos previousFirstPos;
private static BlockPos previousSecondPos;
private static int soundTime = 0;
static class PlacedData {
float time;
List<BlockPos> coordinates;
List<IBlockState> blockStates;
List<ItemStack> itemStacks;
BlockPos firstPos;
BlockPos secondPos;
boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time;
this.coordinates = coordinates;
this.blockStates = blockStates;
this.itemStacks = itemStacks;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.breaking = breaking;
}
}
private static List<PlacedData> placedDataList = new ArrayList<>();
private static final int primaryTextureUnit = 0;
private static final int secondaryTextureUnit = 2;
public static void render(EntityPlayer player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
//Render placed blocks with dissolve effect
//Use fancy shader if config allows, otherwise no dissolve
if (BuildConfig.visuals.useShaders.get()) {
RenderHandler.beginBlockPreviews();
for (int i = 0; i < placedDataList.size(); i++) {
PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
}
}
RenderHandler.endBlockPreviews();
}
//Expire
placedDataList.removeIf(placed -> {
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
return placed.time + totalTime < ClientProxy.ticksInGame;
});
//Render block previews
RayTraceResult lookingAt = ClientProxy.getLookingAt(player);
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL) lookingAt = Minecraft.getInstance().objectMouseOver;
ItemStack mainhand = player.getHeldItemMainhand();
boolean toolInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
BlockPos startPos = null;
EnumFacing sideHit = null;
Vec3d hitVec = null;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.type == RayTraceResult.Type.BLOCK) {
startPos = lookingAt.getBlockPos();
//Check if tool (or none) in hand
//TODO 1.13 replaceable
boolean replaceable = player.world.getBlockState(startPos).getBlock().getMaterial(player.world.getBlockState(startPos)).isReplaceable();
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, lookingAt.sideHit);
if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable && !becomesDoubleSlab) {
startPos = startPos.offset(lookingAt.sideHit);
}
//Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down();
}
sideHit = lookingAt.sideHit;
hitVec = lookingAt.hitVec;
}
//Dont render if in normal mode and modifiers are disabled
//Unless alwaysShowBlockPreview is true in config
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
//Keep blockstate the same for every block in the buildmode
//So dont rotate blocks when in the middle of placing wall etc.
if (BuildModes.isActive(player)) {
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
}
if (sideHit != null) {
//Should be red?
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
//get coordinates
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
//Remember first and last point for the shader
BlockPos firstPos = BlockPos.ORIGIN, secondPos = BlockPos.ORIGIN;
if (!startCoordinates.isEmpty()) {
firstPos = startCoordinates.get(0);
secondPos = startCoordinates.get(startCoordinates.size() - 1);
}
//Limit number of blocks you can place
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (startCoordinates.size() > limit) {
startCoordinates = startCoordinates.subList(0, limit);
}
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
sortOnDistanceToPlayer(newCoordinates, player);
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
Math.abs(hitVec.z - ((int) hitVec.z)));
//Get blockstates
List<ItemStack> itemStacks = new ArrayList<>();
List<IBlockState> blockStates = new ArrayList<>();
if (breaking) {
//Find blockstate of world
for (BlockPos coordinate : newCoordinates) {
blockStates.add(player.world.getBlockState(coordinate));
}
} else {
blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
}
//Check if they are different from previous
//TODO fix triggering when moving player
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
previousCoordinates = newCoordinates;
//remember the rest for placed blocks
previousBlockStates = blockStates;
previousItemStacks = itemStacks;
previousFirstPos = firstPos;
previousSecondPos = secondPos;
//if so, renew randomness of randomizer bag
ItemRandomizerBag.renewRandomness();
//and play sound (max once every tick)
if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
soundTime = ClientProxy.ticksInGame;
if (blockStates.get(0) != null) {
SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world,
newCoordinates.get(0), player);
player.world.playSound(player, player.getPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(),
SoundCategory.BLOCKS, 0.3f, 0.8f);
}
}
}
//Render block previews
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount;
//Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
RenderHandler.beginBlockPreviews();
blockCount = renderBlockPreviews(newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
RenderHandler.endBlockPreviews();
} else {
RenderHandler.beginLines();
Vec3d color = new Vec3d(1f, 1f, 1f);
if (breaking) color = new Vec3d(1f, 0f, 0f);
for (int i = newCoordinates.size() - 1; i >= 0; i--) {
VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.world, newCoordinates.get(i));
RenderHandler.renderBlockOutline(newCoordinates.get(i), collisionShape, color);
}
RenderHandler.endLines();
blockCount = newCoordinates.size();
}
//Display block count and dimensions in actionbar
if (BuildModes.isActive(player)) {
//Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
for (BlockPos pos : startCoordinates) {
if (pos.getX() < minX) minX = pos.getX();
if (pos.getX() > maxX) maxX = pos.getX();
if (pos.getY() < minY) minY = pos.getY();
if (pos.getY() > maxY) maxY = pos.getY();
if (pos.getZ() < minZ) minZ = pos.getZ();
if (pos.getZ() > maxZ) maxZ = pos.getZ();
}
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
String dimensions = "(";
if (dim.getX() > 1) dimensions += dim.getX() + "x";
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x";
dimensions = dimensions.substring(0, dimensions.length() - 1);
if (dimensions.length() > 1) dimensions += ")";
EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
}
}
}
RenderHandler.beginLines();
//Draw outlines if tool in hand
//Find proper raytrace: either normal range or increased range depending on canBreakFar
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver;
RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
if (toolInHand && breakingRaytrace != null && breakingRaytrace.type == RayTraceResult.Type.BLOCK) {
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, breakingRaytrace.getBlockPos());
//Only render first outline if further than normal reach
boolean excludeFirst = objectMouseOver != null && objectMouseOver.type == RayTraceResult.Type.BLOCK;
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
IBlockState blockState = player.world.getBlockState(coordinate);
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) {
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) {
VoxelShape collisionShape = blockState.getCollisionShape(player.world, coordinate);
RenderHandler.renderBlockOutline(coordinate, collisionShape, new Vec3d(0f, 0f, 0f));
}
}
}
}
RenderHandler.endLines();
}
}
//Whether to draw any block previews or outlines
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL ||
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
BuildConfig.visuals.alwaysShowBlockPreview.get();
}
protected static int renderBlockPreviews(List<BlockPos> coordinates, List<IBlockState> blockStates,
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) {
EntityPlayer player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher();
int blocksValid = 0;
if (coordinates.isEmpty()) return blocksValid;
for (int i = coordinates.size() - 1; i >= 0; i--) {
BlockPos blockPos = coordinates.get(i);
IBlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
//Check if can place
//If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks breaking shader)
SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), EnumFacing.UP)) {
ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve,
new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos),
blockPos == secondPos, red));
RenderHandler.renderBlockPreview(dispatcher, blockPos, blockState);
blocksValid++;
}
}
return blocksValid;
}
public static void onBlocksPlaced() {
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, false));
}
}
}
public static void onBlocksBroken() {
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
}
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<IBlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
EntityPlayerSP player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if block previews are enabled
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) {
sortOnDistanceToPlayer(coordinates, player);
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
itemStacks, firstPos, secondPos, true));
}
}
}
private static Consumer<Integer> generateShaderCallback(final float dissolve, final Vec3d blockpos,
final Vec3d firstpos, final Vec3d secondpos,
final boolean highlight, final boolean red) {
Minecraft mc = Minecraft.getInstance();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos");
int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");
GlStateManager.enableTexture2D();
GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
//mask
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit);
OpenGlHelper.glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(ShaderHandler.shaderMaskTextureLocation).getGlTextureId());
//image
ARBShaderObjects.glUniform1iARB(imageUniform, primaryTextureUnit);
OpenGlHelper.glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + primaryTextureUnit);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(TextureMap.LOCATION_BLOCKS_TEXTURE).getGlTextureId());
//blockpos
ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z);
ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z);
ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z);
//dissolve
ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve);
//highlight
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0);
//red
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0);
};
}
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, EntityPlayer player) {
Collections.sort(coordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getEyePosition(1f)).lengthSquared();
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getEyePosition(1f)).lengthSquared();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
});
}
}

View File

@@ -1,176 +0,0 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import org.lwjgl.opengl.GL11;
import java.awt.*;
@OnlyIn(Dist.CLIENT)
public class ModifierRenderer {
protected static final Color colorX = new Color(255, 72, 52);
protected static final Color colorY = new Color(67, 204, 51);
protected static final Color colorZ = new Color(52, 247, 255);
protected static final Color colorRadial = new Color(52, 247, 255);
protected static final int lineAlpha = 200;
protected static final int planeAlpha = 75;
protected static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting
public static void render(ModifierSettingsManager.ModifierSettings modifierSettings) {
RenderHandler.beginLines();
//Mirror lines and areas
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ))
{
Vec3d pos = m.position.add(epsilon);
int radius = m.radius;
if (m.mirrorX)
{
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(posA, posB, colorX, m.drawLines, m.drawPlanes, true);
}
if (m.mirrorY)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(posA, posB, colorY, m.drawLines, m.drawPlanes);
}
if (m.mirrorZ)
{
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(posA, posB, colorZ, m.drawLines, m.drawPlanes, true);
}
//Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ)))
{
drawMirrorLines(m);
}
}
//Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r != null && r.enabled)
{
Vec3d pos = r.position.add(epsilon);
int radius = r.radius;
float angle = 2f * ((float) Math.PI) / r.slices;
Vec3d relStartVec = new Vec3d(radius, 0, 0);
if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f);
for (int i = 0; i < r.slices; i++) {
Vec3d relNewVec = relStartVec.rotateYaw(angle * i);
Vec3d newVec = pos.add(relNewVec);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
}
}
RenderHandler.endLines();
}
//----Mirror----
protected static void drawMirrorPlane(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
if (drawVerticalLines) {
bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
}
tessellator.draw();
}
}
protected static void drawMirrorPlaneY(Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) {
GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
if (drawPlanes) {
bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
tessellator.draw();
}
if (drawLines) {
Vec3d middle = posA.add(posB).scale(0.5);
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}
protected static void drawMirrorLines(Mirror.MirrorSettings m) {
Vec3d pos = m.position.add(epsilon);
GL11.glColor4d(100, 100, 100, 255);
GL11.glLineWidth(2);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferBuilder = tessellator.getBuffer();
bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR);
bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
tessellator.draw();
}
}

View File

@@ -1,331 +0,0 @@
package nl.requios.effortlessbuilding.render;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SimpleSound;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BlockRendererDispatcher;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.resources.I18n;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.SoundEvents;
import net.minecraft.particles.IParticleData;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldEventListener;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.ModeActionMessage;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import javax.annotation.Nullable;
import java.util.List;
/***
* Main render class for Effortless Building
*/
@Mod.EventBusSubscriber(value = Dist.CLIENT)
public class RenderHandler implements IWorldEventListener {
@SubscribeEvent
public static void onRender(RenderWorldLastEvent event) {
EntityPlayer player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
begin(event.getPartialTicks());
//Mirror and radial mirror lines and areas
ModifierRenderer.render(modifierSettings);
//Render block previews
BlockPreviewRenderer.render(player, modifierSettings, modeSettings);
end();
}
@SubscribeEvent
//Display Radial Menu
public static void onRenderGameOverlay(final RenderGameOverlayEvent.Post event) {
Minecraft mc = Minecraft.getInstance();
EntityPlayerSP player = mc.player;
//check if chisel and bits tool in hand (and has menu)
// final boolean hasChiselInHand = CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND);
final RenderGameOverlayEvent.ElementType type = event.getType();
//TODO 1.13 compatibility
if (type == RenderGameOverlayEvent.ElementType.ALL /*&& !hasChiselInHand*/) {
final boolean wasVisible = RadialMenu.instance.isVisible();
if (ClientProxy.keyBindings[3].isKeyDown()) {
if (ReachHelper.getMaxReach(player) > 0) {
RadialMenu.instance.actionUsed = false;
RadialMenu.instance.raiseVisibility();
} else if (ClientProxy.keyBindings[3].isPressed()) {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
} else {
if (!RadialMenu.instance.actionUsed) {
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
if (RadialMenu.instance.switchTo != null) {
playRadialMenuSound();
modeSettings.setBuildMode(RadialMenu.instance.switchTo);
ModeSettingsManager.setModeSettings(player, modeSettings);
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
EffortlessBuilding.log(player, I18n.format(modeSettings.getBuildMode().name), true);
}
//Perform button action
ModeOptions.ActionEnum action = RadialMenu.instance.doAction;
if (action != null) {
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
playRadialMenuSound();
}
RadialMenu.instance.actionUsed = true;
RadialMenu.instance.decreaseVisibility();
}
if (RadialMenu.instance.isVisible()) {
int scaledWidth = mc.mainWindow.getScaledWidth();
int scaledHeight = mc.mainWindow.getScaledHeight();
RadialMenu.instance.configure(scaledWidth, scaledHeight);
if (!wasVisible) {
mc.mouseHelper.ungrabMouse();
}
if (mc.mouseHelper.isMouseGrabbed()) {
KeyBinding.unPressAllKeys();
}
final int mouseX = ((int) mc.mouseHelper.getMouseX()) * scaledWidth / mc.mainWindow.getFramebufferWidth();
final int mouseY = scaledHeight - ((int) mc.mouseHelper.getMouseY()) * scaledHeight / mc.mainWindow.getFramebufferHeight() - 1;
net.minecraftforge.client.ForgeHooksClient.drawScreen(RadialMenu.instance, mouseX, mouseY, event.getPartialTicks());
} else {
if (wasVisible && RadialMenu.instance.doAction != ModeOptions.ActionEnum.OPEN_MODIFIER_SETTINGS) {
mc.mouseHelper.grabMouse();
}
}
}
}
public static void playRadialMenuSound() {
final float volume = 0.1f;
if (volume >= 0.0001f) {
SimpleSound sound = new SimpleSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.MASTER, volume, 1.0f, Minecraft.getInstance().player.getPosition());
Minecraft.getInstance().getSoundHandler().play(sound);
}
}
private static void begin(float partialTicks) {
EntityPlayer player = Minecraft.getInstance().player;
double playerX = player.prevPosX + (player.posX - player.prevPosX) * partialTicks;
double playerY = player.prevPosY + (player.posY - player.prevPosY) * partialTicks;
double playerZ = player.prevPosZ + (player.posZ - player.prevPosZ) * partialTicks;
Vec3d playerPos = new Vec3d(playerX, playerY, playerZ);
GL11.glPushMatrix();
GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z);
GL11.glDepthMask(false);
}
protected static void beginLines() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glDisable(GL11.GL_CULL_FACE);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLineWidth(2);
}
protected static void endLines() {
GL11.glPopAttrib();
}
protected static void beginBlockPreviews() {
GL11.glPushAttrib(GL11.GL_ENABLE_BIT);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_TEXTURE_2D);
// Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
Minecraft.getInstance().textureManager.bindTexture(ShaderHandler.shaderMaskTextureLocation);
GlStateManager.enableBlend();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL14.glBlendColor(1F, 1F, 1F, 0.8f);
}
protected static void endBlockPreviews() {
ShaderHandler.releaseShader();
GlStateManager.disableBlend();
GL11.glPopAttrib();
}
private static void end() {
GL11.glDepthMask(true);
GL11.glPopMatrix();
}
protected static void renderBlockPreview(BlockRendererDispatcher dispatcher, BlockPos blockPos, IBlockState blockState) {
if (blockState == null) return;
GlStateManager.pushMatrix();
GlStateManager.translatef(blockPos.getX(), blockPos.getY(), blockPos.getZ());
GlStateManager.rotatef(-90.0F, 0.0F, 1.0F, 0.0F);
GlStateManager.translatef(-0.01f, -0.01f, 0.01f);
GlStateManager.scalef(1.02f, 1.02f, 1.02f);
try {
dispatcher.renderBlockBrightness(blockState, 0.85f);
} catch (NullPointerException e) {
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString());
//Render outline as backup
GlStateManager.popMatrix();
// ShaderHandler.releaseShader();
GL11.glDisable(GL11.GL_LIGHTING);
renderBlockOutline(blockPos, new Vec3d(1f, 1f, 1f));
GL11.glEnable(GL11.GL_LIGHTING);
GlStateManager.pushMatrix();
}
GlStateManager.popMatrix();
}
protected static void renderBlockOutline(BlockPos pos, Vec3d color) {
renderBlockOutline(pos, pos, color);
}
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
protected static void renderBlockOutline(BlockPos pos1, BlockPos pos2, Vec3d color) {
GL11.glLineWidth(2);
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
//Renders outline with given bounding box
protected static void renderBlockOutline(BlockPos pos, VoxelShape collisionShape, Vec3d color) {
GL11.glLineWidth(2);
// AxisAlignedBB aabb = boundingBox.offset(pos).grow(0.0020000000949949026);
// VoxelShape voxelShape = collisionShape.withOffset(pos.getX(), pos.getY(), pos.getZ());
// WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
}
//IWORLDEVENTLISTENER IMPLEMENTATION
@Override
public void notifyBlockUpdate(IBlockReader worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) {
}
@Override
public void notifyLightSet(BlockPos pos) {
}
@Override
public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) {
}
@Override
public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category,
double x, double y, double z, float volume, float pitch) {
}
@Override
public void playRecord(SoundEvent soundIn, BlockPos pos) {
}
@Override
public void addParticle(IParticleData particleData, boolean alwaysRender, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
}
@Override
public void addParticle(IParticleData particleData, boolean ignoreRange, boolean minimizeLevel, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
}
@Override
public void onEntityAdded(Entity entityIn) {
}
@Override
public void onEntityRemoved(Entity entityIn) {
}
@Override
public void broadcastSound(int soundID, BlockPos pos, int data) {
}
@Override
public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) {
}
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
@Override
public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
Minecraft mc = Minecraft.getInstance();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (!BuildModifiers.isEnabled(modifierSettings, pos)) return;
List<BlockPos> coordinates = BuildModifiers.findCoordinates(mc.player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) {
//Send i as entity id because only one block can be broken per id
//Unless i happens to be the player id, then take something else
int fakeId = mc.player.getEntityId() != i ? i : coordinates.size();
mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress);
}
}
}
}

View File

@@ -1,195 +0,0 @@
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Modified by Requios
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)]
*/
package nl.requios.effortlessbuilding.render;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.util.ResourceLocation;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.logging.log4j.Level;
import org.lwjgl.opengl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public final class ShaderHandler {
private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static final int VERT = 1;
private static final int FRAG = 2;
private static final String VERT_EXTENSION = ".vert";
private static final String FRAG_EXTENSION = ".frag";
public static int rawColor;
public static int dissolve;
public static ResourceLocation shaderMaskTextureLocation = new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png");
public static void init() {
if(!doUseShaders())
return;
// rawColor = createProgram("/assets/effortlessbuilding/shaders/raw_color", FRAG);
dissolve = createProgram("/assets/effortlessbuilding/shaders/dissolve", VERT + FRAG);
}
public static void useShader(int shader, Consumer<Integer> callback) {
if(!doUseShaders())
return;
ARBShaderObjects.glUseProgramObjectARB(shader);
if(shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientProxy.ticksInGame);
if(callback != null)
callback.accept(shader);
}
}
public static void useShader(int shader) {
useShader(shader, null);
}
public static void releaseShader() {
useShader(0);
}
public static boolean doUseShaders() {
return BuildConfig.visuals.useShaders.get() && OpenGlHelper.shadersSupported;
}
private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;
return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}
// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT_ST);
if(frag != null)
fragId = createShader(frag, FRAG_ST);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
StringBuilder source = new StringBuilder();
InputStream in = ShaderHandler.class.getResourceAsStream(filename);
Exception exception = null;
BufferedReader reader;
if(in == null)
return "";
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
Exception innerExc= null;
try {
String line;
while((line = reader.readLine()) != null)
source.append(line).append('\n');
} catch(Exception exc) {
exception = exc;
} finally {
try {
reader.close();
} catch(Exception exc) {
innerExc = exc;
}
}
if(innerExc != null)
throw innerExc;
} catch(Exception exc) {
exception = exc;
} finally {
try {
in.close();
} catch(Exception exc) {
if(exception == null)
exception = exc;
else exc.printStackTrace();
}
if(exception != null)
throw exception;
}
return source.toString();
}
}

View File

@@ -1,52 +0,0 @@
# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here: https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[25,)" #mandatory (24 is current forge version)
# A URL to refer people to when problems occur with this mod
issueTrackerURL="https://bitbucket.org/Requios/effortless-building/issues?status=new&status=open" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId="effortlessbuilding" #mandatory
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
version="${file.jarVersion}" #mandatory
# A display name for the mod
displayName="Effortless Building" #mandatory
# A URL to query for updates for this mod. See the JSON update specification <here>
updateJSONURL="http://myurl.me/" #optional
# A URL for the "homepage" for this mod, displayed in the mod UI
displayURL="https://minecraft.curseforge.com/projects/effortless-building" #optional
# A file name (in the root of the mod JAR) containing a logo for display
logoFile="logo.png" #optional
# A text field displayed in the mod UI
credits="" #optional
# A text field displayed in the mod UI
authors="Requios" #optional
# The description text for the mod (multi line!) (#mandatory)
description='''
Makes building easier by providing tools like mirrors, arrays, QuickReplace and a block randomizer. For survival and creative mode.
'''
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
#[[dependencies.examplemod]] #optional
# # the modid of the dependency
# modId="forge" #mandatory
# # Does this dependency have to exist - if not, ordering below must be specified
# mandatory=true #mandatory
# # The version range of the dependency
# versionRange="[25,)" #mandatory
# # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory
# ordering="NONE"
# # Side this dependency is applied on - BOTH, CLIENT or SERVER
# side="BOTH"
## Here's another dependency
#[[dependencies.examplemod]]
# modId="minecraft"
# mandatory=true
# versionRange="[1.13.2]"
# ordering="NONE"
# side="BOTH"

View File

@@ -1,54 +0,0 @@
{
"key.effortlessbuilding.category": "Effortless Building",
"key.effortlessbuilding.hud.desc": "Modifier Menu",
"key.effortlessbuilding.replace.desc": "Toggle QuickReplace",
"key.effortlessbuilding.creative.desc": "Toggle Survival/Creative Mode",
"key.effortlessbuilding.mode.desc": "Radial Menu",
"key.effortlessbuilding.undo.desc": "Undo",
"key.effortlessbuilding.redo.desc": "Redo",
"key.effortlessbuilding.altplacement.desc": "Alternative placement",
"effortlessbuilding:randomizer_bag": "Randomizer Bag",
"effortlessbuilding:reach_upgrade1": "Reach Upgrade 1",
"effortlessbuilding:reach_upgrade2": "Reach Upgrade 2",
"effortlessbuilding:reach_upgrade3": "Reach Upgrade 3",
"effortlessbuilding.mode.normal": "Normal",
"effortlessbuilding.mode.normal_plus": "Normal+",
"effortlessbuilding.mode.line": "Line",
"effortlessbuilding.mode.wall": "Wall",
"effortlessbuilding.mode.floor": "Floor",
"effortlessbuilding.mode.diagonal_line": "Diagonal Line",
"effortlessbuilding.mode.diagonal_wall": "Diagonal Wall",
"effortlessbuilding.mode.slope_floor": "Slope Floor",
"effortlessbuilding.mode.cube": "Cube",
"effortlessbuilding.mode.circle": "Circle",
"effortlessbuilding.mode.cylinder": "Cylinder",
"effortlessbuilding.mode.sphere": "Sphere",
"effortlessbuilding.action.undo": "Undo",
"effortlessbuilding.action.redo": "Redo",
"effortlessbuilding.action.replace": "Replace",
"effortlessbuilding.action.open_modifier_settings": "Open Modifier Settings",
"effortlessbuilding.action.build_speed": "Build Speed",
"effortlessbuilding.action.filling": "Filling",
"effortlessbuilding.action.raised_edge": "Raised Edge",
"effortlessbuilding.action.thickness": "Line Thickness",
"effortlessbuilding.action.circle_start": "Start Point",
"effortlessbuilding.action.normal_speed": "Normal",
"effortlessbuilding.action.fast_speed": "Fast",
"effortlessbuilding.action.full": "Filled",
"effortlessbuilding.action.hollow": "Hollow",
"effortlessbuilding.action.skeleton": "Skeleton",
"effortlessbuilding.action.short_edge": "Short Edge",
"effortlessbuilding.action.long_edge": "Long Edge",
"effortlessbuilding.action.thickness_1": "1 Block Thick",
"effortlessbuilding.action.thickness_3": "3 Blocks Thick",
"effortlessbuilding.action.thickness_5": "5 Blocks Thick",
"effortlessbuilding.action.start_center": "Middle",
"effortlessbuilding.action.start_corner": "Corner",
"commands.reach.usage": "/reach <level>"
}

View File

@@ -0,0 +1,11 @@
key.effortlessbuilding.category=Effortless Building
key.effortlessbuilding.hud.desc=Open Settings
key.effortlessbuilding.replace.desc=Toggle QuickReplace
key.effortlessbuilding.creative.desc=Toggle Survival/Creative Mode
item.effortlessbuilding:randomizer_bag.name=Randomizer Bag
item.effortlessbuilding:reach_upgrade1.name=Reach Upgrade 1
item.effortlessbuilding:reach_upgrade2.name=Reach Upgrade 2
item.effortlessbuilding:reach_upgrade3.name=Reach Upgrade 3
commands.reach.usage=/reach <level>

View File

@@ -10,7 +10,8 @@
"item": "minecraft:leather" "item": "minecraft:leather"
}, },
"O": { "O": {
"tag": "minecraft:planks" "item": "minecraft:planks",
"data": 32767
} }
}, },
"result": { "result": {

View File

@@ -1,104 +0,0 @@
#version 120
uniform int time; // Passed in, see ShaderHelper.java
uniform float dissolve; // Passed in via Callback
uniform int highlight;
uniform int red;
uniform vec3 blockpos;
uniform vec3 firstpos;
uniform vec3 secondpos;
uniform sampler2D image;
uniform sampler2D mask;
varying vec4 position;
varying vec3 normal;
void main() {
vec3 pixelposition = floor(position.xyz * 8.0) / 8.0;
vec3 worldpos = blockpos + pixelposition.xyz;
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 texcolor = texture2D(image, texcoord);
vec4 color = texcolor;
vec3 firstposc = firstpos + 0.51; //center in block
vec3 secondposc = secondpos + 0.5;
//find place in between first and second pos
float firstToSecond = length(secondposc - firstposc);
float place = 0.0;
if (firstToSecond > 0.5) {
float placeFromFirst = length(worldpos - firstposc) / firstToSecond;
float placeFromSecond = length(worldpos - secondposc) / firstToSecond;
place = (placeFromFirst + (1.0 - placeFromSecond)) / 2.0;
} //else only one block
//find 2d texture coordinate for noise texture based on world position
vec2 maskcoord = vec2(worldpos.y, worldpos.z);
if (abs(normal.y) > 0.5)
maskcoord = vec2(worldpos.x, worldpos.z);
if (abs(normal.z) > 0.5)
maskcoord = vec2(worldpos.x, worldpos.y);
maskcoord /= 20.0;
vec4 maskColor = texture2D(mask, maskcoord);
float maskgs = maskColor.r;
color.rgb *= gl_Color.rgb;
//desaturate
color.rgb *= vec3(0.8);
//add blueish hue
color.rgb += vec3(-0.1, 0.0, 0.2);
//add pulsing blue
float pulse = (sin(time / 5.0) + 1.0) / 2.0;
color.rgb += 0.4 * vec3(-0.5, 0.2, 0.6) * pulse;
//add diagonal highlights
float diagTime = mod(time / 40.0, 1.4) - 0.2;
float diag = smoothstep(diagTime - 0.2, diagTime, place) - smoothstep(diagTime, diagTime + 0.2, place);
color.rgb += 0.2 * diag * vec3(0.0, 0.2, 0.4);
float diagTime2 = mod(time / 70.0, 1.4) - 0.2;
float diag2 = smoothstep(diagTime2 - 0.2, diagTime2, place) - smoothstep(diagTime2, diagTime2 + 0.2, place);
color.rgb += 0.2 * diag2 * vec3(0.0, 0.4, 0.8);
//add edge shading
// vec3 p1;
// //if (firstpos.x < secondpos.x)
//
// vec3 wmf = worldpos - firstposc;
// vec3 wms = worldpos - (secondposc + vec3(0.0, 1.0, 1.0));
// float distToEdge1 = min(length(wmf.xy), length(wmf.xz));
// float distToEdge2 = min(length(wmf.yz), length(wms.xy));
// float distToEdge3 = min(length(wms.xz), length(wms.yz));
// float distToEdge = min(min(distToEdge1, distToEdge2), distToEdge3);
// color.rgb += vec3(0.5 - smoothstep(0, 0.5, distToEdge)) * 0.5;
//add flat shading
// if (abs(normal.x) > 0.5)
// color.rgb -= 0.0;
if (abs(normal.y) > 0.5)
color.rgb += 0.05;
if (abs(normal.z) > 0.5)
color.rgb -= 0.05;
if (highlight == 1 && dissolve == 0.0) {
color.rgb += vec3(0.0, 0.1, -0.2);
}
if (red == 1) {
color.rgb += vec3(0.4, -0.3, -0.5);
}
color.r = max(0, min(1, color.r));
color.g = max(0, min(1, color.g));
color.b = max(0, min(1, color.b));
if (maskgs * 0.3 + place * 0.7 <= dissolve)
gl_FragColor = vec4(texcolor.rgb, 0.0);
else gl_FragColor = color;
}

View File

@@ -1,14 +0,0 @@
#version 120
varying vec4 position;
varying vec3 normal;
void main() {
gl_Position = ftransform();//gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
//gl_BackColor = gl_Color;
position = gl_Vertex;
normal = gl_Normal;
}

View File

@@ -1,15 +0,0 @@
#version 120
uniform sampler2D bgl_RenderedTexture;
void main() {
vec2 texcoord = vec2(gl_TexCoord[0]);
vec4 color = texture2D(bgl_RenderedTexture, texcoord);
float r = color.b * gl_Color.r;
float g = color.g * gl_Color.g;
float b = color.r * gl_Color.b;
float a = color.a * gl_Color.a;
gl_FragColor = vec4(r, g, b, a);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

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