Initial commit

This commit is contained in:
hibo98
2019-08-11 16:06:09 +02:00
commit 8712e4ee3c
46 changed files with 4770 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
dist/
build/
nbproject/private

73
build.xml Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

View 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
View 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>

View 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;
}
}

View 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());
}
}

View 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());
}
}

View 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));
}
}

View 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;
}
}

View File

@@ -0,0 +1,6 @@
package de.anura.realisticminecraft.infobar;
public enum BarStatus {
STANDARD,
AN;
}

View 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);
}
}
}

View 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));
}
}

View 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();
}

View 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();
}
}

View 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;
}
}
}

View File

@@ -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";
}
}

View 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();
}
}

View 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;
}
}
}

View 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());
});
}
}
}

View 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;
}
}
}

View 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;
}
}
}
}

View 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()));
}
}

View 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;
}
}
}

View 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;
}
}

View 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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View 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);
}
}
}

View File

@@ -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));
}
}

View File

@@ -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;
}
}

View 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;
}
}
}

View 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);
}
}

View 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
View 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>