Fix several issues on Gem Hunters, including a duping attack vector resulting from combat logger inventory desync

This commit is contained in:
AlexTheCoder 2017-05-14 01:18:23 -04:00 committed by cnr
parent cc98f4fdd5
commit b73958ec96
5 changed files with 126 additions and 64 deletions

View File

@ -26,15 +26,10 @@ import mineplex.core.updater.event.UpdateEvent;
import mineplex.core.utils.UtilGameProfile;
import mineplex.gemhunters.death.event.QuitNPCDespawnEvent;
import mineplex.gemhunters.economy.EconomyModule;
import mineplex.gemhunters.loot.InventoryModule;
import mineplex.gemhunters.quest.QuestModule;
import mineplex.gemhunters.quest.QuestPlayerData;
public class QuitNPC implements Listener
{
// Managers
private final QuitNPCModule _npc;
private final DisguiseManager _disguise;
// Time
@ -52,10 +47,9 @@ public class QuitNPC implements Listener
private final int _gems;
public QuitNPC(QuitNPCModule npc, Player player, long quitMills)
public QuitNPC(Player player, long quitMills)
{
// Managers
_npc = npc;
_disguise = Managers.get(DisguiseManager.class);
// Time
@ -162,7 +156,6 @@ public class QuitNPC implements Listener
if (killer != null)
{
_npc.setKilledBy(_uuid, killer.getName());
Managers.get(EconomyModule.class).addToStore(killer, "Killing " + F.name(_name + "'s") + " NPC", (int) (_gems * EconomyModule.GEM_KILL_FACTOR));
}
@ -192,4 +185,4 @@ public class QuitNPC implements Listener
{
return _uuid;
}
}
}

View File

@ -1,40 +1,38 @@
package mineplex.gemhunters.death.quitnpc;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import mineplex.core.common.util.UtilPlayer;
import mineplex.gemhunters.economy.CashOutModule;
import org.bukkit.GameMode;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent;
import mineplex.core.MiniPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.common.util.F;
import mineplex.core.common.util.C;
import mineplex.core.common.util.UtilPlayer;
import mineplex.core.common.util.UtilServer;
import mineplex.core.texttutorial.TextTutorialManager;
import mineplex.gemhunters.death.event.QuitNPCDespawnEvent;
import mineplex.gemhunters.death.event.QuitNPCSpawnEvent;
import mineplex.gemhunters.economy.event.PlayerCashOutCompleteEvent;
import mineplex.gemhunters.economy.CashOutModule;
@ReflectivelyCreateMiniPlugin
public class QuitNPCModule extends MiniPlugin
{
private static final long LOG_OUT_TIME = TimeUnit.SECONDS.toMillis(60);
private final CashOutModule _cashOut;
private final Map<UUID, QuitNPC> _npcs;
private final Map<UUID, String> _killedBy;
private final String _serverName;
private final QuitNPCRepository _repo;
private QuitNPCModule()
{
@ -43,7 +41,8 @@ public class QuitNPCModule extends MiniPlugin
_cashOut = require(CashOutModule.class);
_npcs = new HashMap<>();
_killedBy = new HashMap<>();
_serverName = UtilServer.getServerName();
_repo = new QuitNPCRepository();
}
public void spawnNpc(Player player)
@ -73,7 +72,8 @@ public class QuitNPCModule extends MiniPlugin
return;
}
_npcs.put(player.getUniqueId(), new QuitNPC(this, player, LOG_OUT_TIME));
_npcs.put(player.getUniqueId(), new QuitNPC(player, LOG_OUT_TIME));
_repo.insertNpc(player.getUniqueId(), _serverName);
}
@EventHandler(priority = EventPriority.LOWEST)
@ -93,23 +93,30 @@ public class QuitNPCModule extends MiniPlugin
public void npcDespawn(QuitNPCDespawnEvent event)
{
log("Despawning npc for " + _npcs.remove(event.getNpc().getUniqueId()).getName());
_repo.deleteNpc(event.getNpc().getUniqueId());
}
@EventHandler
public void playerJoin(PlayerJoinEvent event)
@EventHandler(priority = EventPriority.HIGHEST)
public void onLogin(AsyncPlayerPreLoginEvent event)
{
Player player = event.getPlayer();
UUID key = player.getUniqueId();
if (_killedBy.containsKey(key))
try
{
player.sendMessage(F.main("Game", "You were killed while you were logged out. You were killed by " + F.name(_killedBy.remove(key)) + "."));
String npcServer = _repo.loadNpcServer(event.getUniqueId()).get();
if (npcServer == null || npcServer.isEmpty())
{
return;
}
if (npcServer.equals(_serverName))
{
return;
}
event.disallow(Result.KICK_OTHER, C.cRed + "You have a combat logger alive on " + npcServer + "! Either wait for it to despawn or join that server directly!");
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public void setKilledBy(UUID dead, String killedBy)
{
_killedBy.put(dead, killedBy);
}
public QuitNPC getNPC(Player player)
@ -121,5 +128,4 @@ public class QuitNPCModule extends MiniPlugin
{
return _npcs.containsKey(player.getUniqueId());
}
}
}

View File

@ -0,0 +1,69 @@
package mineplex.gemhunters.death.quitnpc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import mineplex.core.common.util.UtilServer;
import mineplex.serverdata.database.DBPool;
import mineplex.serverdata.database.RepositoryBase;
import mineplex.serverdata.database.column.ColumnVarChar;
public class QuitNPCRepository extends RepositoryBase
{
private static final String GET_DATA = "SELECT serverName FROM gemHuntersQuitNpcs WHERE uuid=?;";
private static final String INSERT_DATA = "INSERT INTO gemHuntersQuitNpcs (uuid, serverName) VALUES (?, ?);";
private static final String DELETE_DATA = "DELETE FROM gemHuntersQuitNpcs WHERE uuid=?;";
public QuitNPCRepository()
{
super(DBPool.getAccount());
}
public CompletableFuture<String> loadNpcServer(UUID uuid)
{
return CompletableFuture.supplyAsync(() ->
{
try (Connection conn = getConnection())
{
PreparedStatement stmt = conn.prepareStatement(GET_DATA);
stmt.setString(1, uuid.toString());
String serverName = null;
ResultSet resultSet = stmt.executeQuery();
if (resultSet.next())
{
serverName = resultSet.getString("serverName");
}
return serverName;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
});
}
public void deleteNpc(UUID uuid)
{
final String uuidStr = uuid.toString();
UtilServer.runAsync(() ->
{
executeUpdate(DELETE_DATA, new ColumnVarChar("uuid", uuidStr.length(), uuidStr));
});
}
public void insertNpc(UUID uuid, String serverName)
{
final String uuidStr = uuid.toString();
UtilServer.runAsync(() ->
{
executeInsert(INSERT_DATA, null, new ColumnVarChar("uuid", uuidStr.length(), uuidStr), new ColumnVarChar("serverName", serverName.length(), serverName));
});
}
}

View File

@ -1,30 +1,28 @@
package mineplex.gemhunters.join;
import java.util.function.Consumer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import mineplex.core.MiniPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.account.CoreClient;
import mineplex.core.account.CoreClientManager;
import mineplex.core.inventory.InventoryManager;
import mineplex.gemhunters.death.quitnpc.QuitNPC;
import mineplex.gemhunters.death.quitnpc.QuitNPCModule;
import mineplex.gemhunters.economy.EconomyModule;
import mineplex.gemhunters.loot.InventoryModule;
import mineplex.gemhunters.map.ItemMapModule;
import mineplex.gemhunters.persistence.PersistenceData;
import mineplex.gemhunters.persistence.PersistenceModule;
import mineplex.gemhunters.persistence.PersistenceRepository;
import mineplex.gemhunters.quest.QuestModule;
import mineplex.gemhunters.spawn.SpawnModule;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerJoinEvent;
import java.util.function.Consumer;
@ReflectivelyCreateMiniPlugin
public class JoinModule extends MiniPlugin
{
private final CoreClientManager _client;
private final EconomyModule _economy;
private final QuestModule _quest;
@ -81,9 +79,9 @@ public class JoinModule extends MiniPlugin
if (!repository.exists(client))
{
_spawn.teleportToSpawn(player);
runSync(() -> _spawn.teleportToSpawn(player));
}
});
}
}
}

View File

@ -1,5 +1,19 @@
package mineplex.gemhunters.persistence;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import mineplex.core.MiniPlugin;
import mineplex.core.ReflectivelyCreateMiniPlugin;
import mineplex.core.account.CoreClient;
@ -12,24 +26,6 @@ import mineplex.gemhunters.economy.EconomyModule;
import mineplex.gemhunters.loot.InventoryModule;
import mineplex.gemhunters.quest.QuestModule;
import mineplex.gemhunters.quest.QuestPlayerData;
import mineplex.serverdata.commands.ServerTransfer;
import net.minecraft.server.v1_8_R3.EntityItemFrame;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ReflectivelyCreateMiniPlugin
public class PersistenceModule extends MiniPlugin
@ -149,4 +145,4 @@ public class PersistenceModule extends MiniPlugin
{
return _repository;
}
}
}