mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-19 23:31:27 +00:00
Sync!
This commit is contained in:
@@ -4,13 +4,15 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.core.nms.INMS;
|
import com.volmit.iris.core.nms.INMS;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.IrisEngineService;
|
import com.volmit.iris.engine.object.IrisEngineService;
|
||||||
import com.volmit.iris.util.data.KCache;
|
|
||||||
import com.volmit.iris.util.format.Form;
|
import com.volmit.iris.util.format.Form;
|
||||||
import com.volmit.iris.util.mobs.HistoryManager;
|
|
||||||
import com.volmit.iris.util.mobs.IrisMobDataHandler;
|
import com.volmit.iris.util.mobs.IrisMobDataHandler;
|
||||||
import com.volmit.iris.util.mobs.IrisMobPiece;
|
import com.volmit.iris.util.mobs.IrisMobPiece;
|
||||||
import com.volmit.iris.util.scheduling.Looper;
|
import com.volmit.iris.util.scheduling.Looper;
|
||||||
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.bukkit.Chunk;
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
@@ -19,24 +21,28 @@ import org.bukkit.event.EventHandler;
|
|||||||
import org.bukkit.event.EventPriority;
|
import org.bukkit.event.EventPriority;
|
||||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||||
|
|
||||||
import javax.xml.crypto.Data;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDataHandler {
|
public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDataHandler {
|
||||||
|
|
||||||
private HistoryManager<DataType, Integer, Long> history;
|
private HashSet<HistoryData> history;
|
||||||
|
|
||||||
|
private Function<Map<IrisMobPiece, List<Integer>>, LinkedHashMap<IrisMobPiece, List<Integer>>> sortMapFunction;
|
||||||
|
|
||||||
|
private Function<Map<IrisMobPiece, Integer>, LinkedHashMap<IrisMobPiece, Integer>> sortMapSimpleFunction;
|
||||||
|
|
||||||
private int id;
|
private int id;
|
||||||
public int energyMax;
|
public int energyMax;
|
||||||
public int energy;
|
public int energy;
|
||||||
private long irritation = 0;
|
private long iteration = 0; // 1 every second
|
||||||
private HashSet<Chunk> loadedChunks;
|
private HashSet<Chunk> loadedChunks;
|
||||||
private HashMap<Types, Integer> bukkitLimits;
|
private HashMap<Types, Integer> bukkitLimits;
|
||||||
private Function<EntityType, Types> entityType;
|
private Function<EntityType, Types> entityType;
|
||||||
@@ -48,13 +54,58 @@ public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDat
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable(boolean hotload) {
|
public void onEnable(boolean hotload) {
|
||||||
|
|
||||||
this.id = engine.getCacheID();
|
this.id = engine.getCacheID();
|
||||||
this.history = new HistoryManager<>(Long.MAX_VALUE);
|
|
||||||
this.pieces = new ConcurrentLinkedQueue<>();
|
this.pieces = new ConcurrentLinkedQueue<>();
|
||||||
|
this.history = new HashSet<>();
|
||||||
this.entityType = (entityType) -> Types.valueOf(INMS.get().getMobCategory(entityType));
|
this.entityType = (entityType) -> Types.valueOf(INMS.get().getMobCategory(entityType));
|
||||||
this.loadedChunks = new HashSet<>();
|
this.loadedChunks = new HashSet<>();
|
||||||
this.bukkitLimits = getBukkitLimits();
|
this.bukkitLimits = getBukkitLimits();
|
||||||
|
this.sortMapFunction =
|
||||||
|
new Function<>() {
|
||||||
|
private Map<IrisMobPiece, List<Integer>> lastMap;
|
||||||
|
private LinkedHashMap<IrisMobPiece, List<Integer>> cachedSortedMap;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LinkedHashMap<IrisMobPiece, List<Integer>> apply(Map<IrisMobPiece, List<Integer>> inputMap) {
|
||||||
|
if (cachedSortedMap == null || !inputMap.equals(lastMap)) {
|
||||||
|
cachedSortedMap = inputMap.entrySet()
|
||||||
|
.stream()
|
||||||
|
.sorted(Map.Entry.<IrisMobPiece, List<Integer>>comparingByValue(
|
||||||
|
Comparator.comparingInt(list -> list.stream().mapToInt(Integer::intValue).sum())
|
||||||
|
).reversed())
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
Map.Entry::getValue,
|
||||||
|
(e1, e2) -> e1,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
lastMap = new HashMap<>(inputMap);
|
||||||
|
}
|
||||||
|
return cachedSortedMap;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.sortMapSimpleFunction = new Function<>() {
|
||||||
|
private Map<IrisMobPiece, Integer> lastMap;
|
||||||
|
private LinkedHashMap<IrisMobPiece, Integer> cachedSortedMap;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LinkedHashMap<IrisMobPiece, Integer> apply(Map<IrisMobPiece, Integer> inputMap) {
|
||||||
|
if (cachedSortedMap == null || !inputMap.equals(lastMap)) {
|
||||||
|
cachedSortedMap = inputMap.entrySet()
|
||||||
|
.stream()
|
||||||
|
.sorted(Map.Entry.<IrisMobPiece, Integer>comparingByValue(Comparator.reverseOrder()))
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
Map.Entry::getValue,
|
||||||
|
(e1, e2) -> e1,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
lastMap = new HashMap<>(inputMap);
|
||||||
|
}
|
||||||
|
return cachedSortedMap;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
new Ticker();
|
new Ticker();
|
||||||
}
|
}
|
||||||
@@ -77,7 +128,7 @@ public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDat
|
|||||||
protected long loop() {
|
protected long loop() {
|
||||||
long wait = -1;
|
long wait = -1;
|
||||||
try {
|
try {
|
||||||
irritation++;
|
iteration++;
|
||||||
if (engine.isClosed() || engine.getCacheID() != id) {
|
if (engine.isClosed() || engine.getCacheID() != id) {
|
||||||
interrupt();
|
interrupt();
|
||||||
}
|
}
|
||||||
@@ -120,44 +171,81 @@ public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private LinkedHashMap<IrisMobPiece, Integer> test(LinkedHashMap<IrisMobPiece, List<Integer>> req) {
|
||||||
|
LinkedHashMap<IrisMobPiece, Integer> res = new LinkedHashMap<>();
|
||||||
|
for (IrisMobPiece piece : req.keySet()) {
|
||||||
|
res.put(piece, null);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param map Data to do calculations with
|
* @param req Data to do calculations with. List<Integer>> = Requested energy + future
|
||||||
* @return returns the energy distribution for each piece
|
* @return returns the energy distribution for each piece
|
||||||
*/
|
*/
|
||||||
private LinkedHashMap<IrisMobPiece, Integer> assignEnergyToPieces(LinkedHashMap<IrisMobPiece, List<Integer>> map) {
|
private LinkedHashMap<IrisMobPiece, Integer> assignEnergyToPieces(LinkedHashMap<IrisMobPiece, List<Integer>> req) {
|
||||||
Supplier<LinkedHashMap<IrisMobPiece, List<Integer>>> sortedMapSupplier = new Supplier<>() {
|
|
||||||
private LinkedHashMap<IrisMobPiece, List<Integer>> cachedMap;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LinkedHashMap<IrisMobPiece, List<Integer>> get() {
|
|
||||||
if (cachedMap == null) {
|
|
||||||
cachedMap = map.entrySet()
|
|
||||||
.stream()
|
|
||||||
.sorted(Map.Entry.<IrisMobPiece, List<Integer>>comparingByValue(
|
|
||||||
Comparator.comparingInt(list -> list.stream().mapToInt(Integer::intValue).sum())
|
|
||||||
).reversed())
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
Map.Entry::getKey,
|
|
||||||
Map.Entry::getValue,
|
|
||||||
(e1, e2) -> e1,
|
|
||||||
LinkedHashMap::new
|
|
||||||
));
|
|
||||||
}
|
|
||||||
return cachedMap;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Might need caching?
|
// Might need caching?
|
||||||
Function<Integer, Integer> viewHistory = (history) ->
|
int futureView = 60;
|
||||||
map.values().stream()
|
int energy = calculateNewEnergy();
|
||||||
.mapToInt(list -> list.isEmpty() ? 0 : list.get(history))
|
|
||||||
.sum();
|
LinkedHashMap<IrisMobPiece, Integer> finalMap = req.keySet().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
piece -> piece,
|
||||||
|
piece -> null,
|
||||||
|
(existing, replacement) -> existing,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
|
||||||
|
Function<Integer, Stream<Integer>> viewSingleFuture = (future) ->
|
||||||
|
req.values().stream()
|
||||||
|
.mapToInt(list -> list.isEmpty() ? 0 : list.get(future)).boxed();
|
||||||
|
|
||||||
|
Function<Integer, Function<Integer, Stream<Integer>>> viewFuture = (rangeMin) -> (rangeMax) ->
|
||||||
|
IntStream.range(rangeMin, rangeMax)
|
||||||
|
.boxed()
|
||||||
|
.flatMap(viewSingleFuture);
|
||||||
|
|
||||||
|
Function<Integer, Double> viewFutureMedian = (value) -> viewFuture.apply(value).apply(futureView)
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.collectingAndThen(Collectors.toList(),
|
||||||
|
list -> {
|
||||||
|
int size = list.size();
|
||||||
|
if (size % 2 == 0) {
|
||||||
|
return (list.get(size / 2 - 1) + list.get(size / 2)) / 2.0;
|
||||||
|
} else {
|
||||||
|
return list.get(size / 2).doubleValue();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Logic
|
||||||
|
|
||||||
|
if ((predictEnergy(futureView) / viewFutureMedian.apply(0)) > 1.25 && (energy / viewSingleFuture.apply(0).mapToInt(Integer::intValue).sum() > 1)) {
|
||||||
|
|
||||||
|
finalMap = req.entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
Map.Entry::getKey,
|
||||||
|
e -> e.getValue().isEmpty() ? 0 : e.getValue().get(0),
|
||||||
|
(v1, v2) -> v1,
|
||||||
|
LinkedHashMap::new
|
||||||
|
));
|
||||||
|
} else if ((energy / viewSingleFuture.apply(0).mapToInt(Integer::intValue).sum() > 1)) {
|
||||||
|
// hard part
|
||||||
|
|
||||||
|
|
||||||
int i = calculateNewEnergy();
|
} else if ((energy / viewSingleFuture.apply(0).mapToInt(Integer::intValue).sum() < 1)) {
|
||||||
|
double scale = 1;
|
||||||
|
while ((double) energy / viewSingleFuture.apply(0).mapToInt(Integer::intValue).sum() >= scale) {
|
||||||
|
scale -= 0.1;
|
||||||
|
}
|
||||||
|
double finalScale = scale + 0.1;
|
||||||
|
|
||||||
|
LinkedHashMap<IrisMobPiece, Integer> finalMap1 = finalMap;
|
||||||
|
req.forEach((key, value) -> finalMap1.put(key, (int) (value.get(0) * finalScale)));
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return finalMap;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,17 +288,37 @@ public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDat
|
|||||||
|
|
||||||
private void updateMaxEnergy() {
|
private void updateMaxEnergy() {
|
||||||
var e = (int) engine.getDimension().getEnergy().evaluateMax("max", null, engine.getData(), (double) energy);
|
var e = (int) engine.getDimension().getEnergy().evaluateMax("max", null, engine.getData(), (double) energy);
|
||||||
history.addEntry(DataType.ENERGY_MAX, e, irritation);
|
history.add(new HistoryData(DataType.ENERGY_MAX, e, iteration));
|
||||||
energyMax = e;
|
energyMax = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calculateNewEnergy() {
|
private int calculateNewEnergy() {
|
||||||
return (int) engine.getDimension().getEnergy().evaluateMax("cur",null, engine.getData(), (double) energy);
|
var e = engine.getDimension().getEnergy().evaluateMax("cur",null, engine.getData(), (double) energy);
|
||||||
|
history.add(new HistoryData(DataType.ENERGY_ADDITION, (int) e, iteration));
|
||||||
|
return (int) e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param it How many iterations it should get to predict: 1 = second
|
||||||
|
* @return The Iterations/cost
|
||||||
|
*/
|
||||||
|
private Integer predictEnergy(int it) {
|
||||||
|
List<Integer> list = new ArrayList<>();
|
||||||
|
history.stream()
|
||||||
|
.filter(data -> data.getDataType() == DataType.ENERGY_ADDITION) // Filter by target DataType
|
||||||
|
.forEach(data -> {
|
||||||
|
if (data.getIteration() > iteration - it) {
|
||||||
|
list.add((Integer) data.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (int) list.stream().sorted().skip((list.size() - 1) / 2).limit(2 - list.size() % 2).mapToInt(Integer::intValue).average().orElse(Double.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getIrritation() {
|
public long getIteration() {
|
||||||
return irritation;
|
return iteration;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -238,4 +346,12 @@ public class EngineMobHandlerSVC extends IrisEngineService implements IrisMobDat
|
|||||||
updateMaxEnergy();
|
updateMaxEnergy();
|
||||||
return energy;
|
return energy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
private class HistoryData<T> {
|
||||||
|
private DataType dataType;
|
||||||
|
private T value;
|
||||||
|
private long iteration;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package com.volmit.iris.util.mobs;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.util.Deque;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
|
||||||
|
|
||||||
public class HistoryManager<K, V, I> {
|
|
||||||
private final Deque<HistoryEntry<K, V, I>> history = new ConcurrentLinkedDeque<>();
|
|
||||||
private final long maxSize;
|
|
||||||
|
|
||||||
public HistoryManager(long maxSize) {
|
|
||||||
this.maxSize = maxSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addEntry(K key, V value, I irritation) {
|
|
||||||
history.addFirst(new HistoryEntry<>(key, value, irritation));
|
|
||||||
if (history.size() > maxSize) {
|
|
||||||
history.removeLast();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public HistoryEntry<K, V, I> getEntry(int index) {
|
|
||||||
return history.stream().skip(index).findFirst().orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public I get3rd() {
|
|
||||||
return history.stream()
|
|
||||||
.skip(2)
|
|
||||||
.findFirst()
|
|
||||||
.map(HistoryEntry::getExtra)
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public static class HistoryEntry<K, V, I> {
|
|
||||||
private final K key;
|
|
||||||
private final V value;
|
|
||||||
private final I extra;
|
|
||||||
|
|
||||||
public HistoryEntry(K key, V value, I extra) {
|
|
||||||
this.key = key;
|
|
||||||
this.value = value;
|
|
||||||
this.extra = extra;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,11 +26,12 @@ public interface IrisMobDataHandler {
|
|||||||
|
|
||||||
enum DataType {
|
enum DataType {
|
||||||
ENERGY_MAX,
|
ENERGY_MAX,
|
||||||
ENERGY_CONSUMPTION
|
ENERGY_CONSUMPTION,
|
||||||
|
ENERGY_ADDITION
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long getIrritation();
|
long getIteration();
|
||||||
|
|
||||||
Function<EntityType, Types> getMobType();
|
Function<EntityType, Types> getMobType();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user