npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mvs-sync-cro

v1.0.18

Published

Modules for synchronizing with mvs synchronization server

Downloads

12

Readme

  • MVS API 문서

개요

9/6 수정, v 1.0.18

  • HeliosNetwork : 인스턴스 생성 시 NameServer, MV Master로의 연결 관리. 대부분의 유저 프로시저 구현
  • LoadBalancingService : NameServer, MV Master 와의 통신
  • MvsStore : 동기화 정보 관리
  • SyncManager : 동기화 관리
    • MVS와의 연결 소켓 관리 → #initialize
    • 클라이언트의 요청에 따른 메시지 작성 및 전송 → sendPacket
    • 응답 패킷의 메시지 ID에 따른 로직 구현 → #ReadProtocol
    • 메시지 ID에 따른 콜백함수 자동 호출 → onReceivePacket

ChangeLog

  • v 1.0.18
    • add/update/remove NetworkObjectCustomHandler가 적용 이후에 실행되도록 타이밍 조정
    • getBooleanHvInstance() 메소드 추가
    • CreateOrJoinRoom()에 falsy value 체크 추가
  • v 1.0.17
    • 환경변수를 사용하지 않고 HeliosConfig를 사용해 HeliosNetwork 객체 생성
    • WebRequest 요청에 대한 에러 핸들링 추가
    • CreateOrJoinRoom() 메소드 추가
    • InjectOnRoomJoinOrCreateHandler 핸들러 추가
    • 패킷 사이즈 변경(4->8)
  • v 1.0.16
    • 새로운 프로토콜 핸들러 추가(그룹 오너 변경, 룸/그룹 입장, 룸 퇴장)
    • 룸 입장 및 생성 구분, MVS와의 사용자 인증 연동
    • 그룹 오너 추가
  • v 1.0.15
    • 프로토콜 변경
    • 웹소켓 연결 후 heartbeat 전송
  • v 1.0.14
    • 오브젝트 후처리 로직 fix
  • v 1.0.13
    • 동기화 루프 설정(33ms)
    • RPC 패킷 추가
    • Name Server, MV Master(C#) 연동
    • 프로토콜 변경 적용
  • v 1.0.12
    • 오브젝트 변경 감지 자동화
  • v 1.0.11
    • 패킷을 operation, event로 구분
    • SyncManager의 동작을 래핑한 HeliosNetwork API 제공
  • v 1.0.10
    • WebTransport 적용
    • compile shell 변경(환경변수 자동 설정)
    • Console Message 세분화 : info, invalidMessage, invalidProtocol 추가
    • 핸들러 미구현시의 에러를 로그로 변경
  • v 1.0.9
    • proto-ts 적용
    • 공통 SapClient 구현, 해당 모듈을 사용해 LBService 호출
    • syncType, propsId 적용
  • v 1.0.8
    • UX 대응을 위해 Transform 커스텀 패킷으로 변경
  • v 1.0.7
    • Transform 삭제 및 singleton SyncManager 구현 변경
  • v 1.0.6-hotfix1
    • SyncManager 및 WebSocket 유일성 보장
    • getInstance 오버로딩
      • mvsUrl: string
        해당 mvs와 바로 연결
      • mvsOrigin: string, masterUrl?: string, roomId?: number
        MVM에서 받은 location과 mvsOrigin을 조합해 연결
        룸 변경 후 url이 변경되면 재연결
      • sendPacket 시 WebSocket의 상태를 확인해 OPEN일 때까지 대기
  • demo
    • 룸 생성 및 이동 버튼 추가
    • 와플 의존성 제거

라이브러리 개발

  • 빌드 : npm run build
  • 테스트 및 커버리지 확인 : npm run test (5/21일 기준 77.36%)
  • 배포 : npm run build -> npm login -> npm publish --registry=http://192.168.153.214:4873

프로토콜 수정

> @mv/mvs-sync@1.0.17 compile
> cd lib/utils/bufferProtocol && ./compile_pb.sh build


##     ##  ##     ##   ######
###   ###  ##     ##  ##    ##
#### ####  ##     ##  ##
## ### ##  ##     ##   ######
##     ##   ##   ##         ##
##     ##    ## ##    ##    ##
##     ##     ###      ######
@mv/mvs-sync version 1.0.17

Generate by Protocol.proto completed.
Generate by Struct.proto completed.
Generate by Enum.proto completed.
  • 변경된 프로토콜 적용 : npm run compile
  • 컴파일된 프로토콜 삭제 : npm run compile clean

코드 위치 및 사용

  • @mv/mvs-sync http://192.168.158.61/mv1/mvs/mvs-api-js

  • Demo Client http://192.168.158.61/mv1/mvs/racing-test/-/tree/main

npm set registry [http://192.168.154.143:4873/](http://192.168.154.143:4873/)

npm i @mv/mvs-sync

MVS 분산환경 사용 시

import {HeliosNetwork} from "@mv/mvs-sync/dist/utils/HeliosNetwork";

export const HSync = await HeliosNetwork.getInstance({
  mode: 'cloud',
  appKey: '8f9dfaba-1d6b-47e4-bb0c-966e0070f652'
})

룸 변경

  • HSync.CreateRoom() 또는 HSync.JoinRoom시 해당 룸 정보를 바탕으로 MV Master에서 적절한 MVS를 반환

지원 기능

  • 룸 생성 및 입장, 룸 리스트, 유저 아이디 발급, 그룹 리스트, 그룹 입장
  • 초기 객체 리스트, 객체 생성, 객체 파괴, 객체 동기화, 객체 소유권 이전 + RPC
  • 사용 시나리오
    1. 앱 생성 후 NameServer에서 REGION 등록
    2. 앱 키를 환경변수로 등록하고 REGION을 명시 후 HeliosNetwork 객체 생성
    3. 룸 리스트 조회
    4. 원하는 룸 입장 또는 룸 생성
    5. 그룹 리스트 조회
    6. 원하는 그룹 입장 또는 그룹 생성
    7. 씬의 상태 가져오기
    8. 플레이어 아이디 요청
    9. 오브젝트 생성
    10. 생성한 오브젝트 동기화. 갱신 / 삭제 / 소유권 이전 등

클라이언트가 해야할 일

API 정상작동을 위해 해야할 일

  1. mvs-auth-server에서 생성한 앱 키를 환경변수로 등록(REACT_APP_MVS_APP_KEY=APP_UUID)
  2. MVS 분산환경 사용 시 REGION 정보를 NameServer에서 등록 후 인자로
  3. 패킷 전송은 HeliosNetwork 에서, 오브젝트 관리는 MvsStore 에서

SyncManager 클래스에 다 포함되어 있습니다.

패키지 다운로드

npm set registry http://192.168.154.143:4873

npm i @mv/mvs-sync

HeliosSync.ts 파일 생성

import {HeliosNetwork} from "@mv/mvs-sync/dist/utils/HeliosNetwork";

export const HSync = await HeliosNetwork.getInstance({
  mode: 'cloud',
  appKey: 'uuidv6-app-key'
})

웹팩 설정

웹팩 설정 해주셔야 사용 가능합니다

웹팩 설정

  • 링크 들어가기 귀찮으시면 목차로 확인!

    • mvs-sync는 Buffer를 사용하고 있어서 해당 플러그인을 추가해주셔야 합니다
    • 순서대로 하시면 사용 가능하실 것으로 예상됩니다.

    웹팩 override 라이브러리 설치

    • npm install buffer process stream-browserify react-app-rewired

    scripts 수정

    "scripts" : {
        "start": "react-app-rewired start",
        "build": "react-app-rewired build",
        "test": "react-app-rewired test",
        "eject": "react-app-rewired eject"
      },

    설정 파일 생성

    • root에 config-overrides.js 파일 생성

    설정

    const webpack = require("webpack");
    
    module.exports = function override(config, env) {
      config.resolve.fallback = {
        ...config.resolve.fallback,
        stream: require.resolve("stream-browserify"),
        buffer: require.resolve("buffer"),
        "querystring": false,
        'process/browser': require.resolve('process/browser'), // 14:50 수정. mx 스튜디오에서 three js 랑 충돌나서 추가했습니다
      };
      config.resolve.alias = {
        ...config.resolve.alias,
        ws: false,
      };
      config.resolve.extensions = [...config.resolve.extensions, ".ts", ".d.ts",  ".js"];
      config.plugins = [
        ...config.plugins,
        new webpack.ProvidePlugin({
        process: "process/browser",
        Buffer: ["buffer", "Buffer"],
        }),
      ];
    
      return config;
    };

Operation

  • getState()
import {HSync} from "../../mvs/HeliosSync";
// 현재 연결 상태 가져오기
expect(HSync.getState()).toEqual(ConnectState.ON_MVMASTER)
  • Handler()
import {HSync} from "../../mvs/HeliosSync";
// 동기화중인 MVS 정보 가져오기 
const syncManager = HSync.Handler()
  • HeartBeat()
import {HSync} from "../../mvs/HeliosSync";
import {MvsStore} from "@mv/mvs-sync/dist/store/ObjectStateStore";
// MVS로 HeartBeat 패킷 보내기 
HSync.HeartBeat()
const timestamp = MvsStore.healthCheck() // 패킷을 받은 시간
  • async CreateRoom(params:RoomCreateParams)
import {HSync} from "../../mvs/HeliosSync";
// MVS로 CreateRoom 패킷 보내기 
  HSync.InjectOnRoomJoinOrCreateHandler((message: S_ROOM_JOIN_OR_CREATE, sender?: PlayerInfo) => {
    if (message.getResult() === Result.SUCCESS_ROOM_CREATE){
      navigate(PathEnum.CANVAS)
    }
    else {
      alert("Failed room join")
    }
  })
  HSync.CreateRoom({
    roomId: ROOMID,
    appId: APPID,
    authToken: "AUTHORIZATION_TOKEN",
    name: ROOMNAME
  })
  • async JoinRoom(authToken:string, roomId:number)
// MVS로 JoinRoom 패킷 보내기 
  HSync.InjectOnRoomJoinOrCreateHandler((message: S_ROOM_JOIN_OR_CREATE, sender?: PlayerInfo) => {
    if (message.getResult() === Result.SUCCESS_ROOM_JOINED){
      navigate(PathEnum.CANVAS)
    }
    else {
      alert("Failed room join")
    }
  })
  HSync.JoinRoom(
      "AUTHORIZATION_TOKEN", ROOMID
  )
  • JoinGroup(params:GroupJoinParams)
import {HSync} from "../../mvs/HeliosSync";
// MVS로 JoinGroup 패킷 보내기 
  HSync.JoinGroup({
    scene: SCENE_NUMBER,
    channel: CHANNEL_ID
  })
  • MvsRoomList()
import {HSync} from "../../mvs/HeliosSync";
// MVS로 RoomList 패킷 보내기
  HSync.RoomList().then((res)=>setRoomList(res));

  HSync.Handler().onTestRoomListCustomHandler = (message) => {
      const roomList = message.getRoominfosList()
  }
  • async RoomList()
import {HSync} from "../../mvs/HeliosSync";
// MV Master 또는 MVS로 RoomList 패킷 보내기
  HSync.RoomList().then((res)=>setRoomList(res));
  • PlayerId()
import {HSync} from "../../mvs/HeliosSync";
// MVS로 PlayerId 발급 요청
  HSync.PlayerId()
  • GroupList()
import {HSync} from "../../mvs/HeliosSync";
// MVS로 GroupList 패킷 보내기
  HSync.GroupList()
  • RPC(id:ObjectIdParams, method:number, args:any[])
// MVS로 Custom 패킷 보내기
import {HSync} from "../../mvs/HeliosSync";
  // RPC 타입 선언
  export enum METHOD {
    ATTACK,
    PUSH,
    ANIMATE,
    //...
  }
  
  // RPC 전송
  HSync.RPC(obj.id, METHOD.ATTACK, [1, "string", object])

  // 핸들러 정의
  HSync.Handler().onRpcCustomHandler = (objectId, method, args, sender) => {
    switch (method) {
      case METHOD.ATTACK: {
        console.log(objectId, method, args, sender)
      }
      case METHOD.PUSH: {
        console.log(objectId, method, args, sender)
      }
      case METHOD.ANIMATE: {
        console.log(objectId, method, args, sender)
      }
    }
  }

Event

  • InitialObject()
import {HSync} from "../../mvs/HeliosSync";
// MVS로 InitialObject 패킷 보내기
  HSync.InitialObject()
  • CreateObject()
import {HSync} from "../../mvs/HeliosSync";
import {MvsStore} from "@mv/mvs-sync/dist/store/ObjectStateStore";

  // 오브젝트 키 정의
  export enum HeliosKey{
      POSITION,
      ROTATION,
      SCALE,
      HEALTH,
      ISALIVE,
      DESCRIPTION,
  }
  
  // 오브젝트 생성
  MvsStore.addMyObjects([
    {
      prefabId: PREFAB_ID,
      value: [
        HSync.object.getVectorHvInstance(HeliosKey.POSITION, X, Y, Z),
        HSync.object.getVectorHvInstance(HeliosKey.ROTATION, X, Y, Z),
        HSync.object.getVectorHvInstance(HeliosKey.SCALE, X, Y, Z),
        HSync.object.getNumberHvInstance(HeliosKey.HEALTH, HP),
        HSync.object.getBooleanHvInstance(HeliosKey.ISALIVE, true),
        HSync.object.getStringHvInstance(HeliosKey.DESCRIPTION, "Hello World"),
      ]
    }
  ]) // MvsStore에서 생성 패킷을 전송
  • UpdateObject()
import {HSync} from "../../mvs/HeliosSync";
import {MvsStore} from "@mv/mvs-sync/dist/store/ObjectStateStore";
  // 오브젝트 갱신. 변경사항을 저장하고 33ms마다 동기화
  MvsStore.postUpdateObject([
    {
      clientInstanceId: clientInstanceId,
      value: HSync.object.getVectorHvInstance(HeliosKey.POSITION, X, Y, Z)
    }
  ]) // MvsStore에서 갱신 패킷을 전송
  • RemoveObject()
import {MvsStore} from "@mv/mvs-sync/dist/store/ObjectStateStore";
  // 오브젝트 삭제
  MvsStore.removeMyObjects([
    {
      prefabId: PREFAB_ID,
      clientInstanceId: CLIENT_INSTANCE_ID,
      instanceId: INSTANCE_ID
    }
  ]) // MvsStore에서 삭제 패킷을 전송

MVS 프로토콜

export enum MessageId {
  PKT_C_OPERATION = 1000, // 룸 점속 관련 패킷
  PKT_S_OPERATION = 1001,
  PKT_S_EVENT = 1002, // 동기화 패킷
}

enum OperationCode
{
  HEART_BEAT = 0;
  ROOM_JOIN_OR_CREATE = 1;
  ROOM_LEAVE = 2;
  ROOM_LIST = 3;
  PLAYER_ID = 4;
  GROUP_LIST = 5;
  GROUP_JOIN = 6;
  GROUP_LEAVE = 7;
  RAISE_EVENT = 8;
  INIT_VARIABLES = 9;
}

enum EventCode
{
  OTHER_CLIENT_JOINED = 0;
  INITIAL_OBJECTS = 1;
  ADD_NETWORK_OBJECTS = 2;
  REMOVE_NETWORK_OBJECTS = 3;
  UPDATE_NETWORK_OBJECTS = 4;
  CHANGE_OBJECTS_OWNER = 5;
  RPC = 6;
}
  • 요청과 응답 패킷의 MessageId에 해당하는 result number 확인
  • syncManager.messageId로 참조

ResultMessage

export enum ResultCode {
  SUCCESS = 0,
  FAILED = 1,

  // Room 관련 성공
  SUCCESS_ROOM_CREATE = 2,
  SUCCESS_ROOM_JOINED = 3,

  // Group 관련 성공
  SUCCESS_GROUP_CREATE = 4,
  SUCCESS_GROUP_JOINED = 5,

  // Room 관련 에러
  FAILED_ROOM_NOT_EXISTS_ROOM = 10,
  FAILED_ROOM_ALREADY_EXISTS_ROOM = 11,
  FAILED_ROOM_NOT_IN_ROOM = 12, // Player 가 Room 에 들어와 있지 않음

  // Group 관련 에러
  FAILED_GROUP_NOT_EXISTS_GROUP = 20, // 찾는 그룹이 존재하지 않음
  FAILED_GROUP_NOT_IN_GROUP = 21, // 현재 Player 가 그룹 내에 있지 않음
  FAILED_GROUP_ALREADY_EXISTS_GROUP = 22, // 추가하려는 그룹이 이미 존재
  FAILED_GROUP_SAME_GROUP = 23,
  FAILED_GROUP_NOT_EXISTS_PLAYER = 24, // 찾는 플레이어가 존재하지 않음
  FAILED_GROUP_ALREADY_EXISTS_PLAYER = 25, // 추가하려는 플레이어가 이미 존재
}