Sfoglia il codice sorgente

moved hxd.net code to hxbit library

Nicolas Cannasse 8 anni fa
parent
commit
7ba242bafa

+ 0 - 275
hxd/net/ArrayProxy.hx

@@ -1,275 +0,0 @@
-package hxd.net;
-import hxd.net.NetworkSerializable;
-
-class ArrayProxyData<T> extends BaseProxy {
-	public var array : Array<T>;
-	public function new(v) {
-		array = v;
-	}
-}
-
-abstract ArrayProxy<T>(ArrayProxyData<T>) {
-
-	@:noCompletion public var __value(get, never) : Array<T>;
-	@:noCompletion public var length(get, never) : Int;
-	inline function get___value() : Array<T> return this == null ? null : this.array;
-	inline function get_length() return this.array.length;
-
-	inline function new(a) {
-		this = a;
-	}
-
-	public inline function concat( a : Array<T> ) {
-		return this.array.concat(a);
-	}
-
-	public function copy() {
-		return new ArrayProxy(new ArrayProxyData(this.array.copy()));
-	}
-
-	public function filter( t : T->Bool ) {
-		return this.array.filter(t);
-	}
-
-	public inline function indexOf(x:T, ?fromIndex) {
-		return this.array.indexOf(x, fromIndex);
-	}
-
-	public inline function insert(pos:Int,x:T) {
-		this.array.insert(pos, x);
-		this.mark();
-	}
-
-	public inline function iterator() {
-		return this.array.iterator();
-	}
-
-	public inline function join( s : String ) {
-		return this.array.join(s);
-	}
-
-	public inline function lastIndexOf(x:T, ?fromIndex) {
-		return this.array.lastIndexOf(x, fromIndex);
-	}
-
-	public function map<S>( t : T->S ) {
-		return this.array.map(t);
-	}
-
-	public inline function pop() : Null<T> {
-		this.mark();
-		return this.array.pop();
-	}
-
-	public inline function push( x : T ) {
-		this.array.push(x);
-		this.mark();
-	}
-
-	public inline function remove( x : T ) {
-		this.array.remove(x);
-		this.mark();
-	}
-
-	public inline function reverse() {
-		this.array.reverse();
-		this.mark();
-	}
-
-	public inline function shift() : Null<T> {
-		this.mark();
-		return this.array.shift();
-	}
-
-	public inline function slice( pos : Int, ?end : Int ) : Array<T> {
-		return this.array.slice(pos, end);
-	}
-
-	public inline function sort(cmp:T->T->Int) {
-		this.array.sort(cmp);
-		this.mark();
-	}
-
-	public inline function splice( pos : Int, len : Int ) : Array<T> {
-		this.mark();
-		return this.array.splice(pos, len);
-	}
-
-	public inline function toString() {
-		return this.array.toString();
-	}
-
-	public inline function unshift( x : T ) : Void {
-		this.mark();
-		this.array.unshift(x);
-	}
-
-	@:to inline function toIterable() : Iterable<T> {
-		return this.array;
-	}
-
-	@:noCompletion public inline function bindHost(o, bit) {
-		this.bindHost(o, bit);
-	}
-
-	@:noCompletion public inline function unbindHost() {
-		this.unbindHost();
-	}
-
-	@:arrayAccess inline function get(idx:Int) {
-		return this.array[idx];
-	}
-
-	@:arrayAccess inline function set(idx:Int,v:T) {
-		this.array[idx] = v;
-		this.mark();
-	}
-
-	@:from static inline function fromArray<T>( a : Array<T> ) {
-		if( a == null ) return null;
-		return new ArrayProxy(new ArrayProxyData(a));
-	}
-}
-
-abstract ArrayProxy2<T:ProxyChild>(ArrayProxyData<T>) {
-
-	@:noCompletion public var __value(get, never) : Array<T>;
-	@:noCompletion public var length(get, never) : Int;
-	inline function get___value() : Array<T> return this == null ? null : this.array;
-	inline function get_length() return this.array.length;
-
-	inline function new(a) {
-		this = a;
-	}
-
-	inline function bind(v:T) {
-		if( v != null ) v.bindHost(this, 0);
-	}
-
-	inline function unbind(v:T) {
-		if( v != null ) v.unbindHost();
-	}
-
-	public inline function concat( a : Array<T> ) {
-		return this.array.concat(a);
-	}
-
-	public function copy() {
-		return new ArrayProxy2(new ArrayProxyData(this.array.copy()));
-	}
-
-	public function filter( t : T->Bool ) {
-		return this.array.filter(t);
-	}
-
-	public inline function indexOf(x:T, ?fromIndex) {
-		return this.array.indexOf(x, fromIndex);
-	}
-
-	public inline function insert(pos:Int, x:T) {
-		bind(x);
-		this.array.insert(pos, x);
-		this.mark();
-	}
-
-	public inline function iterator() {
-		return this.array.iterator();
-	}
-
-	public inline function join( s : String ) {
-		return this.array.join(s);
-	}
-
-	public inline function lastIndexOf(x:T, ?fromIndex) {
-		return this.array.lastIndexOf(x, fromIndex);
-	}
-
-	public function map<S>( t : T->S ) {
-		return this.array.map(t);
-	}
-
-	public inline function pop() : Null<T> {
-		this.mark();
-		var e = this.array.pop();
-		unbind(e);
-		return e;
-	}
-
-	public inline function push( x : T ) {
-		bind(x);
-		this.array.push(x);
-		this.mark();
-	}
-
-	public inline function remove( x : T ) {
-		var r = this.array.remove(x);
-		if( r ) unbind(x);
-		this.mark();
-		return r;
-	}
-
-	public inline function reverse() {
-		this.array.reverse();
-		this.mark();
-	}
-
-	public inline function shift() : Null<T> {
-		this.mark();
-		var x = this.array.shift();
-		unbind(x);
-		return x;
-	}
-
-	public inline function slice( pos : Int, ?end : Int ) : Array<T> {
-		return this.array.slice(pos, end);
-	}
-
-	public inline function sort(cmp:T->T->Int) {
-		this.array.sort(cmp);
-		this.mark();
-	}
-
-	public inline function splice( pos : Int, len : Int ) : Array<T> {
-		this.mark();
-		var objs = this.array.splice(pos, len);
-		for( o in objs ) unbind(o);
-		return objs;
-	}
-
-	public inline function toString() {
-		return this.array.toString();
-	}
-
-	public inline function unshift( x : T ) : Void {
-		this.mark();
-		bind(x);
-		this.array.unshift(x);
-	}
-
-	@:to inline function toIterable() : Iterable<T> {
-		return this.array;
-	}
-
-	@:noCompletion public inline function bindHost(o,bit) {
-		this.obj = o;
-		this.bit = bit;
-	}
-
-	@:arrayAccess inline function get(idx:Int) {
-		return this.array[idx];
-	}
-
-	@:arrayAccess inline function set(idx:Int, v:T) {
-		unbind(this.array[idx]);
-		bind(v);
-		this.array[idx] = v;
-		this.mark();
-	}
-
-	@:from static inline function fromArray<T:ProxyChild>( a : Array<T> ) {
-		if( a == null ) return null;
-		var p = new ArrayProxy2(new ArrayProxyData(a));
-		for( x in a ) p.bind(x);
-		return p;
-	}
-}

+ 0 - 60
hxd/net/MapProxy.hx

@@ -1,60 +0,0 @@
-package hxd.net;
-import hxd.net.NetworkSerializable;
-
-@:generic class MapData<K,V> extends BaseProxy {
-	public var map : Map<K,V>;
-	public function new(map) {
-		this.map = map;
-	}
-}
-
-abstract MapProxy<K,V>(MapData<K,V>) {
-
-	@:noCompletion public var __value(get, never) : Map<K,V>;
-	inline function get___value() return this == null ? null : this.map;
-
-	public inline function set(key:K, value:V) {
-		this.mark();
-		this.map.set(key, value);
-	}
-
-	@:arrayAccess public inline function get(key:K) return this.map.get(key);
-	public inline function exists(key:K) return this.map.exists(key);
-	public inline function remove(key:K) {
-		var b = this.map.remove(key);
-		if( b ) this.mark();
-		return b;
-	}
-
-	@:noCompletion public inline function bindHost(o, bit) {
-		this.bindHost(o, bit);
-	}
-
-	@:noCompletion public inline function unbindHost() {
-		this.unbindHost();
-	}
-
-	public inline function keys():Iterator<K> {
-		return this.map.keys();
-	}
-
-	public inline function iterator():Iterator<V> {
-		return this.map.iterator();
-	}
-
-	public inline function toString():String {
-		return this.map.toString();
-	}
-
-	@:arrayAccess @:noCompletion public inline function arrayWrite(k:K, v:V):V {
-		this.mark();
-		this.map.set(k, v);
-		return v;
-	}
-
-	@:from static inline function fromMap<K,V>(map:Map<K,V>):MapProxy<K,V> {
-		if( map == null ) return null;
-		return cast new MapData(map);
-	}
-	
-}

+ 0 - 503
hxd/net/NetworkHost.hx

@@ -1,503 +0,0 @@
-package hxd.net;
-
-class NetworkClient {
-
-	var host : NetworkHost;
-	var resultID : Int;
-	public var seqID : Int;
-	public var ownerObject : NetworkSerializable;
-
-	public function new(h) {
-		this.host = h;
-	}
-
-	public function sync() {
-		host.fullSync(this);
-	}
-
-	@:allow(hxd.net.NetworkHost)
-	function send(bytes : haxe.io.Bytes) {
-	}
-
-	public function sendMessage( msg : Dynamic ) {
-		host.sendMessage(msg, this);
-	}
-
-	function error( msg : String ) {
-		throw msg;
-	}
-
-	function processMessage( bytes : haxe.io.Bytes, pos : Int ) {
-		var ctx = host.ctx;
-		ctx.setInput(bytes, pos);
-		var mid = ctx.getByte();
-		switch( mid ) {
-		case NetworkHost.SYNC:
-			var o : hxd.net.NetworkSerializable = cast ctx.refs[ctx.getInt()];
-			var old = o.__bits;
-			var oldH = o.__host;
-			o.__host = null;
-			o.networkSync(ctx);
-			o.__host = oldH;
-			o.__bits = old;
-		case NetworkHost.REG:
-			var o : hxd.net.NetworkSerializable = cast ctx.getAnyRef();
-			o.__host = host;
-			host.makeAlive();
-		case NetworkHost.UNREG:
-			var o : hxd.net.NetworkSerializable = cast ctx.refs[ctx.getInt()];
-			o.__host = null;
-			ctx.refs.remove(o.__uid);
-		case NetworkHost.FULLSYNC:
-			ctx.refs = new Map();
-			@:privateAccess {
-				hxd.net.Serializer.UID = 0;
-				hxd.net.Serializer.SEQ = ctx.getByte();
-				ctx.newObjects = [];
-			};
-			while( true ) {
-				var o = ctx.getAnyRef();
-				if( o == null ) break;
-			}
-			host.makeAlive();
-		case NetworkHost.RPC:
-			var o : hxd.net.NetworkSerializable = cast ctx.refs[ctx.getInt()];
-			var fid = ctx.getByte();
-			if( !host.isAuth ) {
-				var old = o.__host;
-				o.__host = null;
-				o.networkRPC(ctx, fid, this);
-				o.__host = old;
-			} else {
-				host.rpcClientValue = this;
-				o.networkRPC(ctx, fid, this);
-				host.rpcClientValue = null;
-			}
-		case NetworkHost.RPC_WITH_RESULT:
-
-			var old = resultID;
-			resultID = ctx.getInt();
-			var o : hxd.net.NetworkSerializable = cast ctx.refs[ctx.getInt()];
-			var fid = ctx.getByte();
-			if( !host.isAuth ) {
-				var old = o.__host;
-				o.__host = null;
-				o.networkRPC(ctx, fid, this);
-				o.__host = old;
-			} else
-				o.networkRPC(ctx, fid, this);
-
-			if( host.checkEOM ) ctx.addByte(NetworkHost.EOM);
-
-			host.doSend();
-			host.targetClient = null;
-			resultID = old;
-
-		case NetworkHost.RPC_RESULT:
-
-			var resultID = ctx.getInt();
-			var callb = host.rpcWaits.get(resultID);
-			host.rpcWaits.remove(resultID);
-			callb(ctx);
-
-		case NetworkHost.MSG:
-			var msg = haxe.Unserializer.run(ctx.getString());
-			host.onMessage(this, msg);
-
-		case NetworkHost.BMSG:
-			var msg = ctx.getBytes();
-			host.onMessage(this, msg);
-
-		case x:
-			error("Unknown message code " + x);
-		}
-		return @:privateAccess ctx.inPos;
-	}
-
-	function beginRPCResult() {
-		host.flush();
-
-		if( host.logger != null )
-			host.logger("RPC RESULT #" + resultID);
-
-		var ctx = host.ctx;
-		host.hasData = true;
-		host.targetClient = this;
-		ctx.addByte(NetworkHost.RPC_RESULT);
-		ctx.addInt(resultID);
-		// after that RPC will add result value then return
-	}
-
-	public function stop() {
-		if( host == null ) return;
-		host.clients.remove(this);
-		host.pendingClients.remove(this);
-		host = null;
-	}
-
-}
-
-@:allow(hxd.net.NetworkClient)
-class NetworkHost {
-
-	static inline var SYNC 		= 1;
-	static inline var REG 		= 2;
-	static inline var UNREG 	= 3;
-	static inline var FULLSYNC 	= 4;
-	static inline var RPC 		= 5;
-	static inline var RPC_WITH_RESULT = 6;
-	static inline var RPC_RESULT = 7;
-	static inline var MSG		 = 8;
-	static inline var BMSG		 = 9;
-	static inline var EOM		 = 0xFF;
-
-	public var checkEOM(get, never) : Bool;
-	inline function get_checkEOM() return true;
-
-	public static var current : NetworkHost = null;
-
-	public var isAuth(default, null) : Bool;
-
-	/**
-		When a RPC of type Server is performed, this will tell the originating client from the RPC.
-	**/
-	public var rpcClient(get, never) : NetworkClient;
-
-	public var sendRate : Float = 0.;
-	public var totalSentBytes : Int = 0;
-
-	var lastSentTime : Float = 0.;
-	var lastSentBytes = 0;
-	var markHead : NetworkSerializable;
-	var ctx : Serializer;
-	var pendingClients : Array<NetworkClient>;
-	var clients : Array<NetworkClient>;
-	var logger : String -> Void;
-	var hasData = false;
-	var rpcUID = Std.random(0x1000000);
-	var rpcWaits = new Map<Int,Serializer->Void>();
-	var targetClient : NetworkClient;
-	var rpcClientValue : NetworkClient;
-	var aliveEvents : Array<Void->Void>;
-	public var self(default,null) : NetworkClient;
-
-	public function new() {
-		current = this;
-		isAuth = true;
-		self = new NetworkClient(this);
-		clients = [];
-		aliveEvents = [];
-		pendingClients = [];
-		ctx = new Serializer();
-		@:privateAccess ctx.newObjects = [];
-		ctx.begin();
-	}
-
-	public function saveState() {
-		var s = new hxd.net.Serializer();
-		s.beginSave();
-		var refs = [for( r in ctx.refs ) r];
-		refs.sort(sortByUID);
-		for( r in refs )
-			if( !s.refs.exists(r.__uid) )
-				s.addAnyRef(r);
-		s.addAnyRef(null);
-		return s.endSave();
-	}
-
-	public function loadSave( bytes : haxe.io.Bytes ) {
-		ctx.refs = new Map();
-		@:privateAccess ctx.newObjects = [];
-		ctx.setInput(bytes, 0);
-		ctx.beginLoadSave();
-		while( true ) {
-			var v = ctx.getAnyRef();
-			if( v == null ) break;
-		}
-		ctx.endLoadSave();
-		ctx.setInput(null, 0);
-	}
-
-	function mark(o:NetworkSerializable) {
-		if( !isAuth ) {
-			var owner = o.networkGetOwner();
-			if( owner == null || clients[0].ownerObject != owner )
-				throw "Client can't set property on " + o + " without ownership ("+owner + " should be "+clients[0].ownerObject+")";
-			// allow to modify the property localy and send it to server
-		}
-		o.__next = markHead;
-		markHead = o;
-		return true;
-	}
-
-	function get_rpcClient() {
-		return rpcClientValue == null ? self : rpcClientValue;
-	}
-
-	public dynamic function onMessage( from : NetworkClient, msg : Dynamic ) {
-	}
-
-	public function sendMessage( msg : Dynamic, ?to : NetworkClient ) {
-		flush();
-		targetClient = to;
-		if( Std.is(msg, haxe.io.Bytes) ) {
-			ctx.addByte(BMSG);
-			ctx.addBytes(msg);
-		} else {
-			ctx.addByte(MSG);
-			ctx.addString(haxe.Serializer.run(msg));
-		}
-		if( checkEOM ) ctx.addByte(EOM);
-		doSend();
-		targetClient = null;
-	}
-
-	function setTargetOwner( owner : NetworkSerializable ) {
-		if( !isAuth )
-			return true;
-		if( owner == null ) {
-			doSend();
-			targetClient = null;
-			return true;
-		}
-		flush();
-		targetClient = null;
-		for( c in clients )
-			if( c.ownerObject == owner ) {
-				targetClient = c;
-				break;
-			}
-		return targetClient != null; // owner not connected
-	}
-
-	function beginRPC(o:NetworkSerializable, id:Int, onResult:Serializer->Void) {
-		flushProps();
-		hasData = true;
-		if( ctx.refs[o.__uid] == null )
-			throw "Can't call RPC on an object not previously transferred";
-		if( onResult != null ) {
-			var id = rpcUID++;
-			ctx.addByte(RPC_WITH_RESULT);
-			ctx.addInt(id);
-			rpcWaits.set(id, onResult);
-		} else
-			ctx.addByte(RPC);
-		ctx.addInt(o.__uid);
-		ctx.addByte(id);
-		if( logger != null )
-			logger("RPC " + o +"."+o.networkGetName(id,true)+"()");
-		return ctx;
-	}
-
-	inline function endRPC() {
-		if( checkEOM ) ctx.addByte(EOM);
-	}
-
-	function fullSync( c : NetworkClient ) {
-		if( !pendingClients.remove(c) )
-			return;
-		flush();
-
-		// unique client sequence number
-		var seq = clients.length + 1;
-		while( true ) {
-			var found = false;
-			for( c in clients )
-				if( c.seqID == seq ) {
-					found = true;
-					break;
-				}
-			if( !found ) break;
-			seq++;
-		}
-		ctx.addByte(seq);
-		c.seqID = seq;
-
-		clients.push(c);
-		var refs = ctx.refs;
-		ctx.begin();
-		ctx.addByte(FULLSYNC);
-		ctx.addByte(c.seqID);
-		for( o in refs )
-			if( o != null )
-				ctx.addAnyRef(o);
-		ctx.addAnyRef(null);
-		if( checkEOM ) ctx.addByte(EOM);
-		targetClient = c;
-		doSend();
-		targetClient = null;
-	}
-
-	public function defaultLogger( ?filter : String -> Bool ) {
-		setLogger(function(str) {
-			if( filter != null && !filter(str) ) return;
-			str = (isAuth ? "[S] " : "[C] ") + str;
-			str = haxe.Timer.stamp() + " " + str;
-			#if	sys Sys.println(str); #else trace(str); #end
-		});
-	}
-
-	public inline function addAliveEvent(f) {
-		aliveEvents.push(f);
-	}
-
-	public function isAliveComplete() {
-		return @:privateAccess ctx.newObjects.length == 0 && aliveEvents.length == 0;
-	}
-
-	static function sortByUID(o1:Serializable, o2:Serializable) {
-		return o1.__uid - o2.__uid;
-	}
-
-	public function makeAlive() {
-		var objs = @:privateAccess ctx.newObjects;
-		if( objs.length == 0 )
-			return;
-		objs.sort(sortByUID);
-		while( true ) {
-			var o = objs.shift();
-			if( o == null ) break;
-			var n = Std.instance(o, NetworkSerializable);
-			if( n == null ) continue;
-			if( logger != null )
-				logger("Alive " + n +"#" + n.__uid);
-			n.alive();
-		}
-		while( aliveEvents.length > 0 )
-			aliveEvents.shift()();
-	}
-
-	public function setLogger( log : String -> Void ) {
-		this.logger = log;
-	}
-
-	function register( o : NetworkSerializable ) {
-		o.__host = this;
-		if( ctx.refs[o.__uid] != null )
-			return;
-		if( !isAuth ) {
-			var owner = o.networkGetOwner();
-			if( owner == null || owner != self.ownerObject )
-				throw "Can't register "+o+" without ownership (" + owner + " should be " + self.ownerObject + ")";
-		}
-		if( logger != null )
-			logger("Register " + o + "#" + o.__uid);
-		ctx.addByte(REG);
-		ctx.addAnyRef(o);
-		if( checkEOM ) ctx.addByte(EOM);
-	}
-
-	function unmark( o : NetworkSerializable ) {
-		if( o.__next == null )
-			return;
-		var prev = null;
-		var h = markHead;
-		while( h != o ) {
-			prev = h;
-			h = h.__next;
-		}
-		if( prev == null )
-			markHead = o.__next;
-		else
-			prev.__next = o.__next;
-		o.__next = null;
-	}
-
-	function unregister( o : NetworkSerializable ) {
-		if( o.__host == null )
-			return;
-		if( !isAuth ) {
-			var owner = o.networkGetOwner();
-			if( owner == null || owner != self.ownerObject )
-				throw "Can't unregister "+o+" without ownership (" + owner + " should be " + self.ownerObject + ")";
-		}
-		flushProps(); // send changes
-		o.__host = null;
-		o.__bits = 0;
-		unmark(o);
-		if( logger != null )
-			logger("Unregister " + o+"#"+o.__uid);
-		ctx.addByte(UNREG);
-		ctx.addInt(o.__uid);
-		if( checkEOM ) ctx.addByte(EOM);
-		ctx.refs.remove(o.__uid);
-	}
-
-	function doSend() {
-		var bytes;
-		@:privateAccess {
-			bytes = ctx.out.getBytes();
-			ctx.out = new haxe.io.BytesBuffer();
-		}
-		send(bytes);
-		hasData = false;
-	}
-
-	function send( bytes : haxe.io.Bytes ) {
-		if( targetClient != null ) {
-			totalSentBytes += bytes.length;
-			targetClient.send(bytes);
-		}
-		else {
-			totalSentBytes += bytes.length * clients.length;
-			if( clients.length == 0 ) totalSentBytes += bytes.length; // still count for statistics
-			for( c in clients )
-				c.send(bytes);
-		}
-	}
-
-	function flushProps() {
-		var o = markHead;
-		while( o != null ) {
-			if( o.__bits != 0 ) {
-				if( logger != null ) {
-					var props = [];
-					var i = 0;
-					while( 1 << i <= o.__bits ) {
-						if( o.__bits & (1 << i) != 0 )
-							props.push(o.networkGetName(i));
-						i++;
-					}
-					logger("SYNC " + o + "#" + o.__uid + " " + props.join("|"));
-				}
-				ctx.addByte(SYNC);
-				ctx.addInt(o.__uid);
-				o.networkFlush(ctx);
-				if( checkEOM ) ctx.addByte(EOM);
-				hasData = true;
-			}
-			var n = o.__next;
-			o.__next = null;
-			o = n;
-		}
-		markHead = null;
-	}
-
-	public function flush() {
-		flushProps();
-		if( hasData ) doSend();
-		// update sendRate
-		var now = haxe.Timer.stamp();
-		var dt = now - lastSentTime;
-		if( dt < 0.5 )
-			return;
-		var db = totalSentBytes - lastSentBytes;
-		var rate = db / dt;
-		sendRate = (sendRate + rate) * 0.5; // smooth
-		lastSentTime = now;
-		lastSentBytes = totalSentBytes;
-	}
-
-	static function enableReplication( o : NetworkSerializable, b : Bool ) {
-		if( b ) {
-			if( o.__host != null ) return;
-			if( current == null ) throw "No NetworkHost defined";
-			current.register(o);
-		} else {
-			if( o.__host == null ) return;
-			o.__host.unregister(o);
-		}
-	}
-
-
-}

+ 0 - 61
hxd/net/NetworkSerializable.hx

@@ -1,61 +0,0 @@
-package hxd.net;
-
-interface ProxyHost {
-	public function networkSetBit( bit : Int ) : Void;
-}
-
-interface ProxyChild {
-	public function bindHost( p : ProxyHost, bit : Int ) : Void;
-	public function unbindHost() : Void;
-}
-
-@:autoBuild(hxd.net.Macros.buildNetworkSerializable())
-interface NetworkSerializable extends Serializable extends ProxyHost {
-	public var __host : NetworkHost;
-	public var __bits : Int;
-	public var __next : NetworkSerializable;
-	public var enableReplication(get, set) : Bool;
-	public function alive() : Void; // user defined
-
-	public function networkFlush( ctx : Serializer ) : Void;
-	public function networkSync( ctx : Serializer ) : Void;
-	public function networkRPC( ctx : Serializer, rpcID : Int, clientResult : NetworkHost.NetworkClient ) : Void;
-	public function networkGetOwner() : NetworkSerializable;
-	public function networkGetName( propId : Int, isRPC : Bool = false ) : String;
-}
-
-@:genericBuild(hxd.net.Macros.buildSerializableProxy())
-class Proxy<T> {
-}
-
-class BaseProxy implements ProxyHost implements ProxyChild {
-	public var obj : ProxyHost;
-	public var bit : Int;
-	public inline function networkSetBit(_) {
-		mark();
-	}
-	public inline function mark() {
-		if( obj != null ) obj.networkSetBit(bit);
-	}
-	public inline function bindHost(o, bit) {
-		this.obj = o;
-		this.bit = bit;
-	}
-	public inline function unbindHost() {
-		this.obj = null;
-	}
-}
-
-abstract NetworkProperty(Int) {
-
-	public inline function new(x:Int) {
-		this = x;
-	}
-
-	public inline function toInt() {
-		return this;
-	}
-
-	@:op(a|b) inline function opOr(a:NetworkProperty) return new NetworkProperty(this | a.toInt());
-
-}

+ 0 - 29
hxd/net/Schema.hx

@@ -1,29 +0,0 @@
-package hxd.net;
-
-typedef FieldType = Macros.PropTypeDesc<FieldType>;
-
-#if !macro
-class Schema implements Serializable {
-
-	public var checkSum(get,never) : Int;
-	@:s @:notMutable public var fieldsNames : Array<String>;
-	@:s @:notMutable public var fieldsTypes : Array<FieldType>;
-
-	public function new() {
-		fieldsNames = [];
-		fieldsTypes = [];
-	}
-
-	function get_checkSum() {
-		var s = new Serializer();
-		s.begin();
-		var old = __uid;
-		__uid = 0;
-		s.addKnownRef(this);
-		__uid = old;
-		var bytes = s.end();
-		return haxe.crypto.Crc32.make(bytes);
-	}
-
-}
-#end

+ 0 - 15
hxd/net/Serializable.hx

@@ -1,15 +0,0 @@
-package hxd.net;
-
-@:autoBuild(hxd.net.Macros.buildSerializable())
-interface Serializable {
-	public var __uid : Int;
-	public function getCLID() : Int;
-	public function serialize( ctx : Serializer ) : Void;
-	public function unserializeInit() : Void;
-	public function unserialize( ctx : Serializer ) : Void;
-	public function getSerializeSchema() : Schema;
-}
-
-@:genericBuild(hxd.net.Macros.buildSerializableEnum())
-class SerializableEnum<T> {
-}

+ 0 - 734
hxd/net/Serializer.hx

@@ -1,734 +0,0 @@
-package hxd.net;
-
-class ConvertField {
-	public var index : Int;
-	public var same : Bool;
-	public var defaultValue : Dynamic;
-	public var from : Null<Schema.FieldType>;
-	public var to : Null<Schema.FieldType>;
-	public function new(from, to) {
-		this.from = from;
-		this.to = to;
-	}
-}
-
-class Convert {
-
-	public var read : Array<ConvertField>;
-	public var write : Array<ConvertField>;
-
-	public function new( ourSchema : Schema, schema : Schema ) {
-		var ourMap = new Map();
-		for( i in 0...ourSchema.fieldsNames.length )
-			ourMap.set(ourSchema.fieldsNames[i], ourSchema.fieldsTypes[i]);
-		read = [];
-
-		var map = new Map();
-		for( i in 0...schema.fieldsNames.length ) {
-			var oldT = schema.fieldsTypes[i];
-			var newT = ourMap.get(schema.fieldsNames[i]);
-			var c = new ConvertField(oldT, newT);
-			if( newT != null ) {
-				if( sameType(oldT, newT) )
-					c.same = true;
-				else
-					c.defaultValue = getDefault(newT);
-			}
-			c.index = read.length;
-			read.push(c);
-			map.set(schema.fieldsNames[i], c);
-		}
-
-		write = [];
-		for( i in 0...ourSchema.fieldsNames.length ) {
-			var newT = ourSchema.fieldsTypes[i];
-			var c = map.get(ourSchema.fieldsNames[i]);
-			if( c == null ) {
-				c = new ConvertField(null, newT);
-				// resolve default value using a specific method ?
-				c.defaultValue = getDefault(newT);
-			}
-			write.push(c);
-		}
-	}
-
-	public static function sameType( a : Schema.FieldType, b : Schema.FieldType ) {
-		switch( [a, b] ) {
-		case [PMap(ak, av), PMap(bk, bv)]:
-			return sameType(ak, bk) && sameType(av, bv);
-		case [PArray(a), PArray(b)],[PVector(a),PVector(b)],[PNull(a),PNull(b)]:
-			return sameType(a, b);
-		case [PObj(fa), PObj(fb)]:
-			if( fa.length != fb.length ) return false;
-			for( i in 0...fa.length ) {
-				var a = fa[i];
-				var b = fb[i];
-				if( a.name != b.name || a.opt != b.opt || !sameType(a.type, b.type) )
-					return false;
-			}
-			return true;
-		case [PAlias(a), PAlias(b)]:
-			return sameType(a, b);
-		case [PAlias(a), _]:
-			return sameType(a, b);
-		case [_, PAlias(b)]:
-			return sameType(a, b);
-		default:
-			return Type.enumEq(a, b);
-		}
-	}
-
-	public static function getDefault(t:Schema.FieldType) : Dynamic {
-		return switch( t ) {
-		case PInt: 0;
-		case PFloat: 0.;
-		case PArray(_): [];
-		case PMap(k, _):
-			switch( k ) {
-			case PInt: new Map<Int,Dynamic>();
-			case PString: new Map<String,Dynamic>();
-			default: new Map<{},Dynamic>();
-			}
-		case PVector(_): new haxe.ds.Vector<Dynamic>(0);
-		case PBool: false;
-		case PAlias(t): getDefault(t);
-		case PEnum(_), PNull(_), PObj(_), PSerializable(_), PString, PUnknown, PBytes: null;
-		};
-	}
-
-}
-
-class Serializer {
-
-	static var UID = 0;
-	static var SEQ = 0;
-	static inline var SEQ_BITS = 8;
-	static inline var SEQ_MASK = 0xFFFFFFFF >>> SEQ_BITS;
-
-	public static function resetCounters() {
-		UID = 0;
-		SEQ = 0;
-	}
-
-	static inline function allocUID() {
-		return (SEQ << (32 - SEQ_BITS)) | (++UID);
-	}
-
-	static var CLASSES : Array<Class<Dynamic>> = [];
-	static var CL_BYID = null;
-	static var CLIDS = null;
-	static function registerClass( c : Class<Dynamic> ) {
-		if( CLIDS != null ) throw "Too late to register class";
-		var idx = CLASSES.length;
-		CLASSES.push(c);
-		return idx;
-	}
-
-	static function initClassIDS() {
-		var cl = CLASSES;
-		var subClasses = [for( c in cl ) []];
-		var isSub = [];
-		for( i in 0...cl.length ) {
-			var c = cl[i];
-			while( true ) {
-				c = Type.getSuperClass(c);
-				if( c == null ) break;
-				var idx = cl.indexOf(c);
-				if( idx < 0 ) break; // super class is not serializable
-				subClasses[idx].push(i);
-				isSub[i] = true;
-			}
-		}
-
-		inline function hash(name:String) {
-			var v = 1;
-			for( i in 0...name.length )
-				v = v * 223 + StringTools.fastCodeAt(name,i);
-			v = 1 + ((v & 0x3FFFFFFF) % 65423);
-			return v;
-		}
-		CLIDS = [for( i in 0...CLASSES.length ) if( subClasses[i].length == 0 && !isSub[i] ) 0 else hash(Type.getClassName(cl[i]))];
-		CL_BYID = [];
-		for( i in 0...CLIDS.length ) {
-			var cid = CLIDS[i];
-			if( cid == 0 ) continue;
-			if( CL_BYID[cid] != null ) throw "Conflicting CLID between " + Type.getClassName(CL_BYID[cid]) + " and " + Type.getClassName(cl[i]);
-			CL_BYID[cid] = cl[i];
-		}
-	}
-
-	public var refs : Map<Int,Serializable>;
-	var newObjects : Array<Serializable>;
-	var out : haxe.io.BytesBuffer;
-	var input : haxe.io.Bytes;
-	var inPos : Int;
-	var usedClasses : Array<Bool> = [];
-	var convert : Array<Convert>;
-	var mapIndexes : Array<Int>;
-
-	public function new() {
-		if( CLIDS == null ) initClassIDS();
-	}
-
-	public function begin() {
-		out = new haxe.io.BytesBuffer();
-		refs = new Map();
-	}
-
-	public function end() {
-		var bytes = out.getBytes();
-		out = null;
-		refs = null;
-		return bytes;
-	}
-
-	public function setInput(data, pos) {
-		input = data;
-		inPos = pos;
-	}
-
-	public function serialize( s : Serializable ) {
-		begin();
-		addKnownRef(s);
-		return out.getBytes();
-	}
-
-	public function unserialize<T:Serializable>( data : haxe.io.Bytes, c : Class<T>, startPos = 0 ) : T {
-		refs = new Map();
-		setInput(data, startPos);
-		return getKnownRef(c);
-	}
-
-	public inline function getByte() {
-		return input.get(inPos++);
-	}
-
-	public inline function addByte(v:Int) {
-		out.addByte(v);
-	}
-
-	public inline function addInt(v:Int) {
-		if( v >= 0 && v < 0x80 )
-			out.addByte(v);
-		else {
-			out.addByte(0x80);
-			out.addInt32(v);
-		}
-	}
-
-	public inline function addInt32(v:Int) {
-		out.addInt32(v);
-	}
-
-	public inline function addFloat(v:Float) {
-		out.addFloat(v);
-	}
-
-	public inline function addDouble(v:Float) {
-		out.addDouble(v);
-	}
-
-	public inline function addBool(v:Bool) {
-		addByte(v?1:0);
-	}
-
-	public inline function addArray<T>(a:Array<T>,f:T->Void) {
-		if( a == null ) {
-			addByte(0);
-			return;
-		}
-		addInt(a.length + 1);
-		for( v in a )
-			f(v);
-	}
-
-	public inline function addVector<T>(a:haxe.ds.Vector<T>,f:T->Void) {
-		if( a == null ) {
-			addByte(0);
-			return;
-		}
-		addInt(a.length + 1);
-		for( v in a )
-			f(v);
-	}
-
-	public inline function getArray<T>(f:Void->T) : Array<T> {
-		var len = getInt();
-		if( len == 0 )
-			return null;
-		len--;
-		var a = [];
-		for( i in 0...len )
-			a[i] = f();
-		return a;
-	}
-
-	public inline function getVector<T>(f:Void->T) : haxe.ds.Vector<T> {
-		var len = getInt();
-		if( len == 0 )
-			return null;
-		len--;
-		var a = new haxe.ds.Vector<T>(len);
-		for( i in 0...len )
-			a[i] = f();
-		return a;
-	}
-
-	public inline function addMap<K,T>(a:Map<K,T>,fk:K->Void,ft:T->Void) {
-		if( a == null ) {
-			addByte(0);
-			return;
-		}
-		var keys = Lambda.array({ iterator : a.keys });
-		addByte(keys.length + 1);
-		for( k in keys ) {
-			fk(k);
-			ft(a.get(k));
-		}
-	}
-
-	@:extern public inline function getMap<K,T>(fk:Void->K, ft:Void->T) : Map<K,T> {
-		var len = getInt();
-		if( len == 0 )
-			return null;
-		var m = new Map<K,T>();
-		while( --len > 0 ) {
-			var k = fk();
-			var v = ft();
-			m.set(k, v);
-		}
-		return m;
-	}
-
-	public inline function getBool() {
-		return getByte() != 0;
-	}
-
-	public inline function getInt() {
-		var v = getByte();
-		if( v == 0x80 ) {
-			v = input.getInt32(inPos);
-			inPos += 4;
-		}
-		return v;
-	}
-
-	public inline function getInt32() {
-		var v = input.getInt32(inPos);
-		inPos += 4;
-		return v;
-	}
-
-	public inline function getDouble() {
-		var v = input.getDouble(inPos);
-		inPos += 8;
-		return v;
-	}
-
-	public inline function getFloat() {
-		var v = input.getFloat(inPos);
-		inPos += 4;
-		return v;
-	}
-
-	public inline function addString( s : String ) {
-		if( s == null )
-			addByte(0);
-		else {
-			var b = haxe.io.Bytes.ofString(s);
-			addInt(b.length + 1);
-			out.add(b);
-		}
-	}
-
-	public inline function addBytes( b : haxe.io.Bytes ) {
-		if( b == null )
-			addByte(0);
-		else {
-			addInt(b.length + 1);
-			out.add(b);
-		}
-	}
-
-	public inline function getString() {
-		var len = getInt();
-		if( len == 0 )
-			return null;
-		len--;
-		var s = input.getString(inPos, len);
-		inPos += len;
-		return s;
-	}
-
-	public inline function getBytes() {
-		var len = getInt();
-		if( len == 0 )
-			return null;
-		len--;
-		var s = input.sub(inPos, len);
-		inPos += len;
-		return s;
-	}
-
-	public inline function addCLID( clid : Int ) {
-		addByte(clid >> 8);
-		addByte(clid & 0xFF);
-	}
-
-	public inline function getCLID() {
-		return (getByte() << 8) | getByte();
-	}
-
-	public function addAnyRef( s : Serializable ) {
-		if( s == null ) {
-			addByte(0);
-			return;
-		}
-		addInt(s.__uid);
-		if( refs[s.__uid] != null )
-			return;
-		refs[s.__uid] = s;
-		var index = s.getCLID();
-		usedClasses[index] = true;
-		addCLID(index); // index
-		s.serialize(this);
-	}
-
-	public function addKnownRef( s : Serializable ) {
-		if( s == null ) {
-			addByte(0);
-			return;
-		}
-		addInt(s.__uid);
-		if( refs[s.__uid] != null )
-			return;
-		refs[s.__uid] = s;
-		var index = s.getCLID();
-		usedClasses[index] = true;
-		var clid = CLIDS[index];
-		if( clid != 0 )
-			addCLID(clid); // hash
-		s.serialize(this);
-	}
-
-	public function getAnyRef() : Serializable {
-		var id = getInt();
-		if( id == 0 ) return null;
-		if( refs[id] != null )
-			return cast refs[id];
-		var rid = id & SEQ_MASK;
-		if( UID < rid ) UID = rid;
-		var clidx = getCLID();
-		if( mapIndexes != null ) clidx = mapIndexes[clidx];
-		var i : Serializable = Type.createEmptyInstance(CLASSES[clidx]);
-		if( newObjects != null ) newObjects.push(i);
-		i.__uid = id;
-		i.unserializeInit();
-		refs[id] = i;
-		if( convert != null && convert[clidx] != null )
-			convertRef(i, convert[clidx]);
-		else
-			i.unserialize(this);
-		return i;
-	}
-
-	public function getRef<T:Serializable>( c : Class<T>, clidx : Int ) : T {
-		var id = getInt();
-		if( id == 0 ) return null;
-		if( refs[id] != null )
-			return cast refs[id];
-		var rid = id & SEQ_MASK;
-		if( UID < rid ) UID = rid;
-		if( CLIDS[clidx] != 0 ) {
-			var realIdx = getCLID();
-			c = cast CL_BYID[realIdx];
-			if( convert != null ) clidx = untyped c.__clid; // real class convert
-		}
-		var i : T = Type.createEmptyInstance(c);
-		if( newObjects != null ) newObjects.push(i);
-		i.__uid = id;
-		i.unserializeInit();
-		refs[id] = i;
-		if( convert != null && convert[clidx] != null )
-			convertRef(i, convert[clidx]);
-		else
-			i.unserialize(this);
-		return i;
-	}
-
-	public inline function getKnownRef<T:Serializable>( c : Class<T> ) : T {
-		return getRef(c, untyped c.__clid);
-	}
-
-
-	public function beginSave() {
-		begin();
-		usedClasses = [];
-	}
-
-	public function endSave() {
-		var content = end();
-		begin();
-		var classes = [];
-		var schemas = [];
-		var sidx = CLASSES.indexOf(Schema);
-		for( i in 0...usedClasses.length ) {
-			if( !usedClasses[i] || i == sidx ) continue;
-			var c = CLASSES[i];
-			var schema = (Type.createEmptyInstance(c) : Serializable).getSerializeSchema();
-			schemas.push(schema);
-			classes.push(i);
-			addKnownRef(schema);
-			refs.remove(schema.__uid);
-		}
-		var schemaData = end();
-		begin();
-		addString("HXS");
-		addByte(1);
-		for( i in 0...classes.length ) {
-			var index = classes[i];
-			addString(Type.getClassName(CLASSES[index]));
-			addCLID(index);
-			addInt32(schemas[i].checkSum);
-		}
-		addString(null);
-		addInt(schemaData.length);
-		out.add(schemaData);
-		out.add(content);
-		return end();
-	}
-
-	public function beginLoadSave() {
-		var classByName = new Map();
-		var schemas = [];
-		var mapIndexes = [];
-		var indexes = [];
-		var needConvert = false;
-		var needReindex = false;
-		for( i in 0...CLASSES.length ) {
-			classByName.set(Type.getClassName(CLASSES[i]), i);
-			mapIndexes[i] = i;
-		}
-		if( getString() != "HXS" )
-			throw "Invalid HXS data";
-		var version = getByte();
-		if( version != 1 )
-			throw "Unsupported HXS version " + version;
-
-		/*
-			TODO : one last thing not checked is the fact that we can save some data in addKnownRef
-			if the class has no subclass.
-			We need to save this status in our class schema and adapt if it gets changed.
-		*/
-
-		while( true ) {
-			var clname = getString();
-			if( clname == null ) break;
-			var index = getCLID();
-			var crc = getInt32();
-			var ourClassIndex = classByName.get(clname);
-			if( ourClassIndex == null ) throw "Missing class " + clname+" found in HXS data";
-			var ourSchema = (Type.createEmptyInstance(CLASSES[ourClassIndex]) : Serializable).getSerializeSchema();
-			if( ourSchema.checkSum != crc ) {
-				needConvert = true;
-				schemas[index] = ourSchema;
-			}
-			if( index != ourClassIndex ) {
-				needReindex = true;
-				mapIndexes[index] = ourClassIndex;
-			}
-			indexes.push(index);
-		}
-		var schemaDataSize = getInt();
-		if( needConvert ) {
-			convert = [];
-			for( index in indexes ) {
-				var ourSchema = schemas[index];
-				var schema = getKnownRef(Schema);
-				refs.remove(schema.__uid);
-				if( ourSchema != null )
-					convert[mapIndexes[index]] = new Convert(ourSchema, schema);
-			}
-		} else {
-			// skip schema data
-			inPos += schemaDataSize;
-		}
-		if( needReindex )
-			this.mapIndexes = mapIndexes;
-	}
-
-	public function endLoadSave() {
-		convert = null;
-		mapIndexes = null;
-	}
-
-	function convertRef( i : Serializable, c : Convert ) {
-		var values = new haxe.ds.Vector<Dynamic>(c.read.length);
-		var writePos = 0;
-		for( r in c.read )
-			values[r.index] = readValue(r.from);
-		var oldOut = this.out;
-		out = new haxe.io.BytesBuffer();
-		for( w in c.write ) {
-			var v : Dynamic;
-			if( w.from == null )
-				v = w.defaultValue;
-			else {
-				v = values[w.index];
-				if( !w.same ) {
-					if( v == null )
-						v = w.defaultValue;
-					else
-						v = convertValue(v, w.from, w.to);
-				}
-			}
-			writeValue(v, w.to);
-		}
-		var bytes = out.getBytes();
-		out = oldOut;
-		var oldIn = input;
-		var oldPos = inPos;
-		setInput(bytes, 0);
-		i.unserialize(this);
-		setInput(oldIn, oldPos);
-	}
-
-	function isNullable( t : Schema.FieldType ) {
-		return switch( t ) {
-		case PInt, PFloat, PBool: false;
-		default: true;
-		}
-	}
-
-	function convertValue( v : Dynamic, from : Schema.FieldType, to : Schema.FieldType ) : Dynamic {
-
-		if( v == null && isNullable(to) )
-			return null;
-
-		if( Convert.sameType(from,to) )
-			return v;
-
-		switch( [from, to] ) {
-		case [PObj(obj1), PObj(obj2)]:
-			var v2 = {};
-			for( f in obj2 ) {
-				var found = false;
-				var field : Dynamic = null;
-				for( f2 in obj1 )
-					if( f2.name == f.name ) {
-						found = true;
-						field = convertValue(Reflect.field(v, f2.name), f2.type, f.type);
-						break;
-					}
-				if( !found ) {
-					if( f.opt ) continue;
-					field = Convert.getDefault(f.type);
-				} else if( field == null && f.opt )
-					continue;
-				Reflect.setField(v2, f.name, field);
-			}
-			return v2;
-		default:
-		}
-		throw "Cannot convert " + v + " from " + from + " to " + to;
-	}
-
-	function readValue( t : Schema.FieldType ) : Dynamic {
-		return switch( t ) {
-		case PInt: getInt();
-		case PFloat: getFloat();
-		case PAlias(t): readValue(t);
-		case PBool: getBool();
-		case PString: getString();
-		case PArray(t): getArray(function() return readValue(t));
-		case PVector(t): getVector(function() return readValue(t));
-		case PBytes: getBytes();
-		case PEnum(name):
-			var ser = "hxd.net.enumSer." + name.split(".").join("_");
-			if( ser == null ) throw "No enum unserializer found for " + name;
-			return (Type.resolveClass(ser) : Dynamic).doUnserialize(this);
-		case PSerializable(name): getKnownRef(Type.resolveClass(name));
-		case PNull(t): getByte() == 0 ? null : readValue(t);
-		case PObj(fields):
-			var bits = getByte();
-			if( bits == 0 )
-				return null;
-			var o = {};
-			bits--;
-			var nullables = [for( f in fields ) if( isNullable(f.type) ) f];
-			for( f in fields ) {
-				var nidx = nullables.indexOf(f);
-				if( nidx >= 0 && bits & (1 << nidx) == 0 ) continue;
-				Reflect.setField(o, f.name, readValue(f.type));
-			}
-			return o;
-		case PMap(k, v):
-			switch( k ) {
-			case PInt:
-				(getMap(function() return readValue(k), function() return readValue(v)) : Map<Int,Dynamic>);
-			case PString:
-				(getMap(function() return readValue(k), function() return readValue(v)) : Map<String,Dynamic>);
-			default:
-				(getMap(function() return readValue(k), function() return readValue(v)) : Map<{},Dynamic>);
-			}
-		case PUnknown:
-			throw "assert";
-		}
-	}
-
-	function writeValue( v : Dynamic, t : Schema.FieldType )  {
-		switch( t ) {
-		case PInt:
-			addInt(v);
-		case PFloat:
-			addFloat(v);
-		case PAlias(t):
-			writeValue(v,t);
-		case PBool:
-			addBool(v);
-		case PString:
-			addString(v);
-		case PArray(t):
-			addArray(v, function(v) return writeValue(v,t));
-		case PVector(t):
-			addVector(v, function(v) return writeValue(v,t));
-		case PBytes:
-			addBytes(v);
-		case PEnum(name):
-			var ser = "hxd.net.enumSer." + name.split(".").join("_");
-			if( ser == null ) throw "No enum unserializer found for " + name;
-			(Type.resolveClass(ser) : Dynamic).doSerialize(this,v);
-		case PSerializable(_):
-			addKnownRef(v);
-		case PNull(t):
-			if( v == null ) {
-				addByte(0);
-			} else {
-				addByte(1);
-				writeValue(v, t);
-			}
-		case PObj(fields):
-			if( v == null )
-				addByte(0);
-			else {
-				var fbits = 0;
-				var nullables = [for( f in fields ) if( isNullable(f.type) ) f];
-				for( i in 0...nullables.length )
-					if( Reflect.field(v, nullables[i].name) != null )
-						fbits |= 1 << i;
-				addByte(fbits + 1);
-				for( f in fields ) {
-					var nidx = nullables.indexOf(f);
-					var name = f.name;
-					if( nidx >= 0 && fbits & (1 << nidx) == 0 ) continue;
-					writeValue(Reflect.field(v, f.name), f.type);
-				}
-			}
-		case PMap(k, t):
-			addMap(v,function(v) writeValue(v,k), function(v) writeValue(v,t));
-		case PUnknown:
-			throw "assert";
-		}
-	}
-
-}

+ 2 - 0
hxd/net/Socket.hx

@@ -166,6 +166,8 @@ class Socket {
 		#end
 	}
 
+	public static inline var ALLOW_BIND = #if (flash && air3) true #else false #end;
+
 	public function bind( host : String, port : Int, onConnect : Socket -> Void, listenCount = 5 ) {
 		close();
 		openedSocks.push(this);

+ 145 - 143
hxd/net/LocalHost.hx → hxd/net/SocketHost.hx

@@ -1,144 +1,146 @@
-package hxd.net;
-import hxd.net.NetworkHost;
-
-class LocalClient extends NetworkClient {
-
-	var socket : Socket;
-
-	var pendingBuffer : haxe.io.Bytes;
-	var pendingPos : Int;
-	var messageLength : Int = -1;
-
-	public function new(host, s) {
-		super(host);
-		this.socket = s;
-		if( s != null ) s.onData = readData;
-	}
-
-	override function error(msg:String) {
-		socket.close();
-		super.error(msg);
-	}
-
-	function readData() {
-		if( messageLength < 0 ) {
-			if( socket.input.available < 4 )
-				return;
-			messageLength = socket.input.readInt32();
-			if( pendingBuffer == null || pendingBuffer.length < messageLength )
-				pendingBuffer = haxe.io.Bytes.alloc(messageLength);
-			pendingPos = 0;
-		}
-		var len = socket.input.readBytes(pendingBuffer, pendingPos, messageLength - pendingPos);
-		pendingPos += len;
-		if( pendingPos == messageLength ) {
-			pendingPos = 0;
-			while( pendingPos < messageLength ) {
-				var oldPos = pendingPos;
-				pendingPos = processMessage(pendingBuffer, pendingPos);
-				if( host.checkEOM && pendingBuffer.get(pendingPos++) != NetworkHost.EOM )
-					throw "Message missing EOM " + pendingBuffer.sub(oldPos, pendingPos - oldPos).toHex()+"..."+(pendingBuffer.sub(pendingPos,hxd.Math.imin(messageLength-pendingPos,128)).toHex());
-			}
-			messageLength = -1;
-			readData();
-		}
-	}
-
-	override function send( bytes : haxe.io.Bytes ) {
-		socket.out.wait();
-		socket.out.writeInt32(bytes.length);
-		socket.out.write(bytes);
-		socket.out.flush();
-	}
-
-	override function stop() {
-		super.stop();
-		if( socket != null ) {
-			socket.close();
-			socket = null;
-		}
-	}
-
-}
-
-class LocalHost extends NetworkHost {
-
-	var connected = false;
-	var socket : Socket;
-	public var enableSound : Bool = true;
-
-	public function new() {
-		super();
-		isAuth = false;
-	}
-
-	public function close() {
-		if( socket != null ) {
-			socket.close();
-			socket = null;
-		}
-		connected = false;
-	}
-
-	public function connect( host : String, port : Int, ?onConnect : Bool -> Void ) {
-		close();
-		isAuth = false;
-		socket = new Socket();
-		socket.onError = function(msg) {
-			if( !connected ) {
-				socket.onError = function(_) { };
-				onConnect(false);
-			} else
-				throw msg;
-		};
-		self = new LocalClient(this, socket);
-		socket.connect(host, port, function() {
-			connected = true;
-			if( host == "127.0.0.1" ) enableSound = false;
-			clients = [self];
-			onConnect(true);
-		});
-	}
-
-	public function wait( host : String, port : Int, ?onConnected : NetworkClient -> Void ) {
-		close();
-		isAuth = false;
-		socket = new Socket();
-		self = new LocalClient(this, null);
-		socket.bind(host, port, function(s) {
-			var c = new LocalClient(this, s);
-			pendingClients.push(c);
-			s.onError = function(_) c.stop();
-			if( onConnected != null ) onConnected(c);
-		});
-		isAuth = true;
-	}
-
-	public function offlineServer() {
-		close();
-		self = new LocalClient(this, null);
-		isAuth = true;
-	}
-
-	public static function openNewWindow( ?params : Dynamic<String> ) {
-		#if (flash && air3)
-		var opt = new flash.display.NativeWindowInitOptions();
-		opt.renderMode = flash.display.NativeWindowRenderMode.DIRECT;
-		var win = new flash.display.NativeWindow(opt);
-		win.width += flash.Lib.current.stage.stageWidth - win.stage.stageWidth;
-		win.height += flash.Lib.current.stage.stageHeight - win.stage.stageHeight;
-		win.title = "Client";
-		var l = new flash.display.Loader();
-		var ctx = new flash.system.LoaderContext(false, new flash.system.ApplicationDomain());
-		ctx.allowCodeImport = true;
-		win.stage.addChild(l);
-		if( params != null )
-			ctx.parameters = params;
-		l.loadBytes(flash.Lib.current.loaderInfo.bytes, ctx);
-		win.activate();
-		#else
-		throw "Not implemented";
-		#end
-	}
-
+/*
+ * Copyright (C)2015-2016 Nicolas Cannasse
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+package hxd.net;
+
+#if !hxbit
+#error	"Using SocketHost requires compiling with -lib hxbit"
+#end
+import hxbit.NetworkHost;
+
+class SocketClient extends NetworkClient {
+
+	var socket : Socket;
+
+	public function new(host, s) {
+		super(host);
+		this.socket = s;
+		if( s != null )
+			s.onData = function() {
+				// process all pending messages
+				while( readData(socket.input, socket.input.available) ) {
+				}
+			}
+	}
+
+	override function error(msg:String) {
+		socket.close();
+		super.error(msg);
+	}
+
+	override function send( bytes : haxe.io.Bytes ) {
+		socket.out.wait();
+		socket.out.writeInt32(bytes.length);
+		socket.out.write(bytes);
+		socket.out.flush();
+	}
+
+	override function stop() {
+		super.stop();
+		if( socket != null ) {
+			socket.close();
+			socket = null;
+		}
+	}
+
+}
+
+class SocketHost extends NetworkHost {
+
+	var connected = false;
+	var socket : Socket;
+	public var enableSound : Bool = true;
+
+	public function new() {
+		super();
+		isAuth = false;
+	}
+
+	public function close() {
+		if( socket != null ) {
+			socket.close();
+			socket = null;
+		}
+		connected = false;
+	}
+
+	public function connect( host : String, port : Int, ?onConnect : Bool -> Void ) {
+		close();
+		isAuth = false;
+		socket = new Socket();
+		socket.onError = function(msg) {
+			if( !connected ) {
+				socket.onError = function(_) { };
+				onConnect(false);
+			} else
+				throw msg;
+		};
+		self = new SocketClient(this, socket);
+		socket.connect(host, port, function() {
+			connected = true;
+			if( host == "127.0.0.1" ) enableSound = false;
+			clients = [self];
+			onConnect(true);
+		});
+	}
+
+	public function wait( host : String, port : Int, ?onConnected : NetworkClient -> Void ) {
+		close();
+		isAuth = false;
+		socket = new Socket();
+		self = new SocketClient(this, null);
+		socket.bind(host, port, function(s) {
+			var c = new SocketClient(this, s);
+			pendingClients.push(c);
+			s.onError = function(_) c.stop();
+			if( onConnected != null ) onConnected(c);
+		});
+		isAuth = true;
+	}
+
+	public function offlineServer() {
+		close();
+		self = new SocketClient(this, null);
+		isAuth = true;
+	}
+
+	public static function openNewWindow( ?params : Dynamic<String> ) {
+		#if (flash && air3)
+		var opt = new flash.display.NativeWindowInitOptions();
+		opt.renderMode = flash.display.NativeWindowRenderMode.DIRECT;
+		var win = new flash.display.NativeWindow(opt);
+		win.width += flash.Lib.current.stage.stageWidth - win.stage.stageWidth;
+		win.height += flash.Lib.current.stage.stageHeight - win.stage.stageHeight;
+		win.title = "Client";
+		var l = new flash.display.Loader();
+		var ctx = new flash.system.LoaderContext(false, new flash.system.ApplicationDomain());
+		ctx.allowCodeImport = true;
+		win.stage.addChild(l);
+		if( params != null )
+			ctx.parameters = params;
+		l.loadBytes(flash.Lib.current.loaderInfo.bytes, ctx);
+		win.activate();
+		#else
+		throw "Not implemented";
+		#end
+	}
+
 }

+ 0 - 61
hxd/net/VectorProxy.hx

@@ -1,61 +0,0 @@
-package hxd.net;
-import hxd.net.NetworkSerializable;
-
-@:generic
-class VectorProxyData<T> extends BaseProxy {
-	public var array : haxe.ds.Vector<T>;
-	public function new(v) {
-		array = v;
-	}
-}
-
-abstract VectorProxy<T>(VectorProxyData<T>) {
-
-	@:noCompletion public var __value(get, never) : haxe.ds.Vector<T>;
-	@:noCompletion public var length(get, never) : Int;
-	inline function get___value() : haxe.ds.Vector<T> return this == null ? null : this.array;
-	inline function get_length() return this.array.length;
-
-	inline function new(a) {
-		this = a;
-	}
-
-	public inline function copy() {
-		return new VectorProxy(new VectorProxyData(this.array.copy()));
-	}
-
-	public inline function join( s : String ) {
-		return this.array.join(s);
-	}
-
-	public inline function sort(cmp:T->T->Int) {
-		this.array.sort(cmp);
-		this.mark();
-	}
-
-	public inline function toString() {
-		return Std.string(this.array);
-	}
-
-	@:noCompletion public inline function bindHost(o, bit) {
-		this.bindHost(o, bit);
-	}
-
-	@:noCompletion public inline function unbindHost() {
-		this.unbindHost();
-	}
-
-	@:arrayAccess inline function get(idx:Int) {
-		return this.array[idx];
-	}
-
-	@:arrayAccess inline function set(idx:Int,v:T) {
-		this.array[idx] = v;
-		this.mark();
-	}
-
-	@:from static inline function fromVector<T>( a : haxe.ds.Vector<T> ) {
-		if( a == null ) return null;
-		return new VectorProxy(new VectorProxyData(a));
-	}
-}

+ 15 - 4
samples/Network.hx

@@ -1,5 +1,5 @@
 
-class Cursor implements hxd.net.NetworkSerializable {
+class Cursor implements hxbit.NetworkSerializable {
 
 	@:s var color : Int;
 	@:s public var uid : Int;
@@ -79,20 +79,30 @@ class Cursor implements hxd.net.NetworkSerializable {
 
 }
 
+//PARAM=-lib hxbit
 class Network extends hxd.App {
 
 	static var HOST = "127.0.0.1";
 	static var PORT = 6676;
 
-	public var host : hxd.net.LocalHost;
+	public var host : hxd.net.SocketHost;
 	public var event : hxd.WaitEvent;
 	public var uid : Int;
 	public var cursor : Cursor;
 
 	override function init() {
 		event = new hxd.WaitEvent();
-		host = new hxd.net.LocalHost();
+		host = new hxd.net.SocketHost();
 		host.setLogger(function(msg) log(msg));
+
+		if( !hxd.net.Socket.ALLOW_BIND ) {
+			#if flash
+			log("Using network with flash requires compiling with -lib air3 and running through AIR");
+			#else
+			log("Server not allowed on this platform");
+			#end
+		}
+
 		try {
 			host.wait(HOST, PORT, function(c) {
 				log("Client Connected");
@@ -108,8 +118,9 @@ class Network extends hxd.App {
 			start();
 
 			// force a new window to open, which will connect the client
-			hxd.net.LocalHost.openNewWindow();
+			hxd.net.SocketHost.openNewWindow();
 		} catch( e : Dynamic ) {
+
 			// we could not start the server
 			log("Connecting");