사용자:Senouis/Xash3D 분석
Xash3D는 미국의 밸브 코퍼레이션의 첫 게임 엔진인 하프라이프 엔진(흔히 GoldSource 엔진으로 알려졌다)과 호환되면서 Open-source, cross-platform을 지향하는 게임 엔진이다. 하프라이프는 게임 소스 코드 공개를 통한 2차 창작 MOD를 장려하였기 때문에 Xash3D 엔진으로 돌아가는 게임이 많다.
현재는 FWGS(Flying With Gauss의 약어라지만 뭔가 Freeware GoldSource의 약어 같기도 하다)이라는 이름의 동인 개발 서클에 의해 관리되고 있다(러시아 쪽 다큐먼트가 거의 공식 영어 도큐먼트 수준으로 자세하고 러시아 쪽에서 인기 있는 모드의 지원이 많아 러시아인들이 주축이 된 팀으로 보인다)
Xash3D 엔진의 최신 소스 코드는 여기에서 확인할 수 있다.
한편 Emscripten 트랜스컴파일러로 javascript 코드로 C/C++ 코드 컴파일을 한 Github 리포지토리가 있다. 링크
Xash3D 개요
- 개발 언어: C/C++
- 지원 플랫폼: 윈도우즈 / 맥 / 리눅스 계통 / iOS / 안드로이드 / Nintendo 3DS
과거에는 Emscripten을 통한 웹 버전으로 컴파일이 되었으나 CMake 대신 Waf로 빌드 스크립트 구성 프로그램을 바꾸는 바람에 지원이 중단되었다. 따라서 Xash3D의 현 버전은 웹에 적용하려면 지나치게 많은 비용이 든다. 그러나 2000년대 게임들을 돌리는 것을 주 목적으로 하기에 언리얼 엔진 / 유니티 엔진에 비해 코드가 간결하다는 점에서 레거시 버전이라도 리버티게임에 가젯 형태로 자바스크립트로 트랜스컴파일된 물건을 포팅하는 것이 의미가 있다.
Xash3D 전체 구조
Xash3D는 크게 filesystem IO를 담당하는 라이브러리, 메인 메뉴 UI 관련 코드가 있는 라이브러리, 핵심 엔진 기능을 담은 라이브러리, 그리고 그래픽스 라이브러리가 있다. 이 중 레거시가 된 웹 버전인 상단의 HTML5 버전 레포지토리는 다음과 같이 javascript 파일이 생성되었다.
- 파일시스템 IO: browserfs.js
- 메인 메뉴 UI: menu.js
- 게임 엔진 본체: xash.js
- 클라이언트/서버 측에서만 돌아가는 로컬 코드: client.js, server.js
그 외에는 게임별 애셋 로드 코드 등이다.
Xash3D의 구동 과정
사실 모든 게임 엔진은 다음 구조로 동작한다.
- 게임 실행 파일이 xash 라이브러리 파일(어떻게 컴파일했는지에 따라 xash.js, xash.dll, ...) 가져온 다음, 클라이언트 측 코드와 서버 측 코드를 가져와 진입점으로 들어간다.
- 특정 플랫폼에서만 작동하는 네이티브 코드의 경우 Client 측에서 Initialize, VidInitf를 호출하고 Server 측에서는 GameDLLInit를 호출한다.
- 게임 로직은 서버 측 코드에 다 적혀 있고, 클라이언트 측은 주로 입력 처리, 네트워크 데이터를 메세지로 받아 처리한 다음 HUD 표시 및 뷰포트와 카메라, 렌더링 및 그에 필요한 간단한 수학 행렬 연산 정도만 한다.
- 서버 측에서는 주로 게임 모드, 네트워크로 전송할 데이터 값, 개발 콘솔 창에서 쓸 수 있는 변수, 사용자로부터 날아온 각종 이벤트(입력, 무기 사용 등)에 대한 콜백, 그리고 각 엔티티별 코드로 구성되어 있다.
- 게임 모드의 경우 CGameRules 클래스에서 파생하고, 네트워크 데이터 전송 값은 REG_USER_MSG 매크로, 콘솔 변수는 GET_CVAR_***나 CVAR_REGISTER 매크로를 사용해 크기와 종류를 결정하고, 이벤트는 EV_HookEvent에 이벤트 콜백 함수를 등록하며, 엔티티별 코드는 CBaseEntity 클래스에서 파생한다.
그래서 사실 CBaseEntity와 CGameRules 클래스 및 그 특성을 상속한 클래스들 정도만 컴파일해도 이론상으로는 서버 측 코드가 작동한다. 다만 그러면 할 수 있는 것이 없어 보통 하프라이프 코드를 가져와 고치는 식으로 게임 제작이 이루어진다.
여기까지는 게임 코드에서 다루는 것이고, 이제 Xash3D 엔진 자체를 다뤄보자.
Xash3D 모듈
wrapper(index.js)
- mod.js를 리버티게임 내에서 정의하면 인식하도록 script 태그를 페이지에 JavaScript로 추가
engine(xash.js)
현재 이슈
- 현재 Multiplayer가 작동하지 않음: 아마도 WebSocket 문제로 추정 + 포트 27015을 리플리케이팅 특화 코드를 사용할 용도로 서버에서 개방해야 하나?
- Secure WebSocket Connection 필요: microndk/build-emscripten-module.mk에서 WEBSOCKET_URL을 "wss://liberty.banipest.com" 아래로 설정하고 테스트할 것
- 위키 사용자 명칭을 가져오지 못함: Console을 다시 활성화하고 playername 확인 필요
- Multiplayer 항목 진입시 사용자 명칭을 계속 물어봄: engine에서 인식하는데도 이러면 mainui 내 코드를 고쳐서 뜨지 않게 할 것