List <CCardPicture> parse_cards_to_take_from_others(byte player_index, CPacket msg) { // 뺏어올 카드. List <CCardPicture> take_cards_from_others = new List <CCardPicture>(); byte victim_count = msg.pop_byte(); for (byte victim = 0; victim < victim_count; ++victim) { byte victim_index = msg.pop_byte(); byte count_to_take = msg.pop_byte(); for (byte i = 0; i < count_to_take; ++i) { byte card_number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = (byte)msg.pop_byte(); CCardPicture card_pic = this.player_card_manager[victim_index].get_card( card_number, pae_type, position); take_cards_from_others.Add(card_pic); this.player_card_manager[victim_index].remove(card_pic); } } short score = msg.pop_int16(); byte remain_bomb_card_count = msg.pop_byte(); // UI적용. this.player_info_slots[player_index].update_score(score); return(take_cards_from_others); }
public CCardPicture get_card(byte number, PAE_TYPE pae_type, byte position) { CCardPicture card_pic = this.floor_slots[pae_type].Find(obj => obj.is_same(number, pae_type, position)); return(card_pic); }
void ON_FLIP_DECK_CARD_ACK(CPacket msg) { byte player_index = msg.pop_byte(); // 덱에서 뒤집은 카드 정보. byte deck_card_number = msg.pop_byte(); PAE_TYPE deck_card_pae_type = (PAE_TYPE)msg.pop_byte(); byte deck_card_position = msg.pop_byte(); byte same_count_with_deck = msg.pop_byte(); PLAYER_SELECT_CARD_RESULT result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); if (result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_DECK) { if (is_me(player_index)) { CPacket choose_msg = CPacket.create((short)PROTOCOL.CHOOSE_CARD); choose_msg.push((byte)result); choose_msg.push((byte)0); this.local_server.on_receive_from_ai(choose_msg); } } else { CPacket ret = CPacket.create((short)PROTOCOL.TURN_END); this.local_server.on_receive_from_ai(ret); } }
public CCard(byte number, PAE_TYPE pae_type, byte position) { this.number = number; this.pae_type = pae_type; this.position = position; this.status = CARD_STATUS.NONE; }
void apply_card_status( byte number, PAE_TYPE pae_type, byte position, CARD_STATUS status) { CCard card = find_card(number, pae_type, position); card.set_card_status(status); }
List <CCard> find_cards(PAE_TYPE pae_type) { if (this.floor_pae.ContainsKey(pae_type)) { return(this.floor_pae[pae_type]); } return(null); }
/// <summary> /// 플레이어의 바닥 카드 위치를 갱신한다. /// 피를 뺏기거나 옮기거나 했을 때 생기는 빈자리를 채워준다. /// </summary> /// <param name="player_index"></param> void refresh_player_floor_slots(PAE_TYPE pae_type, byte player_index) { int count = this.player_card_manager[player_index].get_card_count(pae_type); for (int i = 0; i < count; ++i) { Vector3 pos = this.player_card_positions[player_index].get_floor_position(i, pae_type); CCardPicture card_pic = this.player_card_manager[player_index].get_card_at(pae_type, i); // pos.z = card_pic.transform.position.z; card_pic.transform.position = pos; } }
CCard pop_specific_card_from_floor(PAE_TYPE pae_type, CARD_STATUS status) { if (!this.floor_pae.ContainsKey(pae_type)) { return(null); } CCard card = this.floor_pae[pae_type].Find(obj => obj.status == status); this.floor_pae[pae_type].Remove(card); return(card); }
void ON_BEGIN_CARD_INFO(CPacket msg) { Queue <CCard> floor_cards = new Queue <CCard>(); this.player_index = msg.pop_byte(); // floor cards. byte floor_count = msg.pop_byte(); for (byte i = 0; i < floor_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = new CCard(number, pae_type, position); floor_cards.Enqueue(card); this.floor_card_manager.puton_card(card); } byte player_count = msg.pop_byte(); for (byte player = 0; player < player_count; ++player) { Queue <CCard> cards = new Queue <CCard>(); byte player_index = msg.pop_byte(); byte card_count = msg.pop_byte(); for (byte i = 0; i < card_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = PAE_TYPE.KWANG; byte position = byte.MaxValue; if (number != byte.MaxValue) { pae_type = (PAE_TYPE)msg.pop_byte(); position = msg.pop_byte(); // AI플레이어 본인 것만 담는다. CCard card = new CCard(number, pae_type, position); this.hand_cards.Add(card); } } } CPacket finished_msg = CPacket.create((short)PROTOCOL.DISTRIBUTED_ALL_CARDS); this.local_server.on_receive_from_ai(finished_msg); }
public byte get_card_count(PAE_TYPE pae_type, CARD_STATUS status) { if (!this.floor_pae.ContainsKey(pae_type)) { return(0); } List <CCard> targets = this.floor_pae[pae_type].FindAll(obj => obj.is_same_status(status)); if (targets == null) { return(0); } return((byte)targets.Count); }
IEnumerator move_flip_card(byte number, PAE_TYPE pae_type, byte position) { // 뒤집은 카드 움직이기. CCardPicture deck_card_picture = this.deck_cards.Pop(); CCard flipped_card = this.card_manager.find_card(number, pae_type, position); deck_card_picture.update_card(flipped_card, get_hwatoo_sprite(flipped_card)); yield return(StartCoroutine(flip_deck_card(deck_card_picture))); yield return(new WaitForSeconds(0.3f)); deck_card_picture.transform.localScale = SCALE_TO_FLOOR; move_card_to_floor(deck_card_picture, CARD_EVENT_TYPE.NONE); yield return(new WaitForSeconds(0.5f)); }
void update_floor_cards(CPacket msg) { this.floor_card_manager.reset(); byte slot_count = msg.pop_byte(); for (byte i = 0; i < slot_count; ++i) { byte card_count = msg.pop_byte(); for (byte card_index = 0; card_index < card_count; ++card_index) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); this.floor_card_manager.puton_card(new CCard(number, pae_type, position)); } } }
//카드를 냈을때 맞는 카드를 가져온다. List <CCard> parse_cards_to_get(CPacket msg) { List <CCard> cards_to_give = new List <CCard>(); byte count_to_give = msg.pop_byte(); //Debug.Log(string.Format("================== count to give. {0}", count_to_give)); for (int i = 0; i < count_to_give; ++i) { byte card_number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = (byte)msg.pop_byte(); CCard card = this.card_manager.find_card(card_number, pae_type, position); cards_to_give.Add(card); //Debug.Log(string.Format("{0}, {1}, {2}", card_number, pae_type, position)); } return(cards_to_give); }
public void on_player_put_card(byte player_index, byte card_number, PAE_TYPE pae_type, byte position, byte slot_index, byte is_shaking) { PLAYER_SELECT_CARD_RESULT result = this.engine.player_put_card( player_index, card_number, pae_type, position, slot_index, is_shaking); if (result == PLAYER_SELECT_CARD_RESULT.ERROR_INVALID_CARD) { return; } clear_received_protocol(); send_select_card_ack(result, player_index, slot_index); }
public CCard pop_card_from_hand( byte card_number, PAE_TYPE pae_type, byte position) { CCard card = this.hand_pae.Find(obj => { return(obj.number == card_number && obj.pae_type == pae_type && obj.position == position); }); if (card == null) { return(null); } this.hand_pae.Remove(card); return(card); }
short get_score_by_type(PAE_TYPE pae_type) { short pae_score = 0; List<CCard> cards = find_cards(pae_type); if (cards == null) { return 0; } switch (pae_type) { case PAE_TYPE.PEE: { byte twopee_count = get_card_count(PAE_TYPE.PEE, CARD_STATUS.TWO_PEE); byte total_pee_count = (byte)(cards.Count + twopee_count); //UnityEngine.Debug.Log(string.Format("[SCORE] Player {0}, total pee {1}, twopee {2}", // this.player_index, total_pee_count, twopee_count)); if (total_pee_count >= 10) { pae_score = (short)(total_pee_count - 9); } } break; case PAE_TYPE.TEE: if (cards.Count >= 5) { pae_score = (short)(cards.Count - 4); } break; case PAE_TYPE.YEOL: if (cards.Count >= 5) { pae_score = (short)(cards.Count - 4); } break; case PAE_TYPE.KWANG: if (cards.Count == 5) { pae_score = 15; } else if (cards.Count == 4) { pae_score = 4; } else if (cards.Count == 3) { // 비광이 포함되어 있으면 2점. 아니면 3점. bool is_exist_beekwang = cards.Exists(obj => obj.is_same_number(CCard.BEE_KWANG)); if (is_exist_beekwang) { pae_score = 2; } else { pae_score = 3; } } break; } //UnityEngine.Debug.Log(string.Format("{0} {1} score", pae_type, pae_score)); return pae_score; }
public int get_card_count(PAE_TYPE pae_type) { return(this.floor_slots[pae_type].Count); }
public void add(CCardPicture card_pic) { PAE_TYPE pae_type = card_pic.card.pae_type; this.floor_slots[pae_type].Add(card_pic); }
public void remove(byte number, PAE_TYPE pae_type, byte position) { CCardPicture card_pic = this.floor_slots[pae_type].Find(obj => obj.is_same(number, pae_type, position)); remove(card_pic); }
public CCardPicture get_card_at(PAE_TYPE pae_type, int index) { return this.floor_slots[pae_type][index]; }
/// <summary> /// 플레이어가 카드를 낼 때 호출된다. /// </summary> /// <param name="player_index"></param> /// <param name="card_number"></param> /// <param name="pae_type"></param> /// <param name="position"></param> /// <returns></returns> public PLAYER_SELECT_CARD_RESULT player_put_card(byte player_index, byte card_number, PAE_TYPE pae_type, byte position, byte slot_index, byte is_shaking) { this.selected_slot_index = slot_index; //UnityEngine.Debug.Log(string.Format("recv {0}, {1}, {2}", // card_number, pae_type, position)); // 클라이언트가 보내온 카드 정보가 실제로 플레이어가 들고 있는 카드인지 확인한다. CCard card = this.player_agents[player_index].pop_card_from_hand( card_number, pae_type, position); if (card == null) { UnityEngine.Debug.LogError(string.Format("invalid card! {0}, {1}, {2}", card_number, pae_type, position)); // error! Invalid slot index. return PLAYER_SELECT_CARD_RESULT.ERROR_INVALID_CARD; } this.card_from_player = card; // 바닥 카드중에서 플레이어가 낸 카드와 같은 숫자의 카드를 구한다. List<CCard> same_cards = this.floor_manager.get_cards(card.number); if (same_cards != null) { this.same_card_count_with_player = (byte)same_cards.Count; } else { this.same_card_count_with_player = 0; } //UnityEngine.Debug.Log("same card(player) " + this.same_card_count_with_player); switch (this.same_card_count_with_player) { case 0: { if (is_shaking == 1) { byte count_from_hand = this.player_agents[player_index].get_same_card_count_from_hand(this.card_from_player.number); if (count_from_hand == 2) { this.card_event_type = CARD_EVENT_TYPE.SHAKING; this.player_agents[player_index].plus_shaking_count(); // 플레이어에게 흔든 카드 정보를 보내줄 때 사용하기 위해서 리스트에 보관해 놓는다. this.shaking_cards = this.player_agents[player_index].find_same_cards_from_hand( this.card_from_player.number); this.shaking_cards.Add(this.card_from_player); } } } break; case 1: { // 폭탄인 경우와 아닌 경우를 구분해서 처리 해 준다. byte count_from_hand = this.player_agents[player_index].get_same_card_count_from_hand(this.card_from_player.number); if (count_from_hand == 2) { this.card_event_type = CARD_EVENT_TYPE.BOMB; get_current_player().plus_shaking_count(); // 플레이어가 선택한 카드와, 바닥 카드, 폭탄 카드를 모두 가져 간다. this.cards_to_give_player.Add(this.card_from_player); this.cards_to_give_player.Add(same_cards[0]); this.bomb_cards_from_player.Add(this.card_from_player); List<CCard> bomb_cards = this.player_agents[player_index].pop_all_cards_from_hand(this.card_from_player.number); for (int i = 0; i < bomb_cards.Count; ++i) { this.cards_to_give_player.Add(bomb_cards[i]); this.bomb_cards_from_player.Add(bomb_cards[i]); } take_cards_from_others(1); this.player_agents[player_index].add_bomb_count(2); } else { // 뒤집이서 뻑이 나오면 못가져갈 수 있으므로 일단 임시변수에 넣어 놓는다. this.cards_to_give_player.Add(this.card_from_player); this.cards_to_give_player.Add(same_cards[0]); } } break; case 2: { if (same_cards[0].pae_type != same_cards[1].pae_type) { // 카드 종류가 다르다면 플레이어가 한장을 선택할 수 있도록 해준다. this.target_cards_to_choice.Clear(); for (int i = 0; i < same_cards.Count; ++i) { this.target_cards_to_choice.Add(same_cards[i]); } this.expected_result_type = PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER; return PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER; } // 같은 종류의 카드라면 플레이어가 선택할 필요가 없으므로 첫번째 카드를 선택해 준다. this.cards_to_give_player.Add(this.card_from_player); this.cards_to_give_player.Add(same_cards[0]); } break; case 3: { //todo:자뻑인지 구분하여 처리하기. this.card_event_type = CARD_EVENT_TYPE.EAT_PPUK; // 쌓여있는 카드를 모두 플레이어에게 준다. this.cards_to_give_player.Add(card); for (int i = 0; i < same_cards.Count; ++i) { this.cards_to_give_player.Add(same_cards[i]); } //todo:상대방 카드 한장 가져오기. 자뻑이었다면 두장 가져오기. take_cards_from_others(1); } break; } return PLAYER_SELECT_CARD_RESULT.COMPLETED; }
public Vector3 get_floor_position(int card_count, PAE_TYPE pae_type) { return this.floor_positions[pae_type] + new Vector3(card_count * 10, 0, 0); }
/// <summary> /// 플레이어가 선택한 카드를 바닥에 내는 장면 구현. /// 폭탄 이벤트가 존재할 경우 같은 번호의 카드 세장을 한꺼번에 내도록 구현한다. /// </summary> /// <param name="player_index"></param> /// <param name="event_type"></param> /// <param name="slot_index"></param> /// <param name="player_card_number"></param> /// <param name="player_card_pae_type"></param> /// <param name="player_card_position"></param> /// <returns></returns> IEnumerator move_player_cards_to_floor( byte player_index, CARD_EVENT_TYPE event_type, List <CCard> bomb_cards_info, byte slot_index, byte player_card_number, PAE_TYPE player_card_pae_type, byte player_card_position) { float card_moving_delay = 0.2f; List <CCardPicture> targets = new List <CCardPicture>(); if (event_type == CARD_EVENT_TYPE.BOMB) { card_moving_delay = 0.1f; // 폭탄인 경우에는 폭탄 카드 수 만큼 낸다. if (this.player_me_index == player_index) { for (int i = 0; i < bomb_cards_info.Count; ++i) { CCardPicture card_picture = this.player_hand_card_manager[player_index].find_card( bomb_cards_info[i].number, bomb_cards_info[i].pae_type, bomb_cards_info[i].position); targets.Add(card_picture); } } else { for (int i = 0; i < bomb_cards_info.Count; ++i) { CCardPicture card_picture = this.player_hand_card_manager[player_index].get_card(i); CCard card = this.card_manager.find_card(bomb_cards_info[i].number, bomb_cards_info[i].pae_type, bomb_cards_info[i].position); card_picture.update_card(card, get_hwatoo_sprite(card)); targets.Add(card_picture); } } } else { // 폭탄이 아닌 경우에는 한장의 카드만 낸다. CCardPicture card_picture = this.player_hand_card_manager[player_index].get_card(slot_index); targets.Add(card_picture); if (this.player_me_index != player_index) { CCard card = this.card_manager.find_card(player_card_number, player_card_pae_type, player_card_position); card_picture.update_card(card, get_hwatoo_sprite(card)); } } if (event_type == CARD_EVENT_TYPE.BOMB) { CVisualFloorSlot slot = this.floor_ui_slots.Find(obj => obj.is_same_card(player_card_number)); Vector3 to = get_ui_slot_position(slot); CEffectManager.Instance.play_dust(to, 0.3f, true); } // 카드 움직이기. for (int i = 0; i < targets.Count; ++i) { // 손에 들고 있는 패에서 제거한다. CCardPicture player_card = targets[i]; this.player_hand_card_manager[player_index].remove(player_card); // 스케일 장면. yield return(StartCoroutine(scale_to( player_card, 3.5f, 0.05f))); yield return(new WaitForSeconds(card_moving_delay)); // 이동 장면. player_card.transform.localScale = SCALE_TO_FLOOR; move_card_to_floor(player_card, event_type); } }
//-------------------------------------------------------- // Handler. //-------------------------------------------------------- public void on_receive(CPlayer owner, CPacket msg) { PROTOCOL protocol = (PROTOCOL)msg.pop_protocol_id(); if (is_received(owner.player_index, protocol)) { //error!! already exist!! return; } checked_protocol(owner.player_index, protocol); //UnityEngine.Debug.Log("protocol " + protocol); switch (protocol) { case PROTOCOL.READY_TO_START: on_ready_req(); break; case PROTOCOL.DISTRIBUTED_ALL_CARDS: { if (all_received(protocol)) { CPacket turn_msg = CPacket.create((short)PROTOCOL.START_TURN); turn_msg.push((byte)0); this.players[this.engine.current_player_index].send(turn_msg); } } break; case PROTOCOL.SELECT_CARD_REQ: { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); byte slot_index = msg.pop_byte(); byte is_shaking = msg.pop_byte(); //UnityEngine.Debug.Log("server. " + slot_index); on_player_put_card( owner.player_index, number, pae_type, position, slot_index, is_shaking); } break; case PROTOCOL.CHOOSE_CARD: { clear_received_protocol(); PLAYER_SELECT_CARD_RESULT client_result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); byte choice_index = msg.pop_byte(); PLAYER_SELECT_CARD_RESULT server_result = this.engine.on_choose_card(owner.player_index, client_result, choice_index); if (server_result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER) { PLAYER_SELECT_CARD_RESULT choose_result = this.engine.flip_process(owner.player_index, TURN_RESULT_TYPE.RESULT_OF_NORMAL_CARD); send_flip_result(choose_result, this.engine.current_player_index); } else { send_turn_result(this.engine.current_player_index); } //send_turn_result(this.engine.current_player_index, this.engine.selected_slot_index); } break; case PROTOCOL.FLIP_BOMB_CARD_REQ: { clear_received_protocol(); if (this.engine.current_player_index != owner.player_index) { break; } if (!owner.agent.decrease_bomb_count()) { // error! UnityEngine.Debug.Log(string.Format("Invalid bomb count!! player {0}", owner.player_index)); break; } PLAYER_SELECT_CARD_RESULT choose_result = this.engine.flip_process(owner.player_index, TURN_RESULT_TYPE.RESULT_OF_BOMB_CARD); send_flip_result(choose_result, this.engine.current_player_index); } break; case PROTOCOL.FLIP_DECK_CARD_REQ: { clear_received_protocol(); PLAYER_SELECT_CARD_RESULT result = this.engine.flip_process(this.engine.current_player_index, TURN_RESULT_TYPE.RESULT_OF_NORMAL_CARD); send_flip_result(result, this.engine.current_player_index); } break; case PROTOCOL.TURN_END: { if (!all_received(PROTOCOL.TURN_END)) { break; } if (this.engine.has_kookjin(this.engine.current_player_index)) { CPacket ask_msg = CPacket.create((short)PROTOCOL.ASK_KOOKJIN_TO_PEE); this.players[this.engine.current_player_index].send(ask_msg); } else { check_game_finish(); } } break; case PROTOCOL.ANSWER_KOOKJIN_TO_PEE: { clear_received_protocol(); owner.agent.kookjin_selected(); byte answer = msg.pop_byte(); if (answer == 1) { // 국진을 쌍피로 이동. owner.agent.move_kookjin_to_pee(); send_player_statistics(owner.player_index); broadcast_move_kookjin(owner.player_index); } check_game_finish(); } break; case PROTOCOL.ANSWER_GO_OR_STOP: { clear_received_protocol(); // answer가 1이면 GO, 0이면 STOP. byte answer = msg.pop_byte(); if (answer == 1) { owner.agent.plus_go_count(); broadcast_go_count(owner); next_turn(); } else { broadcast_game_result(); } } break; } }
short get_score_by_type(PAE_TYPE pae_type) { short pae_score = 0; List <CCard> cards = find_cards(pae_type); if (cards == null) { return(0); } switch (pae_type) { case PAE_TYPE.PEE: { byte twopee_count = get_card_count(PAE_TYPE.PEE, CARD_STATUS.TWO_PEE); byte total_pee_count = (byte)(cards.Count + twopee_count); //UnityEngine.Debug.Log(string.Format("[SCORE] Player {0}, total pee {1}, twopee {2}", // this.player_index, total_pee_count, twopee_count)); if (total_pee_count >= 10) { pae_score = (short)(total_pee_count - 9); } } break; case PAE_TYPE.TEE: if (cards.Count >= 5) { pae_score = (short)(cards.Count - 4); } break; case PAE_TYPE.YEOL: if (cards.Count >= 5) { pae_score = (short)(cards.Count - 4); } break; case PAE_TYPE.KWANG: if (cards.Count == 5) { pae_score = 15; } else if (cards.Count == 4) { pae_score = 4; } else if (cards.Count == 3) { // 비광이 포함되어 있으면 2점. 아니면 3점. bool is_exist_beekwang = cards.Exists(obj => obj.is_same_number(CCard.BEE_KWANG)); if (is_exist_beekwang) { pae_score = 2; } else { pae_score = 3; } } break; } //UnityEngine.Debug.Log(string.Format("{0} {1} score", pae_type, pae_score)); return(pae_score); }
CCard pop_specific_card_from_floor(PAE_TYPE pae_type, CARD_STATUS status) { if (!this.floor_pae.ContainsKey(pae_type)) { return null; } CCard card = this.floor_pae[pae_type].Find(obj => obj.status == status); this.floor_pae[pae_type].Remove(card); return card; }
IEnumerator on_flip_deck_card_ack(CPacket msg) { byte player_index = msg.pop_byte(); // 덱에서 뒤집은 카드 정보. byte deck_card_number = msg.pop_byte(); PAE_TYPE deck_card_pae_type = (PAE_TYPE)msg.pop_byte(); byte deck_card_position = msg.pop_byte(); byte same_count_with_deck = msg.pop_byte(); List <Sprite> target_to_choice = new List <Sprite>(); PLAYER_SELECT_CARD_RESULT result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); if (result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_DECK) { byte count = msg.pop_byte(); for (byte i = 0; i < count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); target_to_choice.Add(get_hwatoo_sprite(card)); } yield return(StartCoroutine(move_flip_card(deck_card_number, deck_card_pae_type, deck_card_position))); if (player_index == this.player_me_index) { CUIManager.Instance.show(UI_PAGE.POPUP_CHOICE_CARD); CPopupChoiceCard popup = CUIManager.Instance.get_uipage(UI_PAGE.POPUP_CHOICE_CARD).GetComponent <CPopupChoiceCard>(); popup.refresh(result, target_to_choice[0], target_to_choice[1]); } } else { List <CCard> cards_to_give = parse_cards_to_get(msg); List <CCardPicture> take_cards_from_others = parse_cards_to_take_from_others(player_index, msg); List <CARD_EVENT_TYPE> events = parse_flip_card_events(msg); refresh_player_floor_slots(PAE_TYPE.PEE, player_index); // 화면 연출 진행. yield return(StartCoroutine(move_flip_card(deck_card_number, deck_card_pae_type, deck_card_position))); if (events.Count > 0) { for (int i = 0; i < events.Count; ++i) { CEffectManager.Instance.play(events[i]); yield return(new WaitForSeconds(1.5f)); } } yield return(StartCoroutine(move_after_flip_card(player_index, take_cards_from_others, cards_to_give))); } }
public bool is_same(byte number, PAE_TYPE pae_type, byte position) { return this.card.is_same(number, pae_type, position); }
public bool is_same(byte number, PAE_TYPE pae_type, byte position) { return(this.card.is_same(number, pae_type, position)); }
Vector3 get_player_card_position(byte player_index, PAE_TYPE pae_type) { int count = this.player_card_manager[player_index].get_card_count(pae_type); return(this.player_card_positions[player_index].get_floor_position(count, pae_type)); }
public CCardPicture find_card(byte number, PAE_TYPE pae_type, byte position) { return this.cards.Find(obj => obj.card.is_same(number, pae_type, position)); }
/// <summary> /// 패킷을 순차적으로 처리하기 위한 루프. /// 카드 움직이는 연출 장면을 순서대로 처리하기 위해 구현한 매소드 이다. /// 코루틴에 의한 카드 이동 연출이 진행중일때도 서버로부터의 패킷은 수신될 수 있으므로 /// 연출 도중에 다른 연출이 수행되는 경우가 생겨 버린다. /// 이런 경우를 방지하려면 두가지 방법이 있다. /// 첫번째. 각 연출 단계마다 다른 클라이언트들과 동기화를 수행한다. /// 두번째. 들어오는 패킷을 큐잉처리 하여 하나의 연출 장면이 끝난 뒤에 다음 패킷을 꺼내어 처리한다. /// 여기서는 두번째 방법으로 구현하였다. /// 첫번째 방법의 경우 동기화 패킷을 수시로 교환해야 하기 때문에 구현하기가 번거롭고 /// 상대방의 네트워크 상태가 좋지 않을 경우 게임 진행이 매끄럽지 못하게 된다. /// </summary> /// <returns></returns> IEnumerator sequential_packet_handler() { while (true) { if (this.waiting_packets.Count <= 0) { yield return(0); continue; } CPacket msg = this.waiting_packets.Dequeue(); PROTOCOL protocol = (PROTOCOL)msg.pop_protocol_id(); switch (protocol) { case PROTOCOL.LOCAL_SERVER_STARTED: { CPacket send = CPacket.create((short)PROTOCOL.READY_TO_START); CNetworkManager.Instance.send(send); } break; case PROTOCOL.BEGIN_CARD_INFO: { reset(); // if (is_test_mode) // { // this.test_auto_slot_index = 0; // } Queue <CCard> floor_cards = new Queue <CCard>(); // floor cards. this.player_me_index = msg.pop_byte(); byte floor_count = msg.pop_byte(); for (byte i = 0; i < floor_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); if (card == null) { Debug.LogError(string.Format("Cannot find the card. {0}, {1}, {2}", number, pae_type, position)); } floor_cards.Enqueue(card); } Dictionary <byte, Queue <CCard> > player_cards = new Dictionary <byte, Queue <CCard> >(); byte player_count = msg.pop_byte(); for (byte player = 0; player < player_count; ++player) { Queue <CCard> cards = new Queue <CCard>(); byte player_index = msg.pop_byte(); byte card_count = msg.pop_byte(); for (byte i = 0; i < card_count; ++i) { byte number = msg.pop_byte(); if (number != byte.MaxValue) { PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); cards.Enqueue(card); } } player_cards.Add(player_index, cards); } yield return(StartCoroutine(distribute_cards(floor_cards, player_cards))); } break; case PROTOCOL.START_TURN: { byte remain_bomb_card_count = msg.pop_byte(); // if (this.is_test_mode) // { // if (this.player_hand_card_manager[0].get_card_count() <= 0) // { // break; // } // // CPacket card_msg = CPacket.create((short)PROTOCOL.SELECT_CARD_REQ); // CCardPicture card_pic = this.player_hand_card_manager[0].get_card(0); // // card_msg.push(card_pic.card.number); // card_msg.push((byte)card_pic.card.pae_type); // card_msg.push(card_pic.card.position); // // card_msg.push(this.test_auto_slot_index); // // ++this.test_auto_slot_index; // // CNetworkManager.Instance.send(card_msg); // } // 내 차례가 되었을 때 카드 선택 기능을 활성화 시켜준다. this.card_collision_manager.enabled = true; this.player_hand_card_manager[0].enable_all_colliders(true); // 이전에 폭탄낸게 남아있다면 가운데 카드를 뒤집을 수 있도록 충돌박스를 켜준다. if (remain_bomb_card_count > 0) { CCardPicture top_card = deck_cards.Peek(); top_card.enable_collider(true); } } break; case PROTOCOL.SELECT_CARD_ACK: yield return(StartCoroutine(on_select_card_ack(msg))); break; case PROTOCOL.FLIP_DECK_CARD_ACK: yield return(StartCoroutine(on_flip_deck_card_ack(msg))); break; case PROTOCOL.CHOICE_ONE_CARD: { List <Sprite> target_cards = new List <Sprite>(); PLAYER_SELECT_CARD_RESULT result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); CCardPicture deck_card = null; if (result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_DECK) { deck_card = this.deck_cards.Pop(); byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); deck_card.update_card(card, get_hwatoo_sprite(card)); } byte count = msg.pop_byte(); for (byte i = 0; i < count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); target_cards.Add(get_hwatoo_sprite(card)); //Debug.Log(string.Format("choice one card. {0}, {1}, {2}", number, pae_type, position)); } CUIManager.Instance.show(UI_PAGE.POPUP_CHOICE_CARD); CPopupChoiceCard popup = CUIManager.Instance.get_uipage(UI_PAGE.POPUP_CHOICE_CARD).GetComponent <CPopupChoiceCard>(); popup.refresh(result, target_cards[0], target_cards[1]); yield return(StartCoroutine(show_choice_card_popup(deck_card))); } break; case PROTOCOL.TURN_RESULT: { // 데이터 파싱 시작 ---------------------------------------- byte player_index = msg.pop_byte(); yield return(StartCoroutine(on_turn_result(player_index, msg))); } break; case PROTOCOL.ASK_GO_OR_STOP: CUIManager.Instance.show(UI_PAGE.POPUP_GO_STOP); break; case PROTOCOL.UPDATE_PLAYER_STATISTICS: update_player_statistics(msg); break; case PROTOCOL.ASK_KOOKJIN_TO_PEE: CUIManager.Instance.show(UI_PAGE.POPUP_ASK_KOOKJIN); break; case PROTOCOL.MOVE_KOOKJIN_TO_PEE: { byte player_index = msg.pop_byte(); yield return(StartCoroutine(move_kookjin_to_pee(player_index))); } break; case PROTOCOL.GAME_RESULT: on_game_result(msg); break; } yield return(0); } }
public CCardPicture get_card(byte number, PAE_TYPE pae_type, byte position) { CCardPicture card_pic = this.floor_slots[pae_type].Find(obj => obj.is_same(number, pae_type, position)); return card_pic; }
public CCardPicture get_card_at(PAE_TYPE pae_type, int index) { return(this.floor_slots[pae_type][index]); }
public int get_card_count(PAE_TYPE pae_type) { return this.floor_slots[pae_type].Count; }
public CCard pop_card_from_hand( byte card_number, PAE_TYPE pae_type, byte position) { CCard card = this.hand_pae.Find(obj => { return obj.number == card_number && obj.pae_type == pae_type && obj.position == position; }); if (card == null) { return null; } this.hand_pae.Remove(card); return card; }
IEnumerator on_select_card_ack(CPacket msg) { // 데이터 파싱 시작 ---------------------------------------- byte player_index = msg.pop_byte(); // 카드 내는 연출을 위해 필요한 변수들. CARD_EVENT_TYPE card_event = CARD_EVENT_TYPE.NONE; List <CCard> bomb_cards_info = new List <CCard>(); List <CCard> shaking_cards_info = new List <CCard>(); byte slot_index = byte.MaxValue; byte player_card_number = byte.MaxValue; PAE_TYPE player_card_pae_type = PAE_TYPE.PEE; byte player_card_position = byte.MaxValue; // 플레이어가 낸 카드 정보. player_card_number = msg.pop_byte(); player_card_pae_type = (PAE_TYPE)msg.pop_byte(); player_card_position = msg.pop_byte(); byte same_count_with_player = msg.pop_byte(); slot_index = msg.pop_byte(); //Debug.Log("on select card ack. " + slot_index); card_event = (CARD_EVENT_TYPE)msg.pop_byte(); //Debug.Log("-------------------- event " + card_event); switch (card_event) { case CARD_EVENT_TYPE.BOMB: { byte bomb_card_count = (byte)msg.pop_byte(); for (byte i = 0; i < bomb_card_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); bomb_cards_info.Add(card); //UnityEngine.Debug.Log(string.Format("BOMB {0}, {1}, {2}", number, pae_type, position)); } } break; case CARD_EVENT_TYPE.SHAKING: { byte shaking_card_count = (byte)msg.pop_byte(); for (byte i = 0; i < shaking_card_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); shaking_cards_info.Add(card); //UnityEngine.Debug.Log(string.Format("SHAKING {0}, {1}, {2}", number, pae_type, position)); } } break; } List <Sprite> target_to_choice = new List <Sprite>(); PLAYER_SELECT_CARD_RESULT select_result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); if (select_result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER) { byte count = msg.pop_byte(); for (byte i = 0; i < count; ++i) // 같은 월의 수만큼 가져갈 패를 보여준다. { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.card_manager.find_card(number, pae_type, position); target_to_choice.Add(get_hwatoo_sprite(card)); } } // 파싱 끝 ------------------------------------------------ refresh_player_floor_slots(PAE_TYPE.PEE, player_index); // 화면 연출 진행. // 흔들었을 경우 흔든 카드의 정보를 출력해 준다. if (card_event == CARD_EVENT_TYPE.SHAKING) { CUIManager.Instance.show(UI_PAGE.POPUP_SHAKING_CARDS); CPopupShakingCards popup = CUIManager.Instance.get_uipage(UI_PAGE.POPUP_SHAKING_CARDS).GetComponent <CPopupShakingCards>(); List <Sprite> sprites = new List <Sprite>(); for (int i = 0; i < shaking_cards_info.Count; ++i) { sprites.Add(get_hwatoo_sprite(shaking_cards_info[i])); } popup.refresh(sprites); yield return(new WaitForSeconds(1.5f)); CUIManager.Instance.hide(UI_PAGE.POPUP_SHAKING_CARDS); } // 플레이어가 낸 카드 움직이기. yield return(StartCoroutine(move_player_cards_to_floor( player_index, card_event, bomb_cards_info, slot_index, player_card_number, player_card_pae_type, player_card_position))); yield return(new WaitForSeconds(0.3f)); if (card_event != CARD_EVENT_TYPE.NONE) { // 흔들기는 위에서 팝업으로 보여줬기 때문에 별도의 이펙트는 필요 없다. if (card_event != CARD_EVENT_TYPE.SHAKING) { CEffectManager.Instance.play(card_event); yield return(new WaitForSeconds(1.5f)); } } if (player_index == this.player_me_index) { // 바닥에 깔린 카드가 두장일 때 둘중 하나를 선택하는 팝업을 출력한다. if (select_result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER) { CUIManager.Instance.show(UI_PAGE.POPUP_CHOICE_CARD); CPopupChoiceCard popup = CUIManager.Instance.get_uipage(UI_PAGE.POPUP_CHOICE_CARD).GetComponent <CPopupChoiceCard>(); popup.refresh(select_result, target_to_choice[0], target_to_choice[1]); } else { // 가운데 카드 뒤집기 요청. CPacket flip_msg = CPacket.create((short)PROTOCOL.FLIP_DECK_CARD_REQ); CNetworkManager.Instance.send(flip_msg); } } }
public void remove(CCardPicture card_pic) { PAE_TYPE pae_type = card_pic.card.pae_type; this.floor_slots[pae_type].Remove(card_pic); }
void ON_SELECT_CARD_ACK(CPacket msg) { byte delay = msg.pop_byte(); byte current_player_index = msg.pop_byte(); //short score = msg.pop_int16(); //byte remain_bomb_card_count = msg.pop_byte(); if (is_me(current_player_index)) { // 카드 내는 연출을 위해 필요한 변수들. CARD_EVENT_TYPE card_event = CARD_EVENT_TYPE.NONE; byte slot_index = byte.MaxValue; byte player_card_number = byte.MaxValue; PAE_TYPE player_card_pae_type = PAE_TYPE.PEE; byte player_card_position = byte.MaxValue; // 플레이어가 낸 카드 정보. player_card_number = msg.pop_byte(); player_card_pae_type = (PAE_TYPE)msg.pop_byte(); player_card_position = msg.pop_byte(); byte same_count_with_player = msg.pop_byte(); slot_index = msg.pop_byte(); card_event = (CARD_EVENT_TYPE)msg.pop_byte(); switch (card_event) { case CARD_EVENT_TYPE.BOMB: { byte bomb_card_count = (byte)msg.pop_byte(); for (byte i = 0; i < bomb_card_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); CCard card = this.hand_cards.Find(obj => obj.is_same(number, pae_type, position)); this.hand_cards.Remove(card); } } break; case CARD_EVENT_TYPE.SHAKING: { byte shaking_card_count = (byte)msg.pop_byte(); for (byte i = 0; i < shaking_card_count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); } this.hand_cards.RemoveAt(slot_index); } break; default: this.hand_cards.RemoveAt(slot_index); break; } PLAYER_SELECT_CARD_RESULT select_result = (PLAYER_SELECT_CARD_RESULT)msg.pop_byte(); if (select_result == PLAYER_SELECT_CARD_RESULT.CHOICE_ONE_CARD_FROM_PLAYER) { byte count = msg.pop_byte(); for (byte i = 0; i < count; ++i) { byte number = msg.pop_byte(); PAE_TYPE pae_type = (PAE_TYPE)msg.pop_byte(); byte position = msg.pop_byte(); } CPacket choose_msg = CPacket.create((short)PROTOCOL.CHOOSE_CARD); choose_msg.push((byte)select_result); choose_msg.push((byte)0); this.local_server.on_receive_from_ai(choose_msg); return; } CPacket ret = CPacket.create((short)PROTOCOL.FLIP_DECK_CARD_REQ); this.local_server.on_receive_from_ai(ret); } }
public byte get_card_count(PAE_TYPE pae_type, CARD_STATUS status) { if (!this.floor_pae.ContainsKey(pae_type)) { return 0; } List<CCard> targets = this.floor_pae[pae_type].FindAll(obj => obj.is_same_status(status)); if (targets == null) { return 0; } return (byte)targets.Count; }
public Vector3 get_floor_position(int card_count, PAE_TYPE pae_type) { return(this.floor_positions[pae_type] + new Vector3(card_count * 10, 0, 0)); }
public CCardPicture find_card(byte number, PAE_TYPE pae_type, byte position) { return(this.cards.Find(obj => obj.card.is_same(number, pae_type, position))); }
List<CCard> find_cards(PAE_TYPE pae_type) { if (this.floor_pae.ContainsKey(pae_type)) { return this.floor_pae[pae_type]; } return null; }