Compare commits

...

87 Commits
1.4 ... main

Author SHA1 Message Date
CakeLancelot d52e149192
Merge pull request #22 from FinnHornhoover/main
Offline Caches & Configuration
2024-06-07 14:11:40 -05:00
FinnHornhoover 16a158906d add guards for file backup 2024-06-07 11:46:01 +03:00
FinnHornhoover 7f9c5d90a1 fixed offline cache enabled condition 2024-04-06 02:31:59 +03:00
FinnHornhoover 17f194810c added comments 2024-04-06 02:31:59 +03:00
FinnHornhoover 87072b0789 cleaned up and added docstrings to cache handler 2024-04-06 02:31:59 +03:00
FinnHornhoover e933bc52fe fixed added versions not showing up immediately 2024-04-06 02:31:59 +03:00
FinnHornhoover 1078778e16 added linguist-vendored 2024-04-06 02:31:59 +03:00
FinnHornhoover 5dca39a17e fixed config json read, limited hash check 2024-04-06 02:31:59 +03:00
FinnHornhoover 0eca42cdf8 fixed valdator function name 2024-04-06 02:31:59 +03:00
FinnHornhoover fa0bdd7b1a fixed hash check timing on config change 2024-04-06 02:31:59 +03:00
FinnHornhoover feafd8d17f added hash check when cache location is changed 2024-04-06 02:31:59 +03:00
FinnHornhoover 6a7b029539 added config modal, bumped version 2024-04-06 02:31:59 +03:00
FinnHornhoover 171177b606 added more proper initial check handling 2024-04-06 02:31:59 +03:00
FinnHornhoover 1c2cf41e97 added default ip, regex for version names 2024-04-06 02:31:59 +03:00
FinnHornhoover 0201f11333 added fixes for validation 2024-04-06 02:31:59 +03:00
FinnHornhoover a859590ef9 fixed version url and path bugs, added validation 2024-04-06 02:31:59 +03:00
FinnHornhoover 356e811bac WIP custom build adjustments 2024-04-06 02:31:57 +03:00
FinnHornhoover cdabb36639 added build management, WIP custom cache checks 2024-04-06 02:31:56 +03:00
FinnHornhoover 547ca778b0 by default, always use cdn 2024-04-06 02:31:56 +03:00
FinnHornhoover 6bae0d1ff6 removed async, adjusted load logic, and hash check 2024-04-06 02:31:56 +03:00
FinnHornhoover 11f0c61a67 edited gitignore for extra files 2024-04-06 02:31:56 +03:00
FinnHornhoover 1d78bc2d9b removed redundant function 2024-04-06 02:31:56 +03:00
FinnHornhoover c78a3e5ada do not immediately start checking hashes 2024-04-06 02:31:56 +03:00
FinnHornhoover c05e9c0dcd reverted version sizes 2024-04-06 02:31:56 +03:00
FinnHornhoover e1ef76744a added script itself and migration logic 2024-04-06 02:31:56 +03:00
FinnHornhoover 04aea6059e added measure against half-flushed objects 2024-04-06 02:31:55 +03:00
FinnHornhoover 600b33a230 switched to ipc through localhost 2024-04-06 02:31:55 +03:00
FinnHornhoover 48efd00a4a use python child process to handle cache ops 2024-04-06 02:31:55 +03:00
FinnHornhoover f28c9c0bb8 WIP added offline cache pointing logic 2024-04-06 02:31:54 +03:00
FinnHornhoover e3f16d8fc9 delegated downloads to wget exe due to memory leak 2024-04-06 02:31:54 +03:00
FinnHornhoover 6f7f1655b9 implemented delete as ipc, adjusted for cache swap 2024-04-06 02:31:54 +03:00
FinnHornhoover 597e80b112 adjusted download and hash check logic and data 2024-04-06 02:31:54 +03:00
FinnHornhoover 79bdba74a5 integrated download and hash functionality 2024-04-06 02:31:54 +03:00
FinnHornhoover 16a99f86c7 added async hash checking 2024-04-06 02:31:54 +03:00
FinnHornhoover 05af8a3f9e WIP ipc downloads 2024-04-06 02:31:54 +03:00
FinnHornhoover 27f0992b52 WIP download bugfix 2024-04-06 02:31:54 +03:00
FinnHornhoover 132b725922 WIP button functionality (download, delete) 2024-04-06 02:31:54 +03:00
CakeLancelot b5ab9aad2d Bump copyright date to 2024 and version to 1.5.2; update build.yml 2024-04-02 06:49:15 -05:00
CakeLancelot 01ee292d10 Introduce automatic artifact building and publishing 2024-04-02 05:06:06 -05:00
CakeLancelot 2183106c73 Fix manifest causing a crash / background process on certain systems
Fixes #21
2024-03-24 01:33:38 -05:00
Gent Semaj db7370ca41
Bump copyright date 2024-02-02 19:01:07 -08:00
CakeLancelot ec0fc87dcd Bump version number to 1.5.1 2023-11-09 13:31:44 -06:00
CakeLancelot cef8c1de93 Revert readJsonSync() change for modifying servers
readJsonSync() apparently produces an immutable JSON, which made it to where you couldn't add or remove servers
2023-10-18 12:47:41 -05:00
CakeLancelot b73329c6de Update version numbers to 1.5 2023-10-07 18:20:10 -05:00
CakeLancelot 2e7dc51aa1
Fix issue where cache swapping wouldn't work if record wasn't already present
Not sure why I re-ordered this before
2023-09-27 05:01:22 -05:00
CakeLancelot 3fc6cabe33 Disable telemetry in player dll
Co-authored-by: gsemaj <gsemaj@proton.me>
2023-09-19 08:59:13 -05:00
CakeLancelot 71e4694ff6 Misc comment cleanup, correct holiday date range, simplify JSON loading 2023-09-19 08:57:50 -05:00
CakeLancelot 76f4a05287 Move server-selector over to path.join(), fix issues with cache swapping
Before, swapping would continually fail if a cache tried to be stored at a directory that already existed. The skipping mechanism likely also didn't work as intended. Both have been fixed now.
Additionally:
* Added .editorconfig file 
* Ran prettier format
* Misc. refactoring
2023-09-19 08:57:29 -05:00
CakeLancelot 97144aad59 Remove initial setup window
Now that we only copy a few json files for the initial setup, the process is so fast the progress window isn't really needed anymore
2023-09-17 13:02:19 -05:00
CakeLancelot 4a465ca689
README: include preleases for release badge 2023-09-17 09:42:41 -05:00
CakeLancelot 43f0c8c684 Revise loader DLL to work under Wine, loading screen beta text, cleanup 2023-09-16 20:57:13 -05:00
CakeLancelot d4dc403e90 Remove now unnecessary attributes from game-client.js 2023-09-14 15:13:23 -05:00
CakeLancelot ab5de9488d Fix DNS resolution
not sure why this works but resolve4 doesn't
2023-09-14 06:44:11 -05:00
CakeLancelot dabb8bf484 Use extra-plugin-dirs in Electron to load plugin, add fusion manifest.
This has the advantage of being self contained (doesn't conflict with Unity 3.x - 5.x loader, so we can use the original one) and **disabling auto updates actually works**.

We can also eliminate any code used to install and verify unity, since it's all self contained.

Also added fusion manifest file to set process as DPI aware, and set ACP to UTF-8 on Windows 10 1903 and above.

Bumped version to 1.4.2
2023-09-14 05:29:34 -05:00
CakeLancelot 043bf219e7 Consistency pass and small tweaks
**Formatting going forward**
Variables: camelCase (capitalization of two letter abbreviations is OK, e.g. playerID)
Classes: PascalCase
CSS: kebab-case
Files: kebab-case

**Other miscellaneous changes**
* The WebPlayer crashing as well as failing to load the config file are now fatal  errors and will quit the app
* Moved some style attributes from index.html into openfusion.css
2023-09-03 05:12:30 -05:00
CakeLancelot 7131026b2f Misc tweaks
loadURL() -> loadUrl() in index.js
Move Bootstrap files
2023-09-02 23:03:00 -05:00
dongresource 7dd018e336 Use local fonts for Bootstrap
bootstrap.min.css was fetching a css snippet for the Roboto font
remotely. Inlined the snippet and modified it to load the font files
locally.
2023-09-03 01:44:09 +02:00
CakeLancelot e19098a13e README update 2023-07-11 19:40:51 -05:00
CakeLancelot 48e2052748
Fix call to nonexistent function in URL redirection
Gotta love runtime errors
2023-04-23 15:37:44 -05:00
CakeLancelot 7b3de1fe52 Bump fs-extra version to 2.0.0
This is the latest version that supports ES5
2023-02-17 20:07:52 -06:00
CakeLancelot 675a5fce50 Update repo URL in package.json 2023-02-11 16:08:25 +00:00
CakeLancelot 2bf916ea58 Fix bug in WebPlayer installation logic
Also run prettier
2023-02-09 12:52:57 -06:00
CakeLancelot d554b6b968 Get version number from package.json on app start
This is easy to miss when prepping a new release so I figured we might as well automate it
2023-02-09 11:56:53 -06:00
CakeLancelot 5da0da1981 Consolidate afterPack scripts into one file 2023-02-09 04:39:21 -06:00
CakeLancelot 101de9d68b Added WebPlayer verification/reinstallation logic 2023-02-09 01:05:41 -06:00
CakeLancelot d0f947c4a5 Add large address aware patch to build process 2023-02-09 03:14:09 +00:00
CakeLancelot 4726a50be7 package.json tweaks, update LICENSE.md date 2023-02-09 01:04:20 +00:00
CakeLancelot 3d9107a7f1 Install Unity Web Player through Electron rather than the bat file
This method is a lot more reliable, as the bat file was known to not work in certain configurations of Windows and on Wine
2023-02-08 15:21:35 -06:00
CakeLancelot c1db7bc047 Refactor cache swapping logic
* Hoist everything into a function
* Add error handling
* Rename vars for clarity
* Skip renaming if the current and new version are the same: this along with the error handling should fix the black screen when using multiple clients
2023-02-08 14:06:54 -06:00
CakeLancelot 51f7eaf33d Minor changes/updates
* Change `name` in package.json to PascalCase, as this is what is used for the creation of folders in AppData, etc.
* Regenerate package-lock.json
* Bump dependency versions
* Update copyright year
2023-02-08 12:44:25 -06:00
CakeLancelot 7bc438d76a
Merge pull request #18 from hichemfantar/patch-prettier
configure prettier for a prettier project
2022-09-12 16:47:42 -05:00
CakeLancelot 3c0b07e61a
Merge pull request #17 from hichemfantar/patch-1
Add missing license file
2022-09-12 15:53:55 -05:00
Hichem Fantar f9c041edc9 format assets but ignore minified files 2022-07-26 15:48:33 +01:00
Hichem Fantar fd92f2de5e switch from tabs to spaces & set indent size to 4 2022-07-26 15:41:07 +01:00
Hichem Fantar 51a876cf2b set endOfLine to lf 2022-07-26 15:29:20 +01:00
CakeLancelot 2640c8f1a6 LICENSE -> LICENSE.md, Add WebPlayer license file 2022-07-25 11:33:39 -05:00
Hichem Fantar e2b704a701
Add prettier script to format entire project 2022-07-18 19:40:47 +01:00
Hichem Fantar 9a083d7a04 configure prettier for a prettier project 2022-07-18 19:19:22 +01:00
Hichem Fantar c964e840e4
Add missing license file 2022-07-18 18:57:07 +01:00
dongresource 0060f37e6c Clean up semicolons, whitespace and a typo 2022-06-29 00:57:30 +02:00
dongresource 9bfe3d6d99 Bump copyright year to 2022 2022-06-28 23:06:05 +02:00
dongresource 63c4616645 Replace default server IP with domain name
Now that the client supports domain resolution in the IP field, it makes
sense to use a domain name for future-proofing.
2022-06-28 23:02:48 +02:00
CakeLancelot 645e5d4279
Merge pull request #16 from OpenFusionProject/qol
Improved server address processing
2022-05-05 18:45:24 -05:00
gsemaj 7ce21cdddc Don't perform lookup for obvious IPs and account for async
This old version of Node forces us to use callbacks, so I had to rearrange some code to ensure the client only launches after the resolution is complete
2022-04-27 20:50:23 -04:00
gsemaj 8d6e546628 Add automatic DNS resolution for server addresses 2022-04-27 13:44:08 -04:00
gsemaj 6e881cbfaf Connect to default port 23000 if port not specified 2022-04-27 13:43:51 -04:00
gsemaj 8d5a8df023 Update package-lock for newer npm versions 2022-04-27 13:00:40 -04:00
74 changed files with 47400 additions and 4256 deletions

19
.editorconfig Normal file
View File

@ -0,0 +1,19 @@
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
# 4 space indentation
[*.js, *.css, *.html, *.json]
indent_style = space
indent_size = 4
# Don't enforce anything in vendored code
[*.min.*]
end_of_line = unset
insert_final_newline = unset
indent_style = unset
indent_style = unset

3
.gitattributes vendored
View File

@ -3,3 +3,6 @@
*.js text eol=lf
*.json text eol=lf
*.md text eol=lf
defaults/* linguist-vendored
lib/* linguist-vendored

47
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,47 @@
name: Publish Build
on:
push:
branches: [ "main" ]
tags: '*'
permissions:
contents: write
jobs:
build:
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 20.x
cache: 'npm'
- name: Install dependencies
run: npm install
- name: Pack into zip and create installer
run: npm run dist
- name: Upload Artifacts
uses: actions/upload-artifact@master
with:
path: dist
publish-release:
if: contains(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
needs: build
steps:
- name: Download artifact
uses: actions/download-artifact@master
- name: Create release
uses: ncipollo/release-action@v1
with:
artifacts: "artifact/*-ia32-win.zip,artifact/*.exe"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

4
.gitignore vendored
View File

@ -9,3 +9,7 @@ resources/app/files/rankurl.txt
node_modules/
dist/
UnityBugReporter.exe
cache_handler/*/
extra/
*.sh
yarn.lock

33
.prettierignore Normal file
View File

@ -0,0 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
locales/
*.pak
*.bin
*.php
rankurl.txt
icudtl.dat
version
resources/app/files/rankurl.txt
node_modules/
dist/
UnityBugReporter.exe
*.min.*

12
.prettierrc Normal file
View File

@ -0,0 +1,12 @@
{
"trailingComma": "es5",
"useTabs": false,
"tabWidth": 4,
"singleQuote": false,
"semi": true,
"bracketSameLine": false,
"bracketSpacing": true,
"jsxSingleQuote": false,
"quoteProps": "as-needed",
"endOfLine": "lf"
}

9
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,9 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
// List of extensions which should be recommended for users of this workspace.
"recommendations": ["esbenp.prettier-vscode"],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": []
}

21
LICENSE.md Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020-2024 OpenFusion Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,2 +1,52 @@
# OpenFusionClient
Electron app for joining OpenFusion servers
[![Current Release](https://img.shields.io/github/v/release/OpenFusionProject/OpenFusionClient?include_prereleases)](https://github.com/OpenFusionProject/OpenFusionClient/releases/latest) [![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?logo=discord)](https://discord.gg/DYavckB)[![License](https://img.shields.io/github/license/OpenFusionProject/OpenFusionClient)](https://github.com/OpenFusionProject/OpenFusionClient/blob/master/LICENSE.md)
An Electron app that allows you to easily join FusionFall servers.
It automatically installs FF's custom build of Unity Web Player, manages text files such as `assetInfo.php`/`loginInfo.php`, and embeds the game, all in a few clicks!
For an overview of how the game client worked originally, please see [this section in the OpenFusion README](https://github.com/OpenFusionProject/OpenFusion#architecture).
## Disclaimer
This repository does not contain any code from the actual FusionFall game client. **Think of it more as a launcher:** it abstracts away having to use a NPAPI plugin capable web browser, along with having to host a HTTP server for it to connect to.
In addition, if you are interested in contributing: do note that **this project likely cannot utilize more modern Javascript techniques**. In order to use NPAPI plugins, a very old version of Electron was needed (0.31.0). This limits the project to only a portion of ES5 in non-strict mode, and a reduced subset of Node/Electron APIs.
## Usage
Provided that you have npm installed, clone the repository, then run install like so:
```
git clone https://github.com/OpenFusionProject/OpenFusionClient.git
npm install
```
After that has completed you can then test OpenFusionClient:
```
npm run start
```
If you would like to package it as a standalone win32 application:
```
npm run pack
```
You can then compress the application directory into a zip file and installer for distribution:
```
npm run dist
```
Before opening a PR or running pack/dist, please do a code formatting pass:
```
npm run prettier
```
## License
MIT unless specified otherwise

File diff suppressed because one or more lines are too long

30
assets/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -47,31 +47,41 @@ img {
}
body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
clear: both;
user-select: none;
background-color: #000;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
#of-versionnumber {
#of-versionnumberdiv {
position: fixed;
bottom: 4px;
right: 8px;
}
.btn-primary {
background-image: url('../../assets/img/btn-primary-bg.png');
background-image: url("../../assets/img/btn-primary-bg.png");
background-repeat: repeat;
}
.btn-success {
background-image: url('../../assets/img/btn-success-bg.png');
background-image: url("../../assets/img/btn-success-bg.png");
background-repeat: repeat;
}
.btn-danger {
background-image: url('../../assets/img/btn-danger-bg.png');
background-image: url("../../assets/img/btn-danger-bg.png");
background-repeat: repeat;
}
.btn-warning {
background-image: url("../../assets/img/btn-warning-bg.png");
background-repeat: repeat;
}
@ -100,6 +110,36 @@ body {
border-color: #6699ff;
}
#of-editcacheconfigmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
#of-editconfigmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
#of-addversionmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
#of-editversionmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
#of-deleteversionmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
#of-restoreversionsmodal > .modal-dialog > .modal-content {
background-color: #093363;
border-color: #6699ff;
}
.form-control,
.form-control:focus {
border-color: #0099ff;
@ -113,6 +153,14 @@ select {
color: #fff;
}
.modal {
overflow-y: auto;
}
.invalidinput {
border-color: #ff0000;
}
button:disabled {
cursor: not-allowed;
pointer-events: all !important;
@ -129,3 +177,12 @@ button > i {
#server-table .server-listing-entry {
cursor: pointer;
}
#client {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: #000;
clear: both;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 176 B

After

Width:  |  Height:  |  Size: 176 B

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,3 +1,3 @@
$(document).ready(function(){
$('[data-bs-tooltip]').tooltip();
$(document).ready(function () {
$("[data-bs-tooltip]").tooltip();
});

17
assets/js/easter-eggs.js Normal file
View File

@ -0,0 +1,17 @@
// You're kind of ruining the surprise by reading this, but whatever
var today = new Date();
var christmasBegin = new Date(today.getFullYear(), 11, 21);
var christmasEnd = new Date(today.getFullYear(), 11, 31);
var sf;
if (today >= christmasBegin && today <= christmasEnd) {
console.log("Christmas Activated.");
sf = new Snowflakes({ zIndex: -100 });
}
function stopEasterEggs() {
if (sf != null) {
sf.destroy();
}
}

View File

@ -1,19 +0,0 @@
// You're kind of ruining the surprise by reading this, but whatever
var today = new Date();
// Check Christmas season: Date constructor in Javascript uses an index
// so 11 is Dec. of this year, and 12 is Jan. of the next
var christmasBegin = new Date(today.getFullYear(), 11, 23);
var christmasEnd = new Date(today.getFullYear(), 12, 8);
var sf
if((today >= christmasBegin && today <= christmasEnd)) {
console.log("Christmas Activated.");
sf = new Snowflakes({zIndex: -100});
}
function stopEasterEggs(){
if (sf != null) {
sf.destroy();
}
}

89
assets/js/game-client.js Normal file
View File

@ -0,0 +1,89 @@
var ipc = require("ipc");
var gameRunning = false;
// Unity invoked methods begin //
// Uncomment and enter credentials to skip login screen
function authDoCallback(param) {
/*var unity = document.getElementById('unityEmbed');
unity.SendMessage("GlobalManager", "SetTEGid", "player");
unity.SendMessage("GlobalManager", "SetAuthid", "0");
unity.SendMessage("GlobalManager", "DoAuth", 0);*/
}
function MarkProgress(param) {}
function redirect(html) {
ipc.send("exit", 0);
}
function HomePage(param) {
ipc.send("exit", 0);
}
function PageOut(param) {
ipc.send("exit", 0);
}
function updateSocialOptions(param) {
ipc.send("exit", 0);
}
function PayPage(param) {
ipc.send("exit", 0);
}
// Unity invoked methods end //
function onResize() {
if (gameRunning == true) {
var unity = document.getElementById("unityEmbed");
unity.style.width = window.innerWidth + "px";
unity.style.height = window.innerHeight + "px";
}
}
function launchGame() {
gameRunning = true;
var sel = document.getElementById("of-serverselector");
sel.remove();
document.body.style.overflow = "hidden";
var object = document.createElement("object");
object.setAttribute(
"classid",
"clsid:444785F1-DE89-4295-863A-D46C3A781394"
);
object.setAttribute(
"codebase",
"undefined/UnityWebPlayer.cab#version=2,0,0,0"
);
object.setAttribute("id", "unityObject");
object.setAttribute("width", "1264");
object.setAttribute("height", "661");
var embed = document.createElement("embed");
embed.setAttribute("type", "application/vnd.ffuwp");
embed.setAttribute(
"pluginspage",
"http://www.unity3d.com/unity-web-player-2.x"
);
embed.setAttribute("id", "unityEmbed");
embed.setAttribute("width", "1280");
embed.setAttribute("height", "680");
embed.setAttribute("src", window.assetUrl + "main.unity3d");
embed.setAttribute("bordercolor", "000000");
embed.setAttribute("backgroundcolor", "000000");
embed.setAttribute("disableContextMenu", true);
embed.setAttribute("textcolor", "ccffff");
embed.setAttribute("logoimage", "assets/img/unity-dexlabs.png");
embed.setAttribute("progressbarimage", "assets/img/unity-loadingbar.png");
embed.setAttribute(
"progressframeimage",
"assets/img/unity-loadingframe.png"
);
var div = document.getElementById("client");
object.appendChild(embed);
div.appendChild(object);
document.title = "OpenFusion";
onResize();
}

View File

@ -1,80 +0,0 @@
var ipc = require("ipc");
var gameRunning = false;
// Unity invoked methods begin //
// Uncomment and enter credentials to skip login screen
function authDoCallback(param) {
/*var unity = document.getElementById('Unity_embed');
unity.SendMessage("GlobalManager", "SetTEGid", "player");
unity.SendMessage("GlobalManager", "SetAuthid", "0");
unity.SendMessage("GlobalManager", "DoAuth", 0);*/
}
function MarkProgress(param) {}
function redirect(html) {
ipc.send("exit", 0);
}
function HomePage(param) {
ipc.send("exit", 0);
}
function PageOut(param) {
ipc.send("exit", 0);
}
function updateSocialOptions(param) {
ipc.send("exit", 0);
}
function PayPage(param) {
ipc.send("exit", 0);
}
// Unity invoked methods end //
function onResize() {
if (gameRunning == true) {
var unity = document.getElementById('Unity_embed');
unity.style.width = window.innerWidth + 'px';
unity.style.height = window.innerHeight + 'px';
}
}
function launchGame() {
gameRunning = true
var sel = document.getElementById("of-serverselector");
sel.remove()
document.body.style.overflow = "hidden";
var object = document.createElement('object');
object.setAttribute('classid', "clsid:444785F1-DE89-4295-863A-D46C3A781394");
object.setAttribute('codebase', "undefined/UnityWebPlayer.cab#version=2,0,0,0");
object.setAttribute('id', "Unity_object");
object.setAttribute('width', "1264");
object.setAttribute('height', "661");
var embed = document.createElement('embed');
embed.setAttribute('type', "application/vnd.unity");
embed.setAttribute('pluginspage', "http://www.unity3d.com/unity-web-player-2.x");
embed.setAttribute('id', "Unity_embed");
embed.setAttribute('width', "1280");
embed.setAttribute('height', "680");
embed.setAttribute('src', window.asseturl+"main.unity3d");
embed.setAttribute('disablecontdparaextmenu', "true");
embed.setAttribute('bordercolor', "000000");
embed.setAttribute('backgroundcolor', "000000");
embed.setAttribute('disableContextMenu', true);
embed.setAttribute('textcolor', "ccffff");
embed.setAttribute('logoimage', "assets/img/unity_dexlabs.png");
embed.setAttribute('progressbarimage', "assets/img/unity_loadingbar.png");
embed.setAttribute('progressframeimage', "assets/img/unity_loadingframe.png");
embed.setAttribute('autoupdateurlsignature', "42180ee5edc4e3d4dd706bcc17cedd8d6ec7b7ac463071fd34ab97fe181f1a78df31db5feb4526677e4f69ef53acaff44471591e68b87f041c80fd54765f0d5725b08aa28f5acf7716ffb2a04e971269f35925c7e38d57dd78f6a206530caaa3da7e32f07f19810efc0ebf29a4eae976a925ad9cc5beb4dd51564c67dc489033");
embed.setAttribute('autoupdateurl', "http://wp-cartoonnetwork.unity3d.com/ff/big/beta-20111013/autodownload_webplugin_beta");
var div = document.getElementById('client');
object.appendChild(embed);
div.appendChild(object);
document.title = "OpenFusion"
onResize();
}

View File

@ -0,0 +1,993 @@
var remote = require("remote");
var remotefs = remote.require("fs-extra");
var dns = remote.require("dns");
var path = remote.require("path");
var dialog = remote.require("dialog");
var net = remote.require("net");
var spawn = require("child_process").spawn;
var userData = remote.require("app").getPath("userData");
var configPath = path.join(userData, "config.json");
var serversPath = path.join(userData, "servers.json");
var versionsPath = path.join(userData, "versions.json");
var cacheRoot = path.join(
userData,
"/../../LocalLow/Unity/Web Player/Cache"
);
var offlineRootDefault = path.join(cacheRoot, "Offline");
var offlineRoot = offlineRootDefault;
var cdnString = "http://cdn.dexlabs.systems/ff/big";
var versionArray;
var serverArray;
var cacheSizes;
var defaultHashes;
var config;
function enableServerListButtons() {
$("#of-connect-button").removeClass("disabled");
$("#of-connect-button").prop("disabled", false);
$("#of-editserver-button").removeClass("disabled");
$("#of-editserver-button").prop("disabled", false);
$("#of-deleteserver-button").removeClass("disabled");
$("#of-deleteserver-button").prop("disabled", false);
}
function disableServerListButtons() {
$("#of-connect-button").addClass("disabled");
$("#of-connect-button").prop("disabled", true);
$("#of-editserver-button").addClass("disabled");
$("#of-editserver-button").prop("disabled", true);
$("#of-deleteserver-button").addClass("disabled");
$("#of-deleteserver-button").prop("disabled", true);
}
function enableVersionAddButton() {
$("#of-addversion-button").removeClass("disabled");
$("#of-addversion-button").prop("disabled", false);
}
function enableVersionListButtons() {
$("#of-editversion-button").removeClass("disabled");
$("#of-editversion-button").prop("disabled", false);
$("#of-deleteversion-button").removeClass("disabled");
$("#of-deleteversion-button").prop("disabled", false);
}
function disableVersionAddButton() {
$("#of-addversion-button").addClass("disabled");
$("#of-addversion-button").prop("disabled", true);
}
function disableVersionListButtons() {
$("#of-editversion-button").addClass("disabled");
$("#of-editversion-button").prop("disabled", true);
$("#of-deleteversion-button").addClass("disabled");
$("#of-deleteversion-button").prop("disabled", true);
}
function getAppVersion() {
appVersion = remote.require("app").getVersion();
// Simplify version, ex. 1.4.0 -> 1.4,
// but only if a revision number isn't present
if (appVersion.endsWith(".0")) {
return appVersion.substr(0, appVersion.length - 2);
} else {
return appVersion;
}
}
function setAppVersionText() {
$("#of-aboutversionnumber").text("Version " + getAppVersion());
$("#of-versionnumber").text("v" + getAppVersion());
}
function validateServerSave(modalName) {
// works everytime a key is entered into the server save form
var descInput = document.getElementById(modalName + "server-descinput");
var ipInput = document.getElementById(modalName + "server-ipinput");
var button = document.getElementById(modalName + "server-savebutton");
var valid = true;
descInput.classList.remove("invalidinput");
ipInput.classList.remove("invalidinput");
if (
descInput.value.length < parseInt(descInput.getAttribute("minlength")) ||
descInput.value.length > parseInt(descInput.getAttribute("maxlength"))
) {
descInput.classList.add("invalidinput");
valid = false;
}
if (!(new RegExp(ipInput.getAttribute("pattern"))).test(ipInput.value)) {
ipInput.classList.add("invalidinput");
valid = false;
}
if (valid) {
button.removeAttribute("disabled");
} else {
button.setAttribute("disabled", "");
}
}
function addServer() {
var jsonToModify = JSON.parse(remotefs.readFileSync(serversPath));
var server = {};
server["uuid"] = uuidv4();
server["description"] =
$("#addserver-descinput").val().length == 0
? "My OpenFusion Server"
: $("#addserver-descinput").val();
server["ip"] =
$("#addserver-ipinput").val().length == 0
? "127.0.0.1:23000"
: $("#addserver-ipinput").val();
server["version"] = $("#addserver-versionselect option:selected").text();
//server['endpoint'] =
jsonToModify["servers"].push(server);
remotefs.writeFileSync(serversPath, JSON.stringify(jsonToModify, null, 4));
loadServerList();
}
function editServer() {
var jsonToModify = JSON.parse(remotefs.readFileSync(serversPath));
$.each(jsonToModify["servers"], function (key, value) {
if (value["uuid"] == getSelectedServer()) {
value["description"] =
$("#editserver-descinput").val().length == 0
? value["description"]
: $("#editserver-descinput").val();
value["ip"] =
$("#editserver-ipinput").val().length == 0
? value["ip"]
: $("#editserver-ipinput").val();
value["version"] = $(
"#editserver-versionselect option:selected"
).text();
}
});
remotefs.writeFileSync(serversPath, JSON.stringify(jsonToModify, null, 4));
loadServerList();
}
function deleteServer() {
var jsonToModify = JSON.parse(remotefs.readFileSync(serversPath));
var result = jsonToModify["servers"].filter(function (obj) {
return obj.uuid === getSelectedServer();
})[0];
var resultindex = jsonToModify["servers"].indexOf(result);
jsonToModify["servers"].splice(resultindex, 1);
remotefs.writeFileSync(serversPath, JSON.stringify(jsonToModify, null, 4));
loadServerList();
}
function restoreDefaultServers() {
remotefs.copySync(
path.join(__dirname, "/defaults/servers.json"),
serversPath
);
loadServerList();
}
function validateVersionSave(modalName) {
// works everytime a key is entered into the version save form
var nameInput = document.getElementById(modalName + "version-nameinput");
var urlInput = document.getElementById(modalName + "version-urlinput");
var button = document.getElementById(modalName + "version-savebutton");
var valid = true;
nameInput.classList.remove("invalidinput");
urlInput.classList.remove("invalidinput");
var matchingVersions = versionArray.filter(function (obj) {
return obj.name === nameInput.value;
});
var allowedMatches = (modalName === "edit") ? 1 : 0;
if (
matchingVersions.length > allowedMatches ||
!(new RegExp(nameInput.getAttribute("pattern"))).test(nameInput.value)
) {
nameInput.classList.add("invalidinput");
valid = false;
}
if (!(new RegExp(urlInput.getAttribute("pattern"))).test(urlInput.value)) {
urlInput.classList.add("invalidinput");
valid = false;
}
if (valid) {
button.removeAttribute("disabled");
} else {
button.setAttribute("disabled", "");
}
}
function addVersion() {
var jsonToModify = JSON.parse(remotefs.readFileSync(versionsPath));
var version = {};
version["name"] =
$("#addversion-nameinput").val().length == 0
? "custom-build-" + uuidv4().substring(0, 8)
: $("#addversion-nameinput").val();
version["url"] =
$("#addversion-urlinput").val().length == 0
? cdnString + "/" + version["name"] + "/"
: $("#addversion-urlinput").val();
var matchingVersions = jsonToModify["versions"].filter(function (obj) {
return obj.name === version["name"];
});
if (matchingVersions.length > 0) return;
jsonToModify["versions"].unshift(version);
remotefs.writeFileSync(versionsPath, JSON.stringify(jsonToModify, null, 4));
loadCacheList();
handleCache("hash-check", version["name"]);
}
function editVersion() {
var jsonToModify = JSON.parse(remotefs.readFileSync(versionsPath));
var editedVersionString = null;
$.each(jsonToModify["versions"], function (key, value) {
if (value["name"] == getSelectedVersion() && !defaultHashes.hasOwnProperty(value["name"])) {
value["name"] =
$("#editversion-nameinput").val().length == 0
? value["name"]
: $("#editversion-nameinput").val();
value["url"] =
$("#editversion-urlinput").val().length == 0
? value["url"]
: $("#editversion-urlinput").val();
editedVersionString = value["name"];
}
});
if (!editedVersionString) return;
remotefs.writeFileSync(versionsPath, JSON.stringify(jsonToModify, null, 4));
loadCacheList();
handleCache("hash-check", editedVersionString);
}
function deleteVersion() {
var jsonToModify = JSON.parse(remotefs.readFileSync(versionsPath));
var result = jsonToModify["versions"].filter(function (obj) {
return obj.name === getSelectedVersion();
})[0];
if (defaultHashes.hasOwnProperty(result.name)) return;
var resultindex = jsonToModify["versions"].indexOf(result);
jsonToModify["versions"].splice(resultindex, 1);
remotefs.writeFileSync(versionsPath, JSON.stringify(jsonToModify, null, 4));
loadCacheList();
delete cacheSizes[result.name];
}
function restoreDefaultVersions() {
remotefs.copySync(
path.join(__dirname, "/defaults/versions.json"),
versionsPath
);
loadCacheList();
handleCache("hash-check");
}
function editConfig() {
var jsonToModify = JSON.parse(remotefs.readFileSync(configPath));
jsonToModify["autoupdate-check"] = $("#editconfig-autoupdate").prop("checked");
jsonToModify["cache-swapping"] = $("#editconfig-cacheswapping").prop("checked");
jsonToModify["enable-offline-cache"] = $("#editconfig-enableofflinecache").prop("checked");
jsonToModify["verify-offline-cache"] = $("#editconfig-verifyofflinecache").prop("checked");
var dirInput = $("#editconfig-offlinecachelocation:text").val();
var shouldChangeRoot = (
remotefs.existsSync(dirInput) &&
remotefs.statSync(dirInput).isDirectory()
);
jsonToModify["offline-cache-location"] = shouldChangeRoot ? dirInput : offlineRoot;
remotefs.writeFileSync(configPath, JSON.stringify(jsonToModify, null, 4));
loadConfig();
// check all offline caches if the offline root changes
if (shouldChangeRoot) handleCache("hash-check", null, "offline");
}
function validateCacheLocation() {
var input = document.getElementById("editconfig-offlinecachelocation");
var button = document.getElementById("editconfig-savebutton");
input.classList.remove("invalidinput");
button.removeAttribute("disabled");
if (!remotefs.existsSync(input.value) || !remotefs.statSync(input.value).isDirectory()) {
input.classList.add("invalidinput");
button.setAttribute("disabled", "");
}
}
function loadGameVersions() {
var versionJson = remotefs.readJsonSync(versionsPath);
versionArray = versionJson["versions"];
$("#addserver-versionselect").empty();
$("#editserver-versionselect").empty();
$.each(versionArray, function (key, value) {
$(new Option(value.name, "val")).appendTo("#addserver-versionselect");
$(new Option(value.name, "val")).appendTo("#editserver-versionselect");
});
}
function loadConfig() {
// Load config object globally
config = remotefs.readJsonSync(configPath);
$("#editconfig-autoupdate").prop("checked", config["autoupdate-check"]);
$("#editconfig-cacheswapping").prop("checked", config["cache-swapping"]);
$("#editconfig-enableofflinecache").prop("checked", config["enable-offline-cache"]);
$("#editconfig-verifyofflinecache").prop("checked", config["verify-offline-cache"]);
// alter offline root globally
offlineRoot = config["offline-cache-location"] || offlineRootDefault;
$("#editconfig-offlinecachelocation:text").val(offlineRoot);
validateCacheLocation();
}
function loadServerList() {
var serverJson = remotefs.readJsonSync(serversPath);
serverArray = serverJson["servers"];
deselectServer(); // Remove selection and disable buttons until another server is selected
$(".server-listing-entry").remove(); // Clear out old stuff, if any
if (serverArray.length > 0) {
// Servers were found in the JSON
$("#server-listing-placeholder").attr("hidden", true);
$.each(serverArray, function (key, value) {
// Create the row, and populate the cells
var row = document.createElement("tr");
row.className = "server-listing-entry";
row.setAttribute("id", value.uuid);
var cellName = document.createElement("td");
cellName.textContent = value.description;
var cellVersion = document.createElement("td");
cellVersion.textContent = value.version;
cellVersion.className = "text-monospace";
row.appendChild(cellName);
row.appendChild(cellVersion);
$("#server-tablebody").append(row);
});
} else {
// No servers are added, make sure placeholder is visible
$("#server-listing-placeholder").attr("hidden", false);
}
}
function loadCacheList() {
// we might want to use a new version right away, so reload them
loadGameVersions();
// load default hashes.json for reference while running the cache handler
if (!defaultHashes) {
defaultHashes = remotefs.readJsonSync(path.join(
__dirname,
"/defaults/hashes.json"
));
}
deselectVersion(); // Remove selection and disable buttons until another server is selected
$(".cache-listing-entry").remove(); // Clear out old stuff, if any
$.each(versionArray, function (key, value) {
var row = document.createElement("tr");
row.className = "cache-listing-entry"
row.setAttribute("id", value.name);
var cellVersion = document.createElement("td");
cellVersion.textContent = value.name;
cellVersion.className = "text-monospace";
var cellPlayableCache = getCacheInfoCell(value.name, "playable");
var cellOfflineCache = getCacheInfoCell(value.name, "offline");
row.appendChild(cellVersion);
row.appendChild(cellPlayableCache);
row.appendChild(cellOfflineCache);
$("#cache-tablebody").append(row);
});
// simulate a cache handler run so that the buttons update properly
storageLoadingStart();
storageLoadingUpdate(cacheSizes);
storageLoadingComplete(cacheSizes);
}
function getCacheElemID(versionString, cacheMode, elementName) {
return [versionString, cacheMode, "cache", elementName].filter(function (value) {
return typeof value !== "undefined";
}).join("-");
}
function getCacheButtonID(versionString, cacheMode, buttonMode) {
return [getCacheElemID(versionString, cacheMode), buttonMode, "button"].join("-");
}
function getCacheLabelText(sizes) {
if (!sizes || sizes.total === 0)
return "?.?? GB / ?.?? GB";
var gb = 1 << 30;
var labelText = (sizes.intact / gb).toFixed(2) + " / " + (sizes.total / gb).toFixed(2) + " GB";
if (sizes.altered > 0) {
labelText += "<br/>(" + (sizes.altered / gb).toFixed(2) + " GB Altered)";
}
return labelText;
}
function getCacheInfoCell(versionString, cacheMode) {
var divID = getCacheElemID(versionString, cacheMode, "div");
var labelID = getCacheElemID(versionString, cacheMode, "label");
var settings = {
download: {
icon: "fas fa-download",
class: "btn btn-success mr-1",
tooltip: "Download Cache"
},
fix: {
icon: "fas fa-hammer",
class: "btn btn-warning mr-1",
tooltip: "Fix Altered Files in Cache"
},
delete: {
icon: "fas fa-trash-alt",
class: "btn btn-danger mr-1",
tooltip: "Delete Cache"
}
};
var cellCache = document.createElement("td");
var divCacheAll = document.createElement("div");
var labelCache = document.createElement("label");
labelCache.setAttribute("id", labelID);
labelCache.setAttribute("for", divID);
// pull existing info from cacheSizes when available
labelCache.innerHTML = getCacheLabelText(
(cacheSizes && cacheSizes[versionString]) ?
cacheSizes[versionString][cacheMode] :
null
);
var divCacheButtons = document.createElement("div");
divCacheButtons.setAttribute("id", labelID);
$.each(settings, function (buttonMode, config) {
// only delete allowed for playable game caches
if (cacheMode === "playable" && buttonMode !== "delete") {
return;
}
var buttonID = getCacheButtonID(versionString, cacheMode, buttonMode);
var iconItalic = document.createElement("i");
iconItalic.setAttribute("class", config.icon);
var buttonCache = document.createElement("button");
buttonCache.setAttribute("id", buttonID);
buttonCache.setAttribute("class", config.class);
buttonCache.setAttribute("title", config.tooltip);
buttonCache.setAttribute("type", "button");
// handler setup
buttonCache.setAttribute("onclick", "handleCache(\"" + buttonMode + "\", \"" + versionString + "\", \"" + cacheMode + "\");");
buttonCache.appendChild(iconItalic);
divCacheButtons.appendChild(buttonCache);
});
divCacheAll.appendChild(labelCache);
divCacheAll.appendChild(divCacheButtons);
cellCache.appendChild(divCacheAll);
return cellCache;
}
function storageLoadingStart(vString, cMode) {
// determine which cache versions and modes to visually update
var versionStrings = [];
$.each(versionArray, function (key, value) {
if (vString) {
if (vString === value.name)
versionStrings.push(value.name);
} else {
versionStrings.push(value.name);
}
});
var cacheModes = (cMode) ? [cMode] : ["offline", "playable"];
// deselect and disable the add version button until they are re-enabled
deselectVersion();
disableVersionAddButton();
// turn buttons into spinners
$.each(versionStrings, function (vKey, versionString) {
$.each(cacheModes, function (cKey, cacheMode) {
var buttonDelete = document.getElementById(getCacheButtonID(versionString, cacheMode, "delete"));
var buttonDownload = document.getElementById(getCacheButtonID(versionString, cacheMode, "download"));
var buttonFix = document.getElementById(getCacheButtonID(versionString, cacheMode, "fix"));
if (!buttonDelete) return;
buttonDelete.setAttribute("disabled", "");
buttonDelete.children[0].setAttribute("class", "fas fa-spinner fa-spin fa-fw");
if (cacheMode === "offline") {
buttonDownload.setAttribute("disabled", "");
buttonDownload.children[0].setAttribute("class", "fas fa-spinner fa-spin fa-fw");
buttonFix.setAttribute("disabled", "");
buttonFix.children[0].setAttribute("class", "fas fa-spinner fa-spin fa-fw");
}
});
});
}
function storageLoadingUpdate(allSizes) {
// update cacheSizes and display results
$.each(allSizes, function (versionString, vSizes) {
$.each(vSizes, function (cacheMode, sizes) {
var label = document.getElementById(getCacheElemID(versionString, cacheMode, "label"));
cacheSizes = cacheSizes || {};
cacheSizes[versionString] = cacheSizes[versionString] || {};
cacheSizes[versionString][cacheMode] = sizes || {};
if (!label) return;
label.innerHTML = getCacheLabelText(sizes);
});
});
}
function storageLoadingComplete(allSizes) {
// re-enable buttons according to the sizes that were read
$.each(allSizes, function (versionString, vSizes) {
$.each(vSizes, function (cacheMode, sizes) {
var buttonDelete = document.getElementById(getCacheButtonID(versionString, cacheMode, "delete"));
var buttonDownload = document.getElementById(getCacheButtonID(versionString, cacheMode, "download"));
var buttonFix = document.getElementById(getCacheButtonID(versionString, cacheMode, "fix"));
if (!buttonDelete) return;
buttonDelete.children[0].setAttribute("class", "fas fa-trash-alt");
if (cacheMode === "offline") {
buttonDownload.children[0].setAttribute("class", "fas fa-download");
buttonFix.children[0].setAttribute("class", "fas fa-hammer");
}
if (sizes.intact > 0 || sizes.altered > 0) {
buttonDelete.removeAttribute("disabled");
if (cacheMode === "offline") {
buttonDownload.setAttribute("disabled", "");
if (sizes.altered > 0 || sizes.intact < sizes.total) {
buttonFix.removeAttribute("disabled");
}
}
} else {
buttonDelete.setAttribute("disabled", "");
if (cacheMode === "offline") {
buttonDownload.removeAttribute("disabled");
buttonFix.setAttribute("disabled", "");
}
}
});
});
// finally, re-enable the version add button
enableVersionAddButton();
}
function handleCache(operation, versionString, cacheMode, callback) {
// see if any versions match (could be undefined or null)
var versions = versionArray.filter(function (obj) {
return obj.name === versionString;
});
// pull version url from the found object, if none found, use the default cdn link
var cdnRoot = (versions.length === 0) ? cdnString : versions[0].url;
var lastSizes = { intact: 0, altered: 0, total: 0 };
var buf = "";
// start loading on the given version and mode (could be undefined or null, which means 'all')
storageLoadingStart(versionString, cacheMode);
// create the server and socket listener
var server = net.createServer(function (sock) {
sock.setEncoding("utf8");
sock.on("data", function (data) {
// read data until the next \n, and keep reading
// sometimes the updates are buffered, so there might be multiple objects
// per update, and partial objects as well
// buffer parsing allows us to handle these cases
buf += data;
var end = buf.indexOf("\n");
while (end > 0) {
var sub = buf.substring(0, end);
buf = buf.substring(end + 1);
// run a storage update here
lastSizes = JSON.parse(sub);
storageLoadingUpdate(lastSizes);
end = buf.indexOf("\n");
}
});
});
// start listening on a randomly acquired port, and spawn cache handler when ready
server.listen(0, "localhost", function () {
spawn(
path.join(__dirname, "lib", "cache_handler.exe"),
[
"--operation", operation,
// roots below contain version-agnostic main directories for caches
"--playable-root", cacheRoot,
"--offline-root", offlineRoot,
"--user-dir", userData,
// CDN root contains version-specific directory, unless cacheMode is "all"
"--cdn-root", cdnRoot,
"--cache-mode", cacheMode || "all",
"--cache-version", versionString || "all",
// learn port from the server object and tell the script where to connect
"--port", server.address().port,
// tell the script which versions and caches are official
"--official-caches"
].concat(Object.keys(defaultHashes)),
{
stdio: "inherit"
}
).on("exit", function (code, signal) {
if (code !== 0 || signal) {
dialog.showErrorBox(
"Sorry!",
"Process \"" + operation + "\" failed with code " + code + " and signal " + signal + "."
);
}
// when the script exits, close the server
server.close();
// set button state accordingly
storageLoadingComplete(lastSizes);
// then run the given callback (if any)
if (callback) callback(lastSizes);
});
});
}
function performCacheSwap(newVersion) {
var currentCache = path.join(cacheRoot, "FusionFall");
var newCache = path.join(cacheRoot, newVersion);
var record = path.join(userData, ".lastver");
// If cache renaming would result in a no-op (ex. launching the same version
// two times), then skip it. This avoids permissions errors with multiple clients
// (file/folder is already open in another process)
var skip = false;
if (remotefs.existsSync(currentCache)) {
// Cache already exists, find out what version it belongs to
if (remotefs.existsSync(record)) {
var lastVersion = remotefs.readFileSync(record, (encoding = "utf8"));
if (lastVersion != newVersion) {
// Remove the directory we're trying to store the
// existing cache to if it already exists for whatever
// reason, as it would cause an EPERM error otherwise.
// This is a no-op if the directory doesn't exist
remotefs.removeSync(path.join(cacheRoot, lastVersion));
// Store old cache to named directory
remotefs.renameSync(
currentCache,
path.join(cacheRoot, lastVersion)
);
} else {
console.log("Cached version unchanged, skipping rename");
skip = true;
}
console.log("Current cache is " + lastVersion);
}
}
// Make note of what version we are launching for next launch
remotefs.writeFileSync(record, newVersion);
if (remotefs.existsSync(newCache) && !skip) {
// Rename saved cache to FusionFall
remotefs.renameSync(newCache, currentCache);
console.log("Current cache swapped to " + newVersion);
}
}
function prepGameInfo(serverUUID) {
var serverInfo = serverArray.filter(function (obj) {
return obj.uuid === serverUUID;
})[0];
var versionInfo = versionArray.filter(function (obj) {
return obj.name === serverInfo.version;
})[0];
// If cache swapping property exists AND is `true`, run cache swapping logic
if (config["cache-swapping"]) {
try {
performCacheSwap(versionInfo.name);
} catch (ex) {
console.log(
"Error when swapping cache, it may get overwritten:\n" + ex
);
}
}
if (!config["enable-offline-cache"]) {
// if we always ignore the offline cache, just use the URL
setGameInfo(serverInfo, versionInfo.url);
return;
}
var offlinePath = path.join(offlineRoot, versionInfo.name);
var offlineURL = "file:///" + offlinePath.replace(/\\/g, "/") + "/";
if (config["verify-offline-cache"]) {
// if required, do a full hash check, and use the offline cache only if it is fully intact
handleCache("hash-check", versionInfo.name, "offline", function (sizes) {
var versionURL = (sizes.intact < sizes.total) ? versionInfo.url : offlineURL;
setGameInfo(serverInfo, versionURL);
});
return;
}
// otherwise, if main.unity3d is present, use the offline cache
var mainPath = path.join(offlinePath, "main.unity3d");
var versionURL = !remotefs.existsSync(mainPath) ? versionInfo.url : offlineURL;
setGameInfo(serverInfo, versionURL);
}
// For writing loginInfo.php, assetInfo.php, etc.
function setGameInfo(serverInfo, versionURL) {
// slash fix if people mess it up via text editors
var versionURLRoot = versionURL.endsWith("/") ? versionURL : versionURL + "/";
window.assetUrl = versionURLRoot; // game-client.js needs to access this
console.log("Cache will expand from " + versionURLRoot);
remotefs.writeFileSync(path.join(__dirname, "assetInfo.php"), assetUrl);
if (serverInfo.hasOwnProperty("endpoint")) {
var httpEndpoint = serverInfo.endpoint.replace("https://", "http://");
remotefs.writeFileSync(
path.join(__dirname, "rankurl.txt"),
httpEndpoint + "getranks"
);
// Write these out too
remotefs.writeFileSync(
path.join(__dirname, "sponsor.php"),
httpEndpoint + "upsell/sponsor.png"
);
remotefs.writeFileSync(
path.join(__dirname, "images.php"),
httpEndpoint + "upsell/"
);
} else {
// Remove/default the endpoint related stuff, this server won't be using it
if (remotefs.existsSync(path.join(__dirname, "rankurl.txt"))) {
remotefs.unlinkSync(path.join(__dirname, "rankurl.txt"));
remotefs.writeFileSync(
path.join(__dirname, "sponsor.php"),
"assets/img/welcome.png"
);
remotefs.writeFileSync(
path.join(__dirname, "images.php"),
"assets/img/"
);
}
}
// Server address parsing
var address;
var port;
var sepPos = serverInfo.ip.indexOf(":");
if (sepPos > -1) {
address = serverInfo.ip.substr(0, sepPos);
port = serverInfo.ip.substr(sepPos + 1);
} else {
address = serverInfo.ip;
port = 23000; // default
}
// DNS resolution. there is no synchronous version for some stupid reason
if (!address.match(/^[0-9.]+$/)) {
dns.lookup(address, (family = 4), function (err, resolvedAddress) {
if (!err) {
console.log("Resolved " + address + " to " + resolvedAddress);
address = resolvedAddress;
} else {
console.log("Err: " + err.code);
}
prepConnection(address, port);
});
} else {
console.log(address + " is an IP; skipping DNS lookup");
prepConnection(address, port);
}
}
function prepConnection(address, port) {
var full = address + ":" + port;
console.log("Will connect to " + full);
remotefs.writeFileSync(path.join(__dirname, "loginInfo.php"), full);
launchGame();
}
// Returns the UUID of the server with the selected background color.
// Yes, there are probably better ways to go about this, but it works well enough.
function getSelectedServer() {
return $("#server-tablebody > tr.bg-primary").prop("id");
}
// Returns the name of the version with the selected background color.
function getSelectedVersion() {
return $("#cache-tablebody > tr.bg-primary").prop("id");
}
function connectToServer() {
// Get ID of the selected server, which corresponds to its UUID in the json
console.log("Connecting to server with UUID of " + getSelectedServer());
// Prevent the user from clicking anywhere else during the transition
$("body,html").css("pointer-events", "none");
stopEasterEggs();
$("#of-serverselector").fadeOut("slow", function () {
setTimeout(function () {
$("body,html").css("pointer-events", "");
prepGameInfo(getSelectedServer());
}, 200);
});
}
// If applicable, deselect currently selected server.
function deselectServer() {
disableServerListButtons();
$(".server-listing-entry").removeClass("bg-primary");
}
// If applicable, deselect currently selected version.
function deselectVersion() {
disableVersionListButtons();
$(".cache-listing-entry").removeClass("bg-primary");
}
// Select a server
$("#server-table").on("click", ".server-listing-entry", function (event) {
enableServerListButtons();
$(this).addClass("bg-primary").siblings().removeClass("bg-primary");
});
// Select a version (if allowed)
$("#cache-table").on("click", ".cache-listing-entry", function (event) {
// wait for the add button to be re-enabled first
if ($("#of-addversion-button").prop("disabled")) return;
// do not select default builds
if (defaultHashes.hasOwnProperty($(this).attr("id"))) return;
enableVersionListButtons();
$(this).addClass("bg-primary").siblings().removeClass("bg-primary");
});
// QoL feature: if you double click on a server it will connect
$("#server-table").on("dblclick", ".server-listing-entry", function (event) {
$(this).addClass("bg-primary").siblings().removeClass("bg-primary");
connectToServer();
});
$("#of-addservermodal").on("show.bs.modal", function (e) {
validateServerSave("add");
});
$("#of-addversionmodal").on("show.bs.modal", function (e) {
validateVersionSave("add");
});
$("#of-editservermodal").on("show.bs.modal", function (e) {
// populate the edit modal with existing values
var jsonToModify = remotefs.readJsonSync(serversPath);
$.each(jsonToModify["servers"], function (key, value) {
if (value["uuid"] == getSelectedServer()) {
$("#editserver-descinput")[0].value = value["description"];
$("#editserver-ipinput")[0].value = value["ip"];
var versionIndex = -1;
$.each($("#editserver-versionselect")[0], function (key, val) {
if (val.text === value["version"]) {
versionIndex = key;
}
});
$("#editserver-versionselect")[0].selectedIndex = versionIndex;
}
});
validateServerSave("edit");
});
$("#of-editversionmodal").on("show.bs.modal", function (e) {
// populate the edit modal with existing values
var jsonToModify = remotefs.readJsonSync(versionsPath);
$.each(jsonToModify["versions"], function (key, value) {
if (value["name"] == getSelectedVersion()) {
$("#editversion-nameinput")[0].value = value["name"];
$("#editversion-urlinput")[0].value = value["url"];
}
});
validateVersionSave("edit");
});
// Replace server name to delete
$("#of-deleteservermodal").on("show.bs.modal", function (e) {
var result = serverArray.filter(function (obj) {
return obj.uuid === getSelectedServer();
})[0];
$("#deleteserver-servername").html(result.description);
});
// Replace version name to delete
$("#of-deleteversionmodal").on("show.bs.modal", function (e) {
var result = versionArray.filter(function (obj) {
return obj.name === getSelectedVersion();
})[0];
$("#deleteversion-versionname").html(result.name);
});
// Run the global hash check once and only if the cache modal is ever shown
$("#of-editcacheconfigmodal").on("show.bs.modal", function (e) {
if (!cacheSizes) handleCache("hash-check");
});
// Keep all config values synced on modal show
// Avoids cases where people forget that they changed the offline root but did not save
$("#of-editconfigmodal").on("show.bs.modal", function (e) {
loadConfig();
});

View File

@ -1,237 +0,0 @@
var remote = require("remote");
var remotefs = remote.require('fs-extra');
var userdir = remote.require('app').getPath('userData');
var versionarray
var serverarray
var config
function enableServerListButtons() {
$('#of-connect-button').removeClass('disabled');
$('#of-connect-button').prop('disabled', false);
$('#of-editserver-button').removeClass('disabled');
$('#of-editserver-button').prop('disabled', false);
$('#of-deleteserver-button').removeClass('disabled');
$('#of-deleteserver-button').prop('disabled', false);
}
function disableServerListButtons() {
$('#of-connect-button').addClass('disabled');
$('#of-connect-button').prop('disabled', true);
$('#of-editserver-button').addClass('disabled');
$('#of-editserver-button').prop('disabled', true);
$('#of-deleteserver-button').addClass('disabled');
$('#of-deleteserver-button').prop('disabled', true);
}
function addServer() {
var jsontomodify = JSON.parse(remotefs.readFileSync(userdir+"\\servers.json"));
var server = {};
server['uuid'] = uuidv4();
server['description'] = $("#addserver-descinput").val().length == 0 ? "My OpenFusion Server" : $("#addserver-descinput").val();
server['ip'] = $("#addserver-ipinput").val().length == 0 ? "127.0.0.1:23000" : $("#addserver-ipinput").val();
server['version'] = $("#addserver-versionselect option:selected").text();
//server['endpoint'] =
jsontomodify['servers'].push(server)
remotefs.writeFileSync(userdir+"\\servers.json", JSON.stringify(jsontomodify, null, 4));
loadServerList();
}
function editServer() {
var jsontomodify = JSON.parse(remotefs.readFileSync(userdir+"\\servers.json"));
$.each(jsontomodify["servers"], function( key, value ) {
if(value["uuid"] == getSelectedServer()) {
value['description'] = $("#editserver-descinput").val().length == 0 ? value['description'] : $("#editserver-descinput").val();
value['ip'] = $("#editserver-ipinput").val().length == 0 ? value['ip'] : $("#editserver-ipinput").val();
value['version'] = $("#editserver-versionselect option:selected").text();
}
});
remotefs.writeFileSync(userdir+"\\servers.json", JSON.stringify(jsontomodify, null, 4));
loadServerList();
}
function deleteServer() {
var jsontomodify = JSON.parse(remotefs.readFileSync(userdir+"\\servers.json"));
var result = jsontomodify['servers'].filter(function(obj) {return (obj.uuid === getSelectedServer())})[0];
var resultindex = jsontomodify['servers'].indexOf(result);
jsontomodify['servers'].splice(resultindex, 1);
remotefs.writeFileSync(userdir+"\\servers.json", JSON.stringify(jsontomodify, null, 4));
loadServerList();
}
function restoreDefaultServers() {
remotefs.copySync(__dirname+"\\defaults\\servers.json", userdir+"\\servers.json");
loadServerList();
}
function loadGameVersions() {
var versionjson = JSON.parse(remotefs.readFileSync(userdir+"\\versions.json"));
versionarray = versionjson['versions'];
$.each(versionarray, function( key, value ) {
$(new Option(value.name, 'val')).appendTo('#addserver-versionselect');
$(new Option(value.name, 'val')).appendTo('#editserver-versionselect');
});
}
function loadConfig() {
// load config object globally
config = JSON.parse(remotefs.readFileSync(userdir+"\\config.json"));
}
function loadServerList() {
var serverjson = JSON.parse(remotefs.readFileSync(userdir+"\\servers.json"));
serverarray = serverjson['servers'];
$(".server-listing-entry").remove(); // Clear out old stuff, if any
disableServerListButtons(); // Disable buttons until another server is selected
if (serverarray.length > 0) {
// Servers were found in the JSON
$("#server-listing-placeholder").attr("hidden",true);
$.each(serverarray, function( key, value ) {
// Create the row, and populate the cells
var row = document.createElement('tr');
row.className = 'server-listing-entry'
row.setAttribute('id', value.uuid);
var cellName = document.createElement('td');
cellName.textContent = value.description
var cellVersion = document.createElement('td');
cellVersion.textContent = value.version
cellVersion.className = 'text-monospace'
row.appendChild(cellName);
row.appendChild(cellVersion);
$("#server-tablebody").append(row);
});
} else {
// No servers are added, make sure placeholder is visible
$("#server-listing-placeholder").attr("hidden",false);
}
}
// For writing loginInfo.php, assetInfo.php, etc.
function setGameInfo(serverUUID) {
var result = serverarray.filter(function(obj) {return (obj.uuid === serverUUID);})[0];
var gameversion = versionarray.filter(function(obj) {return (obj.name === result.version);})[0];
if(config['cache-swapping']) { // if cache swapping property exists AND is `true`, run cache swapping logic
// Cache folder renaming
var cachedir = userdir + '\\..\\..\\LocalLow\\Unity\\Web Player\\Cache';
var curversion = cachedir + '\\Fusionfall';
var newversion = cachedir + '\\' + gameversion.name;
var record = userdir + '\\.lastver';
if (remotefs.existsSync(curversion)) {
// cache already exists
// find out what version it belongs to
if (remotefs.existsSync(record)) {
var lastversion = remotefs.readFileSync(record);
remotefs.renameSync(curversion, cachedir + '\\' + lastversion);
console.log('Cached version ' + lastversion);
} else {
console.log(
"Couldn't find last version record; cache may get overwritten"
);
}
}
if (remotefs.existsSync(newversion)) {
// rename saved cache to FusionFall
remotefs.renameSync(newversion, curversion);
console.log('Loaded cached ' + gameversion.name);
}
// make note of what version we are launching for next launch
remotefs.writeFileSync(record, gameversion.name);
}
window.asseturl = gameversion.url; // gameclient.js needs to access this
remotefs.writeFileSync(__dirname+"\\assetInfo.php", asseturl);
remotefs.writeFileSync(__dirname+"\\loginInfo.php", result.ip);
if (result.hasOwnProperty('endpoint')) {
var httpendpoint = result.endpoint.replace("https://", "http://")
remotefs.writeFileSync(__dirname+"\\rankurl.txt", httpendpoint+"getranks");
// Write these out too
remotefs.writeFileSync(__dirname+"\\sponsor.php", httpendpoint+"upsell/sponsor.png");
remotefs.writeFileSync(__dirname+"\\images.php", httpendpoint+"upsell/");
} else {
// Remove/default the endpoint related stuff, this server won't be using it
if (remotefs.existsSync(__dirname+"\\rankurl.txt")) {
remotefs.unlinkSync(__dirname+"\\rankurl.txt");
remotefs.writeFileSync(__dirname+"\\sponsor.php", "assets/img/welcome.png");
remotefs.writeFileSync(__dirname+"\\images.php", "assets/img/");
}
}
}
// Returns the UUID of the server with the selected background color.
// Yes, there are probably better ways to go about this, but it works well enough.
function getSelectedServer() {
return $("#server-tablebody > tr.bg-primary").prop("id");
}
function connectToServer() {
// Get ID of the selected server, which corresponds to its UUID in the json
console.log("Connecting to server with UUID of " + getSelectedServer());
// Prevent the user from clicking anywhere else during the transition
$('body,html').css('pointer-events','none');
stopEasterEggs();
$('#of-serverselector').fadeOut('slow', function() {
setTimeout(function(){
$('body,html').css('pointer-events','');
setGameInfo(getSelectedServer());
launchGame();
}, 200);
});
}
// If applicable, deselect currently selected server.
function deselectServer() {
disableServerListButtons();
$(".server-listing-entry").removeClass('bg-primary');
}
$('#server-table').on('click', '.server-listing-entry', function(event) {
enableServerListButtons();
$(this).addClass('bg-primary').siblings().removeClass('bg-primary');
});
// QoL feature: if you double click on a server it will connect
$('#server-table').on('dblclick', '.server-listing-entry', function(event) {
$(this).addClass('bg-primary').siblings().removeClass('bg-primary');
connectToServer();
});
$('#of-editservermodal').on('show.bs.modal', function (e) {
var jsontomodify = JSON.parse(remotefs.readFileSync(userdir+"\\servers.json"));
$.each(jsontomodify["servers"], function( key, value ) {
if(value["uuid"] == getSelectedServer()) {
$("#editserver-descinput")[0].value = value['description'];
$("#editserver-ipinput")[0].value = value['ip'];
var versionIndex = -1;
$.each($("#editserver-versionselect")[0], function( key, val ) {
if(val.text === value['version']) {
versionIndex = key;
}
});
$("#editserver-versionselect")[0].selectedIndex = versionIndex;
}
});
});
$('#of-deleteservermodal').on('show.bs.modal', function (e) {
var result = serverarray.filter(function(obj) {return (obj.uuid === getSelectedServer());})[0];
$("#deleteserver-servername").html(result.description);
});

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity type="win32" name="OpenFusion.Client" version="1.5.2.0" processorArchitecture="x86" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="Win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*">
</assemblyIdentity>
</dependentAssembly>
</dependency>
<asmv3:trustInfo>
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
</requestedPrivileges>
</security>
</asmv3:trustInfo>
<asmv3:application>
<asmv3:windowsSettings>
<activeCodePage xmlns="urn:schemas-microsoft-com:smi.2019.WindowsSettings">UTF-8</activeCodePage>
<dpiAware xmlns="urn:schemas-microsoft-com:smi.2005.WindowsSettings">True/PM</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></supportedOS>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"></supportedOS>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"></supportedOS>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>
</application>
</compatibility>
</asmv1:assembly>

View File

@ -0,0 +1,62 @@
Web Player License Agreement
Last updated: June 21, 2013
PLEASE READ CAREFULLY: BY INSTALLING THE SOFTWARE (AS DEFINED BELOW), YOU (EITHER ON BEHALF OF YOURSELF AS AN INDIVIDUAL OR ON BEHALF OF AN ENTITY AS ITS AUTHORIZED REPRESENTATIVE) AGREE TO ALL OF THE TERMS OF THIS END USER LICENSE AGREEMENT REGARDING THE USE OF THE SOFTWARE.
1. GRANT OF LICENSE:
You may install this Software on your computer to experience Unity web content.
2. TITLE:
You acknowledge that no title to the intellectual property in the Software is transferred to you. Title, ownership, rights, and intellectual property rights in and to the Software shall remain that of Unity Technologies. The Software is protected by copyright laws of the United States and international treaties.
3. ANONYMOUS USAGE STATISTICS:
You accept that the first time the Unity Web Player is used, anonymous information about the computer it's loaded on is submitted to Unity Technologies ApS. This only happens once time, and contains no personally identifiable information. The information submitted is:
(a) Operating system and version
(b) The make of the CPU, and number of CPUs present
(c) The graphics card type and vendor name
(d) Graphics card driver name and version (example: "nv4disp.dll 6.10.93.71")
(e) Which graphics API is in use (example: "OpenGL 2.1" or "Direct3D 9.0c")
(f) Amount of system and video RAM present
(g) Current desktop resolution
(h) Version of the Unity Web Player
(i) A number describing whether running on Mac or Windows
(j) A checksum of all the data that gets sent to verify that it did transmit correctly
3. DISTRIBUTION:
You acknowledge that only Unity Technologies ApS and its designated distribution partners may distribute the Unity Web Player, without a special permission.
4. CEASE OF DISTRIBUTION:
In case Unity Technologies ApS and its designated distribution partners permanently cease to distribute the Unity Web Player, versions of the Unity Web Player that have previously been distributed by Unity Technologies ApS become freely redistributable.
5. DISCLAIMER OF WARRANTY:
YOU AGREE THAT UNITY TECHNOLOGIES APS HAS MADE NO EXPRESS WARRANTIES, ORAL OR WRITTEN, TO YOU REGARDING THE PRODUCTS AND THAT THE PRODUCTS ARE BEING PROVIDED TO YOU 'AS IS' WITHOUT WARRANTY OF ANY KIND. UNITY TECHNOLOGIES APS DISCLAIMS ANY AND ALL OTHER WARRANTIES, WHETHER EXPRESSED, IMPLIED, OR STATUTORY. YOUR RIGHTS MAY VARY DEPENDING ON THE STATE IN WHICH YOU LIVE. UNITY TECHNOLOGIES APS SHALL NOT BE LIABLE FOR INDIRECT, INCIDENTAL, SPECIAL, COVER, RELIANCE, OR CONSEQUENTIAL DAMAGES RESULTING FROM THE USE OF THIS PRODUCT.
6. LIMITATION OF LIABILITY:
YOU USE THIS PROGRAM SOLELY AT YOUR OWN RISK. IN NO EVENT SHALL UNITY TECHNOLOGIES APS BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING BUT NOT LIMITED TO ANY LOSS, OR OTHER INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND ARISING OUT OF THE USE OF THE SOFTWARE, EVEN IF UNITY TECHNOLOGIES APS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO EVENT WILL UNITY TECHNOLOGIES APS BE LIABLE FOR ANY CLAIM, WHETHER IN CONTRACT, TORT, OR ANY OTHER THEORY OF LIABILITY, EXCEED THE COST OF THE SOFTWARE. THIS LIMITATION SHALL APPLY TO CLAIMS OF PERSONAL INJURY TO THE EXTENT PERMITTED BY LAW.
7. TERMINATION:
This Agreement shall terminate automatically if you fail to comply with the limitations described in this Agreement. No notice shall be required to effectuate such termination. Upon termination, you must remove and destroy all copies of the Software.
8. MISCELLANEOUS:
Severability: In the event of invalidity of any provision of this Agreement, the parties agree that such invalidity shall not affect the validity of the remaining portions of this Agreement.
Export: You agree that you will not export or re-export the Software outside of the jurisdiction in which you obtained it without the appropriate United States or foreign government licenses.
Governing Law: This Agreement will be governed by the laws of the State of Denmark as they are applied to agreements between Denmark residents entered into and to be performed entirely within Denmark. The United Nations Convention on Contracts for the International Sale of Goods is specifically disclaimed.
Entire Agreement: You agree that this is the entire agreement between you and Unity Technologies ApS, which supersedes any prior agreement, whether written or oral, and all other communications between Unity Technologies ApS and you relating to the subject matter of this Agreement.
Reservation of rights: All rights not expressly granted in this Agreement are reserved by Unity Technologies ApS.
Derivative work: Whether you are licensing the Software as an individual or on behalf of an entity, you may not: (a) reverse engineer, decompile, or disassemble the Software or attempt to discover the source code; (b) modify, or create derivative works based upon, the Software in whole or in part without the express written consent of Unity Technologies ApS; (c) distribute copies of the Software; (d) remove any proprietary notices or labels on the Software; (e) resell, lease, rent, transfer, sublicense, or otherwise transfer rights to the Software.

View File

@ -2,8 +2,8 @@
<plist>
<dict>
<key>CFBundleVersion</key>
<string>3.5.2f2</string>
<string>2.5.5b4</string>
<key>UnityBuildNumber</key>
<string>4c6ee796dacc</string>
<string>50</string>
</dict>
</plist>

28
build/after-pack.js Normal file
View File

@ -0,0 +1,28 @@
const fs = require('fs');
const defaultDir = './dist/win-ia32-unpacked/resources/default_app'
const exeFile = './dist/win-ia32-unpacked/OpenFusionClient.exe'
exports.default = function() {
// remove leftover files from default electron app
fs.rm(defaultDir, { recursive: true }, (err) => {
if (err) {
throw err;
}
});
// patch executable for large address awareness
fs.open(exeFile, "r+", (err, fd) => {
if(!err) {
fs.write(
fd, new Uint8Array([0x22]), 0, 1, 0x166,
(err) => {
if(err) {
throw err;
}
fs.closeSync(fd);
}
);
} else {
throw err;
}
});
}

View File

@ -1,10 +0,0 @@
const fs = require('fs');
const dir = './dist/win-ia32-unpacked/resources/default_app'
exports.default = async function(context) {
fs.rmdir(dir, { recursive: true }, (err) => {
if (err) {
throw err;
}
});
}

Binary file not shown.

View File

@ -1,5 +0,0 @@
PUSHD %~dp0
.\UnityWebPlayer.exe /quiet /S
robocopy WebPlayer "%USERPROFILE%\AppData\LocalLow\Unity\WebPlayer" /s /e
del "%USERPROFILE%\AppData\LocalLow\Unity\WebPlayer\UnityBugReporter.exe"
POPD

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['cache_handler.py'],
pathex=['Z:\\src'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='cache_handler',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True )

View File

@ -0,0 +1,4 @@
aiofiles
httpx
beautifulsoup4
pyinstaller==3.5

View File

@ -1,5 +1,7 @@
{
"autoupdate-check": true,
"cache-swapping": true,
"last-version-initialized": "1.4"
"enable-offline-cache": false,
"verify-offline-cache": false,
"last-version-initialized": "1.6"
}

35695
defaults/hashes.json vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,14 +3,14 @@
{
"uuid": "d9773558-6ddf-4d00-8803-d830a22a842b",
"description": "OpenFusion Public Server - Original",
"ip": "144.202.52.9:23000",
"ip": "play.dexlabs.systems:23000",
"version": "beta-20100104",
"endpoint": "https://api.dexlabs.systems/"
},
{
"uuid": "b84f6859-f500-41f2-bdfa-8e3746639ee9",
"description": "OpenFusion Public Server - Academy",
"ip": "144.202.52.9:24000",
"ip": "play.dexlabs.systems:24000",
"version": "beta-20111013",
"endpoint": "https://api.dexlabs.systems/academy/"
}

File diff suppressed because it is too large Load Diff

247
index.js
View File

@ -1,134 +1,169 @@
var app = require('app'); // Module to control application life.
var ipc = require('ipc');
var fs = require('fs-extra');
var os = require('os');
var dialog = require('dialog');
var BrowserWindow = require('browser-window');
var app = require("app"); // Module to control application life.
var dialog = require("dialog");
var fs = require("fs-extra");
var ipc = require("ipc");
var os = require("os");
var path = require("path");
var BrowserWindow = require("browser-window");
var mainWindow = null;
app.commandLine.appendSwitch('--enable-npapi');
var unityHomeDir = path.join(__dirname, "../../WebPlayer");
// If running in non-packaged / development mode, this dir will be slightly different
if (process.env.npm_node_execpath) {
unityHomeDir = path.join(app.getAppPath(), "/build/WebPlayer");
}
process.env["UNITY_HOME_DIR"] = unityHomeDir;
process.env["UNITY_DISABLE_PLUGIN_UPDATES"] = "yes";
app.commandLine.appendSwitch("enable-npapi");
app.commandLine.appendSwitch(
"load-plugin",
path.join(unityHomeDir, "/loader/npUnity3D32.dll")
);
app.commandLine.appendSwitch("no-proxy-server");
var userData = app.getPath("userData");
var configPath = path.join(userData, "config.json");
var serversPath = path.join(userData, "servers.json");
var versionsPath = path.join(userData, "versions.json");
var hashPath = path.join(userData, "hashes.json");
function initialSetup(firstTime) {
// Display a small window to inform the user that the app is working
setupWindow = new BrowserWindow({width: 275, height: 450, resizable: false, center:true, frame:false});
setupWindow.loadUrl('file://' + __dirname + '/initialsetup.html');
// Exec installUnity.bat and wait for it to finish.
var child = require('child_process').spawn('cmd.exe', ['/c', 'utils\\installUnity.bat']);
child.on('exit', function() {
console.log("Unity installed.");
if(!firstTime) { // migration from pre-1.4
// Back everything up, just in case
fs.copySync(app.getPath('userData')+"\\config.json", app.getPath('userData')+"\\config.json.bak");
fs.copySync(app.getPath('userData')+"\\servers.json", app.getPath('userData')+"\\servers.json.bak");
fs.copySync(app.getPath('userData')+"\\versions.json", app.getPath('userData')+"\\versions.json.bak");
} else { // first-time setup
// Copy default servers
fs.copySync(__dirname+"\\defaults\\servers.json", app.getPath('userData')+"\\servers.json");
if (!firstTime) {
// Migration from pre-1.6
// Back everything up, just in case
if (fs.existsSync(configPath)) fs.copySync(configPath, configPath + ".bak");
if (fs.existsSync(serversPath)) fs.copySync(serversPath, serversPath + ".bak");
if (fs.existsSync(versionsPath)) fs.copySync(versionsPath, versionsPath + ".bak");
if (fs.existsSync(hashPath)) fs.copySync(hashPath, hashPath + ".bak");
} else {
// First-time setup
// Copy default servers
fs.copySync(
path.join(__dirname, "/defaults/servers.json"),
serversPath
);
}
// Copy default versions and config
fs.copySync(__dirname+"\\defaults\\versions.json", app.getPath('userData')+"\\versions.json");
fs.copySync(__dirname+"\\defaults\\config.json", app.getPath('userData')+"\\config.json");
fs.copySync(path.join(__dirname, "/defaults/versions.json"), versionsPath);
fs.copySync(path.join(__dirname, "/defaults/config.json"), configPath);
fs.copySync(path.join(__dirname, "/defaults/hashes.json"), hashPath);
console.log("JSON files copied.");
setupWindow.destroy();
showMainWindow();
})
}
ipc.on("exit", function(id) {
mainWindow.destroy();
ipc.on("exit", function (id) {
mainWindow.destroy();
});
// Quit when all windows are closed.
app.on('window-all-closed', function() {
if (process.platform != 'darwin')
app.quit();
app.on("window-all-closed", function () {
if (process.platform != "darwin") app.quit();
});
app.on('ready', function() {
// Check just in case the user forgot to extract the zip.
zip_check = app.getPath('exe').includes(os.tmpdir());
if (zip_check) {
errormsg =
( "It has been detected that OpenFusionClient is running from the TEMP folder.\n\n"+
"Please extract the entire Client folder to a location of your choice before starting OpenFusionClient.");
dialog.showErrorBox("Error!", errormsg);
return;
}
// Create the browser window.
mainWindow = new BrowserWindow({width: 1280, height: 720, show: false, "web-preferences": {"plugins": true}});
mainWindow.setMinimumSize(640, 480);
// Check for first run
var configPath = app.getPath('userData') + "\\config.json";
try {
if (!fs.existsSync(configPath)) {
console.log("Config file not found. Running initial setup.");
initialSetup(true);
} else {
var config = fs.readJsonSync(configPath);
if(!config['last-version-initialized']) {
console.log("Pre-1.4 config detected. Running migration.");
initialSetup(false);
} else {
showMainWindow();
}
app.on("ready", function () {
// Check just in case the user forgot to extract the zip.
zipCheck = app.getPath("exe").includes(os.tmpdir());
if (zipCheck) {
var errorMessage =
"It has been detected that OpenFusionClient is running from the TEMP folder.\n\n" +
"Please extract the entire Client folder to a location of your choice before starting OpenFusionClient.";
dialog.showErrorBox("Error!", errorMessage);
return;
}
} catch(e) {
console.log("An error occurred while checking for the config.");
}
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1280,
height: 720,
show: false,
"web-preferences": {
plugins: true,
},
});
mainWindow.setMinimumSize(640, 480);
// Makes it so external links are opened in the system browser, not Electron
mainWindow.webContents.on('new-window', function(e, url) {
e.preventDefault();
require('shell').openExternal(url);
});
// Check for first run
try {
if (!fs.existsSync(configPath)) {
console.log("Config file not found. Running initial setup.");
initialSetup(true);
} else {
var config = fs.readJsonSync(configPath);
if (config["last-version-initialized"] !== "1.6") {
console.log("Pre-1.6 config detected. Running migration.");
initialSetup(false);
} else {
showMainWindow();
}
}
} catch (ex) {
dialog.showErrorBox(
"Error!",
"An error occurred while checking for the config. Make sure you have sufficent permissions."
);
app.quit();
}
mainWindow.on('closed', function() {
mainWindow = null;
});
// Makes it so external links are opened in the system browser, not Electron
mainWindow.webContents.on("new-window", function (event, url) {
event.preventDefault();
require("shell").openExternal(url);
});
mainWindow.on("closed", function () {
mainWindow = null;
});
});
function showMainWindow() {
// Load the index.html of the app.
mainWindow.loadUrl('file://' + __dirname + '/index.html');
// Load the index.html of the app.
mainWindow.loadUrl("file://" + __dirname + "/index.html");
// Reduces white flash when opening the program
mainWindow.webContents.on('did-finish-load', function() {
mainWindow.show();
// everything's loaded, tell the renderer process to do its thing
mainWindow.webContents.executeJavaScript("loadConfig();");
mainWindow.webContents.executeJavaScript("loadGameVersions();");
mainWindow.webContents.executeJavaScript("loadServerList();");
});
// Reduces white flash when opening the program
mainWindow.webContents.on("did-finish-load", function () {
mainWindow.webContents.executeJavaScript("setAppVersionText();");
mainWindow.show();
// everything's loaded, tell the renderer process to do its thing
mainWindow.webContents.executeJavaScript("loadConfig();");
mainWindow.webContents.executeJavaScript("loadGameVersions();");
mainWindow.webContents.executeJavaScript("loadServerList();");
mainWindow.webContents.executeJavaScript("loadCacheList();");
});
mainWindow.webContents.on('plugin-crashed', function() {
console.log("Unity Web Player crashed.");
});
mainWindow.webContents.on("plugin-crashed", function () {
var errorMessage =
"Unity Web Player has crashed - please re-open the application.\n" +
"If this error persists, please read the FAQ or ask for support in our Discord server.";
dialog.showErrorBox("Error!", errorMessage);
mainWindow.destroy();
app.quit();
});
mainWindow.webContents.on('will-navigate', function(evt, url) {
evt.preventDefault();
// TODO: showMessageBox rather than showErrorBox?
switch (url) {
case "https://audience.fusionfall.com/ff/regWizard.do?_flowId=fusionfall-registration-flow":
errormsg =
( "The register page is currently unimplemented.\n\n"+
"You can still create an account: type your desired username and password into the provided boxes and click \"Log In\". "+
"Your account will then be automatically created on the server. \nBe sure to remember these details!");
dialog.showErrorBox("Sorry!", errormsg);
break;
case "https://audience.fusionfall.com/ff/login.do":
dialog.showErrorBox("Sorry!", "Account management is not available.");
break;
case "http://forums.fusionfall.com/":
require('shell').openExternal("https://discord.gg/DYavckB");
break;
default:
mainWindow.webContents.loadURL(url);
}
});
mainWindow.webContents.on("will-navigate", function (event, url) {
event.preventDefault();
switch (url) {
case "https://audience.fusionfall.com/ff/regWizard.do?_flowId=fusionfall-registration-flow":
var errorMessage =
"The register page is currently unimplemented.\n\n" +
'You can still create an account: type your desired username and password into the provided boxes and click "Log In". ' +
"Your account will then be automatically created on the server. \nBe sure to remember these details!";
dialog.showErrorBox("Sorry!", errorMessage);
break;
case "https://audience.fusionfall.com/ff/login.do":
dialog.showErrorBox(
"Sorry!",
"Account management is not available."
);
break;
case "http://forums.fusionfall.com/":
require("shell").openExternal("https://discord.gg/DYavckB");
break;
default:
mainWindow.loadUrl(url);
}
});
}

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>OpenFusion: Initial Setup</title>
</head>
<body style="overflow:hidden;background-color:#000;user-select:none;-webkit-user-select:none;">
<center>
<div><img src="assets/img/of-3.png" width="256">
<div>
<img src="assets/img/spinner.gif" width=50px/>
</div>
<div style="margin-top: 15px;">
<p style='text-shadow:1px 1px 8px #4349C4;color:#4A76B7;font-size:18px;font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";'>OpenFusion is setting up...<br>Please wait - this should take <br>less than a minute.</p>
</div>
</div>
</center>
</body>
</html>

BIN
lib/cache_handler.exe vendored Executable file

Binary file not shown.

11453
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +1,79 @@
{
"name": "openfusionclient",
"version": "1.4.0",
"description": "OpenFusionClient",
"main": "index.js",
"scripts": {
"postinstall": "npx patch-package && npm explore electron-prebuilt -- npm run postinstall",
"start": "electron .",
"build": "node build.js",
"pack": "electron-builder --win --ia32 --dir",
"dist": "electron-builder --win --ia32"
},
"author": "OpenFusion Contributors",
"license": "MIT",
"devDependencies": {
"electron-prebuilt": "^0.31.2",
"patch-package": "^6.4.7",
"electron-builder": "^22.10.5"
},
"repository": {
"type": "git",
"url": "https://github.com/OpenFusionProject/Client.git"
},
"build": {
"appId": "xyz.openfusion.client",
"productName": "OpenFusionClient",
"copyright": "© 2020-2021 OpenFusion Contributors",
"electronDownload": {
"version": "0.31.2",
"platform": "win32",
"arch": "ia32"
"name": "OpenFusionClient",
"version": "1.5.2",
"description": "OpenFusionClient",
"main": "index.js",
"scripts": {
"postinstall": "npx patch-package && npm explore electron-prebuilt -- npm run postinstall",
"start": "electron .",
"pack": "electron-builder --win --ia32 --dir",
"dist": "electron-builder --win --ia32 --publish=never",
"prettier": "npx prettier --write ."
},
"electronVersion": "0.31.2",
"win": {
"asar": false,
"target": [
{
"target": "nsis",
"arch": "ia32"
"author": "OpenFusion Contributors",
"license": "MIT",
"devDependencies": {
"electron-builder": "^22.14.13",
"electron-prebuilt": "^0.31.2",
"patch-package": "^6.5.1",
"prettier": "^2.7.1"
},
"repository": {
"type": "git",
"url": "https://github.com/OpenFusionProject/OpenFusionClient.git"
},
"build": {
"appId": "xyz.openfusion.client",
"productName": "OpenFusionClient",
"copyright": "© 2020-2023 OpenFusion Contributors",
"electronDownload": {
"version": "0.31.2",
"platform": "win32",
"arch": "ia32"
},
{
"target": "zip",
"arch": "ia32"
}
]
"electronVersion": "0.31.2",
"win": {
"asar": false,
"target": [
{
"target": "nsis",
"arch": "ia32"
},
{
"target": "zip",
"arch": "ia32"
}
]
},
"nsis": {
"createDesktopShortcut": true,
"createStartMenuShortcut": true
},
"files": [
"!patches${/*}",
"!.vscode${/*}",
"!*.php",
"!rankurl.txt",
"!README.md",
"!LICENSE.md",
"!.npmrc",
"!.prettierrc",
"!.prettierignore"
],
"extraFiles": [
"LICENSE.md",
{
"from": "build/OpenFusionClient.exe.manifest",
"to": "OpenFusionClient.exe.manifest"
},
{
"from": "build/WebPlayer",
"to": "WebPlayer"
}
],
"afterPack": "./build/after-pack.js"
},
"nsis": {
"createDesktopShortcut": true,
"createStartMenuShortcut": true
},
"files": [
"!patches${/*}",
"!*.php",
"!rankurl.txt",
"!README.md",
"!.npmrc"
],
"extraFiles": [
{
"from": "build/utils",
"to": "utils"
}
],
"afterPack": "./build/delete-default-app.js"
},
"dependencies": {
"fs-extra": "^0.30.0"
}
"dependencies": {
"fs-extra": "2.0.0"
}
}