Wide variety of changes for release

This commit is contained in:
Elias Müller 2023-12-27 01:15:04 +01:00
parent 4bfcc5a2ff
commit de559df98c
20 changed files with 427 additions and 45 deletions

@ -56,5 +56,5 @@ tasks.register('copyJarToServer', Exec) {
dependsOn shadowJar
mustRunAfter shadowJar
commandLine 'scp', 'build/libs/spawn-1.0-all.jar', 'root@10.20.6.1:/root/server/plugins'
commandLine 'scp', 'build/libs/spawn-1.0-all.jar', 'root@10.20.6.1:/home/minecraft/server/plugins'
}

@ -1,10 +1,12 @@
package eu.mhsl.craftattack.spawn;
import eu.mhsl.craftattack.spawn.aggregates.displayName.DisplayName;
import eu.mhsl.craftattack.spawn.api.HttpServer;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
import eu.mhsl.craftattack.spawn.appliances.kick.Kick;
import eu.mhsl.craftattack.spawn.appliances.chatMessages.ChatMessages;
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
import eu.mhsl.craftattack.spawn.appliances.panicBan.PanicBan;
import eu.mhsl.craftattack.spawn.appliances.projectStart.ProjectStart;
import eu.mhsl.craftattack.spawn.appliances.debug.Debug;
@ -51,8 +53,11 @@ public final class Main extends JavaPlugin {
new Restart(),
new Kick(),
new PanicBan(),
new Outlawed(),
new DisplayName(),
new Debug()
);
Bukkit.getLogger().info("Loading appliances...");
appliances.forEach(appliance -> {
Bukkit.getLogger().info("Enabling " + appliance.getClass().getSimpleName());
@ -81,7 +86,11 @@ public final class Main extends JavaPlugin {
}
public <T extends Appliance> T getAppliance(Class<T> clazz) {
return this.appliances.stream().filter(clazz::isInstance).map(clazz::cast).findFirst().orElseThrow();
return this.appliances.stream()
.filter(clazz::isInstance)
.map(clazz::cast)
.findFirst()
.orElseThrow(() -> new RuntimeException(String.format("Appliance %s not loaded or instantiated!", clazz)));
}
@SuppressWarnings("unchecked")

@ -0,0 +1,10 @@
package eu.mhsl.craftattack.spawn.aggregate;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
public abstract class Aggregate extends Appliance {
public <T extends Appliance> T queryAppliance(Class<T> clazz) {
return Main.instance().getAppliance(clazz);
}
}

@ -0,0 +1,53 @@
package eu.mhsl.craftattack.spawn.aggregates.displayName;
import eu.mhsl.craftattack.spawn.aggregate.Aggregate;
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarker;
import eu.mhsl.craftattack.spawn.appliances.adminMarker.AdminMarkerListener;
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.ComponentBuilder;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.function.Supplier;
public class DisplayName extends Aggregate {
public void update(Player player) {
TextColor playerColor = queryAppliance(AdminMarker.class).getPlayerColor(player);
List<Supplier<Component>> prefixes = List.of(
() -> queryAppliance(Outlawed.class).getNamePrefix(player)
);
ComponentBuilder<TextComponent, TextComponent.Builder> playerName = Component.text();
prefixes.forEach(supplier -> {
Component prefix = supplier.get();
if(prefix == null) return;
playerName.append(prefix).append(Component.text(" "));
});
playerName.append(Component.text(player.getName(), playerColor));
setGlobal(player, playerName.build());
}
private void setGlobal(Player player, Component component) {
try {
player.customName(component);
player.displayName(component);
player.playerListName(component);
} catch (Exception e) {
//TODO this throws often exceptions, but still works, don't know why
//Main.instance().getLogger().log(Level.SEVERE, e, e::getMessage);
}
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new AdminMarkerListener());
}
}

@ -0,0 +1,13 @@
package eu.mhsl.craftattack.spawn.aggregates.displayName;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerJoinEvent;
public class DisplayNameUpdateListener extends ApplianceListener<DisplayName> {
@EventHandler(priority = EventPriority.LOWEST)
public void onJoin(PlayerJoinEvent event) {
getAppliance().update(event.getPlayer());
}
}

@ -51,7 +51,8 @@ public class HttpServer {
public <TRequest> void post(String path, Class<TRequest> clazz, RequestProvider<TRequest, Request, Object> onCall) {
Spark.post(this.buildRoute(path), (req, resp) -> {
TRequest parsed = new Gson().fromJson(req.body(), clazz);
Main.instance().getLogger().info(req.body());
TRequest parsed = HttpServer.this.gson.fromJson(req.body(), clazz);
return this.process(() -> onCall.apply(parsed, req));
});
}

@ -1,12 +1,19 @@
package eu.mhsl.craftattack.spawn.appliances.adminMarker;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.Color;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class AdminMarker extends Appliance {
public TextColor getPlayerColor(Player player) {
if (player.hasPermission("chatcolor")) return TextColor.color(Color.AQUA.asRGB()); // TODO read permission from config
return TextColor.color(Color.WHITE.asRGB());
}
@Override
protected @NotNull List<Listener> eventHandlers() {

@ -7,17 +7,12 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import java.util.Optional;
public class AdminMarkerListener extends ApplianceListener<AdminMarker> {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player p = event.getPlayer();
p.customName(Optional.ofNullable(p.customName()).orElse(p.displayName()).color(getPlayerColor(p)));
p.displayName(p.displayName().color(getPlayerColor(p)));
p.playerListName(p.playerListName().color(getPlayerColor(p)));
}
private TextColor getPlayerColor(Player player) {

@ -22,6 +22,7 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Villager;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@ -30,10 +31,7 @@ import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
public class Event extends Appliance {
public DisplayVillager.ConfigBound villager;
@ -42,8 +40,8 @@ public class Event extends Appliance {
private final HttpClient eventServerClient = HttpClient.newHttpClient();
private final List<Reward> pendingRewards = new ArrayList<>();
record RewardConfiguration(String material, Map<UUID, Integer> rewards) {}
record Reward(UUID playerUuid, Material material, int amount) {}
record RewardConfiguration(String memorialMaterial, String memorialTitle, String memorialLore, List<UUID> memorials, String material, Map<UUID, Integer> rewards) {}
record Reward(UUID playerUuid, ItemStack itemStack) {}
public Event() {
super("event");
@ -87,6 +85,7 @@ public class Event extends Appliance {
}
try {
Main.instance().getLogger().info("Verbinde mit eventserver: " + p.getName());
p.sendMessage(Component.text("Authentifiziere...", NamedTextColor.GREEN));
record Request(UUID player, UUID room) {}
Request request = new Request(p.getUniqueId(), this.roomId);
@ -95,9 +94,13 @@ public class Event extends Appliance {
.POST(HttpRequest.BodyPublishers.ofString(new Gson().toJson(request)))
.build();
HttpResponse<Void> rawResponse = eventServerClient.send(queueRoomRequest, HttpResponse.BodyHandlers.discarding());
if(rawResponse.statusCode() != 200) {
p.sendMessage(Component.text("Fehler beim beitreten: " + rawResponse.statusCode(), NamedTextColor.RED));
record Response(String error) {}
HttpResponse<String> rawResponse = eventServerClient.send(queueRoomRequest, HttpResponse.BodyHandlers.ofString());
Main.instance().getLogger().info("Response: " + rawResponse.body());
Response response = new Gson().fromJson(rawResponse.body(), Response.class);
if(rawResponse.statusCode() != 200 || response.error != null) {
p.sendMessage(Component.text("Fehler beim betreten: " + response.error, NamedTextColor.RED));
return;
}
@ -116,24 +119,36 @@ public class Event extends Appliance {
private void rewardPlayers(RewardConfiguration rewardConfiguration) {
rewardConfiguration.rewards.forEach((uuid, amount) -> {
Reward reward = new Reward(uuid, Material.matchMaterial(rewardConfiguration.material), amount);
if(reward.material == null) throw new RuntimeException("Material not found");
Reward reward = new Reward(uuid, new ItemStack(Objects.requireNonNull(Material.matchMaterial(rewardConfiguration.material)), amount));
if(Bukkit.getPlayer(uuid) == null) {
pendingRewards.add(reward);
return;
}
giveReward(reward);
});
for (UUID uuid : rewardConfiguration.memorials) {
ItemStack memorialItem = new ItemStack(Objects.requireNonNull(Material.matchMaterial(rewardConfiguration.memorialMaterial)));
ItemMeta meta = memorialItem.getItemMeta();
meta.displayName(Component.text(rewardConfiguration.memorialTitle, NamedTextColor.GOLD));
meta.lore(List.of(Component.text(rewardConfiguration.memorialLore, NamedTextColor.AQUA)));
memorialItem.setItemMeta(meta);
Reward memorial = new Reward(uuid, memorialItem);
if (Bukkit.getPlayer(uuid) == null) {
pendingRewards.add(memorial);
continue;
}
giveReward(memorial);
}
}
private void giveReward(Reward reward) {
Player player = Bukkit.getPlayer(reward.playerUuid);
if(player == null) throw new RuntimeException("Cannot reward offline playerUuid!");
ItemStack rewardStack = new ItemStack(reward.material, reward.amount);
Map<Integer, ItemStack> remaining = player.getInventory().addItem(rewardStack);
Map<Integer, ItemStack> remaining = player.getInventory().addItem(reward.itemStack);
Bukkit.getScheduler().runTask(
Main.instance(),
() -> remaining.values().forEach(remainingStack -> player.getWorld().dropItem(player.getLocation(), remainingStack))

@ -0,0 +1,7 @@
package eu.mhsl.craftattack.spawn.appliances.outlawed;
public class OutlawForcedException extends Exception {
public OutlawForcedException(String message) {
super(message);
}
}

@ -0,0 +1,117 @@
package eu.mhsl.craftattack.spawn.appliances.outlawed;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.aggregates.displayName.DisplayName;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.appliances.whitelist.Whitelist;
import eu.mhsl.craftattack.spawn.config.Configuration;
import eu.mhsl.craftattack.spawn.util.text.DisconnectInfo;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
public class Outlawed extends Appliance {
public enum Status {
DISABLED,
VOLUNTARILY,
FORCED
}
private final Map<Player, Status> playerStatusMap = new WeakHashMap<>();
private final String voluntarilyEntry = "voluntarily";
public Outlawed() {
super("outlawed");
Bukkit.getScheduler().runTaskTimerAsynchronously(
Main.instance(),
() -> {
playerStatusMap.forEach((player, status) -> {
if(status != Status.FORCED) return;
try {
Main.instance().getAppliance(Whitelist.class).integrityCheck(player);
} catch (DisconnectInfo.Throwable e) {
Bukkit.getScheduler().runTask(Main.instance(), () -> e.getDisconnectScreen().applyKick(player));
}
});
},
20*60,
20*60*5
);
}
public void switchLawStatus(Player player) throws OutlawForcedException {
if(getLawStatus(player).equals(Status.FORCED)) {
throw new OutlawForcedException("Dein Vogelfreistatus wurde als Strafe auferlegt und kann daher nicht verändert werden.");
}
setLawStatus(player, isOutlawed(player) ? Status.DISABLED : Status.VOLUNTARILY);
}
public void updateForcedStatus(Player player, boolean forced) {
setLawStatus(player, forced ? Status.FORCED : getLawStatus(player) == Status.FORCED ? Status.DISABLED : getLawStatus(player));
}
public Status getLawStatus(Player player) {
Status status = playerStatusMap.computeIfAbsent(player, p -> {
if(localConfig().getStringList(voluntarilyEntry).contains(p.getUniqueId().toString())) return Status.VOLUNTARILY;
return Status.DISABLED;
});
return status;
}
public void setLawStatus(Player player, Status status) {
playerStatusMap.put(player, status);
Main.instance().getAppliance(DisplayName.class).update(player);
List<String> newList = localConfig().getStringList(voluntarilyEntry);
if(status.equals(Status.VOLUNTARILY)) {
newList.add(player.getUniqueId().toString());
} else {
newList.remove(player.getUniqueId().toString());
}
localConfig().set(voluntarilyEntry, newList.stream().distinct().toList());
Configuration.saveChanges();
}
public boolean isOutlawed(Player player) {
return getLawStatus(player) != Status.DISABLED;
}
public Component getStatusDescription(Status status) {
return switch (status) {
case DISABLED -> Component.text("Vogelfreistatus inaktiv: ", NamedTextColor.GREEN)
.append(Component.text("Es gelten die Standart Regeln!", NamedTextColor.GOLD));
case VOLUNTARILY, FORCED -> Component.text("Vogelfreistatus aktiv: ", NamedTextColor.RED)
.append(Component.text("Du darfst von jedem angegriffen und getötet werden!", NamedTextColor.GOLD));
};
}
public Component getNamePrefix(Player player) {
if(isOutlawed(player)) {
return Component.text("[☠]", NamedTextColor.RED)
.hoverEvent(HoverEvent.showText(Component.text("Vogelfreie Spieler dürfen ohne Grund angegriffen werden!")));
}
return null;
}
@Override
protected @NotNull List<ApplianceCommand<?>> commands() {
return List.of(new OutlawedCommand());
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(new OutlawedReminderListener());
}
}

@ -0,0 +1,27 @@
package eu.mhsl.craftattack.spawn.appliances.outlawed;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class OutlawedCommand extends ApplianceCommand.PlayerChecked<Outlawed> {
public OutlawedCommand() {
super("vogelfrei");
}
@Override
protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception {
try {
getAppliance().switchLawStatus(getPlayer());
sender.sendMessage(
getAppliance()
.getStatusDescription(getAppliance().getLawStatus(getPlayer()))
);
} catch (OutlawForcedException e) {
sender.sendMessage(Component.text(e.getMessage(), NamedTextColor.RED));
}
}
}

@ -0,0 +1,14 @@
package eu.mhsl.craftattack.spawn.appliances.outlawed;
import eu.mhsl.craftattack.spawn.appliance.ApplianceListener;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
public class OutlawedReminderListener extends ApplianceListener<Outlawed> {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
if(getAppliance().isOutlawed(e.getPlayer())) {
e.getPlayer().sendMessage(getAppliance().getStatusDescription(getAppliance().getLawStatus(e.getPlayer())));
}
}
}

@ -7,6 +7,7 @@ import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartCom
import eu.mhsl.craftattack.spawn.appliances.projectStart.command.ProjectStartResetCommand;
import eu.mhsl.craftattack.spawn.appliances.projectStart.listener.PlayerInvincibleListener;
import eu.mhsl.craftattack.spawn.config.Configuration;
import eu.mhsl.craftattack.spawn.util.entity.PlayerUtils;
import eu.mhsl.craftattack.spawn.util.world.BlockCycle;
import eu.mhsl.craftattack.spawn.util.text.ComponentUtil;
import eu.mhsl.craftattack.spawn.util.text.Countdown;
@ -21,13 +22,21 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static java.util.Map.entry;
import static org.bukkit.Sound.MUSIC_DISC_PIGSTEP;
public class ProjectStart extends Appliance {
private final int startMusicAt = 137;
private final Location glassLocation = new Location(Bukkit.getWorld("world"), -224, 67, -368);
private final World startWorld = Bukkit.getWorld("world");
private final Location glassLocation = new Location(startWorld, -224, 67, -368);
private final List<Location> netherFireLocations = List.of(
new Location(startWorld, -211, 68, -354),
new Location(startWorld, -209, 68, -356),
new Location(startWorld, -207, 68, -354),
new Location(startWorld, -209, 68, -352)
);
private final Countdown countdown = new Countdown(
localConfig().getInt("countdown"),
@ -102,6 +111,9 @@ public class ProjectStart extends Appliance {
IteratorUtil.worlds(World::getWorldBorder, worldBorder -> worldBorder.setSize(worldBorder.getMaxSize()));
IteratorUtil.worlds(world -> IteratorUtil.setGameRules(gameRulesAfterStart, false));
IteratorUtil.worlds(world -> world.setFullTime(0));
netherFireLocations.forEach(location -> Objects.requireNonNull(startWorld).getBlockAt(location).setType(Material.FIRE));
Bukkit.getOnlinePlayers().forEach(player -> {
player.setFoodLevel(20);
@ -114,6 +126,9 @@ public class ProjectStart extends Appliance {
player.playSound(Sound.sound(org.bukkit.Sound.ITEM_GOAT_HORN_SOUND_5, Sound.Source.MASTER, 500f, 1f));
player.sendMessage(Component.text("Viel Spaß bei CraftAttack!", NamedTextColor.GREEN));
player.setStatistic(Statistic.TIME_SINCE_REST, 0);
PlayerUtils.resetStatistics(player);
});
Bukkit.getServer().advancementIterator().forEachRemaining(
@ -140,6 +155,7 @@ public class ProjectStart extends Appliance {
IteratorUtil.worlds(world -> world, world -> IteratorUtil.setGameRules(gameRulesAfterStart, true));
blockCycle.reset();
}

@ -9,7 +9,7 @@ public class PlayerJoinListener extends ApplianceListener<Whitelist> {
@EventHandler
public void preLoginEvent(PlayerLoginEvent preLoginEvent) {
try {
getAppliance().login(preLoginEvent);
getAppliance().integrityCheck(preLoginEvent.getPlayer());
} catch (DisconnectInfo.Throwable e) {
preLoginEvent.disallow(
PlayerLoginEvent.Result.KICK_WHITELIST,

@ -2,12 +2,16 @@ package eu.mhsl.craftattack.spawn.appliances.whitelist;
import com.google.gson.Gson;
import eu.mhsl.craftattack.spawn.Main;
import eu.mhsl.craftattack.spawn.api.HttpServer;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliances.outlawed.Outlawed;
import eu.mhsl.craftattack.spawn.util.server.Floodgate;
import eu.mhsl.craftattack.spawn.util.text.DisconnectInfo;
import org.apache.http.client.utils.URIBuilder;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerLoginEvent;
import org.eclipse.jetty.websocket.server.WebSocketHandler;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@ -16,13 +20,15 @@ import java.net.URISyntaxException;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.logging.Level;
public class Whitelist extends Appliance {
private record UserData(UUID uuid, String username, String firstname, String lastname) {}
private record UserData(UUID uuid, String username, String firstname, String lastname, Long banned_until, Long outlawed_until) {}
private final URI apiEndpoint = URI.create(Objects.requireNonNull(localConfig().getString("api")));
@ -30,23 +36,42 @@ public class Whitelist extends Appliance {
super("whitelist");
}
public void login(PlayerLoginEvent login) throws DisconnectInfo.Throwable {
public void integrityCheck(Player player) throws DisconnectInfo.Throwable {
try {
UserData data = this.fetchUserData(login.getPlayer().getUniqueId());
Main.instance().getLogger().info(String.format("Running integrityCheck for %s", player.getName()));
UserData user = this.fetchUserData(player.getUniqueId());
String purePlayerName;
if(Floodgate.isBedrock(login.getPlayer())) {
purePlayerName = Floodgate.getBedrockPlayer(login.getPlayer()).getUsername();
} else {
purePlayerName = login.getPlayer().getName();
if(timestampRelevant(user.banned_until)) {
Instant bannedDate = new Date(user.banned_until * 1000L)
.toInstant()
.plus(1, ChronoUnit.HOURS);
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy").withZone(ZoneOffset.UTC);
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneOffset.UTC);
throw new DisconnectInfo.Throwable(
"Du wurdest vom Server gebannt.",
String.format("Dein Bann läuft am %s um %s ab!", dateFormat.format(bannedDate), timeFormat.format(bannedDate)),
"Wende dich an einen Admin für weitere Informationen.",
player.getUniqueId()
);
}
if(!data.username.equalsIgnoreCase(purePlayerName))
Main.instance().getAppliance(Outlawed.class).updateForcedStatus(player, timestampRelevant(user.outlawed_until));
String purePlayerName;
if(Floodgate.isBedrock(player)) {
purePlayerName = Floodgate.getBedrockPlayer(player).getUsername();
} else {
purePlayerName = player.getName();
}
if(!user.username.trim().equalsIgnoreCase(purePlayerName))
throw new DisconnectInfo.Throwable(
"Nutzername geändert",
String.format("Der Name '%s' stimmt nicht mit '%s' überein.", data.username, login.getPlayer().getName()),
String.format("Der Name '%s' stimmt nicht mit '%s' überein.", user.username, player.getName()),
"Bitte kontaktiere einen Admin, um Deine Anmeldedaten zu aktualisieren!",
login.getPlayer().getUniqueId()
player.getUniqueId()
);
} catch (DisconnectInfo.Throwable e) {
@ -55,13 +80,18 @@ public class Whitelist extends Appliance {
Main.instance().getLogger().log(Level.SEVERE, e, e::getMessage);
throw new DisconnectInfo.Throwable(
"Interner Serverfehler",
"Deine Zugangsdaten konnten nicht abgerufen werden.",
"Deine Anmeldedaten konnten nicht abgerufen/ überprüft werden.",
"Versuche es später erneut oder kontaktiere einen Admin!",
login.getPlayer().getUniqueId()
player.getUniqueId()
);
}
}
private boolean timestampRelevant(Long timestamp) {
if(timestamp == null) return false;
return timestamp > System.currentTimeMillis() / 1000L;
}
private UserData fetchUserData(UUID uuid) throws DisconnectInfo.Throwable {
URIBuilder uriBuilder = new URIBuilder(apiEndpoint);
uriBuilder.addParameter("uuid", uuid.toString());
@ -76,7 +106,7 @@ public class Whitelist extends Appliance {
HttpResponse<String> httpResponse = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if(httpResponse.statusCode() == 400)
if(httpResponse.statusCode() == 404)
throw new DisconnectInfo.Throwable(
"Nicht angemeldet",
"Du bist derzeit nicht als Teilnehmer des CraftAttack-Projektes registriert!",
@ -91,6 +121,23 @@ public class Whitelist extends Appliance {
}
}
@Override
public void httpApi(HttpServer.ApiBuilder apiBuilder) {
record User(UUID user) {}
apiBuilder.post("update", User.class, (user, request) -> {
Main.instance().getLogger().info(String.format("API Triggered Profile update for %s", user.user));
Player player = Bukkit.getPlayer(user.user);
if(player != null) {
try {
this.integrityCheck(player);
} catch (DisconnectInfo.Throwable e) {
e.getDisconnectScreen().applyKick(player);
}
}
return HttpServer.nothing;
});
}
@Override
protected @NotNull List<Listener> eventHandlers() {
return List.of(

@ -3,6 +3,7 @@ package eu.mhsl.craftattack.spawn.appliances.worldmuseum;
import eu.mhsl.craftattack.spawn.appliance.Appliance;
import eu.mhsl.craftattack.spawn.appliance.ApplianceCommand;
import eu.mhsl.craftattack.spawn.util.entity.DisplayVillager;
import eu.mhsl.craftattack.spawn.util.server.Floodgate;
import eu.mhsl.craftattack.spawn.util.server.PluginMessage;
import eu.mhsl.craftattack.spawn.util.listener.DismissInventoryOpenFromHolder;
import eu.mhsl.craftattack.spawn.util.listener.PlayerInteractAtEntityEventListener;
@ -12,6 +13,8 @@ import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.*;
import org.bukkit.event.Listener;
import org.geysermc.cumulus.form.SimpleForm;
import org.geysermc.cumulus.form.util.FormBuilder;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@ -39,6 +42,19 @@ public class WorldMuseum extends Appliance {
}
public void handleVillagerInteraction(Player player) {
if(Floodgate.isBedrock(player)) {
Floodgate.runBedrockOnly(player, floodgatePlayer -> {
floodgatePlayer.sendForm(
SimpleForm.builder()
.title("Nicht unterstützt")
.content("Bedrock-Spieler werden derzeit für das Weltenmuseum aus Kompatiblitätsgründen nicht zugelassen! Tut uns Leid.")
.button("Ok")
.build()
);
});
return;
}
Bukkit.getLogger().info("Sending" + player.getName() + " to WorldMuseum");
PluginMessage.connect(player, localConfig().getString("connect-server-name"));
}

@ -0,0 +1,32 @@
package eu.mhsl.craftattack.spawn.util.entity;
import org.bukkit.Material;
import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
public class PlayerUtils {
public static void resetStatistics(Player player) {
for(Statistic statistic : Statistic.values()) {
for(Material material : Material.values()) {
try {
player.setStatistic(statistic, material, 0);
} catch (IllegalArgumentException e) {
break;
}
}
for(EntityType entityType : EntityType.values()) {
try {
player.setStatistic(statistic, entityType, 0);
} catch (IllegalArgumentException e) {
break;
}
}
try{
player.setStatistic(statistic, 0);
} catch (IllegalArgumentException ignored){}
}
}
}

@ -1,14 +1,16 @@
package eu.mhsl.craftattack.spawn.util.text;
import eu.mhsl.craftattack.spawn.Main;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.UUID;
public record DisconnectInfo(String error, String description, String help, UUID user) {
public void applyKick(Player player) {
player.kick(this.getComponent());
Bukkit.getScheduler().runTask(Main.instance(), () -> player.kick(this.getComponent()));
}
public Component getComponent() {
return Component.text()

@ -33,4 +33,5 @@ commands:
scheduleRestart:
cancelRestart:
kick:
panicBan:
panicBan:
vogelfrei: