···144 generateConfigOption("world.settings.mob-spawner-area-limit.enable", true);
145 generateConfigOption("world.settings.mob-spawner-area-limit.limit", 150);
146 generateConfigOption("world.settings.mob-spawner-area-limit.chunk-radius", 8);
147- generateConfigOption("world.settings.mob-spawner-area-limit.info",
148- "This setting controls the maximum number of entities of a mob spawner type that can exist within the defined chunk radius around a mob spawner. If the number of entities exceeds this limit, the spawner will stop spawning additional entities of that type. This is useful to stop the extreme lag that can be caused by mob spawners.");
149150151 //generateConfigOption("world-settings.eject-from-vehicle-on-teleport.enabled", true);
···144 generateConfigOption("world.settings.mob-spawner-area-limit.enable", true);
145 generateConfigOption("world.settings.mob-spawner-area-limit.limit", 150);
146 generateConfigOption("world.settings.mob-spawner-area-limit.chunk-radius", 8);
147+ generateConfigOption("world.settings.mob-spawner-area-limit.info", "This setting controls the maximum number of entities of a mob spawner type that can exist within the defined chunk radius around a mob spawner. If the number of entities exceeds this limit, the spawner will stop spawning additional entities of that type. This is useful to stop the extreme lag that can be caused by mob spawners.");
0148149150 //generateConfigOption("world-settings.eject-from-vehicle-on-teleport.enabled", true);
···2728 /**
29 * Checks if the date in the log line is today's date
030 * @param date The date in the log line. Format: "yyyy-MM-dd"
31 * @return True if the date in the log line is today's date, false otherwise
32 */
33 private boolean isToday(String date) {
34- String[] dateParts = date.split("-");
35 LocalDateTime logLineDateTime = LocalDateTime.of(Integer.parseInt(dateParts[0]), Integer.parseInt(dateParts[1]), Integer.parseInt(dateParts[2]), 0, 0, 0);
36 LocalDateTime now = LocalDateTime.now();
37 return logLineDateTime.getYear() == now.getYear() && logLineDateTime.getMonthValue() == now.getMonthValue() && logLineDateTime.getDayOfMonth() == now.getDayOfMonth();
···3940 /**
41 * Archives a log line to a log file with the same date as the date in the log line
042 * @param parts The log line to archive to a log file haven been split already e.g. ["2024-03-20", "13:02:27", "[INFO]", "This is a log message..."]
43 */
44 private void archiveLine(String[] parts) {
···60 writer.println(date + " " + time + " " + logLevel + " " + message);
61 writer.close();
6263- // catch any exceptions that occur during the process, and log them. IOExceptions are possible when calling createNewFile()
64 } catch (IOException e) {
65 logger.log(Level.SEVERE, "[Poseidon] Failed to create new log file!");
66 logger.log(Level.SEVERE, e.toString());
···120121 logger.log(Level.INFO, "[Poseidon] Logs built from latest.log!");
122123- // catch any exceptions that occur during the process, and log them
124 } catch (Exception e) {
125 logger.log(Level.SEVERE, "[Poseidon] Failed to build logs from latest.log!");
126 logger.log(Level.SEVERE, e.toString());
···131 // Calculate the initial delay and period for the log rotation task
132 ZonedDateTime now = ZonedDateTime.now();
133 ZonedDateTime nextRun = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
134- if(now.compareTo(nextRun) > 0)
135- nextRun = nextRun.plusDays(1);
136 Duration duration = Duration.between(now, nextRun);
137 long initialDelay = duration.getSeconds();
138 long period = TimeUnit.DAYS.toSeconds(1);
···142143 // Schedule the log rotation task to run every day at midnight offset by one second to avoid missing logs
144 logger.log(Level.INFO, "[Poseidon] Log rotation task scheduled for run in " + initialDelay + " seconds, and then every " + period + " seconds.");
145- logger.log(Level.INFO, "[Poseidon] If latest.log contains logs from earlier, not previously archived dates, they will be archived to the appropriate log files " +
146- "upon first run of the log rotation task. If log files already exist for these dates, the logs will be appended to the existing log files!");
147 Bukkit.getScheduler().scheduleAsyncRepeatingTask(new PoseidonPlugin(), this::buildHistoricalLogsFromLatestLogFile, (initialDelay + 1) * 20, period * 20);
148 }
149}
···2728 /**
29 * Checks if the date in the log line is today's date
30+ *
31 * @param date The date in the log line. Format: "yyyy-MM-dd"
32 * @return True if the date in the log line is today's date, false otherwise
33 */
34 private boolean isToday(String date) {
35+ String[] dateParts = date.split("-");
36 LocalDateTime logLineDateTime = LocalDateTime.of(Integer.parseInt(dateParts[0]), Integer.parseInt(dateParts[1]), Integer.parseInt(dateParts[2]), 0, 0, 0);
37 LocalDateTime now = LocalDateTime.now();
38 return logLineDateTime.getYear() == now.getYear() && logLineDateTime.getMonthValue() == now.getMonthValue() && logLineDateTime.getDayOfMonth() == now.getDayOfMonth();
···4041 /**
42 * Archives a log line to a log file with the same date as the date in the log line
43+ *
44 * @param parts The log line to archive to a log file haven been split already e.g. ["2024-03-20", "13:02:27", "[INFO]", "This is a log message..."]
45 */
46 private void archiveLine(String[] parts) {
···62 writer.println(date + " " + time + " " + logLevel + " " + message);
63 writer.close();
6465+ // catch any exceptions that occur during the process, and log them. IOExceptions are possible when calling createNewFile()
66 } catch (IOException e) {
67 logger.log(Level.SEVERE, "[Poseidon] Failed to create new log file!");
68 logger.log(Level.SEVERE, e.toString());
···122123 logger.log(Level.INFO, "[Poseidon] Logs built from latest.log!");
124125+ // catch any exceptions that occur during the process, and log them
126 } catch (Exception e) {
127 logger.log(Level.SEVERE, "[Poseidon] Failed to build logs from latest.log!");
128 logger.log(Level.SEVERE, e.toString());
···133 // Calculate the initial delay and period for the log rotation task
134 ZonedDateTime now = ZonedDateTime.now();
135 ZonedDateTime nextRun = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
136+ if (now.compareTo(nextRun) > 0) nextRun = nextRun.plusDays(1);
0137 Duration duration = Duration.between(now, nextRun);
138 long initialDelay = duration.getSeconds();
139 long period = TimeUnit.DAYS.toSeconds(1);
···143144 // Schedule the log rotation task to run every day at midnight offset by one second to avoid missing logs
145 logger.log(Level.INFO, "[Poseidon] Log rotation task scheduled for run in " + initialDelay + " seconds, and then every " + period + " seconds.");
146+ logger.log(Level.INFO, "[Poseidon] If latest.log contains logs from earlier, not previously archived dates, they will be archived to the appropriate log files " + "upon first run of the log rotation task. If log files already exist for these dates, the logs will be appended to the existing log files!");
0147 Bukkit.getScheduler().scheduleAsyncRepeatingTask(new PoseidonPlugin(), this::buildHistoricalLogsFromLatestLogFile, (initialDelay + 1) * 20, period * 20);
148 }
149}
···46 loginProcessHandler.userUUIDReceived(uuidResult.getUuid(), true);
47 return;
48 } else if (uuidResult.getReturnType().equals(UUIDResult.ReturnType.ONLINE)) {
49- if(PoseidonConfig.getInstance().getConfigBoolean("settings.uuid-fetcher.get.enforce-case-sensitivity.enabled")) {
50 System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " using GET - " + uuidResult.getUuid().toString() + " however, the username returned was " + uuidAndUsernameResult.getReturnedUsername() + ". The user has been kicked as the server is configured to use case sensitive usernames");
51 loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, that username has invalid casing");
52 return;
···46 loginProcessHandler.userUUIDReceived(uuidResult.getUuid(), true);
47 return;
48 } else if (uuidResult.getReturnType().equals(UUIDResult.ReturnType.ONLINE)) {
49+ if (PoseidonConfig.getInstance().getConfigBoolean("settings.uuid-fetcher.get.enforce-case-sensitivity.enabled")) {
50 System.out.println("[Poseidon] Fetched UUID from Mojang for " + loginPacket.name + " using GET - " + uuidResult.getUuid().toString() + " however, the username returned was " + uuidAndUsernameResult.getReturnedUsername() + ". The user has been kicked as the server is configured to use case sensitive usernames");
51 loginProcessHandler.cancelLoginProcess(ChatColor.RED + "Sorry, that username has invalid casing");
52 return;
+5-5
src/main/java/net/minecraft/server/Block.java
···313 if (world.random.nextFloat() < f) {
314 //Project Poseidon Start - New way to handle block drops to allow for plugins to know what items a block will drop
315 Optional<List<ItemStack>> items = getDrops(world, i, j, k, l);
316- if(items.isPresent()) {
317- for(ItemStack item : items.get()) {
318 this.a(world, i, j, k, item);
319 }
320 }
···325 }
326327 //Project Poseidon - API to get the drops of a block
328- public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data){
329 int id = this.a(data, world.random);
330- if(id <= 0){
331 return Optional.empty();
332- }else{
333 return Optional.of(Arrays.asList(new ItemStack(id, 1, this.a_(data))));
334 }
335 }
···313 if (world.random.nextFloat() < f) {
314 //Project Poseidon Start - New way to handle block drops to allow for plugins to know what items a block will drop
315 Optional<List<ItemStack>> items = getDrops(world, i, j, k, l);
316+ if (items.isPresent()) {
317+ for (ItemStack item : items.get()) {
318 this.a(world, i, j, k, item);
319 }
320 }
···325 }
326327 //Project Poseidon - API to get the drops of a block
328+ public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data) {
329 int id = this.a(data, world.random);
330+ if (id <= 0) {
331 return Optional.empty();
332+ } else {
333 return Optional.of(Arrays.asList(new ItemStack(id, 1, this.a_(data))));
334 }
335 }
+2-2
src/main/java/net/minecraft/server/BlockBed.java
···195 return null;
196 }
197198- public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data){
199- if(!d(data)){
200 return super.getDrops(world, x, y, z, data);
201 }
202 return Optional.empty();
···195 return null;
196 }
197198+ public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data) {
199+ if (!d(data)) {
200 return super.getDrops(world, x, y, z, data);
201 }
202 return Optional.empty();
···89 return this.textureId + j;
90 }
9192- public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data){
93 Optional<List<ItemStack>> ret = super.getDrops(world, x, y, z, data);
94 List<ItemStack> stacks = ret.orElse(new ArrayList<>(3));
95- for(int i = 0; i < 3; i++){
96- if(world.random.nextInt(15) <= 1){
97 stacks.add(new ItemStack(Item.SEEDS));
98 }
99 }
···89 return this.textureId + j;
90 }
9192+ public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data) {
93 Optional<List<ItemStack>> ret = super.getDrops(world, x, y, z, data);
94 List<ItemStack> stacks = ret.orElse(new ArrayList<>(3));
95+ for (int i = 0; i < 3; i++) {
96+ if (world.random.nextInt(15) <= 1) {
97 stacks.add(new ItemStack(Item.SEEDS));
98 }
99 }
···123 this.a.remove(world, i, j, k);
124 }
125126- public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data){
127 return this.a.getDrops(world, x, y, z, data);
128 }
129
···123 this.a.remove(world, i, j, k);
124 }
125126+ public Optional<List<ItemStack>> getDrops(World world, int x, int y, int z, int data) {
127 return this.a.getDrops(world, x, y, z, data);
128 }
129
···78 }
7980 //Poseidon Start - Ensure the mob cound of the specific type of mob is under the defined limit within the area
81- if(poseidonAreaLimit) {
82 double chunkSize = 16.0D;
83 AxisAlignedBB searchArea = AxisAlignedBB.b(this.x - poseidonChunkRadius * chunkSize, 0.0D, this.z - poseidonChunkRadius * chunkSize, this.x + poseidonChunkRadius * chunkSize, 128, this.z + poseidonChunkRadius * chunkSize);
84 List<Entity> existingEntities = this.world.a(entityliving.getClass(), searchArea);
···78 }
7980 //Poseidon Start - Ensure the mob cound of the specific type of mob is under the defined limit within the area
81+ if (poseidonAreaLimit) {
82 double chunkSize = 16.0D;
83 AxisAlignedBB searchArea = AxisAlignedBB.b(this.x - poseidonChunkRadius * chunkSize, 0.0D, this.z - poseidonChunkRadius * chunkSize, this.x + poseidonChunkRadius * chunkSize, 128, this.z + poseidonChunkRadius * chunkSize);
84 List<Entity> existingEntities = this.world.a(entityliving.getClass(), searchArea);
+1-1
src/main/java/org/bukkit/ChatColor.java
···127 /**
128 * Translates alternate color codes in the given text to Minecraft color codes.
129 *
130- * @param altColorChar The character used to denote color codes '&'.
131 * @param textToTranslate The text containing the alternate color codes.
132 * @return The text with the alternate color codes replaced by Minecraft color codes.
133 */
···127 /**
128 * Translates alternate color codes in the given text to Minecraft color codes.
129 *
130+ * @param altColorChar The character used to denote color codes '&'.
131 * @param textToTranslate The text containing the alternate color codes.
132 * @return The text with the alternate color codes replaced by Minecraft color codes.
133 */
+4
src/main/java/org/bukkit/block/Block.java
···285286 /**
287 * Returns a list of items which would drop by destroying this block
0288 * @return a list of dropped items for this type of block
289 */
290 Collection<ItemStack> getDrops();
291292 /**
293 * Returns a list of items which would drop by destroying this block with a specific tool
0294 * @param tool The tool or item in hand used for digging
295 * @return a list of dropped items for this type of block
296 */
···298299 /**
300 * Breaks the block and spawns items as if a player had digged it regardless of the tool
0301 * @return true if the block was broken
302 */
303 boolean breakNaturally();
304305 /**
306 * Breaks the block and spawns items as if a player had digged it
0307 * @param tool The tool or item in hand used for digging
308 * @return true if the block was broken
309 */
···285286 /**
287 * Returns a list of items which would drop by destroying this block
288+ *
289 * @return a list of dropped items for this type of block
290 */
291 Collection<ItemStack> getDrops();
292293 /**
294 * Returns a list of items which would drop by destroying this block with a specific tool
295+ *
296 * @param tool The tool or item in hand used for digging
297 * @return a list of dropped items for this type of block
298 */
···300301 /**
302 * Breaks the block and spawns items as if a player had digged it regardless of the tool
303+ *
304 * @return true if the block was broken
305 */
306 boolean breakNaturally();
307308 /**
309 * Breaks the block and spawns items as if a player had digged it
310+ *
311 * @param tool The tool or item in hand used for digging
312 * @return true if the block was broken
313 */
···50 register("uberbukkit", new FlushInvCommand());
51 register("uberbukkit", new UuidLookupCommand());
52 register("uberbukkit", new CrackedAllowlistCommand());
53-54 register("bukkit", new VersionCommand("version"));
55 register("bukkit", new ReloadCommand("reload"));
56 register("bukkit", new PluginsCommand("plugins"));
···50 register("uberbukkit", new FlushInvCommand());
51 register("uberbukkit", new UuidLookupCommand());
52 register("uberbukkit", new CrackedAllowlistCommand());
53+54 register("bukkit", new VersionCommand("version"));
55 register("bukkit", new ReloadCommand("reload"));
56 register("bukkit", new PluginsCommand("plugins"));