update
This commit is contained in:
@@ -26,3 +26,6 @@ CREATE TABLE IF NOT EXISTS armageddon.person (
|
|||||||
INSERT INTO armageddon.account (id,login,password) VALUES(1,'shmyga', 'd48cc4eb42c058869ae90daef9606e43');
|
INSERT INTO armageddon.account (id,login,password) VALUES(1,'shmyga', 'd48cc4eb42c058869ae90daef9606e43');
|
||||||
INSERT INTO armageddon.person (id,account_id,name) VALUES(1,1,'-=Shmyga=-');
|
INSERT INTO armageddon.person (id,account_id,name) VALUES(1,1,'-=Shmyga=-');
|
||||||
|
|
||||||
|
INSERT INTO armageddon.account (id,login,password) VALUES(2,'a', md5('a'));
|
||||||
|
INSERT INTO armageddon.person (id,account_id,name) VALUES(2,2,'a');
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,11 @@ class PlayerTank extends Tank {
|
|||||||
|
|
||||||
private function updateMove():Void {
|
private function updateMove():Void {
|
||||||
if (moveQueue.length == 0) {
|
if (moveQueue.length == 0) {
|
||||||
stop();
|
//stop();
|
||||||
|
Provider.get(IConnection).send(
|
||||||
|
new GameActionRequest()
|
||||||
|
.setType(GameActionType.STOP)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
switch (keyBinding.get(moveQueue[0])) {
|
switch (keyBinding.get(moveQueue[0])) {
|
||||||
case TankAction.MOVE(direction):
|
case TankAction.MOVE(direction):
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package ru.m.tankz.view.frames;
|
package ru.m.tankz.view.frames;
|
||||||
|
|
||||||
|
import ru.m.tankz.core.MobileEntity;
|
||||||
|
import ru.m.tankz.core.Direction;
|
||||||
|
import ru.m.tankz.proto.GameObjectType;
|
||||||
|
import ru.m.tankz.proto.GameChangeType;
|
||||||
import ru.m.tankz.game.ClientTankz;
|
import ru.m.tankz.game.ClientTankz;
|
||||||
import protohx.Message;
|
import protohx.Message;
|
||||||
import ru.m.tankz.proto.GameUpdateResponse;
|
import ru.m.tankz.proto.GameUpdateResponse;
|
||||||
@@ -32,6 +36,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
|
|||||||
game.init(persons, DEFAULT.CONFIG);
|
game.init(persons, DEFAULT.CONFIG);
|
||||||
content.addEventListener(Event.ENTER_FRAME, updateGame);
|
content.addEventListener(Event.ENTER_FRAME, updateGame);
|
||||||
Provider.get(IConnection).packetHandler.addListener(this);
|
Provider.get(IConnection).packetHandler.addListener(this);
|
||||||
|
render.draw(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onHide():Void {
|
public function onHide():Void {
|
||||||
@@ -41,12 +46,47 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function updateGame(_):Void {
|
private function updateGame(_):Void {
|
||||||
game.update();
|
//game.update();
|
||||||
render.draw(game);
|
//render.draw(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onGameUpdateResponse(packet:GameUpdateResponse):Void {
|
public function onGameUpdateResponse(packet:GameUpdateResponse):Void {
|
||||||
|
for (change in packet.changes) {
|
||||||
|
switch (change.type) {
|
||||||
|
case GameChangeType.DIRECTION:
|
||||||
|
switch (change.objectType) {
|
||||||
|
case GameObjectType.TANK:
|
||||||
|
for (tank in game.tanks) {
|
||||||
|
if (tank.id == change.objectId) {
|
||||||
|
tank.direction = new Direction(change.directionX, change.directionY);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case GameChangeType.MOVED:
|
||||||
|
switch (change.objectType) {
|
||||||
|
case GameObjectType.TANK:
|
||||||
|
for (tank in game.tanks) {
|
||||||
|
if (tank.id == change.objectId) {
|
||||||
|
tank.x = change.x;
|
||||||
|
tank.y = change.y;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case GameChangeType.APPEND:
|
||||||
|
switch (change.objectType) {
|
||||||
|
case GameObjectType.BULLET:
|
||||||
|
for (tank in game.tanks) {
|
||||||
|
if (tank.id == change.parentObjectId) {
|
||||||
|
tank.bullets.push(new MobileEntity(0, change.x, change.y, 0, new Direction(change.directionX, change.directionY)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render.draw(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onPacket(packet:Message):Void {}
|
public function onPacket(packet:Message):Void {}
|
||||||
|
|||||||
@@ -42,11 +42,11 @@ class BaseConnection implements IConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public function send(packet:Message):Void {
|
public function send(packet:Message):Void {
|
||||||
L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
//L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function receive(packet:Message):Void {
|
public function receive(packet:Message):Void {
|
||||||
L.d("Receive", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
//L.d("Receive", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
||||||
var name = "on" + Type.getClassName(Type.getClass(packet)).split(".").pop();
|
var name = "on" + Type.getClassName(Type.getClass(packet)).split(".").pop();
|
||||||
packetHandler.dispatch(function(h) {
|
packetHandler.dispatch(function(h) {
|
||||||
var method = Reflect.field(h, name);
|
var method = Reflect.field(h, name);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ class NekoWebConnection extends NekoConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override public function send(packet:Message):Void {
|
override public function send(packet:Message):Void {
|
||||||
L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
//L.d("Send", Type.getClassName(Type.getClass(packet)).split(".").pop());
|
||||||
try {
|
try {
|
||||||
var data = WebSocketTools.packet2string(packet, builder);
|
var data = WebSocketTools.packet2string(packet, builder);
|
||||||
writeData(data, socket);
|
writeData(data, socket);
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package ru.m.tankz.core;
|
|||||||
|
|
||||||
class Entity implements IEntity {
|
class Entity implements IEntity {
|
||||||
|
|
||||||
public var x(default, default):Float;
|
public var x(default, default):Float = 0;
|
||||||
public var y(default, default):Float;
|
public var y(default, default):Float = 0;
|
||||||
|
|
||||||
public var width(default, default):Float;
|
public var width(default, default):Float;
|
||||||
public var height(default, default):Float;
|
public var height(default, default):Float;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package ru.m.tankz.core;
|
package ru.m.tankz.core;
|
||||||
|
|
||||||
interface IMobileEntity extends IEntity {
|
interface IMobileEntity extends IEntity {
|
||||||
|
public var id(default, null):Int;
|
||||||
|
|
||||||
public var mx(default, default):Float;
|
public var mx(default, default):Float;
|
||||||
public var my(default, default):Float;
|
public var my(default, default):Float;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ru.m.tankz.core;
|
package ru.m.tankz.core;
|
||||||
|
|
||||||
interface ITank extends IMobileEntity {
|
interface ITank extends IMobileEntity {
|
||||||
public var id(default, null):Int;
|
|
||||||
public var bullets:Array<IMobileEntity>;
|
public var bullets:Array<IMobileEntity>;
|
||||||
|
|
||||||
public function shot():Void;
|
public function shot():Void;
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
package ru.m.tankz.core;
|
package ru.m.tankz.core;
|
||||||
|
|
||||||
class MobileEntity extends Entity implements IMobileEntity {
|
class MobileEntity extends Entity implements IMobileEntity {
|
||||||
|
public var id(default, null):Int;
|
||||||
|
|
||||||
public var mx(default, default):Float;
|
public var mx(default, default):Float = 0;
|
||||||
public var my(default, default):Float;
|
public var my(default, default):Float = 0;
|
||||||
|
|
||||||
public var speed(default, null):Float;
|
public var speed(default, null):Float = 0;
|
||||||
public var direction(default, default):Direction;
|
public var direction(default, default):Direction;
|
||||||
|
|
||||||
public function new(x:Float, y:Float, speed:Float, direction:Direction = null) {
|
public function new(id:Int, x:Float, y:Float, speed:Float, direction:Direction = null) {
|
||||||
super(x, y);
|
super(x, y);
|
||||||
|
this.id = id;
|
||||||
this.speed = speed;
|
this.speed = speed;
|
||||||
this.direction = direction == null ? Direction.BOTTOM : direction;
|
this.direction = direction == null ? Direction.BOTTOM : direction;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,10 @@ enum TankAction {
|
|||||||
|
|
||||||
class Tank extends MobileEntity implements ITank {
|
class Tank extends MobileEntity implements ITank {
|
||||||
|
|
||||||
public var id(default, null):Int;
|
|
||||||
public var bullets:Array<IMobileEntity>;
|
public var bullets:Array<IMobileEntity>;
|
||||||
|
|
||||||
public function new(id:Int, x:Float, y:Float) {
|
public function new(id:Int, x:Float, y:Float) {
|
||||||
super(x, y, 4);
|
super(id, x, y, 4);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
bullets = new Array<IMobileEntity>();
|
bullets = new Array<IMobileEntity>();
|
||||||
width = 34;
|
width = 34;
|
||||||
@@ -20,7 +19,7 @@ class Tank extends MobileEntity implements ITank {
|
|||||||
|
|
||||||
public function shot():Void {
|
public function shot():Void {
|
||||||
if (bullets.length >= 5) return;
|
if (bullets.length >= 5) return;
|
||||||
var bullet = new MobileEntity(x + width / 2 - 5, y + height / 2 - 5, 6, direction);
|
var bullet = new MobileEntity(0, x + width / 2 - 5, y + height / 2 - 5, 6, direction);
|
||||||
bullet.width = 10;
|
bullet.width = 10;
|
||||||
bullet.height = 10;
|
bullet.height = 10;
|
||||||
bullet.move(direction);
|
bullet.move(direction);
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ message ExitGameResponse {
|
|||||||
enum GameActionType {
|
enum GameActionType {
|
||||||
MOVE = 1;
|
MOVE = 1;
|
||||||
SHOT = 2;
|
SHOT = 2;
|
||||||
|
STOP = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GameActionRequest {
|
message GameActionRequest {
|
||||||
@@ -103,6 +104,7 @@ message GameActionRequest {
|
|||||||
|
|
||||||
enum GameObjectType {
|
enum GameObjectType {
|
||||||
TANK = 1;
|
TANK = 1;
|
||||||
|
BULLET = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum GameChangeType {
|
enum GameChangeType {
|
||||||
@@ -110,14 +112,18 @@ enum GameChangeType {
|
|||||||
DESTROED = 2;
|
DESTROED = 2;
|
||||||
MODIFIED = 3;
|
MODIFIED = 3;
|
||||||
APPEND = 4;
|
APPEND = 4;
|
||||||
|
DIRECTION = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GameChange {
|
message GameChange {
|
||||||
required GameChangeType type = 1;
|
required GameChangeType type = 1;
|
||||||
required GameObjectType objectType = 2;
|
required GameObjectType objectType = 2;
|
||||||
required int32 objectId = 3;
|
required int32 objectId = 3;
|
||||||
optional int32 newX = 4;
|
optional int32 parentObjectId = 4;
|
||||||
optional int32 newY = 5;
|
optional float x = 5;
|
||||||
|
optional float y = 6;
|
||||||
|
optional int32 directionX = 7;
|
||||||
|
optional int32 directionY = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GameUpdateResponse {
|
message GameUpdateResponse {
|
||||||
|
|||||||
12
src/server/haxe/ru/m/tankz/server/game/Game.hx
Normal file
12
src/server/haxe/ru/m/tankz/server/game/Game.hx
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package ru.m.tankz.server.game;
|
||||||
|
|
||||||
|
import ru.m.tankz.game.ITankz;
|
||||||
|
|
||||||
|
class Game {
|
||||||
|
|
||||||
|
private var tankz:ITankz;
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
package ru.m.tankz.server.session;
|
package ru.m.tankz.server.session;
|
||||||
|
|
||||||
|
import ru.m.tankz.proto.GameObjectType;
|
||||||
|
import ru.m.tankz.proto.GameChangeType;
|
||||||
|
import ru.m.tankz.proto.GameChange;
|
||||||
|
import ru.m.tankz.config.TankzConfig.DEFAULT;
|
||||||
|
import ru.m.tankz.proto.GameUpdateResponse;
|
||||||
|
import haxe.Timer;
|
||||||
|
import ru.m.tankz.core.Direction;
|
||||||
import ru.m.tankz.game.Tankz;
|
import ru.m.tankz.game.Tankz;
|
||||||
import ru.m.tankz.game.ITankz;
|
import ru.m.tankz.game.ITankz;
|
||||||
import ru.m.tankz.proto.GameActionType;
|
import ru.m.tankz.proto.GameActionType;
|
||||||
@@ -31,6 +38,39 @@ import protohx.Message;
|
|||||||
import ru.m.core.connect.IConnection;
|
import ru.m.core.connect.IConnection;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
class NekoTimer {
|
||||||
|
|
||||||
|
private var sleep:Float;
|
||||||
|
private var stopped:Bool;
|
||||||
|
|
||||||
|
public function new(time_ms:Int) {
|
||||||
|
this.sleep = time_ms / 1000.0;
|
||||||
|
this.stopped = false;
|
||||||
|
Thread.create(function() {
|
||||||
|
while (!stopped) {
|
||||||
|
Sys.sleep(sleep);
|
||||||
|
try {
|
||||||
|
run();
|
||||||
|
} catch (error:Dynamic) {
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public dynamic function run() {}
|
||||||
|
|
||||||
|
public function stop() {
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef ObjectState = {
|
||||||
|
var x:Float;
|
||||||
|
var y:Float;
|
||||||
|
var d:Direction;
|
||||||
|
}
|
||||||
|
|
||||||
class GameCenter {
|
class GameCenter {
|
||||||
|
|
||||||
@@ -39,21 +79,27 @@ class GameCenter {
|
|||||||
private var created:Map<Int, Int>;
|
private var created:Map<Int, Int>;
|
||||||
private var persons:Map<Int, Int>;
|
private var persons:Map<Int, Int>;
|
||||||
|
|
||||||
private var running:Map<Int, ITankz>;
|
public var running:Map<Int, ITankz>;
|
||||||
|
private var timers:Map<Int, NekoTimer>;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
games = new Map<Int, Game>();
|
games = new Map<Int, Game>();
|
||||||
created = new Map<Int, Int>();
|
created = new Map<Int, Int>();
|
||||||
persons = new Map<Int, Int>();
|
persons = new Map<Int, Int>();
|
||||||
running = new Map<Int, ITankz>();
|
running = new Map<Int, ITankz>();
|
||||||
|
timers = new Map<Int, NekoTimer>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getReadyGames():Array<Game> {
|
public function getReadyGames():Array<Game> {
|
||||||
return Lambda.array(games).filter(function(g) return g.state == GameState.READY);
|
return Lambda.array(games).filter(function(g) return g.state == GameState.READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCreatedGame(person_id:Int):Game {
|
public function getCreatedGame(peronsId:Int):Game {
|
||||||
return games.get(created.get(person_id));
|
return games.get(created.get(peronsId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPersonGameId(personId:Int):Int {
|
||||||
|
return persons.get(personId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createGame(person:Person):Game {
|
public function createGame(person:Person):Game {
|
||||||
@@ -82,6 +128,10 @@ class GameCenter {
|
|||||||
game.persons.remove(person);
|
game.persons.remove(person);
|
||||||
if (game.persons.length == 0) {
|
if (game.persons.length == 0) {
|
||||||
games.remove(game.id);
|
games.remove(game.id);
|
||||||
|
if (timers.exists(game.id)) {
|
||||||
|
timers.get(game.id).stop();
|
||||||
|
timers.remove(game.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -91,9 +141,57 @@ class GameCenter {
|
|||||||
|
|
||||||
public function start(gameId:Int):Void {
|
public function start(gameId:Int):Void {
|
||||||
if (games.exists(gameId)) {
|
if (games.exists(gameId)) {
|
||||||
games.get(gameId).setState(GameState.STARTED);
|
var game:Game = games.get(gameId);
|
||||||
|
game.setState(GameState.STARTED);
|
||||||
var tankz = new Tankz();
|
var tankz = new Tankz();
|
||||||
|
tankz.init(game.persons, DEFAULT.CONFIG);
|
||||||
running.set(gameId, tankz);
|
running.set(gameId, tankz);
|
||||||
|
var timer = new NekoTimer(30);
|
||||||
|
timer.run = buildUpdater(gameId, tankz);
|
||||||
|
timers.set(gameId, timer);
|
||||||
|
broadcast(gameId, new StartGameResponse().setGame(game));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildUpdater(gameId:Int, tankz:ITankz):Void->Void {
|
||||||
|
return function() {
|
||||||
|
var states = new Map<Int, ObjectState>();
|
||||||
|
for (tank in tankz.tanks) {
|
||||||
|
states.set(tank.id, {
|
||||||
|
x: tank.x,
|
||||||
|
y: tank.y,
|
||||||
|
d: tank.direction
|
||||||
|
});
|
||||||
|
}
|
||||||
|
tankz.update();
|
||||||
|
var changes = new Array<GameChange>();
|
||||||
|
for (tank in tankz.tanks) {
|
||||||
|
if (states.exists(tank.id)) {
|
||||||
|
var state = states.get(tank.id);
|
||||||
|
if (state.d != tank.direction) {
|
||||||
|
trace("DDD");
|
||||||
|
changes.push(new GameChange()
|
||||||
|
.setType(GameChangeType.DIRECTION)
|
||||||
|
.setObjectType(GameObjectType.TANK)
|
||||||
|
.setObjectId(tank.id)
|
||||||
|
.setDirectionX(tank.direction.x)
|
||||||
|
.setDirectionY(tank.direction.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (state.x != tank.x || state.y != tank.y) {
|
||||||
|
changes.push(new GameChange()
|
||||||
|
.setType(GameChangeType.MOVED)
|
||||||
|
.setObjectType(GameObjectType.TANK)
|
||||||
|
.setObjectId(tank.id)
|
||||||
|
.setX(tank.x)
|
||||||
|
.setY(tank.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (changes.length > 0) {
|
||||||
|
broadcast(gameId, new GameUpdateResponse().setChanges(changes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,8 +307,7 @@ class Session implements IConnectionHandler implements IPacketHandler {
|
|||||||
|
|
||||||
public function onStartGameRequest(packet:StartGameRequest):Void {
|
public function onStartGameRequest(packet:StartGameRequest):Void {
|
||||||
var game:Game = games.getCreatedGame(person.id);
|
var game:Game = games.getCreatedGame(person.id);
|
||||||
game.setState(GameState.STARTED);
|
games.start(game.id);
|
||||||
games.broadcast(game.id, new StartGameResponse().setGame(game));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onExitGameRequest(packet:ExitGameRequest):Void {
|
public function onExitGameRequest(packet:ExitGameRequest):Void {
|
||||||
@@ -219,11 +316,18 @@ class Session implements IConnectionHandler implements IPacketHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function onGameActionRequest(packet:GameActionRequest):Void {
|
public function onGameActionRequest(packet:GameActionRequest):Void {
|
||||||
switch (packet.type) {
|
var game:ITankz = games.running.get(games.getPersonGameId(person.id));
|
||||||
case GameActionType.SHOT:
|
for (tank in game.tanks) {
|
||||||
|
if (tank.id == person.id) {
|
||||||
case GameActionType.MOVE:
|
switch (packet.type) {
|
||||||
|
case GameActionType.SHOT:
|
||||||
|
tank.shot();
|
||||||
|
case GameActionType.MOVE:
|
||||||
|
tank.move(new Direction(packet.directionX, packet.directionY));
|
||||||
|
case GameActionType.STOP:
|
||||||
|
tank.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
113
src/server/haxe/ru/m/tankz/server/session/Thread.hx
Normal file
113
src/server/haxe/ru/m/tankz/server/session/Thread.hx
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
package ru.m.tankz.server.session;
|
||||||
|
|
||||||
|
enum ThreadHandle {
|
||||||
|
}
|
||||||
|
|
||||||
|
class Thread {
|
||||||
|
|
||||||
|
var handle : ThreadHandle;
|
||||||
|
|
||||||
|
function new(h) {
|
||||||
|
handle = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Send a message to the thread queue. This message can be readed by using [readMessage].
|
||||||
|
**/
|
||||||
|
public function sendMessage( msg : Dynamic ) {
|
||||||
|
thread_send(handle,msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the current thread.
|
||||||
|
**/
|
||||||
|
public static function current() {
|
||||||
|
return new Thread(thread_current());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a new thread that will execute the [callb] function, then exit.
|
||||||
|
**/
|
||||||
|
public static function create( callb : Void -> Void ) {
|
||||||
|
return new Thread(thread_create(function(_) { return callb(); },null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Reads a message from the thread queue. If [block] is true, the function
|
||||||
|
blocks until a message is available. If [block] is false, the function
|
||||||
|
returns [null] if no message is available.
|
||||||
|
**/
|
||||||
|
public static function readMessage( block : Bool ) : Dynamic {
|
||||||
|
return thread_read_message(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
@:keep function __compare(t) {
|
||||||
|
return untyped __dollar__compare(handle,t.handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Starts an OS message loop after [osInitialize] has been done.
|
||||||
|
In that state, the UI handled by this thread will be updated and
|
||||||
|
[sync] calls can be performed. The loop returns when [exitLoop] is
|
||||||
|
called for this thread.
|
||||||
|
**
|
||||||
|
public static function osLoop() {
|
||||||
|
if( os_loop == null ) throw "Please call osInitialize() first";
|
||||||
|
os_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function [f] will be called by this thread if it's in [osLoop].
|
||||||
|
[sync] returns immediatly. See [osInitialize] remarks.
|
||||||
|
**
|
||||||
|
public function sync( f : Void -> Void ) {
|
||||||
|
os_sync(handle,f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The function [f] will be called by this thread and the calling thread
|
||||||
|
will wait until the result is available then return its value.
|
||||||
|
**
|
||||||
|
public function syncResult<T>( f : Void -> T ) : T {
|
||||||
|
if( this == current() )
|
||||||
|
return f();
|
||||||
|
var v = new neko.vm.Lock();
|
||||||
|
var r = null;
|
||||||
|
sync(function() {
|
||||||
|
r = f();
|
||||||
|
v.release();
|
||||||
|
});
|
||||||
|
v.wait();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Exit from [osLoop].
|
||||||
|
**
|
||||||
|
public function exitLoop() {
|
||||||
|
os_loop_stop(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
If you want to use the [osLoop], [sync] and [syncResult] methods, you
|
||||||
|
need to call [osInitialize] before creating any thread or calling [current].
|
||||||
|
This will load [os.ndll] library and initialize UI methods for each thread.
|
||||||
|
**
|
||||||
|
public static function osInitialize() {
|
||||||
|
os_loop = neko.Lib.load("os","os_loop",0);
|
||||||
|
os_loop_stop = neko.Lib.load("os","os_loop_stop",1);
|
||||||
|
os_sync = neko.Lib.load("os","os_sync",2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static var os_loop = null;
|
||||||
|
static var os_loop_stop = null;
|
||||||
|
static var os_sync = null;
|
||||||
|
*/
|
||||||
|
|
||||||
|
static var thread_create = neko.Lib.load("std","thread_create",2);
|
||||||
|
static var thread_current = neko.Lib.load("std","thread_current",0);
|
||||||
|
static var thread_send = neko.Lib.load("std","thread_send",2);
|
||||||
|
static var thread_read_message = neko.Lib.load("std","thread_read_message",1);
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user