Skip to content

Commit

Permalink
Merge pull request #118 from Tarnadas/dev
Browse files Browse the repository at this point in the history
Radar and Player position
  • Loading branch information
Tarnadas authored Feb 18, 2020
2 parents e2b8680 + 49655b0 commit 2739491
Show file tree
Hide file tree
Showing 62 changed files with 780 additions and 47 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ Download the client/server/emulator bundle in the [release section](https://gith

## Server List

There is a [public server list](https://smmdb.ddns.net/net64) of all Net64+ server, that have enabled listing.
There is a [public server list](https://net64-mod.github.io/servers) of all Net64+ server, that have enabled listing.
Binary file added build/img/courses/00-castle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/01-bob.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/02-wf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/03-jrb.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/04-ccm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/05-bbh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/06-hmc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/07-lll.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/08-ssl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/09-ddd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/10-sl.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/11-wdw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/12-ttm.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/13-thi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/14-ttc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/15-rr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/16-bitdw.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/17-bitfs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/18-bits.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/19-pss.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/20-metal.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/21-wing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/22-vanish.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/23-otr.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added build/img/courses/24-aqua.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified build/img/goomba.png
Binary file modified build/img/kirby.png
Binary file modified build/img/knuckles.png
Binary file modified build/img/luigi.png
Binary file modified build/img/mario.png
Binary file modified build/img/peach.png
Binary file modified build/img/rosalina.png
Binary file modified build/img/sonic.png
Binary file modified build/img/toad.png
Binary file modified build/img/waluigi.png
Binary file modified build/img/wario.png
Binary file modified build/img/yoshi.png
1 change: 1 addition & 0 deletions compat-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ module.exports = function getCompatMin (currentVersion) {
if (major === 2 && minor === 1) return [ '2', '0' ]
if (major === 2 && minor === 2) return [ '2', '0' ]
if (major === 2 && minor === 3) return [ '2', '0' ]
if (major === 2 && minor === 4) return [ '2', '0' ]
throw new Error(`Compatibility list found unknown version ${currentVersion}`)
}
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "net64plus",
"version": "2.3.0",
"version": "2.4.0",
"compatVersion": "1.0.0",
"description": "Net64+ client",
"main": "index.js",
Expand Down Expand Up @@ -35,7 +35,7 @@
"bugs": {
"url": "https://github.com/Tarnadas/net64plus/issues"
},
"homepage": "http://smmdb.ddns.net/net64",
"homepage": "https://net64-mod.github.io/",
"jest": {
"setupFiles": [
"./jest-browser-setup.js"
Expand Down
16 changes: 16 additions & 0 deletions src/main/Connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
} from '../../proto/ServerClientMessage'

const UPDATE_INTERVAL = 32
const SLOW_UPDATE_INTERVAL = 200
const MAX_SERVER_PLAYER = 24

interface GameModeRPC {
Expand Down Expand Up @@ -90,6 +91,8 @@ export class Connection {

private loop: NodeJS.Timer | null = null

private slowLoop: NodeJS.Timer | null = null

private hasError: boolean = false

private timer = Date.now()
Expand All @@ -111,6 +114,7 @@ export class Connection {
}) {
this.disconnect = this.disconnect.bind(this)
this.sendAll = this.sendAll.bind(this)
this.updatePlayerPositions = this.updatePlayerPositions.bind(this)
this.ws = new WS(`ws://${domain || ip || '127.0.0.1'}:${port || 3678}`)
this.ws.on('open', this.onOpen.bind(this, characterId, username))
this.ws.on('error', this.onError.bind(this))
Expand Down Expand Up @@ -182,6 +186,10 @@ export class Connection {
clearInterval(this.loop)
this.loop = null
}
if (this.slowLoop) {
clearInterval(this.slowLoop)
this.slowLoop = null
}
connector.closeWebSocket(code, this.hasError)
updateRPC(
{
Expand Down Expand Up @@ -314,6 +322,7 @@ export class Connection {
emulator!.setGameMode(handshake.gameMode)
connector.setPlayerId(this.playerId)
this.loop = setInterval(this.sendAll, UPDATE_INTERVAL)
this.slowLoop = setInterval(this.updatePlayerPositions, SLOW_UPDATE_INTERVAL)
}

/**
Expand Down Expand Up @@ -428,6 +437,7 @@ export class Connection {
if (playerId == null) return
this.playerId = playerId
emulator!.setPlayerId(playerId)
connector.setPlayerId(playerId)
}

/**
Expand Down Expand Up @@ -660,6 +670,12 @@ export class Connection {
}
}

private updatePlayerPositions (): void {
if (!emulator) return
const positions = emulator.getPlayerPositions()
connector.updatePlayerPositions(positions)
}

/**
* Send password to server.
*
Expand Down
6 changes: 5 additions & 1 deletion src/main/Connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ipcMain } from 'electron'

import { emulator, createEmulator, deleteEmulator, connection, createConnection, deleteConnection } from '.'
import { Emulator } from './Emulator'
import { FilteredEmulator } from '../models/Emulator.model'
import { FilteredEmulator, Position } from '../models/Emulator.model'
import { MainMessage, RendererMessage } from '../models/Message.model'
import { Server } from '../models/Server.model'
import { IPlayerUpdate, IPlayer } from '../../proto/ServerClientMessage'
Expand Down Expand Up @@ -113,6 +113,10 @@ export class Connector {
this.window.webContents.send(MainMessage.SET_PLAYER_ID, playerId)
}

public updatePlayerPositions (positions: {self: Position, cameraAngle: number, positions: (Position | null)[]}): void {
this.window.webContents.send(MainMessage.UPDATE_PLAYER_POSITIONS, positions)
}

public setGameMode (gameMode: number): void {
this.window.webContents.send(MainMessage.GAME_MODE, gameMode)
}
Expand Down
39 changes: 36 additions & 3 deletions src/main/Emulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { promisify } from 'util'
import { spawn } from 'child_process'

import { connector, deleteEmulator } from '.'
import { FilteredEmulator } from '../models/Emulator.model'
import { FilteredEmulator, Position } from '../models/Emulator.model'
import { testEmulatorPid, TestProcess } from '../models/Emulator.mock'
import { buf2hex } from '../utils/Buffer.util'
import winprocess, { Process } from '../declarations/winprocess'

Expand Down Expand Up @@ -118,7 +119,7 @@ export class Emulator {
*/
constructor (processId: number, characterId: number, inGameChatEnabled = false) {
this.inGameChatEnabled = inGameChatEnabled
this.process = winProcess.Process(processId)
this.process = processId === testEmulatorPid ? new TestProcess() : winProcess.Process(processId)
this.process.open()
this.baseAddress = -1
for (let i = 0x00000000; i <= 0x72D00000; i += 0x1000) {
Expand Down Expand Up @@ -201,7 +202,7 @@ export class Emulator {
errorMessage = 'Insufficient permission to read memory. Try starting Net64+ with admin privileges'
break
case 299:
errorMessage = 'Your memory is not set to 16MB. RTFM!'
errorMessage = 'Your memory is not set to 16MB. You are either not using the shipped emulator or you did not restart the emulator after chaning your settings to 16MB'
break
}
connector.setEmulatorError(errorMessage)
Expand Down Expand Up @@ -277,4 +278,36 @@ export class Emulator {
console.error(err)
}
}

public getPlayerRotation (): number {
return this.readMemory(0xFF7709, 1).readUInt8(0)
}

public getPlayerPositions (): {self: Position, cameraAngle: number, positions: (Position | null)[]} {
const positions: (Position | null)[] = new Array(24).fill(null)
const x = this.readMemory(0xFF7706, 2).readInt16LE(0)
const y = this.readMemory(0xFF770A, 2).readInt16LE(0)
const rotation = this.readMemory(0xFF7708, 2).readUInt16LE(0)
const map = this.readMemory(0xFF770F, 1).readUInt8(0)
const self: Position = {
x,
y,
rotation,
course: map
}
for (let offset = 0xFF7800, i = 0; offset < 0xFF9100; offset += 0x100, i++) {
const x = this.readMemory(offset + 6, 2).readInt16LE(0)
const y = this.readMemory(offset + 0xA, 2).readInt16LE(0)
const rotation = this.readMemory(offset + 8, 2).readUInt16LE(0)
const map = this.readMemory(offset + 0xF, 1).readUInt8(0)
positions[i] = {
x,
y,
rotation,
course: map
}
}
const cameraAngle = this.readMemory(0x33c6e4, 2).readUInt16LE(0)
return {self, cameraAngle, positions}
}
}
53 changes: 53 additions & 0 deletions src/models/Emulator.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { FilteredEmulator } from './Emulator.model';
import { Process } from '../declarations/winprocess';

export const testEmulatorPid = -1337

export const testEmulator: FilteredEmulator = {
name: 'Test Emu',
pid: testEmulatorPid,
windowName: 'Test Super Mario 64 - Project64'
}

const MEMORY_SIZE = 0xFFFFFF
const PLAYER_POS_X_OFFSET = 0xFF7706
const PLAYER_POS_Y_OFFSET = 0xFF770A
const PLAYER_ROTATION_OFFSET = 0xFF7708
const PLAYER_COURSE_OFFSET = 0xFF770F

export class TestProcess implements Process {
private memory = Buffer.alloc(MEMORY_SIZE)

constructor() {
this.memory.writeUInt32LE(0x3C1A8032, 0)
this.memory.writeUInt32LE(0x275A7650, 4)
this.memory.writeInt16LE(0x1000, PLAYER_POS_X_OFFSET)
this.memory.writeInt16LE(-0x800, PLAYER_POS_Y_OFFSET)
setInterval(this.updatePlayerLocation.bind(this), 500)
}

private updatePlayerLocation () {
for (let offset = 0; offset <= 0x100; offset += 0x100) {
this.memory.writeInt16LE((this.memory.readInt16LE(PLAYER_POS_X_OFFSET + offset) - 1), PLAYER_POS_X_OFFSET + offset)
this.memory.writeInt16LE((this.memory.readInt16LE(PLAYER_POS_Y_OFFSET + offset) - 1), PLAYER_POS_Y_OFFSET + offset)
this.memory.writeUInt16LE(((this.memory.readUInt16LE(PLAYER_ROTATION_OFFSET + offset) + 0x80) % 0xFFFF), PLAYER_ROTATION_OFFSET + offset)
this.memory.writeUInt8(4, PLAYER_COURSE_OFFSET + offset)
}
}

public open () {}

public readMemory (offset: number, length: number): number | Buffer {
let buffer: Buffer
if (offset + length > MEMORY_SIZE) {
buffer = Buffer.alloc(length)
} else {
buffer = this.memory.slice(offset, offset + length)
}
return buffer
}

public writeMemory (offset: number, buffer: Buffer) {
this.memory.fill(buffer, offset, offset + buffer.length)
}
}
17 changes: 17 additions & 0 deletions src/models/Emulator.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { IPlayer } from "../../proto/ServerClientMessage";

export interface FilteredEmulator {
name: string
pid: number
windowName?: string
}

export interface Position {
x: number
y: number
rotation: number
course: number
}

export interface Player extends IPlayer {
position?: Position
}

export const CHARACTER_IMAGES = [
'mario.png', 'luigi.png', 'yoshi.png', 'wario.png', 'peach.png', 'toad.png', 'waluigi.png', 'rosalina.png', 'sonic.png', 'knuckles.png', 'goomba.png', 'kirby.png'
]
1 change: 1 addition & 0 deletions src/models/Message.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export enum MainMessage {
SET_PLAYERS = 'SET_PLAYERS',
SET_PLAYER = 'SET_PLAYER',
SET_PLAYER_ID = 'SET_PLAYER_ID',
UPDATE_PLAYER_POSITIONS = 'UPDATE_PLAYER_POSITIONS',
GAME_MODE = 'GAME_MODE',
SERVER_FULL = 'SERVER_FULL',
WRONG_VERSION = 'WRONG_VERSION',
Expand Down
10 changes: 8 additions & 2 deletions src/models/Server.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IPlayer } from '../../proto/ServerClientMessage'
import { Player } from './Emulator.model'

export interface Server {
id?: string
Expand All @@ -7,10 +7,16 @@ export interface Server {
port: number
name?: string
description?: string
players?: IPlayer[]
players?: (Player | null)[]
countryCode?: string
gameMode?: number
version?: string
passwordRequired?: boolean | null
isDedicated?: boolean
}

export interface Course {
short: string
long: string
icon: string
}
5 changes: 4 additions & 1 deletion src/models/State.model.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { RouterState as ReactRouterState } from 'react-router-redux'

import { Server } from './Server.model'
import { FilteredEmulator } from './Emulator.model'
import { FilteredEmulator, Position } from './Emulator.model'
import { ChildProcess } from 'child_process'

export interface ElectronServerSaveDataDraft {
Expand Down Expand Up @@ -39,6 +39,9 @@ export type RouterState = Readonly<RouterStateDraft>

export interface ConnectionStateDraft {
server: Server | null
playerId: number | null
selfPos: Position
cameraAngle: number
authenticated: boolean
authenticationThrottle: number
hasToken: boolean
Expand Down
20 changes: 16 additions & 4 deletions src/renderer/Connector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import {
setGameMode,
setPlayer,
setPlayers,
setServer
setServer,
updatePlayerPositions,
setPlayerId
} from './actions/connection'
import { isConnectedToEmulator, setEmulatorError, updateEmulators } from './actions/emulator'
import { MainMessage, RendererMessage } from '../models/Message.model'
import { Server } from '../models/Server.model'
import { IPlayer, IPlayerUpdate } from '../../proto/ServerClientMessage'
import { FilteredEmulator } from '../models/Emulator.model'
import { FilteredEmulator, Position } from '../models/Emulator.model'
import { testEmulator } from '../models/Emulator.mock'

export class Connector {
constructor () {
Expand All @@ -30,6 +33,7 @@ export class Connector {
ipcRenderer.on(MainMessage.SET_PLAYERS, this.onSetPlayers)
ipcRenderer.on(MainMessage.SET_PLAYER, this.onSetPlayer)
ipcRenderer.on(MainMessage.SET_PLAYER_ID, this.onSetPlayerId)
ipcRenderer.on(MainMessage.UPDATE_PLAYER_POSITIONS, this.onUpdatePlayerPositions)
ipcRenderer.on(MainMessage.GAME_MODE, this.onSetGameMode)
ipcRenderer.on(MainMessage.SERVER_FULL, this.onServerFull)
ipcRenderer.on(MainMessage.WRONG_VERSION, this.onWrongVersion)
Expand Down Expand Up @@ -67,9 +71,16 @@ export class Connector {
}

private onUpdateEmulators = (_: Electron.Event, emulators: FilteredEmulator[]) => {
if (process.env.NODE_ENV === 'development') {
emulators.push(testEmulator)
}
store.dispatch(updateEmulators(emulators))
}

private onUpdatePlayerPositions = (_: Electron.Event, positions: {self: Position, cameraAngle: number, positions: (Position | null)[]}) => {
store.dispatch(updatePlayerPositions(positions))
}

private onSetServer = (_: Electron.Event, server: Server) => {
if (process.env.NODE_ENV === 'development') {
console.info('CONNECTED TO SERVER', server)
Expand All @@ -90,6 +101,7 @@ export class Connector {

private onSetPlayerId = (_: Electron.Event, playerId: number) => {
addGlobalMessage('Connected', '[SERVER]', true)
store.dispatch(setPlayerId(playerId))
}

private onSetGameMode = (_: Electron.Event, gameMode: number) => {
Expand Down Expand Up @@ -123,8 +135,8 @@ export class Connector {
{ message: string, senderId: number }
) => {
const server = store.getState().connection.server
if (!server || !server.players) return
const username = server.players[senderId] && server.players[senderId].username
if (!server || !server.players || !server.players[senderId]) return
const username = server.players[senderId] && server.players[senderId]!.username
addGlobalMessage(message, username || '?', false)
}

Expand Down
2 changes: 1 addition & 1 deletion src/renderer/Request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Request {
constructor () {
this.smmdb = axios.create({
// baseURL: 'http://localhost:8080/api',
baseURL: 'https://smmdb.ddns.net/api/',
baseURL: 'https://smmdb.net/api/',
responseType: 'json'
})
let githubApiKey = process.env.NODE_ENV === 'development'
Expand Down
Loading

0 comments on commit 2739491

Please sign in to comment.