Need help with Fenix?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

sekkit
151 Stars 20 Forks Mozilla Public License 2.0 422 Commits 24 Opened issues

Description

A Distributed Online Game Server with Minimum Design

Services available

!
?

Need anything else?

Contributors list

No Data

opencraft

To Warcraft 3 fans:

OpenCraft is not Warcraft III, but for those who's been waiting for Warcraft IV for many years, this project is for you. Targeting Next Generation RTS games while learning from Blizzard's design.

Fenix is part of OpenCraft project, a distributed server designed for https://github.com/sekkit/OpenCraft

QQ Group: 1150593832

Fenix Project

A distributed game server featuring asynchronous event-driven networking, KCP/TCP/Websockets support. From MMORPG to small projects, Fenix is designed to be stable, simple, and super easy to scale. With the power of .NetCore, Fenix can be run on MacOS/Linux/Windows.

Fenix is in a early stage of development, but is also being used in reallife Game projects.

[RELEASES] https://github.com/sekkit/Fenix/releases

Status

· status    macOS/Linux/Windows supported (for client sdk supports macOS/Linux/Windows/Android/iOS)
· status    Unity Mono/IL2CPP compilation passed
· status    KCP/TCP benchmark passed (Recommend to use IL2CPP compilation for client, maybe server also**UNTESTED)
· status     Not all feature completed currently.

Get Started

****Requires .NET5.0 to run in default (Visual 2019 16.8)

  1. Run Unity3D and open Unity project at root path

  2. Open Fenix.sln with Visual Studio 2019(.NetCore 3.1+ SDK installed)

  3. Build solution

  4. Go to ./bin folder, run startredis.bat and startserver.bat

  5. (Unity3d) Press play button in Unity OR (Native) Now build and run Client.App

Features

  1. RPC decleration
    //to tag a function with ServerApi, ServerOnly, ClienApi you can create a RPC protocol without effort.
    [RuntimeData(typeof(MatchData))]
    public partial class MatchService : Service
    {  
        //public new string UniqueName => nameof(MatchService);

    [ServerApi] 
    public async Task JoinMatch(string uid, int match_type, Action<errcode> callback)
    {
        Log.Info("Call=&gt;server_api:JoinMatch");
        var result = await JoinMatchAsync(uid, match_type);
        if(result == true)
           callback(ErrCode.OK);
        else
           callback(ErrCode.ERROR);
    } 

    [ServerOnly]
    [CallbackArgs("code", "user")]
    public void FindMatch(string uid, Action<errcode account> callback)
    {
        callback(ErrCode.OK, null);
    }
}

  1. Unified DB access API for both cache and storage with Distributed Lock.
    Redis for cache and Rocksdb for persistency(also in redis protocol^^)
   var db = Global.DbManager.LoadDb(DbConfig.account_db); //Create and get db
   db.Set("PLAYER0001", userData);
  1. Switch between KCP/TCP/websockets super easy (just open conf/app.json)
[
    {
       "AppName": "Login.App",
       "ExternalIp": "auto",
       "InternalIp": "auto",
       "Port": 17777,
       "DefaultActorNames": [
         "LoginService"
       ],
       "HeartbeatIntervalMS": 5000,
       "ClientNetwork": "NetworkType.KCP"
    }
]
  1. Messagepack/Zeroformatter/Protobuf are easily supported
    AutoGen takes care of serialization&deserializtion ```csharp //AUTOGEN, do not modify it! namespace Shared.Message { [MessageType(ProtocolCode.CHANGENAMEREQ)] [MessagePackObject] public class ChangeNameReq : IMessageWithCallback { [Key(0)] public String name { get; set; }

    [Key(199)]
    public Callback callback
    {
        get => _callback as Callback;
        set => _callback = value;
    } 
    
    

    [MessagePackObject] public class Callback { [Key(0)] [DefaultValue(ErrCode.ERROR)] public ErrCode code { get; set; } = ErrCode.ERROR;

    }

    } } ```

  2. Able to call Actors and Hosts through ActorRef anywhere

    csharp
    var svc = this.GetActorRef(); 
    svc.rpc_login("username", "password", (code2, uid, hostId, hostName, hostAddress) =>
    {
     if (code2 != ErrCode.OK)
     {
          Log.Error("login_failed"); 
          return;
     }
     Log.Info("login_ok");
     //...
    });
    
  3. Architecture specifically designed for Game developers
    Liteweight and easy to use than any other distributable server framework. ``` A Host is a container(Process) for many/single actors. An Actor is an entity with state, able to make rpc calls, has its own lifecycle within the Host.

Scaling is achieved through multiprocesses, interprocess communication are mainly through Global cache or TCP/KCP networking.

Design principle comes from Bigworld, and microservices. The simple, the better. ```

  1. State/Stateless Actor & Disaster Recovery & Access Control ```csharp using Fenix; using Fenix.Common; using Fenix.Common.Attributes; using Shared.Protocol; using System; using Shared.DataModel;

namespace Server.UModule { [RequireModule(typeof(UserModule))] [RequireModule(typeof(ItemModule))] [RequireModule(typeof(RoomModule))] [RequireModule(typeof(MatchModule))] [RequireModule(typeof(FightModule))] [PersistentData(typeof(User), DbConfig.USER)] //Tag an actor with RuntimeData/PersistData, the DB saving process is taken care of. [ActorType(AType.SERVER)] //this actor exists only in server side [AccessLevel(ALevel.CLIENTANDSERVER)] //this actor can be accessed from both client/server //When disaster happens, the actor can be recovered from previous state public partial class Avatar : Actor { public Client.AvatarRef Client => (Client.AvatarRef)this.client;

       public override void onLoad()
       { 
       }

   public override void onClientEnable()
   {
      //向客户端发消息的前提是,已经绑定了ClientAvatarRef,而且一个Actor的ClientRef不是全局可见的,只能在该host进程上调用
      this.Client.client_on_api_test("", (code) =&gt;
      {
          Log.Info("client_on_api_test", code);
      });
   }

   [ServerApi]
   public void ChangeName(string name, Action<errcode> callback)
   {
      Get<account>().uid = name;

      callback(ErrCode.OK);
   }

   [ServerOnly]
   public void OnMatchOk()
   { 
   }

}

}

Contribute

We gladly accept community contributions.

  • Issues: Please report bugs using the Issues section of GitHub
  • Source Code Contributions:
  • See C# Coding Style for reference on coding style.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.