content: package emu.grasscutter.game.dungeons;
  
  import emu.grasscutter.GameConstants;
  import emu.grasscutter.Grasscutter;
  import emu.grasscutter.data.GameData;
  import emu.grasscutter.data.binout.ScenePointEntry;
  import emu.grasscutter.data.excels.DungeonData;
  import emu.grasscutter.game.player.Player;
  import emu.grasscutter.game.props.SceneType;
  import emu.grasscutter.game.quest.enums.QuestTrigger;
  import emu.grasscutter.game.world.Scene;
  import emu.grasscutter.net.packet.BasePacket;
  import emu.grasscutter.net.packet.PacketOpcodes;
  import emu.grasscutter.server.game.BaseGameSystem;
  import emu.grasscutter.server.game.GameServer;
  import emu.grasscutter.server.packet.send.PacketDungeonEntryInfoRsp;
  import emu.grasscutter.server.packet.send.PacketPlayerEnterDungeonRsp;
  import emu.grasscutter.utils.Position;
  
  import java.util.List;
  
  public class DungeonSystem extends BaseGameSystem {
      private static final BasicDungeonSettleListener basicDungeonSettleObserver = new BasicDungeonSettleListener();
  
      public DungeonSystem(GameServer server) {
          super(server);
      }
  
      public void getEntryInfo(Player player, int pointId) {
          ScenePointEntry entry = GameData.getScenePointEntryById(player.getScene().getId(), pointId);
  
          if (entry == null) {
              // Error
              player.sendPacket(new PacketDungeonEntryInfoRsp());
              return;
          }
  
          player.sendPacket(new PacketDungeonEntryInfoRsp(player, entry.getPointData()));
      }
  
      public boolean enterDungeon(Player player, int pointId, int dungeonId) {
          DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
  
          if (data == null) {
              return false;
          }
          Grasscutter.getLogger().info("{}({}) is trying to enter dungeon {}" ,player.getNickname(),player.getUid(),dungeonId);
  
          int sceneId = data.getSceneId();
          player.getScene().setPrevScene(sceneId);
  
          if (player.getWorld().transferPlayerToScene(player, sceneId, data)) {
              player.getScene().addDungeonSettleObserver(basicDungeonSettleObserver);
              player.getQuestManager().triggerEvent(QuestTrigger.QUEST_CONTENT_ENTER_DUNGEON, data.getId());
          }
  
          player.getScene().setPrevScenePoint(pointId);
          player.sendPacket(new PacketPlayerEnterDungeonRsp(pointId, dungeonId));
          return true;
      }
  
      /**
       * used in tower dungeons handoff
       */
      public boolean handoffDungeon(Player player, int dungeonId, List<DungeonSettleListener> dungeonSettleListeners) {
          DungeonData data = GameData.getDungeonDataMap().get(dungeonId);
  
          if (data == null) {
              return false;
          }
          Grasscutter.getLogger().info("{}({}) is trying to enter tower dungeon {}" ,player.getNickname(),player.getUid(),dungeonId);
  
          if (player.getWorld().transferPlayerToScene(player, data.getSceneId(), data)) {
              dungeonSettleListeners.forEach(player.getScene()::addDungeonSettleObserver);
          }
          return true;
      }
  
      public void exitDungeon(Player player) {
          Scene scene = player.getScene();
  
          if (scene==null || scene.getSceneType() != SceneType.SCENE_DUNGEON) {
              return;
          }
  
          // Get previous scene
          int prevScene = scene.getPrevScene() > 0 ? scene.getPrevScene() : 3;
  
          // Get previous position
          DungeonData dungeonData = scene.getDungeonData();
          Position prevPos = new Position(GameConstants.START_POSITION);
  
          if (dungeonData != null) {
              ScenePointEntry entry = GameData.getScenePointEntryById(prevScene, scene.getPrevScenePoint());
  
              if (entry != null) {
                  prevPos.set(entry.getPointData().getTranPos());
              }
          }
          // clean temp team if it has
          player.getTeamManager().cleanTemporaryTeam();
          player.getTowerManager().clearEntry();
  
          // Transfer player back to world
          player.getWorld().transferPlayerToScene(player, prevScene, prevPos);
          player.sendPacket(new BasePacket(PacketOpcodes.PlayerQuitDungeonRsp));
      }
  
      public void updateDailyDungeons() {
          GameData.getScenePointEntries().forEach((id, entry) -> entry.getPointData().updateDailyDungeon());
      }
  }
  