인프런 커뮤니티 질문&답변

고산님의 프로필 이미지
고산

작성한 질문수

따라하며 배우는 웹 게임

상대방 캐릭터 Spawn 해주기

2번째 로그인 시 원래 있던 캐릭터가 생성되지 않습니다.

작성

·

198

0

M.match_join이 호출되긴 하는데
PlayerView.js에서 op_code 값이 2가 나오는지 찍어봐도 찍히지 않고 호출되지 않는 거 같습니다.
import React, { useEffect, useState, useRef } from 'react'
import '../App.css';

const PlayView = () => {
    const [isHit, setIsHit] = useState(false)
    const setTimeOutRef = useRef(null);

    useEffect(() => {
      if(!window.pc.app.gameApp) return;
      window.pc.app.gameApp.socket.onmatchdata = (matchState) => {
        let jsonResult = JSON.parse(String.fromCharCode.apply(null, new Uint8Array(matchState.data)))
        switch (matchState.op_code) {
          case 1:
            onPlayerMove(jsonResult)
            break;
          case 2:
            onHandleInitialData(jsonResult)
            break;
          case 3:
            onPlayerSpawn(jsonResult)
            break;
          default:
            break;
        }
      }

    }, [])

    const onPlayerMove = () => {

    }

    const onHandleInitialData = (data) => {
      const myAccountId = window.pc.app.gameApp.user.user_id;
      console.log('onHandleInitialData', data);
      for (const player of data.players) {
        if(myAccountId === player.user_id) {
          continue;
        }
        console.log(player);
        setTimeout(() => {
          onPlayerSpawn(player);
        }, 1000);
      }
    }

    const onPlayerSpawn = (data) => {
      // Create a new player entity.
      let playerEntity = window.pc.app.root.findByName("Player");
      let newPlayerEntity = playerEntity.clone();

      // Put Location into new player entity.
      if(data.position) {
        let position = data.position;
        newPlayerEntity.rigidbody.teleport(position[0], position[1], position[2]);
      } else {
        newPlayerEntity.rigidbody.teleport(0, 3, 0);
      }
      
      // addChild into Root
      newPlayerEntity.enabled = true;
      let sceneRoot = window.pc.app.root.findByName("Root");
      sceneRoot.addChild(newPlayerEntity);
    }
    

    useEffect(() => {
        window.pc.app.on("boxHit", listener);
        return () => {
          window.pc.app.off("boxHit", listener)
        }
        // window.addEventListener("message", listener)
    
        // return () => {
        //   window.removeEventListener("message", listener);
        // }
      }, [])
      
    const listener = (event) => {
    // if(event.origin !== "http://localhost:3000")
    //   return;
    
    clearTimeout(setTimeOutRef.current);
    setIsHit(true);
    setTimeOutRef.current = setTimeout(() => {
        setIsHit(false);
    }, 1000);
    }
    
  return (
    <div>
        {isHit && <div className='Popup'>Box is hit</div> }
    </div>
  )
}

export default PlayView
 
local nk = require("nakama");
local M = {}

local function on_player_move(context, dispatcher, tick, state, message)
	local player = state.presences[message.sender.session_id]
	if player == nil then
		return
	end

	local ok, decode_data = pcall(nk.json_decode, message.data)
	if not ok then
		nk.session_disconnect(message.sender.session_id)
		return
	end

	player.info["position"] = decode_data.position;
	dispatcher.broadcast_message(1, message.data)

end

local function on_player_spawn(context, dispatcher, tick, state, message)
	-- 실제로 매치에 있는 사람이 보낸 것인지 확인. 아니면 return
	local player = state.presences[message.sender.session_id]
	if player == nil then
		return
	end

	dispatcher.broadcast_message(3, message.data)
end

function M.match_init(context, initial_state)
	local state = {
		presences = {},
		empty_ticks = 0
	}
	local tick_rate = 30 -- 1 tick per second = 1 MatchLoop func invocations per second
	local label = ""

	return state, tick_rate, label
end

function M.match_join_attempt(context, dispatcher, tick, state, presence, metadata)
    local acceptuser = true
    return state, acceptuser
end

function M.match_join(context, dispatcher, tick, state, presences)
	for _, presence in ipairs(presences) do
		
		state.presences[presence.session_id] = presence
		state.presences[presence.session_id].info = {
			user_id = presence.user_id,
			position = {0, 3, 0}
		}
	end

	local player_infos = {}
	for _, p in pairs(state.presences) do
		table.insert(player_infos, p.info)
	end

	local player_init_data = {
		players = player_infos,
		tick = tick
	}
	
	dispatcher.broadcast_message(2, nk.json_encode(player_init_data), presences)

	return state
end

function M.match_leave(context, dispatcher, tick, state, presences)
	for _, presence in ipairs(presences) do
		state.presences[presence.session_id] = nil
	end

	return state
end

function M.match_loop(context, dispatcher, tick, state, messages)

	print("messages: ", nk.json_encode(messages))
	for _, message in ipairs(messages) do
		if (message.op_code == 1) then
			local ok = pcall(on_player_move, context, dispatcher, tick, state, message)
			if not ok then
				nk.session_disconnect(message.sender.session_id)
			end
		end
		if (message.op_code == 3) then
			local ok = pcall(on_player_spawn, context, dispatcher, tick, state, message)
			if not ok then
				nk.session_disconnect(message.sender.session_id)
			end
		end
	end

	return state
end

function M.match_terminate(context, dispatcher, tick, state, grace_seconds)
    return state
end

function M.match_signal(context, dispatcher, tick, state, data)
    return state, data
end

return M

답변 1

0

고산님의 프로필 이미지
고산
질문자

아무리 이것저것 바꿔봐도 해결되지 않습니다.

setTimeout 시간 값을 바꿔도 안되고

애초에 

dispatcher.broadcast_message(2, nk.json_encode(player_init_data), presences)
이후 onmatchdata에 진입을 하지 않고 onPlayerSpawn으로 넘어가버립니다.
고산님의 프로필 이미지
고산
질문자

정확한 해결방법은 아니지만 열려있는 브라우저들을 최대한 줄였더니 성공하는 케이스가 있네요... 원인은 모르겠습니다..

John Ahn님의 프로필 이미지
John Ahn
지식공유자

답이 늦어서 죄송했습니다 ㅠㅠ !! 
담에 또 안되신다면 저장소 주소와 같이 올려주신다면 직접해보겠습니다!!!

고산님의 프로필 이미지
고산

작성한 질문수

질문하기