Skip to content

Commit

Permalink
Config and bug fixes
Browse files Browse the repository at this point in the history
- Added default config
- Raised default analyze speed 
- Raised default section size
- Fixed resets instantly resetting arenas when using slower speeds on larger arenas (math rounding error)
- Arenas now reset each section relative to how many blocks that sections has. So no section will complete way faster than others
- For extremely slow speeds, sections are now reshuffled to make priority for ones that did not get to reset at all for the next tick
- equals() and hashCode() are now overriden in Arena and Section to be more accurate
  • Loading branch information
StrangeOne101 committed Aug 10, 2020
1 parent 44a6cdb commit b92833d
Show file tree
Hide file tree
Showing 13 changed files with 293 additions and 38 deletions.
106 changes: 82 additions & 24 deletions src/com/strangeone101/platinumarenas/Arena.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.strangeone101.platinumarenas;

import com.google.common.collect.Lists;
import io.netty.util.internal.MathUtil;
import org.apache.commons.lang.ArrayUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location;
Expand All @@ -13,15 +11,7 @@

import java.io.File;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;

public class Arena {

Expand Down Expand Up @@ -146,20 +136,24 @@ public void reset(int resetSpeed, Runnable... callback) {

this.beingReset = true;

List<Section> sectionsClone = Lists.newArrayList(getSections());

int perTickEachSection = resetSpeed / getSections().size();
ResetLoopinData data = new ResetLoopinData();
data.sectionList = new ArrayList<>(getSections()); //Clone
data.maxBlocksThisTick = resetSpeed;
data.speed = resetSpeed;
for (Section s : getSections()) {
int sectionAmount = (int)((double)resetSpeed / (double)getTotalBlocks() * (double)s.getTotalBlocks());
if (sectionAmount <= 0) sectionAmount = 1; //Do AT LEAST one block per tick in each section
data.sections.put(s, sectionAmount); //Store the amount of blocks each section should reset per tick
}

loopyReset(sectionsClone, perTickEachSection, callback);
loopyReset(data, callback);
}

/**
* Reset with recursion until complete, with each layer adding delay to the last
* @param sections The sections to reset
* @param amount The amount of blocks each section should reset
* @param data The reset data, including sections and the amounts they reset, etc
*/
private void loopyReset(List<Section> sections, int amount, Runnable... callbacks) {
List<Section> nextTime = new ArrayList<>();
private void loopyReset(ResetLoopinData data, Runnable... callbacks) {
if (cancelReset) {
beingReset = false;
cancelReset = false;
Expand All @@ -169,13 +163,42 @@ private void loopyReset(List<Section> sections, int amount, Runnable... callback
}
return;
}
for (Section s : sections) {
if (!s.reset(amount)) {
nextTime.add(s);
data.blocksThisTick = 0;
List<Section> iteratingList = new ArrayList<>(data.sectionList); //So we don't remove while we are going through it
for (int i = 0; i < iteratingList.size(); i++) {
Section s = iteratingList.get(i);
if (s.reset(data.sections.get(s))) {
data.sections.remove(s);
data.sectionList.remove(s);

if (data.sections.size() == 0) break;

int newTotalAmount = data.sectionList.stream().mapToInt((section) -> section.getTotalBlocks()).sum();

//Recalculate how many blocks to do each tick
for (Section s1 : data.sectionList) {
int sectionAmount = (int) ((double)data.speed / (double)newTotalAmount * (double)s.getTotalBlocks());
if (sectionAmount <= 0) sectionAmount = 1; //Do AT LEAST one block per tick in each section
data.sections.put(s1, sectionAmount); //Store the amount of blocks each section should reset per tick
}
}
data.blocksThisTick += s.getBlocksResetThisTick();


//If we have gone over the max, reshuffle the section order to make sections
//that we didn't get to yet come first next time
if (data.blocksThisTick > data.maxBlocksThisTick) {
List<Section> oldSections = new ArrayList<>(data.sectionList); //Clone it again
data.sectionList.clear();

//Put the next section in the i loop first, continue through the rest, then loop back to the start for the ones already done
for (int j = i + 1; j < oldSections.size() + i + 1; j++) {
data.sectionList.add(oldSections.get(j >= oldSections.size() ? j - oldSections.size() : j));
}
}
}

if (nextTime.size() == 0) {
if (data.sections.size() == 0) {
for (Runnable r : callbacks) r.run();
beingReset = false;
return;
Expand All @@ -184,7 +207,7 @@ private void loopyReset(List<Section> sections, int amount, Runnable... callback
new BukkitRunnable() {
@Override
public void run() {
loopyReset(nextTime, amount, callbacks);
loopyReset(data, callbacks);
}
}.runTaskLater(PlatinumArenas.INSTANCE, 1L);
}
Expand Down Expand Up @@ -353,6 +376,14 @@ private static class CreationLoopinData {
short[] blockAmounts, blockTypes = new short[0];
}

private static class ResetLoopinData {
Map<Section, Integer> sections = new HashMap<>();
List<Section> sectionList = new ArrayList<>();
int blocksThisTick = 0;
int maxBlocksThisTick;
int speed;
}

/**
* Create an arena with recursion and delays to stop serious lag.
* @param data The data of the arena being built
Expand Down Expand Up @@ -520,6 +551,13 @@ public int getLength() {
return corner2.getBlockZ() - corner1.getBlockZ() + 1;
}

/**
* @return The total number of blocks in the arena
*/
public int getTotalBlocks() {
return getWidth() * getHeight() * getLength();
}

/**
* Returns a relative location object for where the provided index is in the arena. Quick math!
* @param width Width
Expand All @@ -540,4 +578,24 @@ public static Location getLocationAtIndex(int width, int height, int length, Wor
public List<Section> getSections() {
return sections;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Arena arena = (Arena) o;
return name.equals(arena.name) &&
Objects.equals(creator, arena.creator) &&
Arrays.equals(keys, arena.keys) &&
corner1.equals(arena.corner1) &&
corner2.equals(arena.corner2) &&
properties.equals(arena.properties);
}

@Override
public int hashCode() {
int result = Objects.hash(name, creator, corner1, corner2, properties);
result = 31 * result + Arrays.hashCode(keys);
return result;
}
}
1 change: 1 addition & 0 deletions src/com/strangeone101/platinumarenas/ArenaIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ public static Collection<Arena> loadAllArenas() {
long took = System.currentTimeMillis() - time;

PlatinumArenas.INSTANCE.getLogger().info("Loaded " + Arena.arenas.size() + " arenas in " + took + "ms!");
PlatinumArenas.INSTANCE.ready = true;

return Arena.arenas.values();
}
Expand Down
60 changes: 50 additions & 10 deletions src/com/strangeone101/platinumarenas/ConfigManager.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,64 @@
package com.strangeone101.platinumarenas;

import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;
import java.io.IOException;

public class ConfigManager {

/**
* How many blocks to analyze/count before waiting a bit before continuing.
*/
public static final int BLOCKS_ANALYZED_PER_SECOND = 40_000;
public static int BLOCKS_ANALYZED_PER_SECOND = 49_600;

/**
* How many blocks can be per section in arenas. Max is 2,147,483,647
*/
public static final int BLOCKS_PER_SECTION = 10000; //2_097_152;
public static int BLOCKS_PER_SECTION = 28_800;

public static int BLOCKS_RESET_PER_SECOND_VERYSLOW = 10 * 20;
public static int BLOCKS_RESET_PER_SECOND_SLOW = 50 * 20;
public static int BLOCKS_RESET_PER_SECOND_NORMAL = 500 * 20;
public static int BLOCKS_RESET_PER_SECOND_FAST = 2000 * 20;
public static int BLOCKS_RESET_PER_SECOND_VERYFAST = 5000 * 20;
public static int BLOCKS_RESET_PER_SECOND_EXTREME = 10000 * 20;

private static YamlConfiguration config;

public static boolean setup() {
File file = new File(PlatinumArenas.INSTANCE.getDataFolder(), "config.yml");
if (!file.exists()) {
if (!Util.saveResource("config.yml", file)) {
PlatinumArenas.INSTANCE.getLogger().severe("Failed to copy default config!");
return false;
}
}
config = new YamlConfiguration();
try {
config.load(file);

BLOCKS_ANALYZED_PER_SECOND = config.getInt("AnalyzeBlockSpeed", BLOCKS_ANALYZED_PER_SECOND);

BLOCKS_PER_SECTION = config.getInt("MaxSectionSize", BLOCKS_PER_SECTION);

@Deprecated
public static final int BLOCKS_RESET_PER_SECOND = 20_000;
BLOCKS_RESET_PER_SECOND_VERYSLOW = config.getInt("Speeds.VerySlow", BLOCKS_RESET_PER_SECOND_VERYSLOW);
BLOCKS_RESET_PER_SECOND_SLOW = config.getInt("Speeds.Slow", BLOCKS_RESET_PER_SECOND_SLOW);
BLOCKS_RESET_PER_SECOND_NORMAL = config.getInt("Speeds.Normal", BLOCKS_RESET_PER_SECOND_NORMAL);
BLOCKS_RESET_PER_SECOND_FAST = config.getInt("Speeds.Fast", BLOCKS_RESET_PER_SECOND_FAST);
BLOCKS_RESET_PER_SECOND_VERYFAST = config.getInt("Speeds.VeryFast", BLOCKS_RESET_PER_SECOND_VERYFAST);
BLOCKS_RESET_PER_SECOND_EXTREME = config.getInt("Speeds.Extreme", BLOCKS_RESET_PER_SECOND_EXTREME);

public static final int BLOCKS_RESET_PER_SECOND_VERYSLOW = 10 * 20;
public static final int BLOCKS_RESET_PER_SECOND_SLOW = 50 * 20;
public static final int BLOCKS_RESET_PER_SECOND_NORMAL = 500 * 20;
public static final int BLOCKS_RESET_PER_SECOND_FAST = 2000 * 20;
public static final int BLOCKS_RESET_PER_SECOND_VERYFAST = 5000 * 20;
public static final int BLOCKS_RESET_PER_SECOND_EXTREME = 10000 * 20;
return true;
} catch (IOException e) {
PlatinumArenas.INSTANCE.getLogger().severe("Failed to load config.yml!");
e.printStackTrace();
return false;
} catch (InvalidConfigurationException e) {
PlatinumArenas.INSTANCE.getLogger().severe("Invalid YML format used in config.yml!");
e.printStackTrace();
return false;
}
}
}
16 changes: 14 additions & 2 deletions src/com/strangeone101/platinumarenas/PlatinumArenas.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class PlatinumArenas extends JavaPlugin {

private IRegionSelection regionSelection;

protected boolean ready;

@Override
public void onEnable() {
INSTANCE = this;
Expand All @@ -40,13 +42,15 @@ public void onEnable() {
folder.mkdirs();
}

if (!ConfigManager.setup()) {
getLogger().warning("Internal defaults will be used due to config not being loaded!");
}

if (Bukkit.getPluginManager().getPlugin("WorldEdit") != null) {
regionSelection = new WorldEditRegionSelection();
} else {
regionSelection = new DefaultRegionSelection();
}


}

/**
Expand All @@ -69,4 +73,12 @@ public void run() {
public IRegionSelection getRegionSelection() {
return regionSelection;
}

/**
* Whether the plugin is ready to use arenas.
* @return True when all arenas have been loaded
*/
public boolean isReady() {
return ready;
}
}
35 changes: 35 additions & 0 deletions src/com/strangeone101/platinumarenas/Section.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;

import java.util.Objects;

public class Section {

private Arena parent; //The arena housing this section
Expand All @@ -28,10 +30,14 @@ public class Section {
*/
private int resetAmountIndex = 0;

private int maxResetPerTick = 0;

private int index;
private int locationIndex;
private int positionIndex;

private int blocksResetThisTick = 0;

private boolean dirty;

Section(Arena parent, Location start, Location end, short[] blockTypes, short[] blockAmounts) {
Expand Down Expand Up @@ -79,6 +85,7 @@ public boolean reset(int max) {
}

int count = 0;
blocksResetThisTick = 0;

while (index < blockTypes.length)
{
Expand All @@ -98,6 +105,7 @@ public boolean reset(int max) {

count++;
positionIndex++;
blocksResetThisTick++;

if (max > 0 && count > max)
{
Expand Down Expand Up @@ -184,6 +192,17 @@ public int getLength() {
return getEnd().getBlockZ() - getStart().getBlockZ() + 1;
}

/**
* @return The total number of blocks in the arena
*/
public int getTotalBlocks() {
return getWidth() * getHeight() * getLength();
}

protected int getBlocksResetThisTick() {
return blocksResetThisTick;
}

public Location getStart() {
return start;
}
Expand All @@ -205,4 +224,20 @@ public String toString()
{
return "Section{" + "start=" + start + ", end=" + end + '}';
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Section section = (Section) o;
return parent.equals(section.parent) &&
start.equals(section.start) &&
end.equals(section.end);
}

@Override
public int hashCode() {
int result = Objects.hash(parent, start, end);
return result;
}
}
Loading

0 comments on commit b92833d

Please sign in to comment.