Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

rabbit97 님의 블로그

20일 일지 본문

프로젝트 Final

20일 일지

rabbit97 2024. 11. 20. 21:11

# 오늘의 회의 내용

 

노티피케이션을 어떻게 사용할 것인가?

 

결국 처음에 내가 구현했던 크리에이트 리스폰스 함수를 불러와서 보내는 방식으로 결정!

 

import { getGameSessionBySocket } from '../../sessions/game.session.js';
import { createResponse } from '../../utils/packet/response/createResponse.js';
import { PACKET_TYPE } from '../../constants/header.js';

const packetType = PACKET_TYPE;

// 유저 위치 업데이트 함수
const updateCharacterPosition = (gameSession, userId, x, y) => {
  const targetUser = gameSession.users.find((user) => user.id === userId);
  if (!targetUser) return false;

  targetUser.position = { x, y };
  return true;
};

// 위치 업데이트 요청 핸들러
const handlePositionUpdate = async (socket, payload) => {
  try {
    const { x, y } = payload;
    const gameSession = getGameSessionBySocket(socket);
    if (!gameSession) {
      throw new Error('해당 유저의 게임 세션이 존재하지 않습니다.');
    }

    const currentUser = gameSession.users.find((user) => user.socket === socket);
    if (!currentUser) {
      throw new Error('유저가 존재하지 않습니다.');
    }

    const opponent = gameSession.users.find((user) => user.socket !== socket);
    if (!opponent) {
      throw new Error('상대 유저가 존재하지 않습니다.');
    }

    // 위치 업데이트 호출
    const success = updateCharacterPosition(gameSession, currentUser.id, x, y);

    if (success) {
      const positionResponseData = {
        success: true,
        failCode: 0,
      };

      // 현재 유저에게 응답 전송
      const positionResponse = await createResponse(
        packetType.POSITION_UPDATE_RESPONSE,
        socket.sequence,
        positionResponseData,
      );
      socket.write(positionResponse);

      // 상대 유저에게 알림 전송
      const notificationData = {
        userId: currentUser.id,
        x,
        y,
      };

      const notificationResponse = await createResponse(
        packetType.POSITION_UPDATE_NOTIFICATION,
        opponent.socket.sequence,
        notificationData,
      );
      opponent.socket.write(notificationResponse);
    } else {
      throw new Error('캐릭터 위치 업데이트에 실패하였습니다.');
    }
  } catch (error) {
    console.error('위치 업데이트 중 에러 발생:', error.message);

    const errorResponse = createResponse(packetType.POSITION_UPDATE_RESPONSE, null, {
      success: false,
      message: 'Error updating position',
      failCode: 1,
    });
    socket.write(errorResponse);
  }
};

export default handlePositionUpdate;

 

그게에 맞춰 로직을 다시 변경하였다.

 

내일쯤이면 아마 게임 시작이 구현 될 것 같은데 이제 내 로직들을 합치면 된다

 

 

추가로 구현한 핸들러

 

디버프 관련 핸들러도 다시 수정하고

import { getGameSessionBySocket } from '../../sessions/game.session.js';
import { createResponse } from '../../utils/packet/response/createResponse.js';
import { PACKET_TYPE, WARNING_TYPE } from '../../constants/header.js';

const packetType = PACKET_TYPE;

// 디버프 전달 요청 핸들러
const handlePassDebuffRequest = async (socket, payload) => {
  try {
    const { targetUserId, debuffCardType } = payload;

    const gameSession = getGameSessionBySocket(socket);
    if (!gameSession) {
      throw new Error('해당 유저의 게임 세션이 존재하지 않습니다.');
    }

    const currentUser = gameSession.users.find((user) => user.socket === socket);
    if (!currentUser) {
      throw new Error('현재 유저가 존재하지 않습니다.');
    }

    const targetUser = gameSession.users.find((user) => user.id === targetUserId);
    if (!targetUser) {
      throw new Error('타겟 유저가 존재하지 않습니다.');
    }

    // 디버프 카드를 전달 로직 추가 (현재 유저의 핸드에서 제거 후 타겟 유저에게 추가)
    const debuffCardIndex = currentUser.character.handCards.findIndex(
      (card) => card.type === debuffCardType,
    );
    if (debuffCardIndex === -1) {
      throw new Error('유저의 핸드에 해당 디버프 카드가 존재하지 않습니다.');
    }

    const [debuffCard] = currentUser.character.handCards.splice(debuffCardIndex, 1);
    targetUser.character.debuffs.push(debuffCard.type);

    // 요청을 보낸 소켓에 성공 여부 보내기
    const passDebuffResponse = createResponse(packetType.PASS_DEBUFF_RESPONSE, socket.sequence, {
      success: true,
      failCode: 0,
    });
    socket.write(passDebuffResponse);

    // 노티피케이션 생성 및 전송
    const notificationData = {
      warningType: WARNING_TYPE,
      expectedAt: Date.now(),
    };

    const notificationResponse = createResponse(
      packetType.WARNING_NOTIFICATION,
      targetUser.socket.sequence,
      notificationData,
    );
    targetUser.socket.write(notificationResponse);
  } catch (error) {
    console.error('디버프 전달 중 에러 발생:', error.message);

    // 요청을 보낸 소켓에 실패 여부 보내기
    const errorResponse = createResponse(packetType.PASS_DEBUFF_RESPONSE, socket.sequence, {
      success: false,
      failCode: 1,
      message: error.message || 'Debuff pass failed',
    });
    socket.write(errorResponse);
  }
};

export default handlePassDebuffRequest;

 

유저 업데이트 로직도 수정을 했다

 

import { getGameSessionBySocket } from '../../sessions/game.session.js';
import { createResponse } from '../../utils/packet/response/createResponse.js';
import { PACKET_TYPE } from '../../constants/header.js';

const packetType = PACKET_TYPE;

// 유저 업데이트 알림 전송 함수
const sendUserUpdateNotification = (gameSession, payload) => {
  const userUpdatePayload = {
    // 업데이트 된 유저의 정보를 담음
    users: payload.users.map((user) => ({
      id: user.id,
      nickname: user.nickname,
      character: {
        characterType: user.character.characterType,
        roleType: user.character.roleType,
        hp: user.character.hp,
        weapon: user.character.weapon,
        stateInfo: user.character.stateInfo,
        equips: user.character.equips,
        debuffs: user.character.debuffs,
        handCards: user.character.handCards,
        bbangCount: user.character.bbangCount,
        handCardsCount: user.character.handCardsCount,
      },
    })),
  };

  gameSession.users.forEach((user) => {
    const userUpdateNotification = createResponse(
      packetType.USER_UPDATE_NOTIFICATION,
      user.socket.sequence,
      userUpdatePayload,
    );
    user.socket.write(userUpdateNotification);
  });
};

// 유저 업데이트 요청 핸들러
const handleUserUpdate = async (socket, payload) => {
  try {
    const { users } = payload;

    const gameSession = getGameSessionBySocket(socket);
    if (!gameSession) {
      throw new Error('해당 유저의 게임 세션이 존재하지 않습니다.');
    }

    // 모든 유저에게 유저 업데이트 알림 전송
    sendUserUpdateNotification(gameSession, { users });
  } catch (error) {
    console.error('유저 업데이트 중 에러 발생:', error.message);
  }
};

export default handleUserUpdate;

 

카드를 버리는 로직은 어제까지만 해도 알고리즘 풀듯이 했는데 사실 그럴 필요가 없는게

 

클라이언트 코드를 보니 대충 구현이 되어있고 서버에서는 잘 버렸는지 확인만 하면 되는거같아서

import { getGameSessionBySocket } from '../../sessions/game.session.js';
import { createResponse } from '../../utils/packet/response/createResponse.js';
import { PACKET_TYPE } from '../../constants/header.js';

const packetType = PACKET_TYPE;

// 카드 버리기 요청 핸들러
const handleDestroyCardRequest = async (socket, payload) => {
  try {
    const { destroyCards } = payload;

    const gameSession = getGameSessionBySocket(socket);
    if (!gameSession) {
      throw new Error('해당 유저의 게임 세션이 존재하지 않습니다.');
    }

    const currentUser = gameSession.users.find((user) => user.socket === socket);
    if (!currentUser) {
      throw new Error('현재 유저가 존재하지 않습니다.');
    }

    // 버릴 카드 목록에서 카드들을 제거
    destroyCards.forEach((destroyCard) => {
      for (let i = 0; i < destroyCard.count; i++) {
        const cardIndex = currentUser.character.handCards.findIndex(
          (card) => card.type === destroyCard.type,
        );
        if (cardIndex !== -1) {
          currentUser.character.handCards.splice(cardIndex, 1);
        } else {
          throw new Error(
            `유저의 핸드에 ${destroyCard.type} 타입의 카드가 충분히 존재하지 않습니다.`,
          );
        }
      }
    });

    // 현재 유저의 남은 카드 목록을 응답
    const remainingHandCards = currentUser.character.handCards.map((card) => ({
      type: card.type,
      count: card.count,
    }));

    const destroyCardResponse = createResponse(packetType.DESTROY_CARD_RESPONSE, socket.sequence, {
      handCards: remainingHandCards,
    });

    socket.write(destroyCardResponse);
  } catch (error) {
    console.error('카드 버리기 중 에러 발생:', error.message);

    // 요청을 보낸 소켓에 실패 여부 보내기
    const errorResponse = createResponse(packetType.DESTROY_CARD_RESPONSE, socket.sequence, {
      handCards: currentUser.character.handCards.map((card) => ({
        type: card.type,
        count: card.count,
      })),
    });
    socket.write(errorResponse);
  }
};

export default handleDestroyCardRequest;

 

로직을 간단하게 수정하였고

 

플리마켓 관련 로직은 아직 작성 중이다.

import { getGameSessionBySocket } from '../../sessions/game.session.js';
import { createResponse } from '../../utils/packet/response/createResponse.js';
import { GLOBAL_FAIL_CODE, PACKET_TYPE } from '../../constants/header.js';

const packetType = PACKET_TYPE;

// 플리마켓 핸들러
const handleFleaMarketPick = async (socket, payload) => {
  try {
    const { pickIndex } = payload;
    const gameSession = getGameSessionBySocket(socket);
    if (!gameSession) {
      throw new Error('해당 유저의 게임 세션이 존재하지 않습니다.');
    }

    const currentUser = gameSession.users.find((user) => user.socket === socket);
    if (!currentUser) {
      throw new Error('유저가 존재하지 않습니다.');
    }

    // 유효한 픽 인덱스인지 검증
    const isValidPickIndex = (index) => {
      // 플리마켓에서 유효한 인덱스인지 확인하는 로직을 구현
      // 일단 다른거부터
      // 플리마켓 카드 사용시 패킷 전송
      return true;
    };

    if (!isValidPickIndex(pickIndex)) {
      throw new Error('유효하지 않은 픽 인덱스입니다.');
    }

    const success = true;

    if (success) {
      const pickResponseData = {
        success: true,
        failCode: GlobalFailCode.NONE_FAILCODE,
      };

      // 현재 유저에게 응답 전송
      const pickResponse = await createResponse(
        packetType.FLEA_MARKET_PICK_RESPONSE,
        socket.sequence,
        pickResponseData,
      );
      socket.write(pickResponse);
    } else {
      throw new Error('플리마켓 픽 처리에 실패하였습니다.');
    }
  } catch (error) {
    console.error('플리마켓 픽 중 에러 발생:', error.message);

    const errorResponse = await createResponse(packetType.FLEA_MARKET_PICK_RESPONSE, null, {
      success: false,
      message: 'Error processing flea market pick',
      failCode: GLOBAL_FAIL_CODE.UNKNOWN_ERROR,
    });
    socket.write(errorResponse);
  }
};

export default handleFleaMarketPick;

 

이렇게 오늘 진행사항은 여기까지고

 

내일 내가 구현한 핸들러들이 잘 작동 했으면 좋겠다

'프로젝트 Final' 카테고리의 다른 글

22일 일지  (1) 2024.11.22
21일 일지  (1) 2024.11.21
19일 일지  (0) 2024.11.19
18일 일지  (0) 2024.11.18
15일 일지  (0) 2024.11.16