Skip to content

Commit

Permalink
Move data to HappyDayData, suspend checks when nobody is on (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
AliceDTRH authored Apr 30, 2022
1 parent e2d3eb2 commit 0bbf54b
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 102 deletions.
75 changes: 75 additions & 0 deletions src/main/java/xyz/alicedtrh/happyday/DebugLogHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright 2019 dumptruckman
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of
* the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package xyz.alicedtrh.happyday;

import org.bukkit.plugin.Plugin;

import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;

/**
* A logger handler for a bukkit plugin that will cause messages below
* {@link Level#INFO} to be logged normally when the plugin's logger is set to
* the level of the message or lower.
* <p/>
* To enable logging of messages below {@link Level#INFO}, the plugin's logger
* must be set to an appropriately lower level. For example, to log all message
* levels: <code>plugin.getLogger().setLevel(Level.ALL);</code>
*/
public class DebugLogHandler extends Handler {

private static final String DEFAULT_DEBUG_PREFIX_FORMAT = "[%1$s-%2$s] %3$s";
private static final String DEFAULT_DEBUG_LOG_PREFIX = "DEBUG";

/**
* Attaches a DebugLogHandler to the given plugin's logger.
*
* @param plugin the plugin to add debug logging for.
*/
public static void attachDebugLogger(Plugin plugin) {
plugin.getLogger().addHandler(new DebugLogHandler(plugin));
}

private final Plugin plugin;
private final String pluginName;

private DebugLogHandler(Plugin plugin) {
this.plugin = plugin;
String prefix = plugin.getDescription().getPrefix();
this.pluginName = prefix != null ? prefix : plugin.getDescription().getName();
}

@Override
public void publish(LogRecord record) {
if (plugin.getLogger().getLevel().intValue() <= record.getLevel().intValue()
&& record.getLevel().intValue() < Level.INFO.intValue()) {
record.setLevel(Level.INFO);
record.setMessage(String.format(DEFAULT_DEBUG_PREFIX_FORMAT, pluginName, DEFAULT_DEBUG_LOG_PREFIX,
record.getMessage()));
}
}

@Override
public void flush() {
}

@Override
public void close() throws SecurityException {
}
}
124 changes: 46 additions & 78 deletions src/main/java/xyz/alicedtrh/happyday/HappyDay.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package xyz.alicedtrh.happyday;

import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.logging.Level;

import org.bukkit.Bukkit;
Expand All @@ -11,124 +14,89 @@
import org.bukkit.scheduler.BukkitScheduler;

public class HappyDay extends JavaPlugin {
static final Long delay = 1200L; // 20 ticks (20tps) * 60 seconds = 1 minute
private static Boolean _hasBeenNightTime = false;
private Integer removedMobs = 0;
private UpgradeableSpawnersDependency UpgradeableSpawners;

/**
* @return the amount of removedMobs
*/
public Integer getRemovedMobs() {
return removedMobs;
}

public void increaseRemovedMobs() {
this.removedMobs++;
}

public void resetRemovedMobs() {
this.removedMobs = 0;
}

/**
* @return the hasBeenNightTime
*/
static Boolean getHasBeenNightTime() {
HappyDay.getPlugin(HappyDay.class).getLogger().finer("hasBeenNightTime get: " + _hasBeenNightTime.toString());
return _hasBeenNightTime;
}

/**
* @param hasBeenNightTime the hasBeenNightTime to set
*/
static void setHasBeenNightTime(Boolean hasBeenNightTime) {
HappyDay.getPlugin(HappyDay.class).getLogger().finer("hasBeenNightTime set: " + hasBeenNightTime.toString());
HappyDay._hasBeenNightTime = hasBeenNightTime;
}
private static final Set<SpawnReason> VALID_SPAWN_REASONS = Collections.unmodifiableSet(EnumSet.of(SpawnReason.NATURAL, SpawnReason.DEFAULT));
private HappyDayData data = HappyDayData.getInstance();

@Override
public void onEnable() {
BukkitScheduler scheduler = Bukkit.getServer().getScheduler();
scheduler.runTaskTimer(this, () -> runCheckTask(), delay, delay);

UpgradeableSpawners = new UpgradeableSpawnersDependency();

if(getConfig().getBoolean("debug") == true) {
scheduler.runTaskTimer(this, this::runCheckTask, HappyDayData.DELAY, HappyDayData.DELAY);
/* TODO: Improve task timers.
We don't want to run more than one CheckTask at once and we don't need to run it this often. */

data.setUpgradeableSpawners(new UpgradeableSpawnersDependency());

if (getConfig().getBoolean("debug")) {
xyz.alicedtrh.happyday.DebugLogHandler.attachDebugLogger(this);
getLogger().setLevel(Level.FINEST);
}

getServer().getPluginManager().registerEvents(new TimeSkipEventListener(), this);
if (data.getWorld() == null) {
getLogger().severe(
"Could not find world \"" + data.getWorldName() + "\", cannot continue without valid world.");
Bukkit.getPluginManager().disablePlugin(this);
}

getServer().getPluginManager().registerEvents(new HappyDayEventListener(), this);

saveDefaultConfig();
}

/**
* @param scheduler
* @throws IllegalArgumentException
*/
public void runCheckTask() {
String worldName = getConfig().getString("world", "world");
World world = Bukkit.getServer().getWorld(worldName); // add try catch
getLogger().finer("CheckTask running");
if (!world.isDayTime()) {
HappyDay.setHasBeenNightTime(true);
if (data.isSuspended()) {
// TODO: Disable the timer entirely instead of just skipping over checks.
getLogger().finer("Plugin is suspended.");
return;
}
if (world.isDayTime() && getHasBeenNightTime()) {
HappyDay.setHasBeenNightTime(false);

getLogger().finer("CheckTask running");
if (data.getWorld().isDayTime()) {
this.getServer().getScheduler().runTaskLater(this, () -> {
if (world.isDayTime()) {
removeMonsters(worldName);
if (data.getWorld().isDayTime()) {
removeMonsters(data.getWorld());
} else {
getLogger().info("Skipping mob removal because it's not day anymore.");
}
}, delay / 4);
}, HappyDayData.DELAY / 4);
}
}

private void removeMonsters(String worldName) {
getLogger().info("Removing monsters.");
World world = this.getServer().getWorld(worldName); // add try catch
private void removeMonsters(World world) {
getLogger().finer("Removing monsters.");
world.getEntitiesByClasses(Stray.class, Zombie.class, Spider.class, Skeleton.class, Creeper.class,
Drowned.class, CaveSpider.class, Husk.class, Phantom.class, Enderman.class, Witch.class, Slime.class)
.forEach(entity -> {
if (shouldRemoveMonster((LivingEntity) entity)) {
if (entity.isValid()) {
this.increaseRemovedMobs();
data.increaseRemovedMobs();
entity.remove();
}
}
});
getLogger().info("Removed "+this.getRemovedMobs()+" monsters.");
this.resetRemovedMobs();
getLogger().info("Removed " + data.getRemovedMobs() + " monsters.");
data.resetRemovedMobs();
}

/**
* @param monster
* @param monster The monster to check
* @return boolean Whether the monster should be removed.
*/
private boolean shouldRemoveMonster(Entity monster) {
// UpgradeAbleSpawners compatibility
if(UpgradeableSpawners.isSpawnedBySpawner(monster)) {
return false;
}

// Is the monster spawned in an unnatural way? (Mob spawner, etc.)
if (monster.fromMobSpawner() || (monster.getEntitySpawnReason() != SpawnReason.NATURAL
&& monster.getEntitySpawnReason() != SpawnReason.DEFAULT)) {
return false;
}
// Was the monster spawned from a UpgradeAbleSpawners spawner? (Requires UpgradeAbleSpawners)
if (data.getUpgradeableSpawners().isSpawnedBySpawner(monster)) return false;

// Was the monster spawned from a mob spawner?
if (monster.fromMobSpawner()) return false;

// Is the monster spawned in an unnatural way?
if (!VALID_SPAWN_REASONS.contains(monster.getEntitySpawnReason())) return false;

// Does it have a custom name?
if (monster.customName() != null) {
return false;
}
if (monster.customName() != null) return false;

// Is it currently inside a cave?
if (monster.getLocation().getBlock().getType() == Material.CAVE_AIR) {
return false;
}

return true;
return monster.getLocation().getBlock().getType() != Material.CAVE_AIR;
}
}
81 changes: 81 additions & 0 deletions src/main/java/xyz/alicedtrh/happyday/HappyDayData.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package xyz.alicedtrh.happyday;

import org.bukkit.Bukkit;
import org.bukkit.World;

public class HappyDayData {
private static volatile HappyDayData instance;
private Integer removedMobs = 0;
private UpgradeableSpawnersDependency UpgradeableSpawners;
private World world;
private String _worldName;
static final Long DELAY = 1200L; // 20 ticks (20tps) * 60 seconds = 1 minute
private boolean suspended = false;

private HappyDayData() {
}

public Integer getRemovedMobs() {
return this.removedMobs;
}

public void increaseRemovedMobs() {
this.removedMobs = this.removedMobs + 1;
}

public void resetRemovedMobs() {
this.removedMobs = 0;
}

public UpgradeableSpawnersDependency getUpgradeableSpawners() {
return UpgradeableSpawners;
}

public void setUpgradeableSpawners(UpgradeableSpawnersDependency upgradeableSpawners) {
UpgradeableSpawners = upgradeableSpawners;
}

public World getWorld() {
if (this.world == null) {
this.world = Bukkit.getServer().getWorld(getWorldName());
}
return world;
}

public String getWorldName() {
if(_worldName == null) {
_worldName = HappyDay.getPlugin(HappyDay.class).getConfig().getString("world", "world");
}
return _worldName;
}

public static HappyDayData getInstance() {
// By using a local variable we can prevent unneeded lookups, improving
// performance up to 40%.
// https://youtu.be/tSZn4wkBIu8?t=459 for more information.
HappyDayData _instance = instance;
if (_instance == null) {
synchronized (HappyDayData.class) {
// _instance is not always true. Do not remove.
if (_instance == null) {
instance = _instance = new HappyDayData();
}
}
}
return _instance;
}

/**
* @return the suspended state
*/
public boolean isSuspended() {
return suspended;
}

/**
* @param suspended suspend the plugin
*/
public void setSuspended(boolean suspended) {
this.suspended = suspended;
}
}
35 changes: 35 additions & 0 deletions src/main/java/xyz/alicedtrh/happyday/HappyDayEventListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package xyz.alicedtrh.happyday;

import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.world.TimeSkipEvent;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;

public final class HappyDayEventListener implements Listener {

@EventHandler(priority = EventPriority.MONITOR)
public void onTimeSkipEvent(TimeSkipEvent event) {
HappyDay happyday = HappyDay.getPlugin(HappyDay.class);
happyday.getLogger().finer("Running checktask");
happyday.runCheckTask();
happyday.getLogger().finer("Running checktask*");
}

@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuitEvent(PlayerQuitEvent event) {
if (Bukkit.getOnlinePlayers().size() < 1) {
HappyDayData.getInstance().setSuspended(true);
}
}

@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoinEvent(PlayerJoinEvent event) {
if (HappyDayData.getInstance().isSuspended()) {
return;
}
HappyDayData.getInstance().setSuspended(false);
}
}
17 changes: 0 additions & 17 deletions src/main/java/xyz/alicedtrh/happyday/TimeSkipEventListener.java

This file was deleted.

Loading

0 comments on commit 0bbf54b

Please sign in to comment.