Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,29 @@ public class GivenCommands {
@Getter @Setter
private static PlaytimeCommand playtimeCommand;
@Getter @Setter
private static PTagCommand pTagCommand;
@Getter @Setter
private static ReloadCommand reloadCommand;
@Getter @Setter
private static SetServerCommand setServerCommand;
@Getter @Setter
private static SyncCommand syncCommand;

public static void init() {
setModulesCommand(new ModulesCommand());
setParseCommand(new ParseCommand());
setPlaytimeCommand(new PlaytimeCommand());
setPTagCommand(new PTagCommand());
setReloadCommand(new ReloadCommand());
setSetServerCommand(new SetServerCommand());
setSyncCommand(new SyncCommand());

getModulesCommand().register();
getParseCommand().register();
getPlaytimeCommand().register();
getPTagCommand().register();
getReloadCommand().register();
getSetServerCommand().register();
getSyncCommand().register();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
package net.streamline.api.base.timers;

import lombok.Getter;
import lombok.Setter;
import singularity.configs.given.GivenConfigs;
import singularity.data.teleportation.TPTicket;
import singularity.utils.MessageUtils;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;

public abstract class AbstractPlayerTeleporter extends Thread {
public static final long TICKING_FREQUENCY = 50L; // Milliseconds

@Getter @Setter
private static AbstractPlayerTeleporter instance;

@Getter @Setter
private static AtomicReference<TeleportStage> stage = new AtomicReference<>(TeleportStage.READY);

@Getter @Setter
private static AtomicLong lastRun = new AtomicLong(0);

public enum TeleportStage {
COLLECTION,
TELEPORTATION,
READY;
}

/**
* Start the teleporter instance.
*/
public static synchronized void startInstance() {
if (instance == null) {
throw new IllegalStateException("Teleporter instance is not set.");
}
if (! instance.isAlive()) {
instance.start();
}
}

/**
* Stop the teleporter instance safely.
*/
public static synchronized void stopInstance() {
if (instance != null && instance.isAlive()) {
instance.interrupt();
try {
instance.join(); // Wait for the thread to finish
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Restore interrupt status
} finally {
instance = null;
}
}
}

/**
* Check if the teleporter can tick again based on the last run time.
*/
public static boolean isAbleToRunAgain() {
long currentTime = System.currentTimeMillis();
long lastRunTime = lastRun.get();

if (lastRunTime == 0 || (lastRunTime + TICKING_FREQUENCY < currentTime)) {
lastRun.set(currentTime);
return true;
}
return false;
}

/**
* Abstract constructor with a custom thread name.
*/
public AbstractPlayerTeleporter() {
super("SL - Player Teleporter");
}

/**
* Main run loop for the teleporter thread.
*/
@Override
public void run() {
while (! isInterrupted()) {
try {
tick();
} catch (Throwable e) {
MessageUtils.logWarning("Error during teleporter tick: ", e);
}
try {
Thread.sleep(TICKING_FREQUENCY);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // Preserve interrupt status
break; // Exit the loop
}
}
}

@Getter @Setter
private static AtomicReference<CompletableFuture<ConcurrentSkipListSet<TPTicket>>> atomicTicketsPending = new AtomicReference<>(null);

public CompletableFuture<ConcurrentSkipListSet<TPTicket>> getTicketsPending() {
if (getAtomicTicketsPending().get() == null) {
getAtomicTicketsPending().set(GivenConfigs.getMainDatabase().pullAllTPTickets());
}

return getAtomicTicketsPending().get();
}

public void unpendTickets() {
getAtomicTicketsPending().set(null);
}

public boolean areTicketsPending() {
return getAtomicTicketsPending().get() != null;
}

/**
* Perform a single tick action if the teleporter is ready.
*/
public void contemplateTick() {
if (isAbleToRunAgain()) {
tick();
}
}

/**
* Abstract tick method to be implemented by subclasses.
*/
public abstract void tick();

/**
* Clear the ticket and log the action.
*
* @param ticket The teleportation ticket to clear.
* @param instance The instance ID for logging.
*/
private static void clearTicket(TPTicket ticket, int instance) {
if (ticket != null) {
ticket.clear();
MessageUtils.logInfo("Cleared teleportation ticket for player " + ticket.getIdentifier() + ". [" + instance + "]");
}
}
}
13 changes: 9 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ subprojects {
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
maven { url "https://oss.sonatype.org/content/repositories/central" }
// Paper / Velocity
maven { url "https://repo.papermc.io/repository/maven-public" }
maven {
name = 'papermc'
url = 'https://repo.papermc.io/repository/maven-public/'
}
// Fabric
maven { url "https://maven.fabricmc.net" }
maven { url "https://libraries.minecraft.net" }
Expand All @@ -69,6 +72,11 @@ subprojects {
maven { url "https://repo.extendedclip.com/content/repositories/placeholderapi" }
}

java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}

processResources {
// Debugging: Print values
doFirst {
Expand All @@ -80,9 +88,6 @@ subprojects {
inputs.property("main", project.ext.pluginMain.toString())
outputs.dir(file("build/generated-src"))

java.sourceCompatibility = JavaVersion.VERSION_11
java.targetCompatibility = JavaVersion.VERSION_11

filesMatching("**/plugin.yml") {
expand (
"name": rootProject.name.toString(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,96 +1,65 @@
package net.streamline.base.runnables;

import lombok.Getter;
import lombok.Setter;
import net.md_5.bungee.api.ServerConnectRequest;
import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ServerConnectEvent;
import net.streamline.api.base.timers.AbstractPlayerTeleporter;
import net.streamline.base.Streamline;
import singularity.configs.given.GivenConfigs;
import singularity.data.teleportation.TPTicket;
import singularity.utils.MessageUtils;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class PlayerTeleporter extends Thread {
public static final long TICKING_FREQUENCY = 50L;

@Getter @Setter
private static PlayerTeleporter instance;
public class PlayerTeleporter extends AbstractPlayerTeleporter {
// private static final ExecutorService executor = Executors.newFixedThreadPool(4); // Adjust as needed

public static void init() {
instance = new PlayerTeleporter();
instance.start();
setInstance(new PlayerTeleporter());
startInstance();
}

public static void stopInstance() {
try {
if (instance != null) {
instance.interrupt();
instance = null;
}
} catch (Exception e) {
// ignore
}
}

@Getter @Setter
private static AtomicReference<TeleportStage> stage = new AtomicReference<>(TeleportStage.READY);
@Getter @Setter
private static AtomicLong lastRun = new AtomicLong(0);

public enum TeleportStage {
COLLECTION,
TELEPORTATION,
READY,
;
}
@Override
public void tick() {
if (areTicketsPending()) return;

public static boolean isAbleToRunAgain() {
return lastRun.get() + TICKING_FREQUENCY < System.currentTimeMillis();
}
getStage().set(TeleportStage.COLLECTION);
ConcurrentSkipListSet<TPTicket> tickets = getTicketsPending().join();

public static void setLastRun() {
lastRun.set(System.currentTimeMillis());
}
getStage().set(TeleportStage.TELEPORTATION);
// tickets.forEach(ticket -> executor.submit(() -> processTicket(ticket)));
tickets.forEach(this::processTicket);

public PlayerTeleporter() {
super("SL - Player Teleporter");
unpendTickets();
getStage().set(TeleportStage.READY);
}

@Override
public void run() {
if (! isAbleToRunAgain()) return;

setLastRun();

stage.set(TeleportStage.COLLECTION);
ConcurrentSkipListSet<TPTicket> tickets = GivenConfigs.getMainDatabase().pullAllTPTickets().join();

stage.set(TeleportStage.TELEPORTATION);
tickets.forEach(ticket -> {
if (ticket.getCreateDate().before(new Date(System.currentTimeMillis() - 7 * 1000))) {
ticket.clear();
private void processTicket(TPTicket ticket) {
try {
if (ticket.getCreateDate().before(new Date(System.currentTimeMillis() - (7 * 1000)))) {
clearTicket(ticket, 1);
return;
}

ProxiedPlayer player = Streamline.getInstance().getProxy().getPlayer(UUID.fromString(ticket.getIdentifier()));
if (player == null) {
ticket.clear();
clearTicket(ticket, 2);
return;
}

teleportPlayerAsync(player, ticket.getTargetServer().getIdentifier());
});

stage.set(TeleportStage.READY);
// clearTicket(ticket, 3); // Handled by the Spigot side
} catch (Exception e) {
MessageUtils.logWarning("Error processing ticket: " + ticket.getIdentifier(), e);
}
}

private static void teleportPlayerAsync(ProxiedPlayer player, String server) {
private void teleportPlayerAsync(ProxiedPlayer player, String server) {
ServerInfo targetServer = Streamline.getInstance().getProxy().getServerInfo(server);
if (targetServer != null) {
ServerConnectRequest request = ServerConnectRequest.builder()
Expand All @@ -100,4 +69,9 @@ private static void teleportPlayerAsync(ProxiedPlayer player, String server) {
player.connect(request);
}
}

private static void clearTicket(TPTicket ticket, int instance) {
ticket.clear();
MessageUtils.logInfo("Cleared teleportation ticket for player " + ticket.getIdentifier() + ". [" + instance + "]");
}
}
6 changes: 3 additions & 3 deletions dependencies.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
ext {
IMPL = [
"com.github.ben-manes.caffeine:caffeine:3.1.8",
"com.github.server-utilities:TheBase:${rootProject.properties['base-version']}",
"com.github.Server-Utilities:TheBase:master-SNAPSHOT",
"org.pf4j:pf4j:3.10.0",
"commons-codec:commons-codec:1.5",
]
SHADOW = [
"com.github.ben-manes.caffeine:caffeine:3.1.8",
"com.github.server-utilities:TheBase:${rootProject.properties['base-version']}",
"com.github.Server-Utilities:TheBase:master-SNAPSHOT",
"org.pf4j:pf4j:3.10.0",
"commons-codec:commons-codec:1.5",
]
ANNO = [
"com.github.ben-manes.caffeine:caffeine:3.1.8",
"com.github.server-utilities:TheBase:${rootProject.properties['base-version']}",
"com.github.Server-Utilities:TheBase:master-SNAPSHOT",
"org.pf4j:pf4j:3.10.0"
]
COMP_ONLY = [
Expand Down
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ org.gradle.vfs.watch = false
# Other properties
name = StreamlineCore
group = com.github.Streamline-Essentials.StreamlineCore
version = 2.5.0.0
version = 2.5.3.0

base-version = c8388399
base-version = 6f2e7e2d

plugin.main = default
Loading