Initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
dist/
|
||||||
|
build/
|
||||||
|
nbproject/private
|
||||||
73
build.xml
Normal file
73
build.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- You may freely edit this file. See commented blocks below for -->
|
||||||
|
<!-- some examples of how to customize the build. -->
|
||||||
|
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||||
|
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||||
|
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||||
|
<!-- the Compile on Save feature is turned off for the project. -->
|
||||||
|
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||||
|
<!-- in the project's Project Properties dialog box.-->
|
||||||
|
<project name="RealisticMinecraft" default="default" basedir=".">
|
||||||
|
<description>Builds, tests, and runs the project RealisticMinecraft.</description>
|
||||||
|
<import file="nbproject/build-impl.xml"/>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
There exist several targets which are by default empty and which can be
|
||||||
|
used for execution of your tasks. These targets are usually executed
|
||||||
|
before and after some main targets. They are:
|
||||||
|
|
||||||
|
-pre-init: called before initialization of project properties
|
||||||
|
-post-init: called after initialization of project properties
|
||||||
|
-pre-compile: called before javac compilation
|
||||||
|
-post-compile: called after javac compilation
|
||||||
|
-pre-compile-single: called before javac compilation of single file
|
||||||
|
-post-compile-single: called after javac compilation of single file
|
||||||
|
-pre-compile-test: called before javac compilation of JUnit tests
|
||||||
|
-post-compile-test: called after javac compilation of JUnit tests
|
||||||
|
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||||
|
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||||
|
-pre-jar: called before JAR building
|
||||||
|
-post-jar: called after JAR building
|
||||||
|
-post-clean: called after cleaning build products
|
||||||
|
|
||||||
|
(Targets beginning with '-' are not intended to be called on their own.)
|
||||||
|
|
||||||
|
Example of inserting an obfuscator after compilation could look like this:
|
||||||
|
|
||||||
|
<target name="-post-compile">
|
||||||
|
<obfuscate>
|
||||||
|
<fileset dir="${build.classes.dir}"/>
|
||||||
|
</obfuscate>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
For list of available properties check the imported
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
|
||||||
|
Another way to customize the build is by overriding existing main targets.
|
||||||
|
The targets of interest are:
|
||||||
|
|
||||||
|
-init-macrodef-javac: defines macro for javac compilation
|
||||||
|
-init-macrodef-junit: defines macro for junit execution
|
||||||
|
-init-macrodef-debug: defines macro for class debugging
|
||||||
|
-init-macrodef-java: defines macro for class execution
|
||||||
|
-do-jar: JAR building
|
||||||
|
run: execution of project
|
||||||
|
-javadoc-build: Javadoc generation
|
||||||
|
test-report: JUnit report generation
|
||||||
|
|
||||||
|
An example of overriding the target for project execution could look like this:
|
||||||
|
|
||||||
|
<target name="run" depends="RealisticMinecraft-impl.jar">
|
||||||
|
<exec dir="bin" executable="launcher.exe">
|
||||||
|
<arg file="${dist.jar}"/>
|
||||||
|
</exec>
|
||||||
|
</target>
|
||||||
|
|
||||||
|
Notice that the overridden target depends on the jar target and not only on
|
||||||
|
the compile target as the regular run target does. Again, for a list of available
|
||||||
|
properties which you can use, check the target you are overriding in the
|
||||||
|
nbproject/build-impl.xml file.
|
||||||
|
|
||||||
|
-->
|
||||||
|
</project>
|
||||||
3
manifest.mf
Normal file
3
manifest.mf
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
X-COMMENT: Main-Class will be added automatically by build
|
||||||
|
|
||||||
1768
nbproject/build-impl.xml
Normal file
1768
nbproject/build-impl.xml
Normal file
File diff suppressed because it is too large
Load Diff
8
nbproject/genfiles.properties
Normal file
8
nbproject/genfiles.properties
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
build.xml.data.CRC32=384066bc
|
||||||
|
build.xml.script.CRC32=61428c28
|
||||||
|
build.xml.stylesheet.CRC32=f85dc8f2@1.91.1.48
|
||||||
|
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||||
|
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||||
|
nbproject/build-impl.xml.data.CRC32=384066bc
|
||||||
|
nbproject/build-impl.xml.script.CRC32=6151eca2
|
||||||
|
nbproject/build-impl.xml.stylesheet.CRC32=3a2fa800@1.91.1.48
|
||||||
102
nbproject/project.properties
Normal file
102
nbproject/project.properties
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
annotation.processing.enabled=true
|
||||||
|
annotation.processing.enabled.in.editor=false
|
||||||
|
annotation.processing.processors.list=
|
||||||
|
annotation.processing.run.all.processors=true
|
||||||
|
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||||
|
application.title=RealisticMinecraft
|
||||||
|
application.vendor=NMerkelt
|
||||||
|
build.classes.dir=${build.dir}/classes
|
||||||
|
build.classes.excludes=**/*.java,**/*.form
|
||||||
|
# This directory is removed when the project is cleaned:
|
||||||
|
build.dir=build
|
||||||
|
build.generated.dir=${build.dir}/generated
|
||||||
|
build.generated.sources.dir=${build.dir}/generated-sources
|
||||||
|
# Only compile against the classpath explicitly listed here:
|
||||||
|
build.sysclasspath=ignore
|
||||||
|
build.test.classes.dir=${build.dir}/test/classes
|
||||||
|
build.test.results.dir=${build.dir}/test/results
|
||||||
|
# Uncomment to specify the preferred debugger connection transport:
|
||||||
|
#debug.transport=dt_socket
|
||||||
|
debug.classpath=\
|
||||||
|
${run.classpath}
|
||||||
|
debug.modulepath=\
|
||||||
|
${run.modulepath}
|
||||||
|
debug.test.classpath=\
|
||||||
|
${run.test.classpath}
|
||||||
|
debug.test.modulepath=\
|
||||||
|
${run.test.modulepath}
|
||||||
|
# Files in build.classes.dir which should be excluded from distribution jar
|
||||||
|
dist.archive.excludes=
|
||||||
|
# This directory is removed when the project is cleaned:
|
||||||
|
dist.dir=dist
|
||||||
|
dist.jar=${dist.dir}/RealisticMinecraft.jar
|
||||||
|
dist.javadoc.dir=${dist.dir}/javadoc
|
||||||
|
dist.jlink.dir=${dist.dir}/jlink
|
||||||
|
dist.jlink.output=${dist.jlink.dir}/RealisticMinecraft
|
||||||
|
endorsed.classpath=
|
||||||
|
excludes=
|
||||||
|
file.reference.AnuraCore.jar=..\\libs\\AnuraCore.jar
|
||||||
|
file.reference.LogBlock.jar=../libs/LogBlock.jar
|
||||||
|
includes=**
|
||||||
|
jar.compress=false
|
||||||
|
javac.classpath=\
|
||||||
|
${libs.Spigot-Server.classpath}:\
|
||||||
|
${file.reference.LogBlock.jar}:\
|
||||||
|
${file.reference.AnuraCore.jar}
|
||||||
|
# Space-separated list of extra javac options
|
||||||
|
javac.compilerargs=
|
||||||
|
javac.deprecation=false
|
||||||
|
javac.external.vm=true
|
||||||
|
javac.modulepath=
|
||||||
|
javac.processormodulepath=
|
||||||
|
javac.processorpath=\
|
||||||
|
${javac.classpath}
|
||||||
|
javac.source=1.8
|
||||||
|
javac.target=1.8
|
||||||
|
javac.test.classpath=\
|
||||||
|
${javac.classpath}:\
|
||||||
|
${build.classes.dir}
|
||||||
|
javac.test.modulepath=\
|
||||||
|
${javac.modulepath}
|
||||||
|
javac.test.processorpath=\
|
||||||
|
${javac.test.classpath}
|
||||||
|
javadoc.additionalparam=
|
||||||
|
javadoc.author=false
|
||||||
|
javadoc.encoding=${source.encoding}
|
||||||
|
javadoc.html5=false
|
||||||
|
javadoc.noindex=false
|
||||||
|
javadoc.nonavbar=false
|
||||||
|
javadoc.notree=false
|
||||||
|
javadoc.private=false
|
||||||
|
javadoc.splitindex=true
|
||||||
|
javadoc.use=true
|
||||||
|
javadoc.version=false
|
||||||
|
javadoc.windowtitle=
|
||||||
|
# The jlink additional root modules to resolve
|
||||||
|
jlink.additionalmodules=
|
||||||
|
# The jlink additional command line parameters
|
||||||
|
jlink.additionalparam=
|
||||||
|
jlink.launcher=true
|
||||||
|
jlink.launcher.name=RealisticMinecraft
|
||||||
|
main.class=de.anura.realisticminecraft.RealisticMinecraft
|
||||||
|
manifest.file=manifest.mf
|
||||||
|
meta.inf.dir=${src.dir}/META-INF
|
||||||
|
mkdist.disabled=false
|
||||||
|
platform.active=default_platform
|
||||||
|
run.classpath=\
|
||||||
|
${javac.classpath}:\
|
||||||
|
${build.classes.dir}
|
||||||
|
# Space-separated list of JVM arguments used when running the project.
|
||||||
|
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
|
||||||
|
# To set system properties for unit tests define test-sys-prop.name=value:
|
||||||
|
run.jvmargs=
|
||||||
|
run.modulepath=\
|
||||||
|
${javac.modulepath}
|
||||||
|
run.test.classpath=\
|
||||||
|
${javac.test.classpath}:\
|
||||||
|
${build.test.classes.dir}
|
||||||
|
run.test.modulepath=\
|
||||||
|
${javac.test.modulepath}
|
||||||
|
source.encoding=UTF-8
|
||||||
|
src.dir=src
|
||||||
|
test.src.dir=test
|
||||||
15
nbproject/project.xml
Normal file
15
nbproject/project.xml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||||
|
<type>org.netbeans.modules.java.j2seproject</type>
|
||||||
|
<configuration>
|
||||||
|
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||||
|
<name>RealisticMinecraft</name>
|
||||||
|
<source-roots>
|
||||||
|
<root id="src.dir"/>
|
||||||
|
</source-roots>
|
||||||
|
<test-roots>
|
||||||
|
<root id="test.src.dir"/>
|
||||||
|
</test-roots>
|
||||||
|
</data>
|
||||||
|
</configuration>
|
||||||
|
</project>
|
||||||
93
src/de/anura/realisticminecraft/RealisticMinecraft.java
Normal file
93
src/de/anura/realisticminecraft/RealisticMinecraft.java
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
package de.anura.realisticminecraft;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import de.anura.core.database.DB;
|
||||||
|
import de.anura.core.msg.Msg;
|
||||||
|
import de.anura.core.msg.Msg.PluginData;
|
||||||
|
import de.anura.realisticminecraft.command.InfobarCmd;
|
||||||
|
import de.anura.realisticminecraft.command.InfobarSetCmd;
|
||||||
|
import de.anura.realisticminecraft.fishing.FishingChunk;
|
||||||
|
import de.anura.realisticminecraft.infobar.InfobarUtil;
|
||||||
|
import de.anura.realisticminecraft.listener.Chairs;
|
||||||
|
import de.anura.realisticminecraft.util.ChairManager;
|
||||||
|
import de.anura.realisticminecraft.infobar.ValueHolder;
|
||||||
|
import de.anura.realisticminecraft.listener.Fishing;
|
||||||
|
import de.anura.realisticminecraft.listener.Infobar;
|
||||||
|
import de.anura.realisticminecraft.listener.Timber;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.command.PluginCommand;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public class RealisticMinecraft extends JavaPlugin {
|
||||||
|
|
||||||
|
private static RealisticMinecraft instance;
|
||||||
|
public static final PluginData PLUGIN_DATA = new PluginData("RealisticMC", Msg.PluginType.SYSTEM);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
instance = this;
|
||||||
|
DB.queryUpdate("CREATE TABLE IF NOT EXISTS `playerTemperature` ("
|
||||||
|
+ " `playerId` INT(10) UNSIGNED NOT NULL,"
|
||||||
|
+ " `value` DECIMAL(7,5) NOT NULL,"
|
||||||
|
+ " `bar` BIT(1) NOT NULL DEFAULT b'0',"
|
||||||
|
+ " PRIMARY KEY (`playerId`),"
|
||||||
|
+ " INDEX `playerTemperature_playerId` (`playerId`),"
|
||||||
|
+ " CONSTRAINT `playerTemperature_playerId` FOREIGN KEY (`playerId`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE"
|
||||||
|
+ ") ENGINE=InnoDB COLLATE='utf8_general_ci' COMMENT='RealisticMinecraft | hibo98'");
|
||||||
|
DB.queryUpdate("CREATE TABLE IF NOT EXISTS `playerThirst` ("
|
||||||
|
+ " `playerId` INT(10) UNSIGNED NOT NULL,"
|
||||||
|
+ " `value` INT(11) NOT NULL,"
|
||||||
|
+ " `bar` BIT(1) NOT NULL DEFAULT b'0',"
|
||||||
|
+ " PRIMARY KEY (`playerId`),"
|
||||||
|
+ " INDEX `playerTemperature_playerId` (`playerId`),"
|
||||||
|
+ " CONSTRAINT `playerThirst_playerId` FOREIGN KEY (`playerId`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE"
|
||||||
|
+ ") ENGINE=InnoDB COLLATE='utf8_general_ci' COMMENT='RealisticMinecraft | hibo98'");
|
||||||
|
DB.queryUpdate("CREATE TABLE IF NOT EXISTS `fishingChunks` ( "
|
||||||
|
+ " `primeKey` INT(11) NOT NULL AUTO_INCREMENT, "
|
||||||
|
+ " `x` INT(11) NOT NULL, "
|
||||||
|
+ " `z` INT(11) NOT NULL, "
|
||||||
|
+ " `world` VARCHAR(50) COLLATE latin1_german1_ci NOT NULL, "
|
||||||
|
+ " `catched` INT(11) NOT NULL, "
|
||||||
|
+ " `lastUpdated` INT(11) NOT NULL, "
|
||||||
|
+ " PRIMARY KEY (`primeKey`) "
|
||||||
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_german1_ci COMMENT='RealisticMinecraft | LukBukkit'");
|
||||||
|
// Chairs
|
||||||
|
Bukkit.getPluginManager().registerEvents(new Chairs(), instance);
|
||||||
|
// Infobar
|
||||||
|
AnuraThread.async(() -> Bukkit.getOnlinePlayers().stream().filter((p) -> p.getGameMode().equals(GameMode.SURVIVAL)).forEach(ValueHolder::new));
|
||||||
|
InfobarCmd infobarCmd = new InfobarCmd();
|
||||||
|
PluginCommand infobar = instance.getCommand("infobar");
|
||||||
|
if (infobar != null) {
|
||||||
|
infobar.setExecutor(infobarCmd);
|
||||||
|
infobar.setTabCompleter(infobarCmd);
|
||||||
|
}
|
||||||
|
InfobarSetCmd infobarSetCmd = new InfobarSetCmd();
|
||||||
|
PluginCommand infobarset = instance.getCommand("infobarset");
|
||||||
|
if (infobarset != null) {
|
||||||
|
infobarset.setExecutor(infobarSetCmd);
|
||||||
|
infobarset.setTabCompleter(infobarSetCmd);
|
||||||
|
}
|
||||||
|
InfobarUtil.enableInfobarTasks();
|
||||||
|
Bukkit.getPluginManager().registerEvents(new Infobar(), instance);
|
||||||
|
// Fishing
|
||||||
|
FishingChunk.init();
|
||||||
|
Bukkit.getPluginManager().registerEvents(new Fishing(), instance);
|
||||||
|
// Trees
|
||||||
|
Bukkit.getPluginManager().registerEvents(new Timber(), instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
ValueHolder.destroyAll();
|
||||||
|
ChairManager.destoryAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealisticMinecraft getInstance() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasLogBlock() {
|
||||||
|
return Bukkit.getServer().getPluginManager().getPlugin("LogBlock") != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
88
src/de/anura/realisticminecraft/command/InfobarCmd.java
Normal file
88
src/de/anura/realisticminecraft/command/InfobarCmd.java
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package de.anura.realisticminecraft.command;
|
||||||
|
|
||||||
|
import de.anura.core.msg.Msg;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import de.anura.realisticminecraft.infobar.TemperaturePlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.ThirstPlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.BarStatus;
|
||||||
|
import de.anura.realisticminecraft.infobar.ValueHolder;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class InfobarCmd implements TabExecutor {
|
||||||
|
|
||||||
|
public InfobarCmd() {
|
||||||
|
// new Help("infobar", "Konfigurieret die Anzeige der Infobars")
|
||||||
|
// .addArgument("durst | temp", "Wählt Durst oder Temperatur aus")
|
||||||
|
// .addArgument("an | standard", "Schaltet die Bar auf AN oder STANDARD")
|
||||||
|
// .build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender cs, Command cmnd, String label, String[] args) {
|
||||||
|
if (!(cs instanceof Player)) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "This is a player command!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (args.length < 2 || args.length > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!((HumanEntity) cs).getGameMode().equals(GameMode.SURVIVAL)) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Dieses Command kann nur im SURVIVAL Mode verwendet werden");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
BarStatus status;
|
||||||
|
try {
|
||||||
|
status = BarStatus.valueOf(args[1].toUpperCase());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ValueHolder valueHolder = ValueHolder.getValueHolder((Player) cs);
|
||||||
|
if (valueHolder == null) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Es ist einer interner Fehler aufgetreten (0)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ThirstPlayer thirstPlayer = valueHolder.getPlayer(ThirstPlayer.class);
|
||||||
|
TemperaturePlayer temperaturePlayer = valueHolder.getPlayer(TemperaturePlayer.class);
|
||||||
|
if (thirstPlayer == null || temperaturePlayer == null) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Es ist einer interner Fehler aufgetreten (1)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (args[0].toLowerCase()) {
|
||||||
|
case "durst":
|
||||||
|
thirstPlayer.getBar().setBarStatus(status);
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Die Durst Infobar wird dir nun" + (status.equals(BarStatus.STANDARD) ? " nicht " : " ") + "immer angezeigt!");
|
||||||
|
return true;
|
||||||
|
case "temp":
|
||||||
|
case "temperatur":
|
||||||
|
temperaturePlayer.getBar().setBarStatus(status);
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Die Temperatur Infobar wird dir nun" + (status.equals(BarStatus.STANDARD) ? " nicht " : " ") + "immer angezeigt!");
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender cs, Command cmnd, String label, String[] args) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
switch (args.length) {
|
||||||
|
case 1:
|
||||||
|
list.add("durst");
|
||||||
|
list.add("temp");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
list.add("an");
|
||||||
|
list.add("standard");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return list.stream().filter((s) -> s.startsWith(args[args.length - 1].toLowerCase())).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
91
src/de/anura/realisticminecraft/command/InfobarSetCmd.java
Normal file
91
src/de/anura/realisticminecraft/command/InfobarSetCmd.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package de.anura.realisticminecraft.command;
|
||||||
|
|
||||||
|
import de.anura.core.msg.Msg;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import de.anura.realisticminecraft.infobar.TemperaturePlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.ThirstPlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.ValueHolder;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabExecutor;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class InfobarSetCmd implements TabExecutor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender cs, Command cmnd, String label, String[] args) {
|
||||||
|
if (!cs.hasPermission("anura.realisticmc.infobarset")) {
|
||||||
|
Msg.noPerms(cs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(cs instanceof Player)) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "This is a player command!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (args.length < 2 || args.length > 3) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!((HumanEntity) cs).getGameMode().equals(GameMode.SURVIVAL)) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Dieses Command kann nur im SURVIVAL Mode verwendet werden");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ValueHolder valueHolder = ValueHolder.getValueHolder((Player) cs);
|
||||||
|
if (valueHolder == null) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Es ist einer interner Fehler aufgetreten (0)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
ThirstPlayer thirstPlayer = valueHolder.getPlayer(ThirstPlayer.class);
|
||||||
|
TemperaturePlayer temperaturePlayer = valueHolder.getPlayer(TemperaturePlayer.class);
|
||||||
|
if (thirstPlayer == null || temperaturePlayer == null) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Es ist einer interner Fehler aufgetreten (1)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Float value;
|
||||||
|
try {
|
||||||
|
value = Float.parseFloat(args[1]);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "%s ist keine Zahl!", args[1]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
switch (args[0].toLowerCase()) {
|
||||||
|
case "durst":
|
||||||
|
if (thirstPlayer.getMIN() > value || thirstPlayer.getMAX() < value) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Der Wert liegt außerhalb des Wertebereich.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
thirstPlayer.setValue(value);
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Der Durst wurde auf %i gesetzt!", value);
|
||||||
|
return true;
|
||||||
|
case "temp":
|
||||||
|
case "temperatur":
|
||||||
|
if (temperaturePlayer.getMIN() > value || temperaturePlayer.getMAX() < value) {
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Der Wert liegt außerhalb des Wertebereich.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
temperaturePlayer.setValue(value);
|
||||||
|
Msg.send(cs, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.SUCCESS, "Die Temperatur wurde auf %i gesetzt!", value);
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender cs, Command cmnd, String label, String[] args) {
|
||||||
|
List<String> list = new ArrayList<>();
|
||||||
|
switch (args.length) {
|
||||||
|
case 1:
|
||||||
|
list.add("durst");
|
||||||
|
list.add("temp");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
return list.stream().filter((s) -> s.startsWith(args[args.length - 1])).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
135
src/de/anura/realisticminecraft/fishing/FishingChunk.java
Normal file
135
src/de/anura/realisticminecraft/fishing/FishingChunk.java
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
package de.anura.realisticminecraft.fishing;
|
||||||
|
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import de.anura.core.database.DB;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
|
||||||
|
public class FishingChunk {
|
||||||
|
|
||||||
|
private static final double CHUNK_REGENERATION = 9.0 / 60.0; // 1 per 7 minutes
|
||||||
|
private static final int MAX_FISHES = 15; // within chunk
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
private int id;
|
||||||
|
private final Chunk chunk;
|
||||||
|
private double catched;
|
||||||
|
private long lastUpdated;
|
||||||
|
|
||||||
|
public FishingChunk(Chunk chunk) {
|
||||||
|
this(chunk, 0, System.currentTimeMillis() / 1000, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public FishingChunk(Chunk chunk, int catched, long lastUpdated, int id) {
|
||||||
|
this.id = id;
|
||||||
|
this.chunk = chunk;
|
||||||
|
this.catched = catched;
|
||||||
|
this.lastUpdated = lastUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk() {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
long notUpdatedTime = System.currentTimeMillis() / 1000 - lastUpdated;
|
||||||
|
long minutes = notUpdatedTime / 60;
|
||||||
|
|
||||||
|
catched -= minutes * CHUNK_REGENERATION;
|
||||||
|
if (catched < 0) {
|
||||||
|
catched = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastUpdated = System.currentTimeMillis() / 1000 - (notUpdatedTime % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getFishes() {
|
||||||
|
update();
|
||||||
|
int fishes = MAX_FISHES - (int) Math.ceil(catched);
|
||||||
|
if (fishes < 0) {
|
||||||
|
fishes = 0;
|
||||||
|
}
|
||||||
|
return fishes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOverfished() {
|
||||||
|
return getFishes() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCatched() {
|
||||||
|
catched += 1;
|
||||||
|
save(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(boolean async) {
|
||||||
|
update();
|
||||||
|
if (id <= 0) {
|
||||||
|
DB.queryUpdate(async, DB.getFirstKey((key) -> {
|
||||||
|
id = key;
|
||||||
|
}), "INSERT INTO fishingChunks (x, z, world, catched, lastUpdated) VALUES (?, ?, ?, ?, ?)",
|
||||||
|
chunk.getX(), chunk.getZ(), chunk.getWorld().getName(), catched, lastUpdated);
|
||||||
|
} else {
|
||||||
|
DB.queryUpdate(async, "UPDATE fishingChunks SET catched = ?, lastUpdated = ? WHERE primeKey = ?",
|
||||||
|
catched, lastUpdated, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
private static LoadingCache<Chunk, FishingChunk> FISHING_CACHE;
|
||||||
|
private static final List<FishingTask> tasks = Collections.synchronizedList(new LinkedList<>());
|
||||||
|
|
||||||
|
public static void init() {
|
||||||
|
CacheLoader<Chunk, FishingChunk> loader = new CacheLoader<Chunk, FishingChunk>() {
|
||||||
|
@Override
|
||||||
|
public FishingChunk load(Chunk chunk) throws Exception {
|
||||||
|
ResultSet rs = DB.querySelect(
|
||||||
|
"SELECT * FROM fishingChunks WHERE x = ? AND z = ? AND world = ?",
|
||||||
|
chunk.getX(), chunk.getZ(), chunk.getWorld().getName()
|
||||||
|
);
|
||||||
|
if (!rs.first()) {
|
||||||
|
return new FishingChunk(chunk);
|
||||||
|
}
|
||||||
|
return new FishingChunk(chunk, rs.getInt("catched"), rs.getInt("lastUpdated"), rs.getInt("primeKey"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
FISHING_CACHE = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterAccess(1, TimeUnit.HOURS)
|
||||||
|
.build(loader);
|
||||||
|
|
||||||
|
AnuraThread.add(Bukkit.getScheduler().runTaskTimerAsynchronously(RealisticMinecraft.getInstance(), () -> {
|
||||||
|
synchronized (tasks) {
|
||||||
|
Iterator<FishingTask> it = tasks.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
FishingTask task = it.next();
|
||||||
|
if (task.getTimestamp() < System.currentTimeMillis()) {
|
||||||
|
task.getR().run();
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 2, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FishingChunk get(Chunk chunk) {
|
||||||
|
return FISHING_CACHE.getUnchecked(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(Chunk chunk) {
|
||||||
|
return FISHING_CACHE.getIfPresent(chunk) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void queueTask(int secounds, Runnable r) {
|
||||||
|
tasks.add(new FishingTask(System.currentTimeMillis() + (secounds * 1000), r));
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/de/anura/realisticminecraft/fishing/FishingTask.java
Normal file
21
src/de/anura/realisticminecraft/fishing/FishingTask.java
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
package de.anura.realisticminecraft.fishing;
|
||||||
|
|
||||||
|
public class FishingTask {
|
||||||
|
|
||||||
|
private final long timestamp;
|
||||||
|
private final Runnable r;
|
||||||
|
|
||||||
|
public FishingTask(long timestamp, Runnable r) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.r = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Runnable getR() {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/de/anura/realisticminecraft/infobar/BarStatus.java
Normal file
6
src/de/anura/realisticminecraft/infobar/BarStatus.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
public enum BarStatus {
|
||||||
|
STANDARD,
|
||||||
|
AN;
|
||||||
|
}
|
||||||
79
src/de/anura/realisticminecraft/infobar/Infobar.java
Normal file
79
src/de/anura/realisticminecraft/infobar/Infobar.java
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import java.util.Objects;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.boss.BarColor;
|
||||||
|
import org.bukkit.boss.BarStyle;
|
||||||
|
import org.bukkit.boss.BossBar;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
public abstract class Infobar<T extends RealisticPlayer> {
|
||||||
|
|
||||||
|
protected final T player;
|
||||||
|
protected final BossBar bossbar;
|
||||||
|
private BarStatus barstatus;
|
||||||
|
private byte displaytime = 0;
|
||||||
|
private BukkitTask task = null;
|
||||||
|
|
||||||
|
public Infobar(T p, String title, BarColor color, BarStyle style, BarStatus status) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
Objects.requireNonNull(status);
|
||||||
|
player = p;
|
||||||
|
bossbar = Bukkit.createBossBar(title, color, style);
|
||||||
|
bossbar.addPlayer(player.getPlayer());
|
||||||
|
barstatus = status;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BarStatus getBarStatus() {
|
||||||
|
return barstatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBarStatus(BarStatus status) {
|
||||||
|
Objects.requireNonNull(status);
|
||||||
|
barstatus = status;
|
||||||
|
update();
|
||||||
|
player.updateDatabase(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBarVisible(boolean visible) {
|
||||||
|
if (stayCondition()) {
|
||||||
|
bossbar.setVisible(true);
|
||||||
|
} else {
|
||||||
|
bossbar.setVisible(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void destroy() {
|
||||||
|
if (bossbar.getPlayers().contains(player.getPlayer())) {
|
||||||
|
bossbar.removePlayer(player.getPlayer());
|
||||||
|
}
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
bossbar.setProgress((player.getValue() - player.getMIN()) / (player.getMAX() - player.getMIN()));
|
||||||
|
setBarVisible(true);
|
||||||
|
startCountdown((byte) 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean stayCondition() {
|
||||||
|
return getBarStatus().equals(BarStatus.AN);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void startCountdown(byte time) {
|
||||||
|
displaytime = time;
|
||||||
|
if (task == null) {
|
||||||
|
task = Bukkit.getScheduler().runTaskTimerAsynchronously(RealisticMinecraft.getInstance(), () -> {
|
||||||
|
if (displaytime > 0) {
|
||||||
|
displaytime--;
|
||||||
|
} else {
|
||||||
|
setBarVisible(false);
|
||||||
|
}
|
||||||
|
}, 20, 20);
|
||||||
|
AnuraThread.add(task);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
src/de/anura/realisticminecraft/infobar/InfobarUtil.java
Normal file
74
src/de/anura/realisticminecraft/infobar/InfobarUtil.java
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import de.anura.core.msg.Message;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
public class InfobarUtil {
|
||||||
|
|
||||||
|
private static int round = 1;
|
||||||
|
|
||||||
|
public static void enableInfobarTasks() {
|
||||||
|
JavaPlugin instance = RealisticMinecraft.getInstance();
|
||||||
|
AnuraThread.add(Bukkit.getScheduler().runTaskTimerAsynchronously(instance, () -> {
|
||||||
|
Bukkit.getOnlinePlayers().stream().filter((p) -> (p.getGameMode().equals(GameMode.SURVIVAL) && !p.isDead())).forEach((p) -> {
|
||||||
|
ValueHolder vh = ValueHolder.getValueHolder(p);
|
||||||
|
if (vh == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ThirstPlayer thP = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
if (thP != null && vh.getPlayer(TemperaturePlayer.class) != null) {
|
||||||
|
thP.calculateNewValue(p.getLocation());
|
||||||
|
}
|
||||||
|
if (round == 5) {
|
||||||
|
TemperaturePlayer tempP = vh.getPlayer(TemperaturePlayer.class);
|
||||||
|
if (tempP != null) {
|
||||||
|
tempP.calculateNewValue(p.getLocation());
|
||||||
|
if (tempP.isMIN()) {
|
||||||
|
Message.sendActionBar(p, ChatColor.RED + "Dir ist zu kalt!");
|
||||||
|
AnuraThread.queueSync(() -> p.damage(0.5));
|
||||||
|
} else if (tempP.isMAX()) {
|
||||||
|
Message.sendActionBar(p, ChatColor.RED + "Dir ist zu heiß!");
|
||||||
|
AnuraThread.queueSync(() -> p.damage(0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (thP != null) {
|
||||||
|
if (thP.getValue() == 0) {
|
||||||
|
Message.sendActionBar(p, ChatColor.RED + "Du bist durstig, trinke etwas!");
|
||||||
|
if (p.getHealth() - 0.5 <= 0) {
|
||||||
|
}
|
||||||
|
AnuraThread.queueSync(() -> p.damage(0.5));
|
||||||
|
} else if (thP.isThirsty() || thP.isWeak()) {
|
||||||
|
Message.sendActionBar(p, ChatColor.YELLOW + "Du bist durstig, trinke etwas!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (round == 5) {
|
||||||
|
round = 0;
|
||||||
|
}
|
||||||
|
round++;
|
||||||
|
}, 20, 20));
|
||||||
|
|
||||||
|
AnuraThread.add(Bukkit.getScheduler().runTaskTimerAsynchronously(instance, () -> {
|
||||||
|
Bukkit.getOnlinePlayers().stream().filter((p) -> (p.getGameMode().equals(GameMode.SURVIVAL) && !p.isDead())).forEach((p) -> {
|
||||||
|
ValueHolder vh = ValueHolder.getValueHolder(p);
|
||||||
|
if (vh == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TemperaturePlayer tmp = vh.getPlayer(TemperaturePlayer.class);
|
||||||
|
if (tmp != null) {
|
||||||
|
tmp.updateDatabase(false);
|
||||||
|
}
|
||||||
|
ThirstPlayer thp = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
if (thp != null) {
|
||||||
|
thp.updateDatabase(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 20 * 60, 20 * 60));
|
||||||
|
}
|
||||||
|
}
|
||||||
101
src/de/anura/realisticminecraft/infobar/RealisticPlayer.java
Normal file
101
src/de/anura/realisticminecraft/infobar/RealisticPlayer.java
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.database.DB;
|
||||||
|
import java.util.Objects;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public abstract class RealisticPlayer {
|
||||||
|
|
||||||
|
protected final short MIN;
|
||||||
|
protected final short MAX;
|
||||||
|
protected final short DEFAULT;
|
||||||
|
protected float value;
|
||||||
|
protected final Player player;
|
||||||
|
protected Infobar<? extends RealisticPlayer> bar;
|
||||||
|
|
||||||
|
protected RealisticPlayer(Player p, float value, short MIN, short MAX, short DEFAULT) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
player = p;
|
||||||
|
this.MIN = MIN;
|
||||||
|
this.MAX = MAX;
|
||||||
|
this.DEFAULT = DEFAULT;
|
||||||
|
if (value == -1) {
|
||||||
|
this.value = DEFAULT;
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getValue() {
|
||||||
|
return ((int) (value * 10)) / 10f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float setValue(float value) {
|
||||||
|
boolean updated = this.value != value;
|
||||||
|
if (updated) {
|
||||||
|
changeValue(value);
|
||||||
|
if (value > MAX) {
|
||||||
|
this.value = MAX;
|
||||||
|
} else if (value < MIN) {
|
||||||
|
this.value = MIN;
|
||||||
|
} else {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
bar.update();
|
||||||
|
}
|
||||||
|
return getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float addValue(float modifier) {
|
||||||
|
if (blockmodify() || modifier == 0) {
|
||||||
|
return getValue();
|
||||||
|
}
|
||||||
|
return setValue(value + modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getMIN() {
|
||||||
|
return MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMIN() {
|
||||||
|
return value == MIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getMAX() {
|
||||||
|
return MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMAX() {
|
||||||
|
return value == MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getDEFAULT() {
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExtremeValue() {
|
||||||
|
return isMIN() || isMAX();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Infobar<? extends RealisticPlayer> getBar() {
|
||||||
|
return bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void changeValue(float newValue) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean blockmodify();
|
||||||
|
|
||||||
|
protected abstract float calculateNewValue(Location l);
|
||||||
|
|
||||||
|
protected void updateDatabase(boolean async) {
|
||||||
|
DB.queryUpdate(async, "INSERT INTO " + getTableName() + " (`playerId`, `value`, `bar`) VALUES((SELECT id FROM players WHERE uuid = ?),?,?) ON DUPLICATE KEY UPDATE value = ?, bar = ?", player.getUniqueId().toString(), value, bar.getBarStatus().ordinal(), value, bar.getBarStatus().ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract String getTableName();
|
||||||
|
}
|
||||||
29
src/de/anura/realisticminecraft/infobar/TemperatureBar.java
Normal file
29
src/de/anura/realisticminecraft/infobar/TemperatureBar.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import org.bukkit.boss.BarColor;
|
||||||
|
import org.bukkit.boss.BarStyle;
|
||||||
|
|
||||||
|
public class TemperatureBar extends Infobar<TemperaturePlayer> {
|
||||||
|
|
||||||
|
public TemperatureBar(TemperaturePlayer p, BarStatus status) {
|
||||||
|
super(p, "Temperatur", BarColor.GREEN, BarStyle.SOLID, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
super.update();
|
||||||
|
bossbar.setTitle("Temperatur (" + player.getValue() + "°M)");
|
||||||
|
if (player.isExtremeValue()) {
|
||||||
|
bossbar.setColor(BarColor.RED);
|
||||||
|
} else if (player.isWarning()) {
|
||||||
|
bossbar.setColor(BarColor.YELLOW);
|
||||||
|
} else {
|
||||||
|
bossbar.setColor(BarColor.GREEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean stayCondition() {
|
||||||
|
return super.stayCondition() || player.isWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
221
src/de/anura/realisticminecraft/infobar/TemperatureModifier.java
Normal file
221
src/de/anura/realisticminecraft/infobar/TemperatureModifier.java
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.selections.CuboidSelection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.type.Furnace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public abstract class TemperatureModifier {
|
||||||
|
|
||||||
|
private static final float RAIN_MOD = -0.075f;
|
||||||
|
private static final float WATER_MOD = -0.5f;
|
||||||
|
private static final float FIRE_MOD = 0.5f;
|
||||||
|
private static final float WARM_MOD = 0.2f;
|
||||||
|
|
||||||
|
public static final float DRINK_MOD = -1f;
|
||||||
|
public static final float EAT_MOD = 2f;
|
||||||
|
|
||||||
|
public static float getModifier(Player p, Location l, TemperaturePlayer tp) {
|
||||||
|
float modifier = Biome.getModifier(l.getBlock());
|
||||||
|
if (modifier == 0) {
|
||||||
|
if (tp.getValue() < tp.getDEFAULT()) {
|
||||||
|
modifier += 0.1f;
|
||||||
|
} else if (tp.getValue() > tp.getDEFAULT()) {
|
||||||
|
modifier += -0.1f;
|
||||||
|
}
|
||||||
|
} else if (modifier > 0) {
|
||||||
|
World w = l.getWorld();
|
||||||
|
if (w != null && w.hasStorm() && tp.getValue() > tp.getDEFAULT() && tp.isWarning()) {
|
||||||
|
modifier = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
modifier += getRainModifier(l);
|
||||||
|
modifier += getWaterModifier(l, tp);
|
||||||
|
modifier += getFireModifier(p);
|
||||||
|
modifier += getLavaModifer(l);
|
||||||
|
modifier += getWarmModifier(l);
|
||||||
|
modifier += Equipment.getModifier(p.getEquipment(), modifier);
|
||||||
|
// if (TheTownAPI.isInWarriors() && WarriorsProvider.isNomaden(p)) {
|
||||||
|
// if (tp.getValue() > tp.getDEFAULT() && modifier > 0
|
||||||
|
// || tp.getValue() < tp.getDEFAULT() && modifier < 0) {
|
||||||
|
// modifier *= 0.25f;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getRainModifier(Location l) {
|
||||||
|
World w = l.getWorld();
|
||||||
|
return w != null && w.hasStorm() && l.getBlock().getRelative(BlockFace.UP).getLightFromSky() == 0xF ? RAIN_MOD : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getWaterModifier(Location l, TemperaturePlayer tp) {
|
||||||
|
if (l.getWorld() != null) {
|
||||||
|
Block b = l.getBlock();
|
||||||
|
if (b.getTemperature() >= 0.9f && tp.getValue() < tp.getDEFAULT()) {
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
return b.getType().equals(Material.WATER) ? WATER_MOD : 0;
|
||||||
|
}
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getFireModifier(Player p) {
|
||||||
|
return p.getFireTicks() > 0 ? FIRE_MOD : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getLavaModifer(Location l) {
|
||||||
|
return new CuboidSelection(l.getBlock(), 3).getCount(Material.LAVA) > 0 ? FIRE_MOD : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getWarmModifier(Location l) {
|
||||||
|
CuboidSelection sel = new CuboidSelection(l.getBlock(), 3);
|
||||||
|
ArrayList<Block> blocks = sel.getBlocks(Material.FURNACE);
|
||||||
|
boolean lit_furnace = false;
|
||||||
|
for (Block b : blocks) {
|
||||||
|
BlockData bd = b.getBlockData();
|
||||||
|
if (bd instanceof Furnace) {
|
||||||
|
Furnace f = (Furnace) bd;
|
||||||
|
if (f.isLit()) {
|
||||||
|
lit_furnace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lit_furnace || sel.getCount(Material.FIRE) > 0 ? WARM_MOD : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum Biome {
|
||||||
|
COLD(-1f, 0.5f, 1.5f, 1f, -0.05f, 0.5f),
|
||||||
|
WARM(0.9f, 1f, 1.5f, 1f, 0.05f, 1f),
|
||||||
|
HOT(1f, 2f, 2f, 1f, 0.05f, 1.5f);
|
||||||
|
|
||||||
|
private final float minTemp, maxTemp, daySkalar, nightSkalar, modifier, sunModifier;
|
||||||
|
|
||||||
|
private Biome(float min, float max, float day, float night, float modifier, float sun) {
|
||||||
|
minTemp = min;
|
||||||
|
maxTemp = max;
|
||||||
|
daySkalar = day;
|
||||||
|
nightSkalar = night;
|
||||||
|
this.modifier = modifier;
|
||||||
|
sunModifier = sun;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMinTemp() {
|
||||||
|
return minTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getMaxTemp() {
|
||||||
|
return maxTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getDaySkalar() {
|
||||||
|
return daySkalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getNightSkalar() {
|
||||||
|
return nightSkalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getModifier() {
|
||||||
|
return modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getSunModifier() {
|
||||||
|
return sunModifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getModifier(Block b) {
|
||||||
|
float modifier = 0;
|
||||||
|
for (Biome biome : values()) {
|
||||||
|
if (b.getTemperature() >= biome.getMinTemp() && b.getTemperature() <= biome.getMaxTemp()) {
|
||||||
|
if (isDay(b)) {
|
||||||
|
if (b.getLightFromSky() == 0xF && !b.getWorld().hasStorm()) {
|
||||||
|
modifier += biome.getModifier() * biome.getDaySkalar() * biome.getSunModifier();
|
||||||
|
} else {
|
||||||
|
modifier += biome.getModifier() * biome.getDaySkalar();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
modifier += biome.getModifier() * biome.getNightSkalar();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return modifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isDay(Block b) {
|
||||||
|
return b.getWorld().getTime() > 500 && b.getWorld().getTime() < 11500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static enum Equipment {
|
||||||
|
LEATHER_BHL(5, Material.LEATHER_BOOTS, Material.LEATHER_HELMET, Material.LEATHER_LEGGINGS),
|
||||||
|
LEATHER_C(15, Material.LEATHER_CHESTPLATE),
|
||||||
|
IRON_BHL(7.5f, Material.IRON_BOOTS, Material.IRON_HELMET, Material.IRON_LEGGINGS),
|
||||||
|
IRON_C(17.5f, Material.IRON_CHESTPLATE),
|
||||||
|
GOLD_BHL(10, Material.GOLDEN_BOOTS, Material.GOLDEN_HELMET, Material.GOLDEN_LEGGINGS),
|
||||||
|
GOLD_C(20, Material.GOLDEN_CHESTPLATE),
|
||||||
|
DIAMOND_BHL(12.5f, Material.DIAMOND_BOOTS, Material.DIAMOND_HELMET, Material.DIAMOND_LEGGINGS),
|
||||||
|
DIAMOND_C(22.5f, Material.DIAMOND_CHESTPLATE);
|
||||||
|
|
||||||
|
private Equipment(float percentage, Material... mat) {
|
||||||
|
this.percentage = percentage;
|
||||||
|
this.material = Arrays.asList(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Material> material;
|
||||||
|
private final float percentage;
|
||||||
|
|
||||||
|
private boolean contains(Material m) {
|
||||||
|
return material.contains(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getPercentage() {
|
||||||
|
return percentage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float getModifier(float tempModifier) {
|
||||||
|
return tempModifier * getPercentage() / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static float getModifier(Material m, float tempModifier) {
|
||||||
|
for (Equipment e : values()) {
|
||||||
|
if (e.contains(m)) {
|
||||||
|
return e.getModifier(tempModifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float getModifier(EntityEquipment ee, float tempModifier) {
|
||||||
|
float modifier = 0;
|
||||||
|
ItemStack boots = ee.getBoots();
|
||||||
|
if (boots != null) {
|
||||||
|
modifier += getModifier(boots.getType(), tempModifier);
|
||||||
|
}
|
||||||
|
ItemStack chestplate = ee.getChestplate();
|
||||||
|
if (chestplate != null) {
|
||||||
|
modifier += getModifier(chestplate.getType(), tempModifier);
|
||||||
|
}
|
||||||
|
ItemStack helmet = ee.getHelmet();
|
||||||
|
if (helmet != null) {
|
||||||
|
modifier += getModifier(helmet.getType(), tempModifier);
|
||||||
|
}
|
||||||
|
ItemStack leggins = ee.getLeggings();
|
||||||
|
if (leggins != null) {
|
||||||
|
modifier += getModifier(leggins.getType(), tempModifier);
|
||||||
|
}
|
||||||
|
return modifier * -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class TemperaturePlayer extends RealisticPlayer {
|
||||||
|
|
||||||
|
private static final short MIN_TEMP_WARNING = 20;
|
||||||
|
private static final short MAX_TEMP_WARNING = 40;
|
||||||
|
private static final short MIN_TEMP = 15;
|
||||||
|
private static final short MAX_TEMP = 45;
|
||||||
|
private static final short DEFAULT_TEMP = 30;
|
||||||
|
|
||||||
|
private static final short MIN_TEMP_DRINK = 30;
|
||||||
|
private static final short MAX_TEMP_EAT = 35;
|
||||||
|
|
||||||
|
public TemperaturePlayer(Player p) {
|
||||||
|
this(p, -1, BarStatus.STANDARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemperaturePlayer(Player p, float temp, BarStatus status) {
|
||||||
|
super(p, temp, MIN_TEMP, MAX_TEMP, DEFAULT_TEMP);
|
||||||
|
bar = new TemperatureBar(this, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWarning() {
|
||||||
|
return value >= MAX_TEMP_WARNING || value <= MIN_TEMP_WARNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float calculateNewValue(Location l) {
|
||||||
|
float modifier = TemperatureModifier.getModifier(player, l, this);
|
||||||
|
float returnField = modifier == 0 ? getValue() : addValue(modifier);
|
||||||
|
if (value >= MAX_TEMP_WARNING) {
|
||||||
|
ValueHolder vh = ValueHolder.getValueHolder(player);
|
||||||
|
if (vh != null) {
|
||||||
|
ThirstPlayer tp = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
if (tp != null) {
|
||||||
|
tp.addValue(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float drink() {
|
||||||
|
return value > MIN_TEMP_DRINK ? addValue(TemperatureModifier.DRINK_MOD) : getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float eatSoup() {
|
||||||
|
return value < MAX_TEMP_EAT ? addValue(TemperatureModifier.EAT_MOD) : getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean blockmodify() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableName() {
|
||||||
|
return getStaticTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getStaticTableName() {
|
||||||
|
return "playerTemperature";
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/de/anura/realisticminecraft/infobar/ThirstBar.java
Normal file
16
src/de/anura/realisticminecraft/infobar/ThirstBar.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import org.bukkit.boss.BarColor;
|
||||||
|
import org.bukkit.boss.BarStyle;
|
||||||
|
|
||||||
|
public class ThirstBar extends Infobar<ThirstPlayer> {
|
||||||
|
|
||||||
|
public ThirstBar(ThirstPlayer p, BarStatus status) {
|
||||||
|
super(p, "Durst", BarColor.BLUE, BarStyle.SOLID, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean stayCondition() {
|
||||||
|
return super.stayCondition() || player.isNoSprint();
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/de/anura/realisticminecraft/infobar/ThirstPlayer.java
Normal file
118
src/de/anura/realisticminecraft/infobar/ThirstPlayer.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.tools.Potions;
|
||||||
|
import de.anura.core.tools.Potions.CustomPotion;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Biome;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
public class ThirstPlayer extends RealisticPlayer {
|
||||||
|
|
||||||
|
private static final CustomPotion POTION_THIRSTY = new CustomPotion(new PotionEffect(PotionEffectType.CONFUSION, 0, 0), true);
|
||||||
|
private static final CustomPotion POTION_WEAK_I = new CustomPotion(new PotionEffect(PotionEffectType.WEAKNESS, 0, 0), true);
|
||||||
|
private static final CustomPotion POTION_WEAK_II = new CustomPotion(new PotionEffect(PotionEffectType.SLOW, 0, 0), true);
|
||||||
|
|
||||||
|
private static final short THIRSTY = 5;
|
||||||
|
private static final short WEAK = 10;
|
||||||
|
private static final short NO_SPRINT = 20;
|
||||||
|
|
||||||
|
private static final short MIN_V = 0;
|
||||||
|
private static final short MAX_V = 100;
|
||||||
|
|
||||||
|
private static final float BASIC_MOD = -0.015f;
|
||||||
|
private static final float DRINK_MOD = 10f;
|
||||||
|
private static final float RAIN_MOD = 1f;
|
||||||
|
private static final float FOODLEVEL_MOD = -1f;
|
||||||
|
|
||||||
|
private static final float NOMADEN_MOD = 0.25f;
|
||||||
|
|
||||||
|
public ThirstPlayer(Player p) {
|
||||||
|
this(p, -1, BarStatus.STANDARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThirstPlayer(Player p, float thirst, BarStatus status) {
|
||||||
|
super(p, thirst, MIN_V, MAX_V, MAX_V);
|
||||||
|
bar = new ThirstBar(this, status);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean blockmodify() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isThirsty() {
|
||||||
|
return value <= THIRSTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWeak() {
|
||||||
|
return value <= WEAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNoSprint() {
|
||||||
|
return value <= NO_SPRINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float calculateNewValue(Location l) {
|
||||||
|
float mod = BASIC_MOD;
|
||||||
|
// if (TheTownAPI.isInWarriors() && WarriorsProvider.isNomaden(player)) {
|
||||||
|
// mod *= NOMADEN_MOD;
|
||||||
|
// }
|
||||||
|
World w = l.getWorld();
|
||||||
|
if (w != null && w.hasStorm() && l.getPitch() < -75 && l.getBlock().getRelative(BlockFace.UP).getLightFromSky() == 0xF) {
|
||||||
|
mod += RAIN_MOD;
|
||||||
|
}
|
||||||
|
return addValue(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void changeValue(float newValue) {
|
||||||
|
if (!isWeak() && newValue <= WEAK) {
|
||||||
|
Potions.addCustomPotion(player, POTION_WEAK_I);
|
||||||
|
Potions.addCustomPotion(player, POTION_WEAK_II);
|
||||||
|
} else if (isWeak() && newValue > WEAK) {
|
||||||
|
Potions.removeCustomPotion(player, POTION_WEAK_I);
|
||||||
|
Potions.removeCustomPotion(player, POTION_WEAK_II);
|
||||||
|
}
|
||||||
|
if (!isThirsty() && newValue <= THIRSTY) {
|
||||||
|
Potions.addCustomPotion(player, POTION_THIRSTY);
|
||||||
|
} else if (isThirsty() && newValue > THIRSTY) {
|
||||||
|
Potions.removeCustomPotion(player, POTION_THIRSTY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float drink() {
|
||||||
|
return addValue(DRINK_MOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float foodLevelChange() {
|
||||||
|
// if (TheTownAPI.isInWarriors() && WarriorsProvider.isNomaden(player)) {
|
||||||
|
// return addValue(FOODLEVEL_MOD * NOMADEN_MOD);
|
||||||
|
// }
|
||||||
|
return addValue(FOODLEVEL_MOD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTableName() {
|
||||||
|
return getStaticTableName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getStaticTableName() {
|
||||||
|
return "playerThirst";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isOcean(Biome b) {
|
||||||
|
switch (b) {
|
||||||
|
case OCEAN:
|
||||||
|
case DEEP_OCEAN:
|
||||||
|
case FROZEN_OCEAN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
90
src/de/anura/realisticminecraft/infobar/ValueHolder.java
Normal file
90
src/de/anura/realisticminecraft/infobar/ValueHolder.java
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package de.anura.realisticminecraft.infobar;
|
||||||
|
|
||||||
|
import de.anura.core.database.DB;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class ValueHolder {
|
||||||
|
|
||||||
|
private static final List<Class<? extends RealisticPlayer>> PLAYERS = Arrays.asList(TemperaturePlayer.class, ThirstPlayer.class);
|
||||||
|
private static final Map<Player, ValueHolder> ALL = new ConcurrentHashMap<>();
|
||||||
|
private final Map<Class<? extends RealisticPlayer>, RealisticPlayer> values = new ConcurrentHashMap<>();
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
public ValueHolder(Player p) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
ALL.put(p, this);
|
||||||
|
player = p;
|
||||||
|
PLAYERS.forEach(this::createPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Player getPlayer() {
|
||||||
|
return player;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Nullable
|
||||||
|
public <T extends RealisticPlayer> T getPlayer(Class<T> clazz) {
|
||||||
|
return (T) values.get(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RealisticPlayer> getPlayersList() {
|
||||||
|
return values.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends RealisticPlayer> void createPlayer(Class<T> clazz) {
|
||||||
|
ResultSet rs = null;
|
||||||
|
try {
|
||||||
|
rs = DB.querySelect("SELECT value, bar FROM " + clazz.getDeclaredMethod("getStaticTableName").invoke(null) + " WHERE playerId = (SELECT id FROM players WHERE uuid = ?)", player.getUniqueId().toString());
|
||||||
|
if (rs.next()) {
|
||||||
|
T rp = clazz.getConstructor(Player.class, float.class, BarStatus.class).newInstance(player, rs.getFloat("value"), BarStatus.values()[rs.getInt("bar")]);
|
||||||
|
values.put(clazz, rp);
|
||||||
|
} else {
|
||||||
|
values.put(clazz, clazz.getConstructor(Player.class).newInstance(player));
|
||||||
|
}
|
||||||
|
} catch (SQLException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException ex) {
|
||||||
|
Logger.getLogger(ValueHolder.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
DB.closeRessources(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends RealisticPlayer> void resetPlayer(Class<T> clazz) {
|
||||||
|
values.get(clazz).setValue(values.get(clazz).getDEFAULT());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetHoldings() {
|
||||||
|
PLAYERS.forEach(this::resetPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static ValueHolder getValueHolder(Player p) {
|
||||||
|
return ALL.get(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeValueHolder(Player p) {
|
||||||
|
remove(ALL.remove(p));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destroyAll() {
|
||||||
|
ALL.values().forEach(ValueHolder::remove);
|
||||||
|
ALL.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void remove(ValueHolder vh) {
|
||||||
|
if (vh != null) {
|
||||||
|
vh.getPlayersList().forEach((rp) -> {
|
||||||
|
rp.updateDatabase(false);
|
||||||
|
rp.getBar().destroy();
|
||||||
|
rp.changeValue(rp.getDEFAULT());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
src/de/anura/realisticminecraft/listener/Chairs.java
Normal file
105
src/de/anura/realisticminecraft/listener/Chairs.java
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package de.anura.realisticminecraft.listener;
|
||||||
|
|
||||||
|
import de.anura.core.events.AnuraLeaveEvent;
|
||||||
|
import de.anura.core.msg.Msg;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import de.anura.realisticminecraft.util.ChairManager;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.Bisected.Half;
|
||||||
|
import org.bukkit.block.data.type.Stairs;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
import org.spigotmc.event.entity.EntityDismountEvent;
|
||||||
|
|
||||||
|
public class Chairs implements Listener {
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onBlockBreak(BlockBreakEvent e) {
|
||||||
|
if (e.getBlock().getBlockData() instanceof Stairs && ChairManager.isSittingAnyone(e.getBlock())) {
|
||||||
|
ChairManager.playerStandUp(e.getBlock());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onDismount(EntityDismountEvent e) {
|
||||||
|
if (e.getEntity() instanceof Player && e.getDismounted() instanceof ArmorStand) {
|
||||||
|
Player p = (Player) e.getEntity();
|
||||||
|
if (ChairManager.isSitting(p)) {
|
||||||
|
ChairManager.playerStandUp(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onBlockInteract(PlayerInteractEvent e) {
|
||||||
|
final Player p = e.getPlayer();
|
||||||
|
EquipmentSlot eq = e.getHand();
|
||||||
|
if (e.getAction().equals(Action.RIGHT_CLICK_BLOCK) && !p.isSneaking() && eq != null && eq.equals(EquipmentSlot.HAND)) {
|
||||||
|
final Block b = e.getClickedBlock();
|
||||||
|
if (b != null && b.getBlockData() instanceof Stairs) {
|
||||||
|
Stairs s = (Stairs) b.getBlockData();
|
||||||
|
if (s.getHalf().equals(Half.BOTTOM)) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
Material above = b.getLocation().add(0, 1, 0).getBlock().getType();
|
||||||
|
if (!cloudAbove(above) && above.isSolid()) {
|
||||||
|
Msg.send(p, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Da ist kein Platz zum Sitzen!");
|
||||||
|
} else if (ChairManager.isSittingAnyone(b)) {
|
||||||
|
if (!ChairManager.isSittingPlayer(b, p)) {
|
||||||
|
Msg.send(p, RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, "Hier sitzt bereits jemand!");
|
||||||
|
}
|
||||||
|
} else if (ChairManager.isSitting(p)) {
|
||||||
|
ChairManager.playerStandUp(p);
|
||||||
|
ChairManager.playerSitDown(p, s, b);
|
||||||
|
} else {
|
||||||
|
ChairManager.playerSitDown(p, s, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onPlayerLeave(AnuraLeaveEvent e) {
|
||||||
|
if (ChairManager.isSitting(e.getPlayer())) {
|
||||||
|
ChairManager.playerStandUp(e.getPlayer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean cloudAbove(Material m) {
|
||||||
|
switch(m) {
|
||||||
|
case BLACK_WALL_BANNER:
|
||||||
|
case BLUE_WALL_BANNER:
|
||||||
|
case BROWN_WALL_BANNER:
|
||||||
|
case CYAN_WALL_BANNER:
|
||||||
|
case GRAY_WALL_BANNER:
|
||||||
|
case GREEN_WALL_BANNER:
|
||||||
|
case LIGHT_BLUE_WALL_BANNER:
|
||||||
|
case LIGHT_GRAY_WALL_BANNER:
|
||||||
|
case LIME_WALL_BANNER:
|
||||||
|
case MAGENTA_WALL_BANNER:
|
||||||
|
case ORANGE_WALL_BANNER:
|
||||||
|
case PINK_WALL_BANNER:
|
||||||
|
case PURPLE_WALL_BANNER:
|
||||||
|
case RED_WALL_BANNER:
|
||||||
|
case WHITE_WALL_BANNER:
|
||||||
|
case YELLOW_WALL_BANNER:
|
||||||
|
case ACACIA_WALL_SIGN:
|
||||||
|
case BIRCH_WALL_SIGN:
|
||||||
|
case DARK_OAK_WALL_SIGN:
|
||||||
|
case JUNGLE_WALL_SIGN:
|
||||||
|
case OAK_WALL_SIGN:
|
||||||
|
case SPRUCE_WALL_SIGN:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/de/anura/realisticminecraft/listener/Fishing.java
Normal file
67
src/de/anura/realisticminecraft/listener/Fishing.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package de.anura.realisticminecraft.listener;
|
||||||
|
|
||||||
|
import de.anura.core.msg.Message;
|
||||||
|
import de.anura.core.msg.Msg;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import de.anura.realisticminecraft.fishing.FishingChunk;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Chunk;
|
||||||
|
import org.bukkit.entity.FishHook;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.PlayerFishEvent;
|
||||||
|
|
||||||
|
public class Fishing implements Listener {
|
||||||
|
|
||||||
|
private static final String FAILED_HOOK_NAME = ChatColor.DARK_RED + "✖✖✖";
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onFish(PlayerFishEvent ev) {
|
||||||
|
|
||||||
|
FishHook hook = ev.getHook();
|
||||||
|
Chunk chunk = hook.getLocation().getChunk();
|
||||||
|
|
||||||
|
|
||||||
|
switch (ev.getState()) {
|
||||||
|
case FISHING: {
|
||||||
|
if (!FishingChunk.contains(chunk)) {
|
||||||
|
FishingChunk.queueTask(0, () -> FishingChunk.get(chunk));
|
||||||
|
}
|
||||||
|
// Wir warten 5 Sekunden, da dieser State (FISHING) direkt aufgerufen wird, wenn man die Angel auswirft.
|
||||||
|
FishingChunk.queueTask(5 , () -> {
|
||||||
|
if (hook.isDead() || !hook.isValid()) return;
|
||||||
|
|
||||||
|
FishingChunk newHookChunk = FishingChunk.get(hook.getLocation().getChunk());
|
||||||
|
if (!newHookChunk.isOverfished()) return;
|
||||||
|
|
||||||
|
Message.sendActionBar(ev.getPlayer(), Msg.getMsg(RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, true, "Dieser Teil des Gewässer scheint überfischt zu sein!"));
|
||||||
|
|
||||||
|
hook.setCustomName(FAILED_HOOK_NAME);
|
||||||
|
hook.setCustomNameVisible(true);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case BITE: {
|
||||||
|
FishingChunk fishingChunk = FishingChunk.get(chunk);
|
||||||
|
if (fishingChunk.isOverfished()) {
|
||||||
|
Message.sendActionBar(ev.getPlayer(), Msg.getMsg(RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, true, "Dieser Teil des Gewässer scheint überfischt zu sein!"));
|
||||||
|
hook.setCustomName(FAILED_HOOK_NAME);
|
||||||
|
hook.setCustomNameVisible(true);
|
||||||
|
ev.setCancelled(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CAUGHT_FISH: {
|
||||||
|
FishingChunk fishingChunk = FishingChunk.get(chunk);
|
||||||
|
if (fishingChunk.isOverfished()) {
|
||||||
|
Message.sendActionBar(ev.getPlayer(), Msg.getMsg(RealisticMinecraft.PLUGIN_DATA, Msg.MsgType.ERROR, true, "Dieser Teil des Gewässer scheint überfischt zu sein!"));
|
||||||
|
ev.setCancelled(true);
|
||||||
|
ev.setExpToDrop(0);
|
||||||
|
} else {
|
||||||
|
fishingChunk.addCatched();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
132
src/de/anura/realisticminecraft/listener/Infobar.java
Normal file
132
src/de/anura/realisticminecraft/listener/Infobar.java
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
package de.anura.realisticminecraft.listener;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import de.anura.core.events.AnuraLeaveEvent;
|
||||||
|
import de.anura.core.tools.Potions;
|
||||||
|
import de.anura.core.tools.Potions.CustomPotion;
|
||||||
|
import de.anura.realisticminecraft.infobar.TemperaturePlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.ThirstPlayer;
|
||||||
|
import de.anura.realisticminecraft.infobar.ValueHolder;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerGameModeChangeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerItemConsumeEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerToggleSprintEvent;
|
||||||
|
import org.bukkit.potion.PotionEffect;
|
||||||
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
|
||||||
|
public class Infobar implements Listener {
|
||||||
|
|
||||||
|
private static final CustomPotion POTION_HUNGER_I = new CustomPotion(new PotionEffect(PotionEffectType.SLOW_DIGGING, 0, 0), true);
|
||||||
|
private static final CustomPotion POTION_HUNGER_II = new CustomPotion(new PotionEffect(PotionEffectType.SLOW, 0, 0), true);
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onDeath(PlayerDeathEvent e) {
|
||||||
|
if (e.getEntity().getHealth() <= 0) {
|
||||||
|
AnuraThread.async(() -> {
|
||||||
|
final ValueHolder vh = ValueHolder.getValueHolder(e.getEntity());
|
||||||
|
if (vh != null) {
|
||||||
|
vh.resetHoldings();
|
||||||
|
}
|
||||||
|
Potions.removeCustomPotion(e.getEntity(), POTION_HUNGER_I);
|
||||||
|
Potions.removeCustomPotion(e.getEntity(), POTION_HUNGER_II);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onItemConsume(PlayerItemConsumeEvent e) {
|
||||||
|
final ValueHolder vh = ValueHolder.getValueHolder(e.getPlayer());
|
||||||
|
if (vh == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final TemperaturePlayer tp = vh.getPlayer(TemperaturePlayer.class);
|
||||||
|
final ThirstPlayer thp = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
switch (e.getItem().getType()) {
|
||||||
|
case MILK_BUCKET:
|
||||||
|
case POTION:
|
||||||
|
if (tp != null) {
|
||||||
|
tp.drink();
|
||||||
|
}
|
||||||
|
if (thp != null) {
|
||||||
|
thp.drink();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MUSHROOM_STEW:
|
||||||
|
if (tp != null) {
|
||||||
|
tp.eatSoup();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onFoodLevelChange(FoodLevelChangeEvent e) {
|
||||||
|
if (e.getEntity() instanceof Player) {
|
||||||
|
Player p = (Player) e.getEntity();
|
||||||
|
if (e.getFoodLevel() < p.getFoodLevel()) {
|
||||||
|
final ValueHolder vh = ValueHolder.getValueHolder(p);
|
||||||
|
if (vh != null) {
|
||||||
|
ThirstPlayer tP = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
if (tP != null) {
|
||||||
|
tP.foodLevelChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (e.getFoodLevel() < 4) {
|
||||||
|
Potions.addCustomPotion(p, POTION_HUNGER_I);
|
||||||
|
Potions.addCustomPotion(p, POTION_HUNGER_II);
|
||||||
|
} else {
|
||||||
|
Potions.removeCustomPotion(p, POTION_HUNGER_I);
|
||||||
|
Potions.removeCustomPotion(p, POTION_HUNGER_II);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onLogin(PlayerJoinEvent e) {
|
||||||
|
if (e.getPlayer().getGameMode().equals(GameMode.SURVIVAL)) {
|
||||||
|
AnuraThread.async(() -> new ValueHolder(e.getPlayer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onChangeGameMode(PlayerGameModeChangeEvent e) {
|
||||||
|
AnuraThread.async(() -> {
|
||||||
|
if (e.getNewGameMode().equals(GameMode.SURVIVAL)) {
|
||||||
|
new ValueHolder(e.getPlayer());
|
||||||
|
if (e.getPlayer().getFoodLevel() < 4) {
|
||||||
|
Potions.addCustomPotion(e.getPlayer(), POTION_HUNGER_I);
|
||||||
|
Potions.addCustomPotion(e.getPlayer(), POTION_HUNGER_II);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ValueHolder.removeValueHolder(e.getPlayer());
|
||||||
|
Potions.removeCustomPotion(e.getPlayer(), POTION_HUNGER_I);
|
||||||
|
Potions.removeCustomPotion(e.getPlayer(), POTION_HUNGER_II);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onSprint(PlayerToggleSprintEvent e) {
|
||||||
|
if (e.isSprinting()) {
|
||||||
|
ValueHolder vh = ValueHolder.getValueHolder(e.getPlayer());
|
||||||
|
if (vh != null) {
|
||||||
|
ThirstPlayer tp = vh.getPlayer(ThirstPlayer.class);
|
||||||
|
if (tp != null) {
|
||||||
|
e.setCancelled(tp.isNoSprint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onDisconnect(AnuraLeaveEvent e) {
|
||||||
|
AnuraThread.async(() -> ValueHolder.removeValueHolder(e.getPlayer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/de/anura/realisticminecraft/listener/Timber.java
Normal file
83
src/de/anura/realisticminecraft/listener/Timber.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package de.anura.realisticminecraft.listener;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import de.anura.realisticminecraft.timber.TreeFeller;
|
||||||
|
import de.anura.realisticminecraft.timber.parser.TreeParser;
|
||||||
|
import org.bukkit.Axis;
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.Orientable;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.EventPriority;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.inventory.EntityEquipment;
|
||||||
|
|
||||||
|
public class Timber implements Listener {
|
||||||
|
|
||||||
|
private static final Map<Player, BlockFace> LAST_INTERACT = new WeakHashMap<>();
|
||||||
|
|
||||||
|
public static BlockFace getLastInteract(Player p) {
|
||||||
|
return LAST_INTERACT.get(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
|
public void onBlockBreak(BlockBreakEvent e) {
|
||||||
|
if (isInOwnRegion() == e.getPlayer().isSneaking()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isTimberLog(e.getBlock().getType())) {
|
||||||
|
EntityEquipment eq = e.getPlayer().getEquipment();
|
||||||
|
if (e.getPlayer().getGameMode().equals(GameMode.SURVIVAL)
|
||||||
|
&& eq != null && TreeFeller.isAxe(eq.getItemInMainHand().getType())
|
||||||
|
&& ((Orientable) e.getBlock().getBlockData()).getAxis().equals(Axis.Y)) {
|
||||||
|
e.setCancelled(true);
|
||||||
|
AnuraThread.async(() -> {
|
||||||
|
TreeParser treeParser = TreeParser.newTreeParser(e.getBlock());
|
||||||
|
new TreeFeller(e.getPlayer(), treeParser.parse(getLastInteract(e.getPlayer())))
|
||||||
|
.cut(eq.getItemInMainHand());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(ignoreCancelled = true)
|
||||||
|
public void onBlockInteract(PlayerInteractEvent e) {
|
||||||
|
final Player p = e.getPlayer();
|
||||||
|
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
|
||||||
|
if (!p.getGameMode().equals(GameMode.SURVIVAL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Block clickedBlock = e.getClickedBlock();
|
||||||
|
if (clickedBlock != null && isTimberLog(clickedBlock.getType())) {
|
||||||
|
LAST_INTERACT.put(p, e.getBlockFace());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInOwnRegion() {
|
||||||
|
return false;//TODO: Get from region management
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isTimberLog(Material m) {
|
||||||
|
switch (m) {
|
||||||
|
case ACACIA_LOG:
|
||||||
|
case BIRCH_LOG:
|
||||||
|
case DARK_OAK_LOG:
|
||||||
|
case JUNGLE_LOG:
|
||||||
|
case OAK_LOG:
|
||||||
|
case SPRUCE_LOG:
|
||||||
|
//@TODO: Check BARK
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
src/de/anura/realisticminecraft/timber/Tree.java
Normal file
88
src/de/anura/realisticminecraft/timber/Tree.java
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
package de.anura.realisticminecraft.timber;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Random;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
|
||||||
|
public class Tree {
|
||||||
|
|
||||||
|
private final HashSet<Block> logList;
|
||||||
|
private final HashSet<Block> leaveList;
|
||||||
|
private final Block lowestLog;
|
||||||
|
private Block highestBlock;
|
||||||
|
private final BlockFace direction;
|
||||||
|
private final Material wood;
|
||||||
|
private final Material leave;
|
||||||
|
private final TreeSpecies species;
|
||||||
|
|
||||||
|
public Tree(Block first, HashSet<Block> logs, HashSet<Block> leaves, BlockFace fallDirection, Material wood, Material leave, TreeSpecies species) {
|
||||||
|
this.logList = logs;
|
||||||
|
this.leaveList = leaves;
|
||||||
|
this.lowestLog = first;
|
||||||
|
this.wood = wood;
|
||||||
|
this.leave = leave;
|
||||||
|
this.species = species;
|
||||||
|
if (fallDirection == null || fallDirection.equals(BlockFace.UP) || fallDirection.equals(BlockFace.DOWN)) {
|
||||||
|
direction = BlockFace.values()[new Random().nextInt(4)];
|
||||||
|
} else {
|
||||||
|
direction = fallDirection.getOppositeFace();
|
||||||
|
}
|
||||||
|
Location loc = first.getLocation();
|
||||||
|
loc.setY(0);
|
||||||
|
highestBlock = loc.getBlock();
|
||||||
|
logs.forEach((b) -> {
|
||||||
|
if (b.getLocation().getY() > highestBlock.getLocation().getY()) {
|
||||||
|
highestBlock = b;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
leaves.forEach((b) -> {
|
||||||
|
if (b.getLocation().getY() > highestBlock.getLocation().getY()) {
|
||||||
|
highestBlock = b;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<Block> getLogs() {
|
||||||
|
return logList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<Block> getLeaves() {
|
||||||
|
return leaveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeigth() {
|
||||||
|
return highestBlock.getLocation().getBlockY() - lowestLog.getLocation().getBlockY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getLowestLog() {
|
||||||
|
return lowestLog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLowestLogLoc() {
|
||||||
|
return lowestLog.getLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockFace getFallDirection() {
|
||||||
|
return direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCuttable() {
|
||||||
|
return leaveList.size() > 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getWood() {
|
||||||
|
return wood;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Material getLeave() {
|
||||||
|
return leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TreeSpecies getSpecies() {
|
||||||
|
return species;
|
||||||
|
}
|
||||||
|
}
|
||||||
212
src/de/anura/realisticminecraft/timber/TreeFeller.java
Normal file
212
src/de/anura/realisticminecraft/timber/TreeFeller.java
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
package de.anura.realisticminecraft.timber;
|
||||||
|
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import java.util.Random;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import de.anura.realisticminecraft.timber.event.AppleDropEvent;
|
||||||
|
import de.anura.realisticminecraft.timber.event.TreeCutEvent;
|
||||||
|
import de.anura.realisticminecraft.util.LogBlockProvider;
|
||||||
|
import org.bukkit.Axis;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.block.data.Orientable;
|
||||||
|
import org.bukkit.block.data.type.Leaves;
|
||||||
|
import org.bukkit.entity.FallingBlock;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.Damageable;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
||||||
|
public class TreeFeller {
|
||||||
|
|
||||||
|
private final Tree t;
|
||||||
|
private final Player p;
|
||||||
|
private TreeCutEvent treeCutEvent;
|
||||||
|
|
||||||
|
public TreeFeller(Player p, Tree t) {
|
||||||
|
this.p = p;
|
||||||
|
this.t = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cut(ItemStack axe) {
|
||||||
|
if (!t.isCuttable()) {
|
||||||
|
AnuraThread.queueSync(() -> {
|
||||||
|
t.getLowestLogLoc().getBlock().breakNaturally(axe);
|
||||||
|
});
|
||||||
|
calculateDamage(axe, 1);
|
||||||
|
p.getInventory().setItemInMainHand(axe);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
treeCutEvent = new TreeCutEvent(p, t.getLowestLog());
|
||||||
|
Bukkit.getPluginManager().callEvent(treeCutEvent);
|
||||||
|
if (treeCutEvent.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
calculateDamage(axe, 5);
|
||||||
|
p.getInventory().setItemInMainHand(axe);
|
||||||
|
World w = t.getLowestLogLoc().getWorld();
|
||||||
|
if (w != null) {
|
||||||
|
w.playSound(t.getLowestLogLoc(), Sound.BLOCK_GRASS_BREAK, 1, 0.1f);
|
||||||
|
}
|
||||||
|
for (int i = 0; i <= t.getHeigth(); i++) {
|
||||||
|
cutLog(i);
|
||||||
|
cutLeaves(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cutLog(int stage) {
|
||||||
|
BlockData log = getLogOrientation();
|
||||||
|
t.getLogs().stream().filter(b -> b.getLocation().getBlockY() == t.getLowestLogLoc().getBlockY() + stage).forEach(b -> {
|
||||||
|
AnuraThread.queueSync(() -> {
|
||||||
|
queueBlockBreak(p, b);
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
Location pLocation = getPossibleLocation(b, stage);
|
||||||
|
FallingBlock spawnFallingBlock = b.getWorld().spawnFallingBlock(pLocation.add(0.5, 0, 0.5), log);
|
||||||
|
spawnFallingBlock.setDropItem(false);
|
||||||
|
queueFallingBlock(p, pLocation, log);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cutLeaves(int stage) {
|
||||||
|
BlockData ld = getLeavesData();
|
||||||
|
Random r = new Random();
|
||||||
|
short appleCount = 0;
|
||||||
|
for (Block b : t.getLeaves()) {
|
||||||
|
if (b.getLocation().getBlockY() == t.getLowestLogLoc().getBlockY() + stage) {
|
||||||
|
if (r.nextBoolean()) {
|
||||||
|
ItemStack is;
|
||||||
|
if (treeCutEvent.getSaplingDropChance() > 0 && r.nextInt(treeCutEvent.getSaplingDropChance()) == 0) {
|
||||||
|
is = new ItemStack(getSaplingMaterial());
|
||||||
|
} else if (treeCutEvent.getAppleDropChance() > 0 && r.nextInt(treeCutEvent.getAppleDropChance()) == 0) {
|
||||||
|
is = new ItemStack(Material.APPLE);
|
||||||
|
appleCount++;
|
||||||
|
} else if (treeCutEvent.getLeavesDropChance() > 0 && r.nextInt(treeCutEvent.getLeavesDropChance()) == 0) {
|
||||||
|
is = new ItemStack(t.getLeave());
|
||||||
|
} else {
|
||||||
|
AnuraThread.queueSync(() -> {
|
||||||
|
queueBlockBreak(p, b);
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
});
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
AnuraThread.queueSync(() -> {
|
||||||
|
b.getWorld().dropItemNaturally(getPossibleLocation(b, stage).add(0.5, 0, 0.5), is);
|
||||||
|
queueBlockBreak(p, b);
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
AnuraThread.queueSync(() -> {
|
||||||
|
queueBlockBreak(p, b);
|
||||||
|
b.setType(Material.AIR);
|
||||||
|
Location pLocation = getPossibleLocation(b, stage);
|
||||||
|
b.getWorld().spawnFallingBlock(pLocation.add(0.5, 0, 0.5), ld);
|
||||||
|
queueFallingBlock(p, pLocation, ld);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (appleCount > 0) {
|
||||||
|
Bukkit.getPluginManager().callEvent(new AppleDropEvent(p, appleCount));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void calculateDamage(ItemStack is, int damage) {
|
||||||
|
ItemMeta im = is.getItemMeta();
|
||||||
|
if (!(im instanceof Damageable)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Damageable d = (Damageable) im;
|
||||||
|
if (is.getType().getMaxDurability() - d.getDamage() - damage < 0) {
|
||||||
|
is.setType(Material.AIR);
|
||||||
|
} else {
|
||||||
|
d.setDamage((short) (d.getDamage() + damage));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockData getLogOrientation() {
|
||||||
|
Orientable o = (Orientable) t.getWood().createBlockData();
|
||||||
|
o.setAxis(convertDirection(t.getFallDirection()));
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockData getLeavesData() {
|
||||||
|
Leaves l = (Leaves) t.getLeave().createBlockData();
|
||||||
|
l.setPersistent(true);//@TODO: Check if needed
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Material getSaplingMaterial() {
|
||||||
|
switch (t.getWood()) {
|
||||||
|
case BIRCH_LOG:
|
||||||
|
return Material.BIRCH_SAPLING;
|
||||||
|
case SPRUCE_LOG:
|
||||||
|
return Material.SPRUCE_SAPLING;
|
||||||
|
case JUNGLE_LOG:
|
||||||
|
return Material.JUNGLE_SAPLING;
|
||||||
|
case ACACIA_LOG:
|
||||||
|
return Material.ACACIA_SAPLING;
|
||||||
|
case DARK_OAK_LOG:
|
||||||
|
return Material.DARK_OAK_SAPLING;
|
||||||
|
case OAK_LOG:
|
||||||
|
default:
|
||||||
|
return Material.OAK_SAPLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Location getPossibleLocation(Block start, int stage) {
|
||||||
|
if (stage != 0) {
|
||||||
|
for (int i = 1; i <= stage; i++) {
|
||||||
|
Block b = start.getRelative(t.getFallDirection(), i);
|
||||||
|
if (b.getType().isSolid() && !t.getLogs().contains(b) && !t.getLeaves().contains(b)) {
|
||||||
|
return start.getRelative(t.getFallDirection(), i - 1).getLocation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return start.getRelative(t.getFallDirection(), stage).getLocation();
|
||||||
|
}
|
||||||
|
return start.getLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Axis convertDirection(BlockFace bf) {
|
||||||
|
switch (bf) {
|
||||||
|
case NORTH:
|
||||||
|
case SOUTH:
|
||||||
|
return Axis.Z;
|
||||||
|
case EAST:
|
||||||
|
case WEST:
|
||||||
|
default:
|
||||||
|
return Axis.X;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAxe(Material mat) {
|
||||||
|
switch (mat) {
|
||||||
|
case WOODEN_AXE:
|
||||||
|
case STONE_AXE:
|
||||||
|
case IRON_AXE:
|
||||||
|
case GOLDEN_AXE:
|
||||||
|
case DIAMOND_AXE:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void queueBlockBreak(Player p, Block b) {
|
||||||
|
if (RealisticMinecraft.hasLogBlock()) {
|
||||||
|
LogBlockProvider.queueBlockBreak(p, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void queueFallingBlock(Player p, Location l, BlockData bd) {
|
||||||
|
if (RealisticMinecraft.hasLogBlock()) {
|
||||||
|
LogBlockProvider.queueFalling(p, l, bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.event;
|
||||||
|
|
||||||
|
import de.anura.core.events.AnuraPlayerEvent;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
public class AppleDropEvent extends AnuraPlayerEvent {
|
||||||
|
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
private final short amount;
|
||||||
|
|
||||||
|
public AppleDropEvent(Player p, short amount) {
|
||||||
|
super(p, true);
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.event;
|
||||||
|
|
||||||
|
import de.anura.core.events.AnuraPlayerEvent;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
|
||||||
|
public class TreeCutEvent extends AnuraPlayerEvent implements Cancellable {
|
||||||
|
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
private final Block block;
|
||||||
|
private boolean cancel = false;
|
||||||
|
private short saplingDropChance = 25;
|
||||||
|
private short appleDropChance = 110;
|
||||||
|
private short leavesDropChance = 45;
|
||||||
|
|
||||||
|
public TreeCutEvent(Player p, Block b) {
|
||||||
|
super(p, true);
|
||||||
|
this.block = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Block getBlock() {
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getSaplingDropChance() {
|
||||||
|
return saplingDropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSaplingDropChance(short dropChance) {
|
||||||
|
this.saplingDropChance = dropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getAppleDropChance() {
|
||||||
|
return appleDropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppleDropChance(short dropChance) {
|
||||||
|
this.appleDropChance = dropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getLeavesDropChance() {
|
||||||
|
return leavesDropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLeavesDropChance(short dropChance) {
|
||||||
|
this.leavesDropChance = dropChance;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return cancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCancelled(boolean cancel) {
|
||||||
|
this.cancel = cancel;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class AcaciaTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
protected AcaciaTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.ACACIA_LOG;
|
||||||
|
leave = Material.ACACIA_LEAVES;
|
||||||
|
species = TreeSpecies.ACACIA;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(1, 1, 1), new Vector(-1, 1, -1), new Vector(-1, 1, 1), new Vector(1, 1, -1),
|
||||||
|
new Vector(0, 1, 1), new Vector(0, 1, -1), new Vector(-1, 1, 0), new Vector(1, 1, 0),
|
||||||
|
new Vector(0, 1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class BigBirchTreeParser extends BirchTreeParser {
|
||||||
|
|
||||||
|
protected BigBirchTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class BigJungleTreeParser extends JungleTreeParser {
|
||||||
|
|
||||||
|
protected BigJungleTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(1, 1, 1), new Vector(-1, 1, -1), new Vector(-1, 1, 1), new Vector(1, 1, -1),
|
||||||
|
new Vector(1, 0, 1), new Vector(-1, 0, -1), new Vector(-1, 0, 1), new Vector(1, 0, -1),
|
||||||
|
new Vector(0, 1, 1), new Vector(0, 1, -1), new Vector(-1, 1, 0), new Vector(1, 1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class BigOakTreeParser extends OakTreeParser {
|
||||||
|
|
||||||
|
protected BigOakTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class BigSpruceTreeParser extends SpruceTreeParser {
|
||||||
|
|
||||||
|
public BigSpruceTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(0, 1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
|
public class BirchTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
protected BirchTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.BIRCH_LOG;
|
||||||
|
leave = Material.BIRCH_LEAVES;
|
||||||
|
species = TreeSpecies.BIRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class DarkOakTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
protected DarkOakTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.DARK_OAK_LOG;
|
||||||
|
leave = Material.DARK_OAK_LEAVES;
|
||||||
|
species = TreeSpecies.DARK_OAK;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(1, 0, 1), new Vector(-1, 0, -1), new Vector(-1, 0, 1), new Vector(1, 0, -1),
|
||||||
|
new Vector(0, 1, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
|
public class JungleTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
protected JungleTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.JUNGLE_LOG;
|
||||||
|
leave = Material.JUNGLE_LEAVES;
|
||||||
|
species = TreeSpecies.JUNGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
|
||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
|
public class LeaveParser {
|
||||||
|
|
||||||
|
private final Block firstBlock;
|
||||||
|
private final TreeParser tp;
|
||||||
|
private final HashSet<Block> leaveList = new HashSet<>();
|
||||||
|
|
||||||
|
protected LeaveParser(TreeParser tp, Block firstBlock) {
|
||||||
|
this.tp = tp;
|
||||||
|
this.firstBlock = firstBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HashSet<Block> parse() {
|
||||||
|
tp.getDirsLeaves().stream()
|
||||||
|
.map((v) -> firstBlock.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()))
|
||||||
|
.forEach(this::parseLeaves);
|
||||||
|
return leaveList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseLeaves(Block b) {
|
||||||
|
if (leaveList.contains(b) ||
|
||||||
|
TreeParser.isDistanceBiggerThan(firstBlock.getLocation(), b.getLocation(), tp.getMaxLeavesDistance())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isLeaves(b)) {
|
||||||
|
leaveList.add(b);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tp.getDirsLeaves().stream().map((v) -> b.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()))
|
||||||
|
.filter((r) -> (r.getLocation().getBlockY() >= firstBlock.getLocation().getBlockY()))
|
||||||
|
.forEach(this::parseLeaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isLeaves(Block b) {
|
||||||
|
return b.getType().equals(tp.leave);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/de/anura/realisticminecraft/timber/parser/LogParser.java
Normal file
54
src/de/anura/realisticminecraft/timber/parser/LogParser.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
|
||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
|
public class LogParser {
|
||||||
|
|
||||||
|
private final Block firstBlock;
|
||||||
|
private final TreeParser tp;
|
||||||
|
private final HashSet<Block> logList = new HashSet<>();
|
||||||
|
|
||||||
|
protected LogParser(TreeParser tp, Block firstBlock) {
|
||||||
|
this.tp = tp;
|
||||||
|
this.firstBlock = firstBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HashSet<Block> parse() {
|
||||||
|
tp.getDirsLog().stream()
|
||||||
|
.map((v) -> firstBlock.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()))
|
||||||
|
.forEach(this::parseLog);
|
||||||
|
return logList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseLog(Block b) {
|
||||||
|
if (logList.contains(b) ||
|
||||||
|
TreeParser.isDistanceBiggerThan(firstBlock.getLocation(), b.getLocation(), tp.getMaxLogDistance())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isWood(b)) {
|
||||||
|
logList.add(b);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tp.getDirsLog().stream().map((v) -> b.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()))
|
||||||
|
.forEach(this::parseLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWood(Block b) {
|
||||||
|
try {
|
||||||
|
return b.getType().equals(tp.wood);
|
||||||
|
} catch (ConcurrentModificationException ex) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(2);
|
||||||
|
} catch (InterruptedException ex1) {
|
||||||
|
Logger.getLogger(LogParser.class.getName()).log(Level.SEVERE, null, ex1);
|
||||||
|
}
|
||||||
|
return isWood(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import java.util.Collection;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class OakTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
protected OakTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.OAK_LOG;
|
||||||
|
leave = Material.OAK_LEAVES;
|
||||||
|
species = TreeSpecies.GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Sets.newHashSet(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(1, 1, 1), new Vector(-1, 1, -1), new Vector(-1, 1, 1), new Vector(1, 1, -1),
|
||||||
|
new Vector(1, 0, 1), new Vector(-1, 0, -1), new Vector(-1, 0, 1), new Vector(1, 0, -1),
|
||||||
|
new Vector(1, 1, 0), new Vector(-1, 1, 0), new Vector(0, 1, 1), new Vector(0, 1, -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
|
||||||
|
public class SpruceTreeParser extends TreeParser {
|
||||||
|
|
||||||
|
SpruceTreeParser(Block first) {
|
||||||
|
super(first);
|
||||||
|
wood = Material.SPRUCE_LOG;
|
||||||
|
leave = Material.SPRUCE_LEAVES;
|
||||||
|
species = TreeSpecies.REDWOOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLeavesDistance() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxLogDistance() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMaxTrunkSize() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
128
src/de/anura/realisticminecraft/timber/parser/TreeParser.java
Normal file
128
src/de/anura/realisticminecraft/timber/parser/TreeParser.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package de.anura.realisticminecraft.timber.parser;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import de.anura.realisticminecraft.listener.Timber;
|
||||||
|
import de.anura.realisticminecraft.timber.Tree;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.TreeSpecies;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public abstract class TreeParser {
|
||||||
|
|
||||||
|
private final HashSet<Block> logList = new HashSet<>();
|
||||||
|
private final HashSet<Block> leaveList = new HashSet<>();
|
||||||
|
private final Block firstBlock;
|
||||||
|
protected Material wood;
|
||||||
|
protected Material leave;
|
||||||
|
protected TreeSpecies species;
|
||||||
|
|
||||||
|
protected TreeParser(Block first) {
|
||||||
|
firstBlock = first;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tree parse(BlockFace bf) {
|
||||||
|
parseTrunk(firstBlock);
|
||||||
|
if (getMaxTrunkSize() > 0) {
|
||||||
|
getDirsStamm().stream().map((v) -> firstBlock.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()))
|
||||||
|
.forEach(this::parseTrunk);
|
||||||
|
}
|
||||||
|
new HashSet<>(logList).forEach((b) -> {
|
||||||
|
logList.addAll(new LogParser(this, b).parse());
|
||||||
|
});
|
||||||
|
logList.forEach((b) -> {
|
||||||
|
leaveList.addAll(new LeaveParser(this, b).parse());
|
||||||
|
});
|
||||||
|
return new Tree(firstBlock, logList, leaveList, bf, wood, leave, species);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseTrunk(Block b) {
|
||||||
|
if (logList.size() > 1 && logList.contains(b) || TreeParser.isDistanceBiggerThan(firstBlock.getLocation(), b.getLocation(), getMaxTrunkSize())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isWood(b)) {
|
||||||
|
logList.add(b);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parseTrunk(b.getRelative(BlockFace.UP));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isWood(Block b) {
|
||||||
|
return b.getType().equals(wood);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Vector> getDirsLog() {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Vector> getDirsStamm() {
|
||||||
|
return Arrays.asList(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0),
|
||||||
|
new Vector(1, 0, 1), new Vector(-1, 0, 1), new Vector(-1, 0, -1), new Vector(1, 0, -1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Collection<Vector> getDirsLeaves() {
|
||||||
|
return Arrays.asList(new Vector(0, 1, 0), new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1),
|
||||||
|
new Vector(-1, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract int getMaxLeavesDistance();
|
||||||
|
|
||||||
|
protected abstract int getMaxLogDistance();
|
||||||
|
|
||||||
|
protected abstract int getMaxTrunkSize();
|
||||||
|
|
||||||
|
protected static boolean isDistanceBiggerThan(Location l1, Location l2, int distance) {
|
||||||
|
int loc1 = l1.getBlockX();
|
||||||
|
int loc2 = l2.getBlockX();
|
||||||
|
int loc3 = l1.getBlockZ();
|
||||||
|
int loc4 = l2.getBlockZ();
|
||||||
|
return (Math.max(loc1, loc2) - Math.min(loc1, loc2)) > distance || (Math.max(loc3, loc4) - Math.min(loc3, loc4)) > distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TreeParser newTreeParser(Block b) {
|
||||||
|
if (!Timber.isTimberLog(b.getType())) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
boolean fourLog = false;
|
||||||
|
for (Vector v : Arrays.asList(new Vector(0, 0, -1), new Vector(1, 0, 0), new Vector(0, 0, 1), new Vector(-1, 0, 0))) {
|
||||||
|
if (b.getRelative(v.getBlockX(), v.getBlockY(), v.getBlockZ()).getType().equals(b.getType())) {
|
||||||
|
fourLog = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (b.getType()) {
|
||||||
|
case DARK_OAK_LOG:
|
||||||
|
return new DarkOakTreeParser(b);
|
||||||
|
case ACACIA_LOG:
|
||||||
|
return new AcaciaTreeParser(b);
|
||||||
|
case JUNGLE_LOG:
|
||||||
|
if (fourLog) {
|
||||||
|
return new BigJungleTreeParser(b);
|
||||||
|
}
|
||||||
|
return new JungleTreeParser(b);
|
||||||
|
case SPRUCE_LOG:
|
||||||
|
if (fourLog) {
|
||||||
|
return new BigSpruceTreeParser(b);
|
||||||
|
}
|
||||||
|
return new SpruceTreeParser(b);
|
||||||
|
case BIRCH_LOG:
|
||||||
|
if (fourLog) {
|
||||||
|
return new BigBirchTreeParser(b);
|
||||||
|
}
|
||||||
|
return new BirchTreeParser(b);
|
||||||
|
case OAK_LOG:
|
||||||
|
if (fourLog) {
|
||||||
|
return new BigOakTreeParser(b);
|
||||||
|
}
|
||||||
|
return new OakTreeParser(b);
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
105
src/de/anura/realisticminecraft/util/ChairManager.java
Normal file
105
src/de/anura/realisticminecraft/util/ChairManager.java
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package de.anura.realisticminecraft.util;
|
||||||
|
|
||||||
|
import de.anura.core.util.Blocks;
|
||||||
|
import de.anura.core.util.Util;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import net.minecraft.server.v1_14_R1.EntityArmorStand;
|
||||||
|
import net.minecraft.server.v1_14_R1.PlayerConnection;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.attribute.Attribute;
|
||||||
|
import org.bukkit.attribute.AttributeInstance;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.data.type.Stairs;
|
||||||
|
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
|
||||||
|
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
|
||||||
|
import org.bukkit.entity.ArmorStand;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
|
|
||||||
|
public abstract class ChairManager {
|
||||||
|
|
||||||
|
private static final Map<Player, ArmorStand> SITTING_PLAYERS = new WeakHashMap<>();
|
||||||
|
private static final Map<Player, Block> SITTING_BLOCKS = new WeakHashMap<>();
|
||||||
|
private static Field f;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
f = PlayerConnection.class.getDeclaredField("B");
|
||||||
|
f.setAccessible(true);
|
||||||
|
} catch (NoSuchFieldException | SecurityException ex) {
|
||||||
|
Logger.getLogger(ChairManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playerSitDown(Player p, Stairs s, Block b) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
Objects.requireNonNull(s);
|
||||||
|
Objects.requireNonNull(b);
|
||||||
|
//Anti Fly-Kick
|
||||||
|
try {
|
||||||
|
f.set(((CraftPlayer) p).getHandle().playerConnection, false);
|
||||||
|
} catch (SecurityException | IllegalArgumentException | IllegalAccessException ex) {
|
||||||
|
Logger.getLogger(ChairManager.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
//ArmorStand creation
|
||||||
|
Location loc = b.getLocation().add(0.5, 0.25, 0.5);
|
||||||
|
loc.setYaw(Blocks.faceToYaw(s.getFacing()));
|
||||||
|
World w = loc.getWorld();
|
||||||
|
if (w != null) {
|
||||||
|
CraftWorld cw = (CraftWorld) w;
|
||||||
|
EntityArmorStand nms_as = new EntityArmorStand(cw.getHandle(), loc.getX(), loc.getY(), loc.getZ());
|
||||||
|
nms_as.setInvisible(true);
|
||||||
|
nms_as.setMarker(true);
|
||||||
|
ArmorStand as = (ArmorStand) cw.addEntity(nms_as, SpawnReason.CUSTOM);
|
||||||
|
as.setGravity(false);
|
||||||
|
AttributeInstance maxHealth = as.getAttribute(Attribute.GENERIC_MAX_HEALTH);
|
||||||
|
if (maxHealth != null) {
|
||||||
|
maxHealth.setBaseValue(0);
|
||||||
|
}
|
||||||
|
as.teleport(loc);
|
||||||
|
as.addPassenger(p);
|
||||||
|
SITTING_PLAYERS.put(p, as);
|
||||||
|
SITTING_BLOCKS.put(p, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playerStandUp(Player p) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
ArmorStand as = SITTING_PLAYERS.remove(p);
|
||||||
|
as.removePassenger(p);
|
||||||
|
as.remove();
|
||||||
|
SITTING_BLOCKS.remove(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void playerStandUp(Block b) {
|
||||||
|
Objects.requireNonNull(b);
|
||||||
|
playerStandUp(Util.getKeyByValue(SITTING_BLOCKS, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSittingAnyone(Block b) {
|
||||||
|
Objects.requireNonNull(b);
|
||||||
|
return SITTING_BLOCKS.containsValue(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSittingPlayer(Block b, Player p) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
Objects.requireNonNull(b);
|
||||||
|
return SITTING_BLOCKS.containsValue(b) && Util.getKeyByValue(SITTING_BLOCKS, b).equals(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isSitting(Player p) {
|
||||||
|
Objects.requireNonNull(p);
|
||||||
|
return SITTING_PLAYERS.containsKey(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void destoryAll() {
|
||||||
|
new HashSet<>(SITTING_PLAYERS.keySet()).stream().forEach(ChairManager::playerStandUp);
|
||||||
|
}
|
||||||
|
}
|
||||||
91
src/de/anura/realisticminecraft/util/LogBlockProvider.java
Normal file
91
src/de/anura/realisticminecraft/util/LogBlockProvider.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package de.anura.realisticminecraft.util;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import de.anura.core.AnuraThread;
|
||||||
|
import de.diddiz.LogBlock.Actor;
|
||||||
|
import de.diddiz.LogBlock.LogBlock;
|
||||||
|
import de.diddiz.util.BukkitUtils;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import de.anura.realisticminecraft.RealisticMinecraft;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.data.BlockData;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class LogBlockProvider {
|
||||||
|
|
||||||
|
private static final LogBlock plugin = (LogBlock) Bukkit.getServer().getPluginManager().getPlugin("LogBlock");
|
||||||
|
private static final Cache<Location, Object> cache = CacheBuilder.newBuilder()
|
||||||
|
.expireAfterWrite(15, TimeUnit.SECONDS).build();
|
||||||
|
private static final Queue<Runnable> queue = new ConcurrentLinkedQueue<>();
|
||||||
|
private static final Object value = new Object();
|
||||||
|
private static boolean queueStarted = false;
|
||||||
|
|
||||||
|
private static Actor getActor(Player p) {
|
||||||
|
return new Actor(p.getName(), p.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void queueFalling(Player p, Location l, BlockData bd) {
|
||||||
|
startQueue();
|
||||||
|
Actor a = getActor(p);
|
||||||
|
queue.add(() -> queueFallingBlock(a, l, bd));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void queueFallingBlock(Actor a, Location l, BlockData bd) {
|
||||||
|
Location loc = l;
|
||||||
|
int x = loc.getBlockX();
|
||||||
|
int y = loc.getBlockY();
|
||||||
|
int z = loc.getBlockZ();
|
||||||
|
// Blocks only fall if they have a chance to start a velocity
|
||||||
|
if (l.getBlock().getRelative(BlockFace.DOWN).getType() == Material.AIR) {
|
||||||
|
while (y > 0 && canFall(loc.getWorld(), x, (y - 1), z)) {
|
||||||
|
y--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If y is 0 then the sand block fell out of the world :(
|
||||||
|
if (y != 0) {
|
||||||
|
Location finalLoc = new Location(loc.getWorld(), x, y, z);
|
||||||
|
Block finalBlock = finalLoc.getBlock();
|
||||||
|
// Run this check to avoid false positives
|
||||||
|
if (!BukkitUtils.getFallingEntityKillers().contains(finalBlock.getType())) {
|
||||||
|
cache.put(finalLoc, value);
|
||||||
|
if (finalBlock.getType() == Material.AIR || finalLoc.equals(l)) {
|
||||||
|
plugin.getConsumer().queueBlockPlace(a, finalLoc, bd);
|
||||||
|
} else {
|
||||||
|
plugin.getConsumer().queueBlockReplace(a, finalLoc, finalBlock.getBlockData(), bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void queueBlockBreak(Player p, Block b) {
|
||||||
|
plugin.getConsumer().queueBlockBreak(getActor(p), b.getState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canFall(World w, int x, int y, int z) {
|
||||||
|
return BukkitUtils.canFallIn(w, x, (y - 1), z) && cache.getIfPresent(new Location(w, x, y, z)) == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startQueue() {
|
||||||
|
if (queueStarted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
queueStarted = true;
|
||||||
|
AnuraThread.add(Bukkit.getScheduler().runTaskTimerAsynchronously(RealisticMinecraft.getInstance(), () -> {
|
||||||
|
for (int i = 0; i < 200; i++) {
|
||||||
|
Runnable poll = queue.poll();
|
||||||
|
if (poll == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
poll.run();//TODO: Check SYNC
|
||||||
|
}
|
||||||
|
}, 10, 10));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/plugin.yml
Normal file
15
src/plugin.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# Maven Generated Properties
|
||||||
|
name: RealisticMinecraft
|
||||||
|
version: 0.1
|
||||||
|
author: hibo98
|
||||||
|
# Custom Properties
|
||||||
|
main: de.anura.realisticminecraft.RealisticMinecraft
|
||||||
|
depend: [Core]
|
||||||
|
api-version: 1.14
|
||||||
|
commands:
|
||||||
|
infobar:
|
||||||
|
description: Konfigurieret die Infobars
|
||||||
|
usage: §c/infobar <durst|temp(eratur)> <an|standard>
|
||||||
|
infobarset:
|
||||||
|
description: Setzt Werte für die Infobar
|
||||||
|
usage: §c/infobarset <durst|temp(eratur)> <value>
|
||||||
Reference in New Issue
Block a user