Moved to gradle & started work on separating API and plugin
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package net.nuggetmc.tplus.api;
|
||||
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.nuggetmc.tplus.api.agent.legacyagent.ai.NeuralNetwork;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
public interface Terminator {
|
||||
|
||||
String getBotName();
|
||||
|
||||
GameProfile getGameProfile();
|
||||
|
||||
NeuralNetwork getNeuralNetwork();
|
||||
|
||||
void setNeuralNetwork(NeuralNetwork neuralNetwork);
|
||||
|
||||
boolean hasNeuralNetwork();
|
||||
|
||||
Location getLocation();
|
||||
|
||||
float getHealth();
|
||||
|
||||
float getMaxHealth();
|
||||
|
||||
void ignite();
|
||||
|
||||
boolean isOnFire();
|
||||
|
||||
boolean isFalling();
|
||||
|
||||
boolean isBlocking();
|
||||
|
||||
void block(int length, int cooldown);
|
||||
|
||||
boolean isInWater();
|
||||
|
||||
void jump(Vector velocity);
|
||||
|
||||
void jump();
|
||||
|
||||
void walk(Vector velocity);
|
||||
|
||||
void look(BlockFace face);
|
||||
|
||||
void attack(Entity target);
|
||||
|
||||
void attemptBlockPlace(Location loc, Material type, boolean down);
|
||||
|
||||
void punch();
|
||||
|
||||
void swim();
|
||||
|
||||
void sneak();
|
||||
|
||||
void stand();
|
||||
|
||||
void addFriction(double factor);
|
||||
|
||||
void removeVisually();
|
||||
|
||||
int getKills();
|
||||
|
||||
void incrementKills();
|
||||
|
||||
void setItem(ItemStack item);
|
||||
|
||||
void setItem(ItemStack item, EquipmentSlot slot);
|
||||
|
||||
void setItemOffhand(ItemStack item);
|
||||
|
||||
void setDefaultItem(ItemStack item);
|
||||
|
||||
Vector getOffset();
|
||||
|
||||
Vector getVelocity();
|
||||
|
||||
void setVelocity(Vector velocity);
|
||||
|
||||
void addVelocity(Vector velocity);
|
||||
|
||||
int getAliveTicks();
|
||||
|
||||
boolean tickDelay(int ticks);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
public enum ActivationType {
|
||||
TANH,
|
||||
SIN_X,
|
||||
SIN_X2,
|
||||
COS_X,
|
||||
COS_X2
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
import net.nuggetmc.tplus.api.Terminator;
|
||||
import net.nuggetmc.tplus.utils.MathUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
// If this is laggy, try only instantiating this once and update it instead of creating a new instance every tick
|
||||
public class BotData {
|
||||
|
||||
private final Map<BotDataType, Double> values;
|
||||
|
||||
private BotData(Terminator bot, LivingEntity target) {
|
||||
this.values = new HashMap<>();
|
||||
|
||||
Location a = bot.getLocation();
|
||||
Location b = target.getLocation();
|
||||
|
||||
float health = bot.getHealth();
|
||||
|
||||
values.put(BotDataType.CRITICAL_HEALTH, health >= 5 ? 0 : 5D - health);
|
||||
values.put(BotDataType.DISTANCE_XZ, Math.sqrt(MathUtils.square(a.getX() - b.getX()) + MathUtils.square(a.getZ() - b.getZ())));
|
||||
values.put(BotDataType.DISTANCE_Y, b.getY() - a.getY());
|
||||
values.put(BotDataType.ENEMY_BLOCKING, target instanceof Player && ((Player) target).isBlocking() ? 1D : 0);
|
||||
}
|
||||
|
||||
public static BotData generate(Terminator bot, LivingEntity target) {
|
||||
return new BotData(bot, target);
|
||||
}
|
||||
|
||||
public Map<BotDataType, Double> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public double getValue(BotDataType dataType) {
|
||||
return values.get(dataType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
List<String> strings = new ArrayList<>();
|
||||
|
||||
values.forEach((type, value) -> strings.add(type.name() + "=" + MathUtils.round2Dec(value)));
|
||||
|
||||
Collections.sort(strings);
|
||||
|
||||
return "BotData{" + StringUtils.join(strings, ",") + "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
public enum BotDataType {
|
||||
CRITICAL_HEALTH("h"),
|
||||
DISTANCE_XZ("xz"),
|
||||
DISTANCE_Y("y"),
|
||||
ENEMY_BLOCKING("b");
|
||||
|
||||
private final String shorthand;
|
||||
|
||||
BotDataType(String shorthand) {
|
||||
this.shorthand = shorthand;
|
||||
}
|
||||
|
||||
public String getShorthand() {
|
||||
return shorthand;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
public enum BotNode {
|
||||
BLOCK, // block (can't attack while blocking)
|
||||
JUMP, // jump
|
||||
LEFT, // left strafe
|
||||
RIGHT // right strafe (if L and R are opposite, move forward)
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.nuggetmc.tplus.utils.MathUtils;
|
||||
import net.nuggetmc.tplus.utils.ChatUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class NeuralNetwork {
|
||||
|
||||
// thinking about making an enum called BotNode, and have a map here, .check(Node.L) or fetch
|
||||
// also randomize activation point between 0 and 0.5
|
||||
// randomize the blocking length and cooldown
|
||||
// also the XZ offset randomizers!! (or maybe just turn them off entirely, that works too)
|
||||
|
||||
// b, j, l, r, ox, oz, av, bl, bc, dlr
|
||||
|
||||
private final Map<BotNode, NodeConnections> nodes;
|
||||
|
||||
private final boolean dynamicLR;
|
||||
|
||||
public static final NeuralNetwork RANDOM = new NeuralNetwork(new HashMap<>());
|
||||
|
||||
private NeuralNetwork(Map<BotNode, Map<BotDataType, Double>> profile) {
|
||||
this.nodes = new HashMap<>();
|
||||
this.dynamicLR = true;
|
||||
|
||||
if (profile == null) {
|
||||
Arrays.stream(BotNode.values()).forEach(n -> this.nodes.put(n, new NodeConnections()));
|
||||
} else {
|
||||
profile.forEach((nodeType, map) -> nodes.put(nodeType, new NodeConnections(map)));
|
||||
}
|
||||
}
|
||||
|
||||
public static NeuralNetwork createNetworkFromProfile(Map<BotNode, Map<BotDataType, Double>> profile) {
|
||||
return new NeuralNetwork(profile);
|
||||
}
|
||||
|
||||
public static NeuralNetwork generateRandomNetwork() {
|
||||
return new NeuralNetwork(null);
|
||||
}
|
||||
|
||||
public NodeConnections fetch(BotNode node) {
|
||||
return nodes.get(node);
|
||||
}
|
||||
|
||||
public boolean check(BotNode node) {
|
||||
return nodes.get(node).check();
|
||||
}
|
||||
|
||||
public double value(BotNode node) {
|
||||
return nodes.get(node).value();
|
||||
}
|
||||
|
||||
public void feed(BotData data) {
|
||||
nodes.values().forEach(n -> n.test(data));
|
||||
}
|
||||
|
||||
public Map<BotNode, NodeConnections> nodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public boolean dynamicLR() {
|
||||
return dynamicLR;
|
||||
}
|
||||
|
||||
public Map<BotNode, Map<BotDataType, Double>> values() {
|
||||
Map<BotNode, Map<BotDataType, Double>> output = new HashMap<>();
|
||||
nodes.forEach((nodeType, node) -> output.put(nodeType, node.getValues()));
|
||||
return output;
|
||||
}
|
||||
|
||||
public String output() {
|
||||
List<String> strings = new ArrayList<>();
|
||||
nodes.forEach((type, node) -> strings.add(type.name().toLowerCase() + "=" + (node.check() ? ChatUtils.ON + "1" : ChatUtils.OFF + "0") + ChatColor.RESET));
|
||||
Collections.sort(strings);
|
||||
return "[" + StringUtils.join(strings, ", ") + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
List<String> strings = new ArrayList<>();
|
||||
|
||||
nodes.forEach((nodeType, node) -> {
|
||||
List<String> values = new ArrayList<>();
|
||||
values.add("name=\"" + nodeType.name().toLowerCase() + "\"");
|
||||
node.getValues().forEach((dataType, value) -> values.add(dataType.getShorthand() + "=" + MathUtils.round2Dec(value)));
|
||||
strings.add("{" + StringUtils.join(values, ",") + "}");
|
||||
});
|
||||
|
||||
return "NeuralNetwork{nodes:[" + StringUtils.join(strings, ",") + "]}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package net.nuggetmc.tplus.api.agent.legacyagent.ai;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class NodeConnections {
|
||||
|
||||
/*
|
||||
* more node ideas
|
||||
* how much the bot is to the left or right of target (not horizontal distance)
|
||||
* bot velocity?
|
||||
* if the player is temporarily invincible (has damage ticks > 0)
|
||||
*/
|
||||
|
||||
private final Map<BotDataType, Double> connections;
|
||||
|
||||
private boolean active;
|
||||
|
||||
private double value;
|
||||
|
||||
public NodeConnections() {
|
||||
this.connections = new HashMap<>();
|
||||
|
||||
Arrays.stream(BotDataType.values()).forEach(type -> connections.put(type, generateValue()));
|
||||
}
|
||||
|
||||
public NodeConnections(Map<BotDataType, Double> values) {
|
||||
this.connections = values;
|
||||
}
|
||||
|
||||
private double generateValue() {
|
||||
return ThreadLocalRandom.current().nextDouble(-10, 10);
|
||||
}
|
||||
|
||||
public boolean check() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public double value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Map<BotDataType, Double> getValues() {
|
||||
return connections;
|
||||
}
|
||||
|
||||
public double getValue(BotDataType dataType) {
|
||||
return connections.get(dataType);
|
||||
}
|
||||
|
||||
/*
|
||||
* maybe a sinusoidal activation function?
|
||||
* maybe generate a random activation function?
|
||||
* definitely something less.. broad
|
||||
*/
|
||||
public void test(BotData data) {
|
||||
this.activationFunction(data);
|
||||
this.active = this.value >= 0.5;
|
||||
}
|
||||
|
||||
/*
|
||||
* try sin, sin x^2, cos, cos x^2
|
||||
*/
|
||||
private void activationFunction(BotData data) {
|
||||
this.value = Math.tanh(data.getValues().entrySet().stream().mapToDouble(entry -> connections.get(entry.getKey()) * entry.getValue()).sum());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user