Merge from Jack

This commit is contained in:
SongWei 2020-02-22 18:56:38 +11:00
commit a573a55238
10 changed files with 289 additions and 0 deletions

9
README.md Normal file
View File

@ -0,0 +1,9 @@
# A3Web
Arma 3 Realtime Map
## To build extension
```
GOARCH=386 CGO_ENABLED=1 go build -o liba3web.so -buildmode=c-shared .
```

1
addons/$PBOPREFIX$ Normal file
View File

@ -0,0 +1 @@
x\huashui\a3web

27
addons/config.cpp Normal file
View File

@ -0,0 +1,27 @@
class CfgPatches
{
class a3web
{
name = "Arma 3 Realtime Map";
author = "jack77213";
url = "https://arma.huashui.cf";
requiredVersion = 1.92;
requiredAddons[] = {"A3_Functions_F"};
units[] = {};
weapons[] = {};
};
};
class CfgFunctions
{
class huashui
{
class a3web
{
file = "x\huashui\a3web";
class a3web { postInit=1; };
};
};
};

25
addons/fn_a3web.sqf Normal file
View File

@ -0,0 +1,25 @@
[] spawn {
//if (!hasInterface) exitWith {};
if (!isServer) exitWith {};
//if (!isDedicated) exitWith {};
addMissionEventHandler ["ExtensionCallback", {
params ["_name", "_function", "_data"];
if (_name isEqualTo "a3web") then
{
diag_log format ["ExtensionCallback %1, %2, %3", _name, _function, _data];
};
}];
waitUntil {time > 0};
a3web_interval = 1;
while {true} do {
sleep a3web_interval;
private _units = allUnits apply {
[netid _x, isPlayer _x, name _x, str (side _x), getPos _x];
};
"liba3web" callExtension ["http:post:/units-info", [_units]];
};
};

3
extension/go.mod Normal file
View File

@ -0,0 +1,3 @@
module gitea.hijack.moe/huashui/a3web/extension
go 1.13

0
extension/go.sum Normal file
View File

84
extension/liba3web.go Normal file
View File

@ -0,0 +1,84 @@
package main
/*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef int(*callbackProc)(char const *name, char const *function, char const *data);
static inline int bridge_cb(callbackProc cb, char const *name, char const *function, char const *data) {
return cb(name, function, data);
}
static inline uint min(uint a, uint b) { return a < b ? a : b; }
*/
import "C"
import (
"fmt"
"log"
"strings"
"unsafe"
"net/http"
)
var cb C.callbackProc
var name = C.CString("a3web")
var serverURL = "https://localhost"
// RVExtensionRegisterCallback on extension load
//export RVExtensionRegisterCallback
func RVExtensionRegisterCallback(cbptr unsafe.Pointer) {
cb = C.callbackProc(cbptr)
log.Println("Calling callback function ……")
function := C.CString("registered")
defer C.free(unsafe.Pointer(function))
C.bridge_cb(cb, name, function, function)
}
// RVExtensionVersion on extension load
//export RVExtensionVersion
func RVExtensionVersion(output *C.char, outputsize C.size_t) {
version := C.CString("Version 0.1")
defer C.free(unsafe.Pointer(version))
var size = C.min(C.strlen(version)+1, outputsize-1)
C.strncpy(output, version, size)
}
// RVExtensionArgs STRING callExtension ARRAY
//export RVExtensionArgs
func RVExtensionArgs(output *C.char, outputsize C.size_t, function *C.char, argv **C.char, argc C.int) {
var offset = unsafe.Sizeof(uintptr(0))
var out []string
for index := C.int(0); index < argc; index++ {
out = append(out, C.GoString(*argv))
argv = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(argv)) + offset))
}
go handleArgs(C.GoString(function), argc, out)
}
// RVExtension STRING callExtension STRING
//export RVExtension
func RVExtension(output *C.char, outputsize C.size_t, function *C.char) {
result := C.CString(fmt.Sprintf("Hello, %s!", C.GoString(function)))
defer C.free(unsafe.Pointer(result))
var size = C.min(C.strlen(result)+1, outputsize-1)
C.strncpy(output, result, size)
}
func main() {}
func handleArgs(function string, argc C.int, argv []string) {
fns := strings.Split(strings.ToLower(function), ":")
if len(fns) == 3 && fns[0] == "http" && fns[1] == "post" {
resp, err := http.Post(serverURL + fns[2], "", strings.NewReader(argv[0]))
if err != nil {
log.Printf("Error Sending HTTP Request: %s", err)
return
}
resp.Body.Close()
}
}

8
server/go.mod Normal file
View File

@ -0,0 +1,8 @@
module gitea.hijack.moe/huashui/a3web/server
go 1.13
require (
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2
github.com/gin-gonic/gin v1.5.0
)

38
server/go.sum Normal file
View File

@ -0,0 +1,38 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2 h1:xLG16iua01X7Gzms9045s2Y2niNpvSY/Zb1oBwgNYZY=
github.com/gin-contrib/static v0.0.0-20191128031702-f81c604d8ac2/go.mod h1:VhW/Ch/3FhimwZb8Oj+qJmdMmoB8r7lmJ5auRjm50oQ=
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

94
server/main.go Normal file
View File

@ -0,0 +1,94 @@
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"sync"
"github.com/gin-contrib/static"
"github.com/gin-gonic/gin"
)
var (
unitsInfo = make([]unitInfo, 0)
unitsInfoMutex = sync.RWMutex{}
)
type position []float64
type unitInfo struct {
NetID string `json:"netid"`
IsPlayer bool `json:"isplayer"`
ProfileName string `json:"profilename"`
Side string `json:"side"`
Position position `json:"position"`
}
func (u *unitInfo) UnmarshalJSON(buf []byte) error {
tmp := []interface{}{
&u.NetID,
&u.IsPlayer,
&u.ProfileName,
&u.Side,
&u.Position,
}
wantLen := len(tmp)
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
if g, e := len(tmp), wantLen; g != e {
return fmt.Errorf("wrong number of fields in Notification: %d != %d", g, e)
}
return nil
}
func main() {
listenAddress := os.Getenv("LISTEN_ADDR")
if listenAddress == "" {
listenAddress = ":5000"
}
router := gin.Default()
router.Use(static.Serve("/", static.LocalFile("../ui/public", false)))
router.Use(static.Serve("/maps", static.LocalFile("../maps", false)))
router.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "pong")
})
router.POST("/ping", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
})
router.POST("/units-info", updateUnitsInfo)
router.GET("/units-info", getUnitsInfo)
router.Run(listenAddress)
}
func updateUnitsInfo(c *gin.Context) {
ups := make([]unitInfo, 0)
err := c.ShouldBindJSON(&ups)
if err != nil {
log.Println(err)
c.JSON(http.StatusBadRequest, err)
return
}
unitsInfoMutex.Lock()
defer unitsInfoMutex.Unlock()
unitsInfo = ups
c.JSON(http.StatusOK, nil)
}
func getUnitsInfo(c *gin.Context) {
unitsInfoMutex.RLock()
defer unitsInfoMutex.RUnlock()
c.JSON(http.StatusOK, unitsInfo)
}