Skip to content

Commit

Permalink
feat/minions (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
MatzHilven authored Jul 1, 2024
1 parent 527172e commit d99b136
Show file tree
Hide file tree
Showing 23 changed files with 731 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@ build/
### NixOS ###
.envrc
.env

worlds/
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<dependency>
<groupId>com.github.Minestom</groupId>
<artifactId>Minestom</artifactId>
<version>f1d5940855</version>
<version>8ea7760e6a</version>
</dependency>

<dependency>
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/com/slampvp/factory/FactoryServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.common.menu.MenuListener;
import com.slampvp.factory.database.DatabaseManager;
import com.slampvp.factory.minion.MinionManager;
import com.slampvp.factory.player.PlayerListener;
import com.slampvp.factory.plot.PlotGenerator;
import com.slampvp.factory.plot.PlotManager;
Expand All @@ -21,18 +22,14 @@
import java.util.Set;
import java.util.stream.Stream;


public final class FactoryServer {
public static final Logger LOGGER = LoggerFactory.getLogger(FactoryServer.class);

public static void main(String[] args) {
long start = System.currentTimeMillis();
MinecraftServer minecraftServer = MinecraftServer.init();
MojangAuth.init();

MinecraftServer.getSchedulerManager().buildShutdownTask(() -> {
DatabaseManager.getInstance().close();
});

InstanceManager instanceManager = MinecraftServer.getInstanceManager();
InstanceContainer instanceContainer = instanceManager.createInstanceContainer();

Expand All @@ -44,14 +41,21 @@ public static void main(String[] args) {
new PlayerListener(instanceContainer);
new MenuListener();

PlotManager.getInstance().init();
DatabaseManager.getInstance().init();
PlotManager.getInstance().init();
MinionManager.getInstance().init();

streamPackage("com.slampvp.factory.command", FactoryCommand.class).forEach(c ->
MinecraftServer.getCommandManager().register(c)
);

MinecraftServer.getSchedulerManager().buildShutdownTask(() -> {
DatabaseManager.getInstance().close();
instanceContainer.saveChunksToStorage();
});

minecraftServer.start("0.0.0.0", 25565);
LOGGER.info("Server started in {}ms.", System.currentTimeMillis() - start);
}

public static <T> Stream<T> streamPackage(String packageName, Class<T> clazz) {
Expand Down Expand Up @@ -87,5 +91,4 @@ public static <T> Stream<T> streamPackage(String packageName, Class<T> clazz) {
})
.filter(java.util.Objects::nonNull);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.slampvp.factory.command.minion;

import com.slampvp.factory.command.Command;
import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.minion.models.Minion;
import com.slampvp.factory.player.Rank;

@Command(description = "Minion command.", usage = "/minion", minimumRank = Rank.ADMIN, playerOnly = false)
public class MinionCommand extends FactoryCommand {
public MinionCommand() {
super("minion");
}

@Override
public void init() {
addSyntax(((sender, context) -> {
Minion.all().forEach(minion -> {
sender.sendMessage(minion.toString());
});
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package com.slampvp.factory.command.minion.sub;

import com.slampvp.factory.command.Command;
import com.slampvp.factory.command.FactoryCommand;
import com.slampvp.factory.common.Locale;
import com.slampvp.factory.common.StringUtil;
import com.slampvp.factory.minion.models.Minion;
import com.slampvp.factory.minion.models.Minions;
import com.slampvp.factory.player.Rank;
import net.minestom.server.command.builder.arguments.ArgumentString;
import net.minestom.server.command.builder.arguments.ArgumentType;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentEntity;
import net.minestom.server.command.builder.arguments.number.ArgumentInteger;
import net.minestom.server.command.builder.arguments.number.ArgumentNumber;
import net.minestom.server.command.builder.suggestion.SuggestionEntry;
import net.minestom.server.entity.Player;

import java.util.ArrayList;
import java.util.Optional;

@Command(
description = "Give a minion to a player.",
usage = "/minion give <player> <minion> [amount]",
minimumRank = Rank.ADMIN,
playerOnly = false
)
public class GiveCommand extends FactoryCommand {
public GiveCommand() {
super("give");
}

@Override
public void init() {
ArgumentEntity argumentPlayer = ArgumentType.Entity("player").singleEntity(true).onlyPlayers(true);
ArgumentString argumentMinion = ArgumentType.String("minion");
ArgumentNumber<Integer> argumentAmount = ArgumentType.Integer("amount").min(1);

argumentMinion.setSuggestionCallback((sender, context, suggestion) -> {
String arg = suggestion.getInput().substring(suggestion.getStart() - 1, suggestion.getStart() + suggestion.getLength() - 1);
StringUtil.copyPartialMatches(arg, Minion.all().stream().map(Minion::id).toList(), new ArrayList<>()).forEach(string -> {
suggestion.addEntry(new SuggestionEntry(string));
});
});

addSyntax((sender, context) -> {
Player target = context.get(argumentPlayer).findFirstPlayer(sender);

if (target == null) {
sender.sendMessage(Locale.Command.INVALID_PLAYER);
return;
}

Optional<Minion> optionalMinion = Minion.byId(context.get(argumentMinion));

if (optionalMinion.isEmpty()) {
sender.sendMessage(Locale.Minion.INVALID_ID);
return;
}

Minion minion = optionalMinion.get();

target.getInventory().addItemStack(minion.getItem());
}, argumentPlayer, argumentMinion);

addSyntax((sender, context) -> {
Player target = context.get(argumentPlayer).findFirstPlayer(sender);

if (target == null) {
sender.sendMessage(Locale.Command.INVALID_PLAYER);
return;
}

Optional<Minion> optionalMinion = Minion.byId(context.get(argumentMinion));

if (optionalMinion.isEmpty()) {
sender.sendMessage(Locale.Minion.INVALID_ID);
return;
}

int amount = context.get(argumentAmount);

Minion minion = optionalMinion.get();

for (int i = 0; i < amount; i++) {
target.getInventory().addItemStack(minion.getItem());
}
}, argumentPlayer, argumentMinion, argumentAmount);
}
}
17 changes: 17 additions & 0 deletions src/main/java/com/slampvp/factory/common/ItemStackUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.slampvp.factory.common;

import net.minestom.server.entity.PlayerSkin;
import net.minestom.server.item.ItemComponent;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.component.HeadProfile;
import org.jetbrains.annotations.NotNull;

public class ItemStackUtil {
public static @NotNull ItemStack.Builder texturedHead(String texture) {
ItemStack.Builder skull = ItemStack.builder(Material.PLAYER_HEAD);
HeadProfile profile = new HeadProfile(new PlayerSkin(texture, null));
skull.set(ItemComponent.PROFILE, profile);
return skull;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/slampvp/factory/common/Locale.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,19 @@ interface Plot {
Component.text("You've successfully merged your plots!").color(NamedTextColor.GREEN)
);
}

/**
* Minion-related messages.
*/
interface Minion {
TextComponent PREFIX = Component.text()
.append(Component.text("[").color(NamedTextColor.RED).decorate(TextDecoration.BOLD))
.append(Component.text("Minion").color(NamedTextColor.BLUE).decorate(TextDecoration.BOLD))
.append(Component.text("] ").color(NamedTextColor.RED).decorate(TextDecoration.BOLD))
.build();

TextComponent INVALID_ID = PREFIX.append(
Component.text("Cannot find a minion with specified id!").color(NamedTextColor.RED)
);
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/slampvp/factory/common/StringUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.slampvp.factory.common;

import java.util.Collection;

public class StringUtil {
public static <T extends Collection<? super String>> T copyPartialMatches(String token, Iterable<String> originals, T collection)
throws UnsupportedOperationException, IllegalArgumentException {
if (token.length() == 1 && Integer.toHexString(token.charAt(0) | 0x10000).substring(1).equals("0000")) {
token = "";
}

for (String string : originals) {
if (startsWithIgnoreCase(string, token)) {
collection.add(string);
}
}
return collection;
}

private static boolean startsWithIgnoreCase(String string, String prefix) throws IllegalArgumentException, NullPointerException {
return string.length() >= prefix.length() && string.regionMatches(true, 0, prefix, 0, prefix.length());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.slampvp.factory.database;

import net.minestom.server.coordinate.BlockVec;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
Expand All @@ -17,17 +18,34 @@ public static String pointToString(Point point) {
return null;
}

public static BlockVec stringToBlockVec(String string) {
Float[] array = parseString(string);
if (array.length == 0) {
return null;
}
return new BlockVec(array[0], array[1], array[2]);
}

public static Vec stringToVec(String string) {
Float[] array = parseString(string);
if (array.length == 0) {
return null;
}
return new Vec(array[0], array[1], array[2]);
}

public static Pos stringToPos(String string) {
Float[] array = parseString(string);
if (array.length == 0) {
return null;
}
return new Pos(array[0], array[1], array[2], array[3], array[4]);
}

private static Float @NotNull [] parseString(@NotNull String string) {
private static Float @NotNull [] parseString(String string) {
if (string == null) {
return new Float[0];
}
return Arrays.stream(string
.substring(1, string.length() - 1)
.split(","))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ public CompletableFuture<Long> executeUpdate(String query, SQLConsumer<PreparedS

return Long.valueOf(-1);
} catch (SQLException e) {
FactoryServer.LOGGER.error(e.getMessage());
throw new RuntimeException(e);
}
}, executor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ CONSTRAINT fk_plot FOREIGN KEY (plot_id) REFERENCES plots (id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS index_plot_flags_on_all ON plot_flags (plot_id, target, flags);
CREATE INDEX IF NOT EXISTS index_plot_flags_on_plot_id ON plot_flags (plot_id);
CREATE TABLE IF NOT EXISTS minions
(
id SERIAL,
minion_id TEXT NOT NULL,
owner VARCHAR(36) NOT NULL,
time_active BIGINT NOT NULL,
amount_generated BIGINT NOT NULL,
position VEC NOT NULL,
chest_position VEC,
PRIMARY KEY (id)
);
CREATE INDEX IF NOT EXISTS index_minions_on_owner ON minions (owner);
END
$$;
""";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.slampvp.factory.database.queries;

import org.intellij.lang.annotations.Language;

public final class MinionQueries {
public static final class Insert {
@Language("PostgreSQL")
public static final String MINION = """
INSERT INTO minions (minion_id, owner, time_active, amount_generated, position, chest_position)
VALUES (?,?,?,?,?,?);
""";
}

public static final class Select {
@Language("PostgreSQL")
public static final String BY_OWNER = "SELECT * FROM minions WHERE owner = ?";
}

public static final class Delete {
@Language("PostgreSQL")
public static final String BY_ID = "DELETE FROM plots WHERE id = ?";
}
}
37 changes: 37 additions & 0 deletions src/main/java/com/slampvp/factory/minion/MinionListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.slampvp.factory.minion;

import com.slampvp.factory.minion.models.Minion;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.event.GlobalEventHandler;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.item.ItemStack;
import net.minestom.server.tag.Tag;

import java.util.Optional;

public class MinionListener {
public MinionListener() {
GlobalEventHandler globalEventHandler = MinecraftServer.getGlobalEventHandler();
MinionManager minionManager = MinionManager.getInstance();

globalEventHandler.addListener(PlayerBlockPlaceEvent.class, event -> {
Player player = event.getPlayer();
ItemStack itemInHand = player.getItemInHand(event.getHand());

String minionId = itemInHand.getTag(Tag.String("minion"));
if (minionId == null) {
return;
}

Optional<Minion> optionalMinion = Minion.byId(minionId);
if (optionalMinion.isEmpty()) {
return;
}

event.setCancelled(true);
player.setItemInMainHand(itemInHand.withAmount(itemInHand.amount() - 1));
minionManager.addMinion(player, event.getBlockPosition().asVec(), optionalMinion.get());
});
}
}
Loading

0 comments on commit d99b136

Please sign in to comment.