- 编程
- 数学
- 动漫
jasonxudeveloper / nino Goto Github PK
View Code? Open in Web Editor NEWDefinite useful and high performance modules for C# projects, especially for Unity. 实用的高性能C#模块,尤其在Unity平台能带来令人难以置信的效益。
License: MIT License
Definite useful and high performance modules for C# projects, especially for Unity. 实用的高性能C#模块,尤其在Unity平台能带来令人难以置信的效益。
License: MIT License
[NinoSerialize]
public partial class DataTest
{
[NinoMember(0)] public int a = 0;
[NinoMember(1)] public int b = 0;
[NinoMember(2)] public componentA compA;
[NinoMember(3)] public componentB compB;
}
[NinoSerialize] public partial class componentA { public int aa = 1; }
[NinoSerialize] public partial class componentB { public int bb = 2; }
DataTest test1 = new DataTest();
test1.a = 1;
test1.b = 2;
test1.compA = new();
DataTest test2 = new DataTest();
test1.a = 1;
test1.b = 2;
test1.compB = new();
在member中新增分组ID。 只对应序列化对应分组ID的数据
主工程:
`using Nino.Serialization;
namespace NinoData.Chat
{
[NinoSerialize]
public partial class SystemData
{
[NinoMember(1)]
public string name;
[NinoMember(2)]
public string notice;
}
}
`
热更工程:
` NinoData.Chat.SystemData systemData=new NinoData.Chat.SystemData() { name="111",notice="222"};
var dt = Nino.Serialization.Serializer.Serialize(systemData);
JEngine.Core.Log.PrintError(BitConverter.ToString(dt));
Nino.Serialization.Deserializer.Deserialize<NinoData.Chat.SystemData> (dt);
Debug.LogError("热更新"+ systemData.name);`
能输出序列化的byte 反序列化报错:
TargetException: Non-static field requires a target
System.Reflection.RuntimeFieldInfo.SetValue (System.Object obj, System.Object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) (at <1f66344f2f89470293d8b67d71308c07>:0)
System.Reflection.FieldInfo.SetValue (System.Object obj, System.Object value) (at <1f66344f2f89470293d8b67d71308c07>:0)
Nino.Serialization.Deserializer.Deserialize (System.Type type, System.Object val, System.Span1[T] data, Nino.Serialization.Reader reader, Nino.Serialization.CompressOption option, System.Boolean returnDispose) (at Assets/Dependencies/Nino/Serialization/Deserializer.cs:268) Nino.Serialization.Deserializer.Deserialize (System.Type type, System.Byte[] data, Nino.Serialization.CompressOption option) (at Assets/Dependencies/Nino/Serialization/Deserializer.cs:68) Nino.Serialization.ILRuntimeResolver.Deserialize_0 (ILRuntime.Runtime.Intepreter.ILIntepreter intp, ILRuntime.Runtime.Stack.StackObject* esp, System.Collections.Generic.List
1[T] mStack, ILRuntime.CLR.Method.CLRMethod method, System.Boolean isNewObj) (at Assets/Dependencies/Nino/Serialization/ILRuntimeResolver.cs:193)
ILRuntime.Runtime.Intepreter.ILIntepreter.Execute (ILRuntime.CLR.Method.ILMethod method, ILRuntime.Runtime.Stack.StackObject* esp, System.Boolean& unhandledException) (at Assets/Dependencies/ILRuntime/ILRuntime/Runtime/Intepreter/ILIntepreter.cs:2087)
Rethrow as ILRuntimeException: Non-static field requires a target
IL_006a: call !!0 Nino.Serialization.Deserializer::Deserialize<NinoData.Chat.SystemData>(System.Byte[],Nino.Serialization.CompressOption)
UI.LoginGame.LoginGame.Start() (at HotUpdateScripts/UI/LoginGame/LoginGame.cs:38)
IL_006a: call !!0 Nino.Serialization.Deserializer::Deserialize<NinoData.Chat.SystemData>(System.Byte[],Nino.Serialization.CompressOption)
UI.LoginGame.LoginGame.Start() (at HotUpdateScripts/UI/LoginGame/LoginGame.cs:38)
UnityEngine.DebugLogHandler:LogException(Exception, Object)
JEngine.Core.Logger:LogException(Exception, Object) (at Assets/Dependencies/JEngine/Core/Logger/LogHandler.cs:201)
UnityEngine.Debug:LogException(Exception)
JEngine.Core.LifeCycleMgr:ExecuteItems(List1, Boolean, Func
2) (at Assets/Dependencies/JEngine/Core/Manager/LifeCycleMgr.cs:326)
JEngine.Core.LifeCycleMgr:LateUpdate() (at Assets/Dependencies/JEngine/Core/Manager/LifeCycleMgr.cs:485)
按F12 查看热更工程的SystemData:
`#region 程序集 Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// F:\MoeMaster\MoeMaster\Library\ScriptAssemblies\Assembly-CSharp.dll
#endregion
using Nino.Serialization;
namespace NinoData.Chat
{
[NinoSerialize(false)]
public class SystemData
{
[NinoMemberAttribute(1)]
public string name;
[NinoMemberAttribute(2)]
public string notice;
public SystemData();
}
}`
原因是生成的代码使用了ref,不符合C#语法,报编译错误
1.0.21版本32位内存对齐有问题,Generate后,模拟器运行会闪退。
static void Main(string[] args)
{
var rawData = File.ReadAllBytes("3.map");
MemoryStream ms = new MemoryStream();
DeflateStream compressedzipStream = new DeflateStream(ms, CompressionMode.Compress);
compressedzipStream.Write(rawData, 0, rawData.Length);
compressedzipStream.Close();
var Srcdata = ms.ToArray();
ms.Dispose();
compressedzipStream.Dispose();
while (true)
{
var decode_data = Nino.Shared.Mgr.CompressMgr.Decompress(Srcdata);
GC.Collect();
Thread.Sleep(100);
}
}
[NinoSerialize(true)]
public partial class IncludeAllClass
{
public int a;
public long b;
public float c;
public double d;
public string str;
}
[NinoSerialize(true)]模式下:
问题 : 字段str未初始化时, 反序列化异常;
期望 : string 反序列化时做 空判断
[Serializable]
[NinoSerialize]
public partial class PlayerLoginState2
{
[NinoMember(0)] public List<int> TestService;
public PlayerLoginState2()
{
TestService = new List<int>();
}
}
在PlayerLoginState1和PlayerLoginState2一样的定义,PlayerLoginState1放在主工程,PlayerLoginState2放在热更工程;
在主工程调用
PlayerLoginState1 playerLoginState1 = new PlayerLoginState1();
playerLoginState1.TestService.Add(0);
string test1 = Convert.ToBase64String(Nino.Serialization.Serializer.Serialize(playerLoginState1));
Debug.Log("test1 Serialize OK >" + test1);
var test2 = Nino.Serialization.Deserializer.Deserialize<PlayerLoginState1>(Convert.FromBase64String(test1));
Debug.Log("test1 Deserialize OK");
不会出问题。
在热更工程调用以下代码:
PlayerLoginState1 playerLoginState1 = new PlayerLoginState1();
playerLoginState1.TestService.Add(0);
string test1 = Convert.ToBase64String(Nino.Serialization.Serializer.Serialize(playerLoginState1));
Debug.Log("test1 Serialize OK >" + test1);
var test2 = Nino.Serialization.Deserializer.Deserialize<PlayerLoginState1>(Convert.FromBase64String(test1));
Debug.Log("test1 Deserialize OK");
//
PlayerLoginState2 playerLoginState2 = new PlayerLoginState2();
playerLoginState2.TestService.Add(0);
string test3 = Convert.ToBase64String(Nino.Serialization.Serializer.Serialize(playerLoginState2));
Debug.Log("test2 Serialize OK >" + test3);
var test4 = Nino.Serialization.Deserializer.Deserialize<PlayerLoginState2>(Convert.FromBase64String(test3));
Debug.Log("test2 Deserialize OK");
运行结果:
test1 Serialize OK >42bkZgAA
test1 Deserialize OK
test2 Serialize OK >42bkZgAA
InvalidOperationException: The type System.Int32 does not have NinoSerialize attribute or custom importer/exporter
==========ILRuntime StackTrace==========
IL_0382: call !0 System.Runtime.CompilerServices.TaskAwaiter`1<System.Boolean>::GetResult()
HotUpdateScripts.Lcgames.LoadingPanel/<AccountLogin>d__17.MoveNext() (at HotUpdateScripts/Lcgames/UI/Panel/Base/LoadingPanel.cs:16707566)
--- End of stack trace from previous location ---
IL_00e9: call !!0 Nino.Serialization.Deserializer::Deserialize<HotUpdateScripts.Lcgames.PlayerLoginState2>(System.Byte[],System.Text.Encoding,Nino.Serialization.CompressOption)
在热更工程如果不调用 playerLoginState2.TestService.Add(0); 也不会出问题
[NinoMember(9)] public int LoginAppID = -1;
反序列化代码生成
reader.DecompressAndReadNumber<System.Int32>(ref value.LoginAppID);
值是错误的
用反射正常
序列化结果的二进制数组,怎么保存读取比较快速?
[Serializable]
[NinoSerialize]
public partial class test
{
[NinoMember(0)] public Dictionary<int, Dictionary<int, string>> testA;
}
主工程没问题
The type System.Int32 does not have NinoSerialize attribute or custom importer/exporter
using System;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using 协议;
using System.Runtime.Serialization.Formatters.Binary;
class MainClass
{
public static void Main(string[] args)
{
MessagePackage package = new MessagePackage
{
agreement = AgreementType.Move,
move = new Move(1, 2, 3, 4, 5, 6, 7)
};
var a = Nino.Serialization.Serializer.Serialize<MessagePackage>(package);
var b = Nino.Serialization.Deserializer.Deserialize<MessagePackage>(a);
Console.WriteLine(b.move.x);
}
}
public enum AgreementType
{
Enter = 1,
EnemyEnter = 2,
List = 3,
Move = 4,
ReadyCreatEnemy = 5,
OnGameEnd = 6,
Attack = 7,
Hit = 7,
OnHit = 8,
ReadyDTDown = 9,
ReadyDTUp = 10,
GetTime = 11,
GetID = 12,
}
[NinoSerialize(true)]
public partial class MessagePackage
{
public AgreementType agreement;
public Move move;
}
[NinoSerialize]
public partial class Move
{
[NinoMember(1)]
public int id;
[NinoMember(2)]
public float x;
[NinoMember(3)]
public float y;
[NinoMember(4)]
public float z;
[NinoMember(5)]
public float eulerX;
[NinoMember(6)]
public float eulerY;
[NinoMember(7)]
public float eulerZ;
public Move(int id,float x,float y,float z,float eulerX,float eulerY,float eulerZ)
{
this.id = id;
this.x = x;
this.y = y;
this.z = z;
this.eulerX = eulerX;
this.eulerY = eulerY;
this.eulerX = eulerZ;
}
}
MessagePacket:
public struct MessagePacket
{
public byte MessageID;
public ArraySegment<byte> MessageData;
public MessagePacket(byte messageID, ArraySegment<byte> messageData)
{
MessageData = messageData;
MessageID = messageID;
}
public MessagePacket(byte messageID, byte[] messageData)
{
MessageData = messageData;
MessageID = messageID;
}
public static MessagePacket ReadFrom(ArraySegment<byte> data)
{
return new MessagePacket(data.Array[0], data.Slice(1));
}
public static MessagePacket ReadFrom(byte[] data)
{
return new MessagePacket(data[0], data.AsSpan().Slice(1).ToArray());
}
public byte[] ToBytes()
{
var buffer = new byte[MessageData.Count + 1];
buffer[0] = MessageID;
MessageData.CopyTo(buffer, 1);
return buffer;
}
}
Npc:
[NinoSerialize]
public partial class Npc
{
[NinoMember(1)]
public int InstanceID;
[NinoMember(2)]
public int NpcID;
[NinoMember(3)]
public Vector3 ServerPosition;
[NinoMember(4)]
public bool IsMove;
[NinoMember(5)]
public int Blood;
}
主工程测试:
var npc = new Npc();
npc.NpcID = 1;
npc.ServerPosition = new Vector3(0f, 0f, 0f);
var messagePacket = new MessagePacket(0x02, Nino.Serialization.Serializer.Serialize(npc));
var temp = messagePacket.ToBytes();
var rst = MessagePacket.ReadFrom(temp);
var npc2 = Nino.Serialization.Deserializer.Deserialize<Npc>(rst.MessageData);
Debug.Log(npc2.NpcID);
Debug.Log(npc2.ServerPosition);
输出
TestNino
(0.00, 0.00, 0.00)
热更工程测试:
TestNino
Specified cast is not valid.
多态相关,抽象类直接作为成员变量时序列化报错
using Nino.Serialization;
using UnityEngine;
namespace Nino.Test.Editor.Serialization
{
public abstract class AbstractClass
{
[NinoMember(1)]
public int B;
}
[NinoSerialize]
public class ClassA: AbstractClass
{
[NinoMember(2)]
public int A;
}
[NinoSerialize]
public class ClassB
{
[NinoMember(1)]
public AbstractClass Class;
}
public static class Test12
{
private const string SerializationTest12 = "Nino/Test/Serialization/Test12 - Serialize (Abstract)";
[UnityEditor.MenuItem(SerializationTest12,priority=12)]
public static void Main()
{
ClassB b = new ClassB();
b.Class = new ClassA()
{
A = 1,
B = 2,
};
var bytes = Serializer.Serialize(b);
ClassB bb = Deserializer.Deserialize<ClassB>(bytes);
Debug.Log(bb.Class.GetType());
}
}
}
InvalidOperationException: The type Nino.Test.Editor.Serialization.AbstractClass does not have NinoSerialize attribute or custom importer/exporter
Nino.Serialization.TypeModel.TryGetModel (System.Type type, Nino.Serialization.TypeModel& model) (at Assets/Nino/Serialization/TypeModel.cs:207)
Nino.Serialization.Serializer.Serialize[T] (System.Type type, T value, Nino.Serialization.Writer writer, Nino.Serialization.CompressOption option, System.Boolean returnValue) (at Assets/Nino/Serialization/Serializer.cs:171)
Nino.Serialization.Serializer.Serialize[T] (System.Type type, T value, Nino.Serialization.Writer writer, Nino.Serialization.CompressOption option, System.Boolean returnValue) (at Assets/Nino/Serialization/Serializer.cs:218)
Nino.Serialization.Serializer.Serialize[T] (T val, Nino.Serialization.CompressOption option) (at Assets/Nino/Serialization/Serializer.cs:51)
Nino.Test.Editor.Serialization.Test12.Main () (at Assets/Nino/Test/Editor/Serialization/Test12.cs:39)
想用nino替换掉odin的持久化功能,odin老是丢数据。
比如下面这种数据结构
[NinoSerialize]
public class Test0
{
[NinoMember(1)] public List<Test1> a = new List<Test1>();
}
[NinoSerialize]
public class Test1
{
}
[NinoSerialize]
public class Test2: Test1
{
}
{
Test0 test = new Test0();
test.a.Add(new Test1());
test.a.Add(new Test2());
var bytes = Nino.Serialization.Serializer.Serialize(test);
test = Nino.Serialization.Deserializer.Deserialize<Test0>(bytes);
}
Nino/src/Nino.Serialization/TypeModel.cs
Line 257 in fd7d5af
[NinoSerialize]
public partial class IntRange
{
[NinoMember(0)]
public int _min;
[NinoMember(1)]
public int _max;
}
[NinoSerialize]
public partial class Item
{
[NinoMember(0)]
public IntRange Range;
}
序列化类 放在主工程
using Nino.Serialization;
namespace NinoData.Chat
{
[NinoSerialize]
public partial class SystemData
{
[NinoMember(1)]
public string name;
[NinoMember(2)]
public string notice;
}
}
主工程测试 测试ok
var data = Nino.Serialization.Serializer.Serialize(new NinoData.Chat.SystemData() { name = "111", notice = "bbb" });
Nino.Serialization.Deserializer.Deserialize< NinoData.Chat.SystemData> (data);
Debug.LogError("主工程ok");
热更工程
NinoData.Chat.SystemData systemData = new NinoData.Chat.SystemData() { name = "123" };
var dt = Nino.Serialization.Serializer.Serialize(systemData);
var data = Nino.Serialization.Deserializer.Deserialize<NinoData.Chat.SystemData> (dt);
报错:
InvalidOperationException: Failed to retrieve unbox type
Nino.Serialization.Serializer.Serialize[T] (System.Type type, T value, Nino.Serialization.Writer writer, Nino.Serialization.CompressOption option, System.Boolean returnValue) (at Assets/Dependencies/Nino/Serialization/Serializer.cs:215)
Nino.Serialization.Serializer.Serialize[T] (System.Type type, T value, Nino.Serialization.Writer writer, Nino.Serialization.CompressOption option, System.Boolean returnValue) (at Assets/Dependencies/Nino/Serialization/Serializer.cs:211)
Nino.Serialization.Serializer.Serialize[T] (T val, Nino.Serialization.CompressOption option) (at Assets/Dependencies/Nino/Serialization/Serializer.cs:51)
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <1f66344f2f89470293d8b67d71308c07>:0)
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
System.Reflection.RuntimeMethodInfo.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) (at <1f66344f2f89470293d8b67d71308c07>:0)
System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) (at <1f66344f2f89470293d8b67d71308c07>:0)
ILRuntime.CLR.Method.CLRMethod.Invoke (ILRuntime.Runtime.Intepreter.ILIntepreter intepreter, ILRuntime.Runtime.Stack.StackObject* esp, System.Collections.Generic.List1[T] mStack, System.Boolean isNewObj) (at Assets/Dependencies/ILRuntime/ILRuntime/CLR/Method/CLRMethod.cs:346) ILRuntime.Runtime.Intepreter.ILIntepreter.Execute (ILRuntime.CLR.Method.ILMethod method, ILRuntime.Runtime.Stack.StackObject* esp, System.Boolean& unhandledException) (at Assets/Dependencies/ILRuntime/ILRuntime/Runtime/Intepreter/ILIntepreter.cs:2103) Rethrow as ILRuntimeException: Exception has been thrown by the target of an invocation. IL_004b: call System.Byte[] Nino.Serialization.Serializer::Serialize<NinoData.Chat.SystemData>(!!0,Nino.Serialization.CompressOption) UI.LoginGame.LoginGame.Start() (at HotUpdateScripts/UI/LoginGame/LoginGame.cs:35) IL_004b: call System.Byte[] Nino.Serialization.Serializer::Serialize<NinoData.Chat.SystemData>(!!0,Nino.Serialization.CompressOption) UI.LoginGame.LoginGame.Start() (at HotUpdateScripts/UI/LoginGame/LoginGame.cs:35) UnityEngine.DebugLogHandler:LogException(Exception, Object) JEngine.Core.Logger:LogException(Exception, Object) (at Assets/Dependencies/JEngine/Core/Logger/LogHandler.cs:201) UnityEngine.Debug:LogException(Exception) JEngine.Core.LifeCycleMgr:ExecuteItems(List
1, Boolean, Func`2) (at Assets/Dependencies/JEngine/Core/Manager/LifeCycleMgr.cs:326)
JEngine.Core.LifeCycleMgr:LateUpdate() (at Assets/Dependencies/JEngine/Core/Manager/LifeCycleMgr.cs:485)
using System.Collections.Generic;
using JEngine.Core;
using Nino.Serialization;
using UnityEngine;
namespace Nino.Test
{
public class NinoDemo : MonoBehaviour
{
[NinoSerialize]
public class NinoTestData
{
public enum Sex
{
Male,
Female
}
[NinoMember(1)] public string name;
[NinoMember(2)] public int id;
[NinoMember(3)] public bool isHasPet;
[NinoMember(4)] public Sex sex;
}
public void Awake()
{
var _list = new List<NinoTestData>();
_list.Add(new NinoTestData
{
sex = NinoTestData.Sex.Male,
name = "A",
id = -1,
isHasPet = false
});
_list.Add(new NinoTestData
{
sex = NinoTestData.Sex.Male,
name = "B",
id = 1,
isHasPet = true
});
var buf = Serializer.Serialize(_list);
Log.Print($"Nino 将_list数据序列化为了 {buf.Length} bytes");
var _list2 = Deserializer.Deserialize<List<NinoTestData>>(buf);
Log.Print($"Nino 反序列化了一个_list2,内部有{_list2.Count}个元素");
Log.Print($"_list2[0].sex = {_list2[0].sex}\n" +
$"_list2[0].name = {_list2[0].name}\n" +
$"_list2[0].id = {_list2[0].id}\n" +
$"_list2[0].isHasPet = {_list2[0].isHasPet}\n");
Log.Print($"_list2[1].sex = {_list2[1].sex}\n" +
$"_list2[1].name = {_list2[1].name}\n" +
$"_list2[1].id = {_list2[1].id}\n" +
$"_list2[1].isHasPet = {_list2[1].isHasPet}\n");
var _arr = new NinoTestData[2];
_arr[0] = new NinoTestData
{
sex = NinoTestData.Sex.Male,
name = "C",
id = 2,
isHasPet = true
};
_arr[1] = new NinoTestData
{
sex = NinoTestData.Sex.Male,
name = "D",
id = 3,
isHasPet = false
};
buf = Serializer.Serialize(_arr);
Log.Print($"Nino 将_arr数据序列化为了 {buf.Length} bytes");
var _arr2 = Deserializer.Deserialize<List<NinoTestData>>(buf);
Log.Print($"Nino 反序列化了一个_arr2,内部有{_arr2.Count}个元素");
Log.Print($"_arr2[0].sex = {_arr2[0].sex}\n" +
$"_arr2[0].name = {_arr2[0].name}\n" +
$"_arr2[0].id = {_arr2[0].id}\n" +
$"_arr2[0].isHasPet = {_arr2[0].isHasPet}\n");
Log.Print($"_arr2[1].sex = {_arr2[1].sex}\n" +
$"_arr2[1].name = {_arr2[1].name}\n" +
$"_arr2[1].id = {_arr2[1].id}\n" +
$"_arr2[1].isHasPet = {_arr2[1].isHasPet}\n");
}
}
}
UncheckedList的作用是什么?
Assets\Pkg\Nino\Serialization\ILRuntimeResolver.cs(306,34): error CS0115: 'SerializationHelper1ILTypeInstanceAdapter.Adapter.Serialize(ILTypeInstance, Writer)': no suitable method found to override
Assets\Pkg\Nino\Serialization\ILRuntimeResolver.cs(279,22): error CS0534: 'SerializationHelper1ILTypeInstanceAdapter.Adapter' does not implement inherited abstract member 'NinoWrapperBase<ILTypeInstance>.GetSize(ILTypeInstance)'
Assets\Pkg\Nino\Serialization\ILRuntimeResolver.cs(279,22): error CS0534: 'SerializationHelper1ILTypeInstanceAdapter.Adapter' does not implement inherited abstract member 'NinoWrapperBase<ILTypeInstance>.Serialize(ILTypeInstance, ref Writer)'
Nino\Serialization\ILRuntimeResolver.cs 看一下 这个文件
[NinoSerialize(false)] public partial class componentB : MonoBehaviour
{
[NinoMember(0)]
public int bb = 2;
}
serialize(false)
单独设置member报错
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.