Giter Site home page Giter Site logo

goto-bus-stop / aocmultiny Goto Github PK

View Code? Open in Web Editor NEW
6.0 4.0 1.0 520 KB

[wip] Tiny NAT-traversing Age of Empires 2 Multiplayer client.

License: GNU General Public License v3.0

Makefile 0.44% C++ 82.22% C 16.87% JavaScript 0.47%
age-of-empires matchmaking directplay multiplayer

aocmultiny's Introduction

aocmultiny

Tiny NAT-traversing Age of Empires 2 Multiplayer client.

VERY work in progress, it's probably pretty difficult to get it to compile.

The idea is to get a single portable zero-install executable that you can hand to a few friends and immediately start playing. No creating accounts, no installation, no router configuration, etc. Just the bare minimum.

Design

Fluctuating. I wanted to build the matchmaking part using IRC, but that's turning out to be a bit difficult, because you would need server-side adjustments to get IP addresses for the NAT traversal stuff (…I think.)

Anyway, it comes in two parts: matchmaking and connecting. Matchmaking will be using a nickname (no real authentication), and using public or passworded rooms (like IRC channels). Players can chat in rooms and the first player to join a room (the host) can start the game. Initially, up to 8 players can join a room, but in the future there'll have to be more for UserPatch spectator mode. (≤8 players + ≤32 spectators.) Connecting is probably going to be using ICE somehow (libnice?), but I don't know yet how to direct Age of Empires traffic onto an ICE-established socket. All in due time :D

UserPatch includes automatic port forwarding using UPNP, but that doesn't always cut it, and you still need to exchange IP addresses manually.

Building

On Linuxes:

  1. Install Wine and Mingw32. Something like apt-get install wine mingw32 mingw32-binutils.
  2. Download and build wxWidgets 3.1.0 using MinGW.
  3. Download the last DirectX SDK with DirectPlay (August 2007).
  4. Symlink dxguid.lib and dplayx.lib from the DirectPlay SDK into lib/.
  5. make to build
  6. make run to run

On Windowses with Visual Studio:

  1. Download and build wxWidgets using Visual Studio. Import one of the VS project files that comes with wxWidgets and build it.
  2. Download the last DirectX SDK with DirectPlay (August 2007).
  3. Configure environment variables:
    • WXWIN= path to your wxWidgets build base directory.
  4. Import the AoCMultiny.sln solution file.

Credits/References

License

GPL 3.0

aocmultiny's People

Contributors

goto-bus-stop avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

animal-uk

aocmultiny's Issues

Matchmaking

GET/PUT /rooms
GET/PUT /players


Old idea

IRC channels are game rooms.
For now we'll need a max of 8 users per channel, but in the future we can +v players, and -v spectators, and allow up to 32 users per channel.

The first player to join a channel creates it and gets +o. +o is the host. Hosts can start a game.

When a game starts, a CTCP message should be sent to the channel. Like how IRC clients implement /me: CTCP #channel ACTION text, we could use CTCP #room GAME_STARTING. DirectPlay connection info needs to be sent to the players, which could either be a message to the room or to individual players: CTCP nick GAME_LAUNCH <host_ip> <dp_session_guid>.

May prefer to use a slightly modified IRC server that doesn't allow you to fake CTCP messages as easily (perhaps by sending them from the server, and not the room host)

dplib: move most of DPLobby to a new DPSession class

A DPSession will represent a single game session, and the DPLobby class will map to DirectPlay's own lobby stuff with some sugar sprinkled on top.

Currently:

auto lobby = new DPLobby(new DPGameAoC(), "Player name");
lobby->host();
lobby->launch();

Maybe-future:

auto lobby = new DPLobby();
auto game = new DPGameAoC();
auto session = lobby->hostSession(game);
session->launch();

// maybe?
auto session = lobby->joinSession(game, address, sessionGuid);
session->launch();

dplib: fluent DPAddress creation

Currently dplib hardcodes TCP/IP or libnice service provider addresses, which is a bit restrictive (although you're unlikely to use anything other than TCP/IP from the defaults, but who knows).

Idea:

Shorthands for common stuff:

DPAddress::ip("164.145.25.145"); // → tcp/ip address with a specific IP
DPAddress::ip(); // tcp/ip address with empty IP, for hosting sessions

Address builder for other stuff:

class DPAddress {
public:
  DPAddress (GUID serviceProviderGuid);
  DPAddress* add (GUID dataType, void* data, int dataSize);
  DPAddress* add (GUID dataType, string str) {
    return add(dataType, str.c_str(), str.length());
  }
};

// tcp/ip address with an IP component
new DPAddress(DPSPGUID_TCPIP)
  ->add(DPAID_INet, "164.145.25.145");
// libnice service provider address with custom signaling and STUN servers, and a known host SDP
new DPAddress(DPSPGUID_NICE)
  ->add(DPAID_ICESignalingServer, "aocmultiny.net:7788")
  ->add(DPAID_ICETURN, "turn.l.google.com:6345")
  ->add(DPAID_ICESDP, hostSdp, hostSdpLen);
// or even, but not sure if this is doable with types and stuff:
new DPAddress(DPSPGUID_NICE, {
  { DPAID_ICESignalingServer, "aocmultiny.net:7788" },
  { DPAID_ICETURN, "turn.l.google.com:6345" },
  { DPAID_ICESDP, hostSdp, hostSdpLen },
});

expand and extract DirectPlay library `dplib`

The DirectPlay library parts can be pretty useful for other apps too (especially because there is hardly any documentation for DirectPlay lobbying) so it could be published as a standalone library. It'd need a bit more work though because currently it only deals with the data structures necessary to start a lobbyable application, and not actually running a game and keeping it alive.

Licensing

I put an MIT thing on this first but I think I want to go a more copyleft direction. Probably GPL for the final application, and LGPL for the library bits (dplib, maaaybe nicesp?).

Will put GPL on the repo for now, the library bits could be switched to a more permissive license later.

GUI

Maybeee

  • wxWidgets, or
  • Native WinAPI (waaa??????), or
  • HTML + WebView

fix leaks

I'm a C++ noob so this thing leaks all over the place

Mod Management

This would likely be a separate library, but documenting here so I don't forget:

A mod manager for AoC for data mods and visual mods. Existing data mods can be combined together by diffing the various mods with the original data files, and stacking the diffs.

(A new JSON-based data format could be nice too on top of that.)

non-destructively auto-install userpatch

To ensure that players all have the same game version, it'd be good to provide (optionally, ideally) a UserPatch installer. This shouldn't overwrite anything (eg. a Vooblyfied aoc should still work with voobly). I'm not sure if running the UP setup on a Vooblyfied aoc works or if it needs an original exe.

If UP setup works on Vooblyfied installs, aocmultiny can just ship a UP setup and run it, and revert to a backup when the game is finished.

Another option is to then move the UP executable to eg. age2_x1.aocmultiny.exe and add a DirectPlay registry entry for it. That might also make switching game types easier in the future (eg. to support exe mods like Forgotten Empires)

dplib: DPServiceProvider class

New thing for dplib: a base class for DPlay service providers. DPServiceProvider would be a wrapper around IDirectPlaySP, minus the Get- and SetSPData methods (which will be used to associate the DPServiceProvider to IDirectPlaySP instances internally).

Implement Service Provider callbacks as virtual methods in the subclass.

class MyServiceProvider: public dplib::DPServiceProvider {
private:
  SomeProxiedConnection connection;
public:
  virtual HRESULT Open (DPSP_OPENDATA* data) {
    // Can use `this` to store stuff, instead of SetSPData and GetSPData.
    this->connection.open("http://myproxy.com");
    return DP_OK;
  }
  virtual HRESULT Send (DPSP_SENDDATA* data) {
    this->connection.send(data->idPlayerTo, data->lpMessage, data->dwMessageSize);
    return DP_OK;
  }
};

Then, SPInit will be something like:

HRESULT WINAPI SPInit (SPINITDATA* data) {
  auto sp = new MyServiceProvider(data);
  return sp->init();
}

DPServiceProvider could also provide overloads for hooks. Eg, it could turn EnumSessions from EnumSessions (DPSP_ENUMSESSIONSDATA* data) into EnumSessions (void* message, int size, bool returnStatus).

class DPServiceProvider {
public:
  HRESULT EnumSessions (void* message, int size, bool returnStatus);
  HRESULT EnumSessions (DPSP_ENUMSESSIONSDATA* data) {
    this->EnumSessions(
      data->lpMessage,
      data->dwMessageSize,
      data->bReturnStatus
    );
  }
};

And subclasses could choose to either use the simplified overloaded fn, or the raw DirectPlay-style struct parameter.

Likely methods:

EnumSessions
Reply
Send
CreatePlayer
DeletePlayer
GetAddress
GetCaps
Open
Close // actually DPlay's CloseEx hook
Shutdown // actually DPlay's ShutdownEx hook
GetAddressChoices
SendEx // could refer to the same Send() overload as Send() by default
SendToGroupEx // or just SendToGroup
Cancel
GetMessageQueue

DPlay's CloseEx and ShutdownEx would have to be used instead of its Close and Shutdown, because the standard Close and Shutdown hooks don't get the IDirectPlaySP interface passed in, so we couldn't use GetSPData to retrieve the DPServiceProvider instance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.