Files
sweetgum-server/src/main/java/service/BanService.java
2024-10-03 21:36:04 +02:00

209 lines
7.4 KiB
Java

package service;
import client.Character;
import client.Client;
import client.autoban.AutobanFactory;
import config.YamlConfig;
import database.account.Account;
import lombok.extern.slf4j.Slf4j;
import net.packet.Packet;
import net.server.Server;
import net.server.coordinator.session.Hwid;
import server.TimerManager;
import server.ban.HwidBanManager;
import server.ban.IpBanManager;
import server.ban.MacBanManager;
import tools.PacketCreator;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
public class BanService {
private final AccountService accountService;
private final TransitionService transitionService;
private final IpBanManager ipBanManager;
private final MacBanManager macBanManager;
private final HwidBanManager hwidBanManager;
public BanService(AccountService accountService, TransitionService transitionService, IpBanManager ipBanManager,
MacBanManager macBanManager, HwidBanManager hwidBanManager) {
this.accountService = accountService;
this.transitionService = transitionService;
this.ipBanManager = ipBanManager;
this.macBanManager = macBanManager;
this.hwidBanManager = hwidBanManager;
}
public void autoban(Character chr, AutobanFactory type, String reason) {
autoban(chr, "Autobanned for (" + type.name() + ": " + reason + ")");
}
private void autoban(Character chr, String reason) {
if (isExempt(chr)) {
return;
}
chr.setBanned();
accountService.ban(chr.getAccountID(), null, (byte) 0, reason);
chr.sendPacket(PacketCreator.sendPolice("You have been blocked by the#b %s Police for HACK reason.#k".formatted("Cosmic")));
TimerManager.getInstance().schedule(() -> transitionService.disconnect(chr.getClient(), false),
TimeUnit.SECONDS.toMillis(5));
var bannedName = Character.makeMapleReadable(chr.getName());
Packet autobanGmNotice = PacketCreator.serverNotice(6, bannedName + " was autobanned for " + reason);
Server.getInstance().broadcastGMMessage(chr.getWorld(), autobanGmNotice);
}
public void addPoint(Character chr, AutobanFactory type, String reason) {
if (isExempt(chr)) {
return;
}
var autobanManager = chr.getAutobanManager();
boolean shouldAutoban = autobanManager.addPoint(type);
if (shouldAutoban) {
autoban(chr, type, reason);
}
if (YamlConfig.config.server.USE_AUTOBAN_LOG) {
log.info("Autoban - chr {} caused {} {}", Character.makeMapleReadable(chr.getName()), type.name(), reason);
}
}
private boolean isExempt(Character chr) {
return !YamlConfig.config.server.USE_AUTOBAN || chr.isGM() || chr.isBanned();
}
public void permaBan(Client c, String victimName, byte reason, String description) {
ban(c, victimName, null, reason, description);
}
public void tempBan(Client c, String victimName, Duration duration, byte reason, String description) {
ban(c, victimName, duration, reason, description);
}
private void ban(Client c, String victimName, Duration duration, byte reason, String description) {
Character victim = c.getChannelServer().getPlayerStorage().getCharacterByName(victimName);
boolean success;
if (victim == null) {
success = banOfflineChr(victimName, duration, reason, description);
} else {
success = banOnlineChr(c, victim, duration, reason, description);
}
if (!success) {
c.sendPacket(PacketCreator.getGMEffect(6, (byte) 1));
return;
}
c.sendPacket(PacketCreator.getGMEffect(4, (byte) 0));
Server.getInstance().broadcastMessage(c.getWorld(), PacketCreator.serverNotice(6, "%s has been banned.".formatted(victimName)));
}
private boolean banOfflineChr(String victimName, Duration duration, byte reason, String description) {
Optional<Account> foundAccount = accountService.getAccountIdByChrName(victimName);
if (foundAccount.isEmpty()) {
return false;
}
Account account = foundAccount.get();
saveBan(account.id(), duration, reason, description);
banIp(account.ip(), account.id());
banMacs(account.macs(), account.id());
banHwid(account.hwid(), account.id());
return true;
}
private boolean banOnlineChr(Client c, Character victim, Duration duration, byte reason, String description) {
victim.setBanned();
String readableName = Character.makeMapleReadable(victim.getName());
String ip = victim.getClient().getRemoteAddress();
String enrichedDescription = "[%s] %s (IP: %s)".formatted(description, readableName, ip);
saveBan(victim.getAccountID(), duration, reason, enrichedDescription);
banIp(ip, victim.getAccountID());
Account victimAccount = victim.getClient().getAccount();
banMacs(victimAccount.macs(), victim.getAccountID());
banHwid(victimAccount.hwid(), victim.getAccountID());
victim.sendPacket(PacketCreator.sendPolice("You have been banned by %s.".formatted(c.getPlayer().getName())));
TimerManager.getInstance().schedule(() -> transitionService.disconnect(victim.getClient(), true),
TimeUnit.SECONDS.toMillis(5));
return true;
}
private void saveBan(int accountId, Duration duration, byte reason, String description) {
final Instant bannedUntil;
if (duration != null) {
bannedUntil = Instant.now().plus(duration);
} else {
bannedUntil = null;
}
accountService.ban(accountId, bannedUntil, reason, description);
}
private void banIp(String ip, int accountId) {
if (ip == null || ip.isEmpty()) {
return;
}
ipBanManager.banIp(ip, accountId);
}
private void banMacs(String macs, int accountId) {
if (macs == null || macs.isEmpty()) {
return;
}
List<String> macsToBan = Arrays.asList(macs.split(", "));
macsToBan.forEach(mac -> macBanManager.banMac(mac, accountId));
}
private void banHwid(Hwid hwid, int accountId) {
if (hwid == null) {
return;
}
hwidBanManager.banHwid(hwid, accountId);
}
public boolean unban(String chrName) {
Optional<Account> foundAccount = accountService.getAccountIdByChrName(chrName);
if (foundAccount.isEmpty()) {
return false;
}
int accountId = foundAccount.get().id();
accountService.unban(accountId);
ipBanManager.unbanAccountIps(accountId);
macBanManager.unbanAccountMacs(accountId);
hwidBanManager.unbanAccountHwids(accountId);
return true;
}
public boolean isBanned(Client c) {
return isIpBanned(c) || isHwidBanned(c) || isMacBanned(c);
}
private boolean isIpBanned(Client c) {
String ip = c.getRemoteAddress();
return ip != null && ipBanManager.isBanned(ip);
}
private boolean isHwidBanned(Client c) {
Hwid hwid = c.getHwid();
return hwid != null && hwidBanManager.isBanned(hwid);
}
private boolean isMacBanned(Client c) {
Set<String> macs = c.getMacs();
return macs.stream().anyMatch(macBanManager::isBanned);
}
}