This commit is contained in:
kento2 2026-07-07 21:38:52 +02:00
parent 7e5bd1bb6d
commit 5073d933d2
24 changed files with 168 additions and 111 deletions

View file

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="UsePropertyAccessSyntax" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>

6
.idea/kotlinc.xml generated
View file

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.0.20" />
</component>
</project>

5
.idea/misc.xml generated
View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21 (3)" project-jdk-type="JavaSDK" />
</project>

View file

@ -1,29 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="core [runServer]" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="HOST_NATS" value="nats://172.17.0.1:4222" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runServer" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>

View file

@ -1,5 +0,0 @@
all:
./gradlew build
install:
cp core-bukkit-impl/build/libs/core-bukkit-impl-all.jar /var/scrow/ /var/scrow/

View file

@ -1,5 +1,4 @@
TODO
- fix kencommandapi greedy strings & arguments: probably issue with shading
- make core-lib-impl: a library -> avoid shading massive core-lib
- logging in general, log some exceptions to game chat
- notification: Friend is now offline/online
@ -12,4 +11,4 @@ modules
- **core-bukkit-api** stateful api, for minecraft development, depends on core-lib
- **core-bukkit-api** stateful plugin, same as core-bukkit-api but implements it
- **core-velocity-api** stateful api, for proxy development, depends on core-lib
- **core-velocity-impl** stateful plugin, same as core-velocity-api but implements it
- **core-velocity-impl** stateful plugin, same as core-velocity-api but implements it

View file

@ -7,4 +7,8 @@ subprojects {
tasks.withType<Jar> {
archiveVersion = ""
}
configurations.configureEach {
resolutionStrategy.cacheChangingModulesFor(0, TimeUnit.SECONDS)
}
}

View file

@ -13,7 +13,9 @@ dependencies {
compileOnly(libs.papermc.api)
api(libs.nats)
api(libs.scrow.commandapi.bukkit)
api(libs.scrow.commandapi.bukkit) {
isChanging = true
}
}
publishing {

View file

@ -14,8 +14,12 @@ dependencies {
implementation(libs.bson)
implementation(libs.nats)
implementation(libs.scrow.commandapi.bukkit)
implementation(libs.scrow.commandapi.bukkit) {
isChanging = true
}
implementation(libs.postgres)
compileOnly(libs.luckperms)
}
tasks {

View file

@ -1,12 +1,13 @@
package de.kentoj.scrow.bukkit;
import de.kentoj.scrow.bukkit.chatstyle.ChatStyleListener;
import de.kentoj.scrow.bukkit.chatstyle.NoPrefixPrefixCache;
import de.kentoj.scrow.bukkit.command.economy.CoinsCommand;
import de.kentoj.scrow.bukkit.command.friends.FriendCommand;
import de.kentoj.scrow.bukkit.command.instance.InstanceCache;
import de.kentoj.scrow.bukkit.command.instance.InstanceCommand;
import de.kentoj.scrow.bukkit.command.instance.LobbyCommand;
import de.kentoj.scrow.bukkit.command.instance.PlayCommand;
import de.kentoj.scrow.bukkit.listener.ChatStyleListener;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.IOException;
@ -15,7 +16,7 @@ import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
public class CoreImplPlugin extends JavaPlugin {
public final class CoreImplPlugin extends JavaPlugin {
@Override
public void onEnable() {
@ -29,7 +30,7 @@ public class CoreImplPlugin extends JavaPlugin {
ScrowAPI.getCommandApi().register(new LobbyCommand().getRootLiteral());
}
getServer().getPluginManager().registerEvents(new ChatStyleListener(), this);
getServer().getPluginManager().registerEvents(new ChatStyleListener(new NoPrefixPrefixCache()), this);
// TODO/FIXME
//registerServer();

View file

@ -15,7 +15,6 @@ import de.kentoj.scrowlib.instancemanager.InstanceManagerImpl;
import de.kentoj.scrowlib.messaging.InMemoyMessageBroker;
import de.kentoj.scrowlib.messaging.NatsMessageBroker;
import de.kentoj.scrowlib.player.NetworkPlayerImpl;
import de.kentoj.scrowlib.utils.EnvUtils;
import io.nats.client.Nats;
import io.nats.client.Options;
import lombok.AccessLevel;
@ -35,7 +34,7 @@ public class ScrowAPISurface {
ScrowAPI.setCorePlugin(plugin);
var natsHost = System.getenv("HOST_NATS");
if (natsHost!= null) {
if (natsHost != null) {
try {
var options = Options.builder()
.server(natsHost)
@ -56,7 +55,7 @@ public class ScrowAPISurface {
Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader());
var props = new Properties();
props.setProperty("user", "postgres");
ScrowAPI.setJdbi(Jdbi.create(hostPostgres));
ScrowAPI.setJdbi(Jdbi.create(hostPostgres, props));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}

View file

@ -0,0 +1,32 @@
package de.kentoj.scrow.bukkit.chatstyle;
import de.kentoj.scrowlib.utils.ComponentUtils;
import io.papermc.paper.event.player.AsyncChatEvent;
import lombok.RequiredArgsConstructor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
@RequiredArgsConstructor
public class ChatStyleListener implements Listener {
private final PrefixCache prefixCache;
@EventHandler
public void onChat(AsyncChatEvent ev) {
Component formattedMessage = formatMessage(ev.getPlayer(), ev.message());
ev.renderer((source, sourceDisplayName, message, viewer) -> formattedMessage);
}
private Component formatMessage(Player player, Component message) {
var prefix = prefixCache.getPrefix(player.getUniqueId());
Component msg = prefix != null
? prefix.append(Component.text("").color(NamedTextColor.DARK_GRAY))
: Component.empty();
return msg.append(Component.text(player.getName() + ": ").color(NamedTextColor.GRAY))
.append(ComponentUtils.resolveURLS(message).colorIfAbsent(NamedTextColor.GRAY));
}
}

View file

@ -0,0 +1,36 @@
package de.kentoj.scrow.bukkit.chatstyle;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.event.user.UserDataRecalculateEvent;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class LuckPermsPrefixCache implements PrefixCache {
private final Map<UUID, Component> cache = new HashMap<>();
// TODO load on join, unload on quit
public LuckPermsPrefixCache(LuckPerms luckPerms) {
//noinspection resource
luckPerms.getEventBus().subscribe(UserDataRecalculateEvent.class, this::onDataChange);
}
private void onDataChange(UserDataRecalculateEvent ev) {
var playerId = ev.getUser().getUniqueId();
if (Bukkit.getPlayer(playerId) == null) return;
var prefix = ev.getUser().getCachedData().getMetaData().getPrefix();
var prefixComponent = PlainTextComponentSerializer.plainText().deserialize(prefix);
cache.put(playerId, prefixComponent);
}
@Override
public @Nullable Component getPrefix(UUID playerId) {
return cache.get(playerId);
}
}

View file

@ -0,0 +1,13 @@
package de.kentoj.scrow.bukkit.chatstyle;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public class NoPrefixPrefixCache implements PrefixCache {
@Override
public @Nullable Component getPrefix(UUID playerId) {
return null;
}
}

View file

@ -0,0 +1,11 @@
package de.kentoj.scrow.bukkit.chatstyle;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
public interface PrefixCache {
@Nullable Component getPrefix(UUID playerId);
}

View file

@ -1,29 +0,0 @@
package de.kentoj.scrow.bukkit.listener;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
public class ChatStyleListener implements Listener {
@EventHandler
public void onChat(AsyncChatEvent event) {
Player player = event.getPlayer();
Component formattedMessage = formatMessage(player, event.message());
event.renderer((source, sourceDisplayName, message, viewer) -> formattedMessage);
}
private Component formatMessage(Player player, Component message) {
return Component.text()
.append(player.displayName()
.append(Component.text(": "))
.color(NamedTextColor.GRAY))
.append(message.color(NamedTextColor.WHITE))
.build();
}
}

View file

@ -13,7 +13,9 @@ dependencies {
compileOnly(libs.adventure.api)
compileOnly(libs.adventure.minimessage)
api(libs.bson)
api(libs.scrow.commandapi.core)
api(libs.scrow.commandapi.core) {
this.isChanging = true
}
}
publishing {

View file

@ -0,0 +1,23 @@
package de.kentoj.scrowlib.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextReplacementConfig;
import net.kyori.adventure.text.event.ClickEvent;
import java.util.regex.Pattern;
@NoArgsConstructor(access = AccessLevel.NONE)
public class ComponentUtils {
private static final Pattern URL_REGEX = Pattern.compile("(https?://)?[a-z0-9]+(\\.[a-z0-9]+)*(\\.[a-z0-9]{1,10})((/+)[^/ ]*)*", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
private static final TextReplacementConfig REPLACER = TextReplacementConfig.builder()
.match(URL_REGEX)
.replacement((c) -> c.clickEvent(ClickEvent.openUrl(c.content().startsWith("http") ? c.content() : "https://" + c.content())))
.build();
public static Component resolveURLS(Component component) {
return component.replaceText(REPLACER);
}
}

View file

@ -12,7 +12,9 @@ dependencies {
api(project(":core-lib"))
api(libs.velocity.api)
api(libs.scrow.commandapi.velocity)
api(libs.scrow.commandapi.velocity) {
isChanging = true
}
}
publishing {

View file

@ -1,47 +1,53 @@
package de.kentoj.scrow.corevelocity;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import de.kentoj.scrow.corevelocity.command.OnlineCommand;
import de.kentoj.scrow.corevelocity.misc.OnlineCommand;
import de.kentoj.scrow.corevelocity.network.FriendNotifications;
import de.kentoj.scrow.corevelocity.network.SendPlayerWatchdog;
import de.kentoj.scrow.corevelocity.network.ServerRegisterWatchdog;
import de.kentoj.scrow.corevelocity.privmsg.LastTargetCache;
import de.kentoj.scrow.corevelocity.privmsg.MsgCommand;
import de.kentoj.scrow.corevelocity.privmsg.PrivMsgHandler;
import de.kentoj.scrow.corevelocity.privmsg.ReplyCommand;
import de.kentoj.scrow.corevelocity.network.SendPlayerWatchdog;
import de.kentoj.scrow.corevelocity.network.ServerRegisterWatchdog;
import de.kentoj.scrow.generated.BuildInfo;
import de.kentoj.scrow.velocity.ScrowAPI;
import de.kentoj.scrowlib.convention.ScrowMessageStyle;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import net.kyori.adventure.text.format.NamedTextColor;
@Slf4j
@Plugin(
id = "corevelocity",
name = "CoreVelocity",
authors = {"gradlehater57"},
version = BuildInfo.VERSION // may not resolve until building for the first time
)
@Log
public class CoreVelocityPlugin {
public final class CoreVelocityPlugin {
@Inject
public CoreVelocityPlugin(ProxyServer server) {
private ProxyServer server;
@Subscribe
private void onInit(ProxyInitializeEvent __) {
ScrowAPISurface.initScrowAPI(server);
var cmds = ScrowAPI.getCommandApi();
{
var lastTargetCache = new LastTargetCache();
var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE);
var privmsgHelper = new PrivMsgHandler(style);
cmds.register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).getRootLiteral());
cmds.register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).getRootLiteral());
cmds.register(new OnlineCommand(server).getRootLiteral());
}
var lastTargetCache = new LastTargetCache();
var style = new ScrowMessageStyle("MSG", NamedTextColor.LIGHT_PURPLE);
var privmsgHelper = new PrivMsgHandler(style);
cmds.register(new ReplyCommand(server, lastTargetCache, privmsgHelper, style).getRootLiteral());
cmds.register(new MsgCommand(server, lastTargetCache, privmsgHelper, style).getRootLiteral());
cmds.register(new OnlineCommand(server).getRootLiteral());
var registerWatchdog = new ServerRegisterWatchdog(server);
var sendPlayerWatchdog = new SendPlayerWatchdog(server);
registerWatchdog.listen();
sendPlayerWatchdog.listen();
server.getEventManager().register(this, new FriendNotifications());
}
}

View file

@ -45,7 +45,7 @@ public class ScrowAPISurface {
Class.forName("org.postgresql.Driver", true, ScrowAPISurface.class.getClassLoader());
var props = new Properties();
props.setProperty("user", "postgres");
ScrowAPI.setJdbi(Jdbi.create(hostPostgres));
ScrowAPI.setJdbi(Jdbi.create(hostPostgres, props));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}

View file

@ -1,4 +1,4 @@
package de.kentoj.scrow.corevelocity.command;
package de.kentoj.scrow.corevelocity.misc;
import com.leakyabstractions.result.api.Result;
import com.leakyabstractions.result.core.Results;

View file

@ -13,7 +13,7 @@ public class PrivMsgHandler {
private final ScrowMessageStyle style;
public void handle(Player player, Player target, String msg) {
target.sendMessage(style.ok(text(player.getUsername() + " -> You: ").append(Component.text(msg))));
player.sendMessage(style.ok(text("You -> " + player.getUsername() + ": ").append(Component.text(msg))));
target.sendMessage(style.ok(text(target.getUsername() + " -> You: ").append(Component.text(msg))));
player.sendMessage(style.ok(text("You -> " + target.getUsername() + ": ").append(Component.text(msg))));
}
}

View file

@ -8,6 +8,7 @@ papermc = "1.21.11-rc3-R0.1-SNAPSHOT"
velocity = "3.5.0-SNAPSHOT"
bson = "5.8.0"
adventure = "5.2.0"
luckperms = "5.5"
[plugins]
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
@ -29,6 +30,8 @@ papermc-api = { module = "io.papermc.paper:paper-api", version.ref = "papermc" }
velocity-api = { module = "com.velocitypowered:velocity-api", version.ref = "velocity" }
adventure-api = { module = "net.kyori:adventure-api", version.ref = "adventure" }
adventure-minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure" }
# https://luckperms.net/wiki/Developer-API
luckperms = { module = "net.luckperms:api", version.ref = "luckperms" }
# http://forge.kentoj.de/scrow/-/packages/maven/de.kentoj.scrow:kencommandapi-core
scrow-commandapi-core = { module = "de.kentoj.scrow:kencommandapi-core", version.ref = "scrow-commandapi" }