123 lines
4.0 KiB
Java
123 lines
4.0 KiB
Java
package com.disklexar.mmorpg.player;
|
|
|
|
import com.disklexar.mmorpg.MmorpgPlugin;
|
|
import com.disklexar.mmorpg.core.config.MmorpgConfig;
|
|
import com.disklexar.mmorpg.core.service.Service;
|
|
import com.disklexar.mmorpg.persistence.repository.PlayerProfileRepository;
|
|
import com.disklexar.mmorpg.player.model.PlayerProfile;
|
|
import com.disklexar.mmorpg.rpg.race.RaceCatalog;
|
|
import com.hypixel.hytale.logger.HytaleLogger;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
import java.sql.SQLException;
|
|
import java.util.Map;
|
|
import java.util.Optional;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.logging.Level;
|
|
|
|
/**
|
|
* Tracks online player sessions and synchronizes profiles with SQLite.
|
|
*/
|
|
public final class PlayerSessionService implements Service {
|
|
|
|
private final MmorpgPlugin plugin;
|
|
private final MmorpgConfig config;
|
|
private final PlayerProfileRepository repository;
|
|
private final HytaleLogger logger;
|
|
private final Map<UUID, PlayerProfile> sessions = new ConcurrentHashMap<>();
|
|
private final Map<UUID, Long> connectedAt = new ConcurrentHashMap<>();
|
|
|
|
public PlayerSessionService(
|
|
@Nonnull MmorpgPlugin plugin,
|
|
@Nonnull MmorpgConfig config,
|
|
@Nonnull PlayerProfileRepository repository) {
|
|
this.plugin = plugin;
|
|
this.config = config;
|
|
this.repository = repository;
|
|
this.logger = plugin.getLogger();
|
|
}
|
|
|
|
@Override
|
|
public void start() {
|
|
try {
|
|
repository.clearConnectedFlags();
|
|
} catch (SQLException e) {
|
|
logger.at(Level.WARNING).log("Failed to reset connection flags: %s", e.getMessage());
|
|
}
|
|
logger.at(Level.INFO).log("Player session service started");
|
|
}
|
|
|
|
@Override
|
|
public void shutdown() {
|
|
for (PlayerProfile profile : sessions.values()) {
|
|
accumulatePlaytime(profile.getUuid(), profile);
|
|
profile.setConnected(false);
|
|
saveQuietly(profile);
|
|
}
|
|
sessions.clear();
|
|
connectedAt.clear();
|
|
logger.at(Level.INFO).log("Player session service stopped");
|
|
}
|
|
|
|
/**
|
|
* Loads (or creates) a profile and marks the player connected.
|
|
*/
|
|
@Nonnull
|
|
public PlayerProfile loadOrCreate(@Nonnull UUID uuid, @Nonnull String displayName) throws SQLException {
|
|
long now = System.currentTimeMillis();
|
|
Optional<PlayerProfile> existing = repository.findByUuid(uuid);
|
|
PlayerProfile profile;
|
|
if (existing.isPresent()) {
|
|
profile = existing.get();
|
|
profile.setDisplayName(displayName);
|
|
} else {
|
|
profile = new PlayerProfile(uuid, displayName, now);
|
|
profile.setLevel(config.getDefaultLevel());
|
|
profile.setRaceId(RaceCatalog.DEFAULT_RACE_ID);
|
|
logger.at(Level.INFO).log("Created new MMORPG profile for %s", displayName);
|
|
}
|
|
|
|
profile.setConnected(true);
|
|
profile.setLastDateConnected(now);
|
|
profile.touch();
|
|
sessions.put(uuid, profile);
|
|
connectedAt.put(uuid, now);
|
|
saveQuietly(profile);
|
|
return profile;
|
|
}
|
|
|
|
@Nullable
|
|
public PlayerProfile getSession(@Nonnull UUID uuid) {
|
|
return sessions.get(uuid);
|
|
}
|
|
|
|
public void unload(@Nonnull UUID uuid) {
|
|
PlayerProfile profile = sessions.remove(uuid);
|
|
if (profile == null) {
|
|
return;
|
|
}
|
|
accumulatePlaytime(uuid, profile);
|
|
profile.setConnected(false);
|
|
profile.touch();
|
|
saveQuietly(profile);
|
|
}
|
|
|
|
private void accumulatePlaytime(@Nonnull UUID uuid, @Nonnull PlayerProfile profile) {
|
|
Long start = connectedAt.remove(uuid);
|
|
if (start != null) {
|
|
profile.addTimePlay(System.currentTimeMillis() - start);
|
|
}
|
|
}
|
|
|
|
private void saveQuietly(@Nonnull PlayerProfile profile) {
|
|
try {
|
|
repository.save(profile);
|
|
} catch (SQLException e) {
|
|
logger.at(Level.WARNING).log(
|
|
"Failed to save profile for %s: %s", profile.getUuid(), e.getMessage());
|
|
}
|
|
}
|
|
}
|