mirror of
https://github.com/renorris/openfsd
synced 2026-03-22 23:05:36 +08:00
Compare commits
9 Commits
v1.0-beta.
...
v1.0-beta.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e09ff9e64e | ||
|
|
933edc0478 | ||
|
|
6e3a179a3a | ||
|
|
f63d89eb3e | ||
|
|
bc7a37e490 | ||
|
|
7d17066289 | ||
|
|
2943735be6 | ||
|
|
c0155e78d4 | ||
|
|
2f423ed824 |
@@ -3,4 +3,5 @@ docker-compose.yml
|
||||
mkdocs.yml
|
||||
README.md
|
||||
docs
|
||||
**tmp**
|
||||
**tmp**
|
||||
build-and-push.sh
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
.vscode
|
||||
*.db
|
||||
**tmp**
|
||||
build-and-push.sh
|
||||
|
||||
@@ -16,7 +16,8 @@ type Client struct {
|
||||
cancelCtx func()
|
||||
sendChan chan string
|
||||
|
||||
lat, lon, visRange atomic.Float64
|
||||
coords atomic.Value
|
||||
visRange atomic.Float64
|
||||
closestVelocityClientDistance float64 // The closest Velocity-compatible client in meters
|
||||
|
||||
flightPlan atomic.String
|
||||
@@ -37,11 +38,12 @@ type Client struct {
|
||||
}
|
||||
|
||||
type LatLon struct {
|
||||
lat, lon float64
|
||||
}
|
||||
|
||||
func newClient(ctx context.Context, conn net.Conn, scanner *bufio.Scanner, loginData loginData) (client *Client) {
|
||||
clientCtx, cancel := context.WithCancel(ctx)
|
||||
return &Client{
|
||||
client = &Client{
|
||||
conn: conn,
|
||||
scanner: scanner,
|
||||
ctx: clientCtx,
|
||||
@@ -49,6 +51,8 @@ func newClient(ctx context.Context, conn net.Conn, scanner *bufio.Scanner, login
|
||||
sendChan: make(chan string, 32),
|
||||
loginData: loginData,
|
||||
}
|
||||
client.setLatLon(0, 0)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) senderWorker() {
|
||||
@@ -125,5 +129,10 @@ func (s *Server) eventLoop(client *Client) {
|
||||
}
|
||||
|
||||
func (c *Client) latLon() [2]float64 {
|
||||
return [2]float64{c.lat.Load(), c.lon.Load()}
|
||||
latLon := c.coords.Load().(LatLon)
|
||||
return [2]float64{latLon.lat, latLon.lon}
|
||||
}
|
||||
|
||||
func (c *Client) setLatLon(lat, lon float64) {
|
||||
c.coords.Store(LatLon{lat: lat, lon: lon})
|
||||
}
|
||||
|
||||
@@ -165,13 +165,17 @@ func (s *Server) handlePilotPosition(client *Client, packet []byte) {
|
||||
client.lastUpdated.Store(time.Now())
|
||||
|
||||
// Check if we need to update the sendfast state
|
||||
if client.sendFastEnabled {
|
||||
if (client.closestVelocityClientDistance / 1852.0) > 5.0 { // 5.0 nautical miles
|
||||
sendDisableSendFastPacket(client)
|
||||
}
|
||||
} else {
|
||||
if (client.closestVelocityClientDistance / 1852.0) < 5.0 { // 5.0 nautical miles
|
||||
sendEnableSendFastPacket(client)
|
||||
if client.protoRevision == 101 {
|
||||
if client.sendFastEnabled {
|
||||
if (client.closestVelocityClientDistance / 1852.0) > 5.0 { // 5.0 nautical miles
|
||||
client.sendFastEnabled = false
|
||||
sendDisableSendFastPacket(client)
|
||||
}
|
||||
} else {
|
||||
if (client.closestVelocityClientDistance / 1852.0) < 5.0 { // 5.0 nautical miles
|
||||
client.sendFastEnabled = true
|
||||
sendEnableSendFastPacket(client)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,13 +110,14 @@ func (s *Server) handleGetOnlineUsers(c *gin.Context) {
|
||||
}
|
||||
|
||||
for _, client := range clientMap {
|
||||
latLon := client.latLon()
|
||||
genData := OnlineUserGeneralData{
|
||||
Callsign: client.callsign,
|
||||
CID: client.cid,
|
||||
Name: client.realName,
|
||||
NetworkRating: int(client.networkRating),
|
||||
Latitude: client.lat.Load(),
|
||||
Longitude: client.lon.Load(),
|
||||
Latitude: latLon[0],
|
||||
Longitude: latLon[1],
|
||||
LogonTime: client.loginTime,
|
||||
LastUpdated: client.lastUpdated.Load(),
|
||||
}
|
||||
@@ -126,7 +127,7 @@ func (s *Server) handleGetOnlineUsers(c *gin.Context) {
|
||||
OnlineUserGeneralData: genData,
|
||||
Frequency: client.frequency.Load(),
|
||||
Facility: client.facilityType,
|
||||
VisRange: int(client.visRange.Load()),
|
||||
VisRange: int(client.visRange.Load() * 0.000539957), // Convert meters to nautical miles
|
||||
}
|
||||
resData.ATC = append(resData.ATC, atc)
|
||||
} else {
|
||||
|
||||
@@ -68,8 +68,7 @@ func (p *postOffice) updatePosition(client *Client, newCenter [2]float64, newVis
|
||||
oldMin, oldMax := calculateBoundingBox(client.latLon(), client.visRange.Load())
|
||||
newMin, newMax := calculateBoundingBox(newCenter, newVisRange)
|
||||
|
||||
client.lat.Store(newCenter[0])
|
||||
client.lon.Store(newCenter[1])
|
||||
client.setLatLon(newCenter[0], newCenter[1])
|
||||
client.visRange.Store(newVisRange)
|
||||
|
||||
// Avoid redundant updates
|
||||
@@ -99,13 +98,15 @@ func (p *postOffice) search(client *Client, callback func(recipient *Client) boo
|
||||
return true // Ignore self
|
||||
}
|
||||
|
||||
if foundClient.protoRevision == 101 {
|
||||
dist := distance(client.lat.Load(), client.lon.Load(), foundClient.lat.Load(), foundClient.lon.Load())
|
||||
if !client.isAtc && client.protoRevision == 101 && foundClient.protoRevision == 101 {
|
||||
clientLatLon := client.latLon()
|
||||
foundClientLatLon := foundClient.latLon()
|
||||
dist := distance(clientLatLon[0], clientLatLon[1], foundClientLatLon[0], foundClientLatLon[1])
|
||||
if dist < client.closestVelocityClientDistance {
|
||||
client.closestVelocityClientDistance = dist
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return callback(foundClient)
|
||||
})
|
||||
p.treeLock.RUnlock()
|
||||
|
||||
97
web/data.go
97
web/data.go
@@ -145,6 +145,15 @@ func (s *Server) handleGetServersJSON(c *gin.Context) {
|
||||
ClientsConnectionAllowed: 99,
|
||||
IsSweatbox: isSweatbox,
|
||||
},
|
||||
{
|
||||
Ident: "AUTOMATIC",
|
||||
HostnameOrIp: serverHostname,
|
||||
Location: serverLocation,
|
||||
Name: serverIdent,
|
||||
ClientConnectionsAllowed: true,
|
||||
ClientsConnectionAllowed: 99,
|
||||
IsSweatbox: isSweatbox,
|
||||
},
|
||||
}
|
||||
|
||||
res, err := json.Marshal(&dataJson)
|
||||
@@ -190,6 +199,15 @@ func (s *Server) generateServersTxt() (txt string, err error) {
|
||||
ClientsConnectionAllowed: 99,
|
||||
IsSweatbox: false,
|
||||
},
|
||||
{
|
||||
Ident: "AUTOMATIC",
|
||||
HostnameOrIp: serverHostname,
|
||||
Location: serverLocation,
|
||||
Name: serverIdent,
|
||||
ClientConnectionsAllowed: true,
|
||||
ClientsConnectionAllowed: 99,
|
||||
IsSweatbox: false,
|
||||
},
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
@@ -250,8 +268,49 @@ func (s *Server) getBaseURLOrErr(c *gin.Context) (baseURL string, ok bool) {
|
||||
}
|
||||
|
||||
type Datafeed struct {
|
||||
Pilots []fsd.OnlineUserPilot `json:"pilots"`
|
||||
ATC []fsd.OnlineUserATC `json:"atc"`
|
||||
General DatafeedGeneral `json:"general"`
|
||||
Pilots []DatafeedPilot `json:"pilots"`
|
||||
ATC []DatafeedATC `json:"controllers"`
|
||||
}
|
||||
|
||||
type DatafeedGeneral struct {
|
||||
Version int `json:"version"`
|
||||
UpdateTimestamp time.Time `json:"update_timestamp"`
|
||||
ConnectedClients int `json:"connected_clients"`
|
||||
UniqueUsers int `json:"unique_users"`
|
||||
}
|
||||
|
||||
type DatafeedPilot struct {
|
||||
fsd.OnlineUserPilot
|
||||
Server string `json:"server"`
|
||||
PilotRating int `json:"pilot_rating"` // INOP placeholder
|
||||
MilitaryRating int `json:"military_rating"` // INOP placeholder
|
||||
QnhIHg float64 `json:"qnh_i_hg"` // INOP placeholder
|
||||
QnhMb int `json:"qnh_mb"` // INOP placeholder
|
||||
FlightPlan *DatafeedFlightplan `json:"flight_plan,omitempty"` // INOP placeholder
|
||||
}
|
||||
|
||||
type DatafeedFlightplan struct {
|
||||
FlightRules string `json:"flight_rules"`
|
||||
Aircraft string `json:"aircraft"`
|
||||
AircraftFAA string `json:"aircraft_faa"`
|
||||
AircraftShort string `json:"aircraft_short"`
|
||||
Departure string `json:"departure"`
|
||||
Arrival string `json:"arrival"`
|
||||
Alternate string `json:"alternate"`
|
||||
DepTime string `json:"deptime"`
|
||||
EnrouteTime string `json:"enroute_time"`
|
||||
FuelTime string `json:"fuel_time"`
|
||||
Remarks string `json:"remarks"`
|
||||
Route string `json:"route"`
|
||||
RevisionID int `json:"revision_id"`
|
||||
AssignedTransponder string `json:"assigned_transponder"`
|
||||
}
|
||||
|
||||
type DatafeedATC struct {
|
||||
fsd.OnlineUserATC
|
||||
Server string `json:"server"`
|
||||
TextATIS []string `json:"text_atis"` // INOP placeholder
|
||||
}
|
||||
|
||||
type DatafeedCache struct {
|
||||
@@ -294,10 +353,38 @@ func (s *Server) generateDatafeed() (feed *DatafeedCache, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
dataFeed := Datafeed{
|
||||
Pilots: onlineUsers.Pilots,
|
||||
ATC: onlineUsers.ATC,
|
||||
General: DatafeedGeneral{
|
||||
Version: 3,
|
||||
UpdateTimestamp: now,
|
||||
ConnectedClients: len(onlineUsers.Pilots) + len(onlineUsers.ATC),
|
||||
UniqueUsers: len(onlineUsers.Pilots) + len(onlineUsers.ATC),
|
||||
},
|
||||
Pilots: []DatafeedPilot{},
|
||||
ATC: []DatafeedATC{},
|
||||
}
|
||||
|
||||
for _, pilot := range onlineUsers.Pilots {
|
||||
dataFeed.Pilots = append(dataFeed.Pilots, DatafeedPilot{
|
||||
OnlineUserPilot: pilot,
|
||||
Server: "OPENFSD",
|
||||
PilotRating: 1,
|
||||
MilitaryRating: 1,
|
||||
QnhIHg: 29.92,
|
||||
QnhMb: 1013,
|
||||
})
|
||||
}
|
||||
|
||||
for _, atc := range onlineUsers.ATC {
|
||||
dataFeed.ATC = append(dataFeed.ATC, DatafeedATC{
|
||||
OnlineUserATC: atc,
|
||||
Server: "OPENFSD",
|
||||
TextATIS: []string{},
|
||||
})
|
||||
}
|
||||
|
||||
buf := bytes.Buffer{}
|
||||
encoder := json.NewEncoder(&buf)
|
||||
if err = encoder.Encode(&dataFeed); err != nil {
|
||||
@@ -306,7 +393,7 @@ func (s *Server) generateDatafeed() (feed *DatafeedCache, err error) {
|
||||
|
||||
feed = &DatafeedCache{
|
||||
jsonStr: buf.String(),
|
||||
lastUpdated: time.Now(),
|
||||
lastUpdated: now,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ CONNECTED CLIENTS = 1
|
||||
;
|
||||
;
|
||||
!SERVERS:
|
||||
{{ range . }}{{ .Ident }}:{{ .HostnameOrIp }}:{{ .Location }}:{{ .Ident }}:{{ .ClientsConnectionAllowed }}:{{ end }}
|
||||
{{ range $index, $element := . }}{{ if $index }}
|
||||
{{ end }}{{ $element.Ident }}:{{ $element.HostnameOrIp }}:{{ $element.Location }}:{{ $element.Name }}:{{ $element.ClientsConnectionAllowed }}:{{ end }}
|
||||
;
|
||||
; END
|
||||
|
||||
Reference in New Issue
Block a user