├── BrowserProxy ├── .gitattributes ├── BrowserProxy.rc ├── packages.config ├── BrowserProxy.def ├── platform.h ├── BrowserProxy.rgs ├── resource.h ├── SettingsRequestHandler.h ├── coupling.js ├── BrowserProxy.vcxproj.filters ├── VoiceTrainerProxy.h └── settings.html ├── SetupThereEdge ├── version.py ├── .gitignore ├── icon.ico ├── version.rs ├── SetupThereEdge.pyproj └── SetupThereEdge.py ├── Resources ├── sg │ ├── hud.png │ ├── logo_gin.png │ ├── hud_holdem.png │ ├── deck_motumotu.png │ ├── deck_standard.png │ ├── hud_cracked.png │ ├── logo_cracked.png │ ├── logo_hearts.png │ ├── logo_holdem.png │ ├── logo_motumotu.png │ ├── logo_spades.png │ ├── cards_hud_bg_goth.png │ ├── cards_hud_bg_reno.png │ ├── cards_hud_bg_tiki.png │ ├── cards_hud_bg_celtic.png │ ├── cards_hud_bg_blueswirl.png │ ├── cards_hud_bg_moroccan.png │ ├── ak_cracked_hud.html │ ├── ak_gin_hud.html │ ├── ak_hearts_hud.html │ ├── ak_motumotu_hud.html │ ├── ak_spades_hud.html │ ├── hud_hearts.css │ ├── hud_spades.css │ ├── ak_texasholdem_hud.html │ └── hud_cracked.css ├── trade │ ├── trade.png │ ├── trade.html │ └── trade.css ├── compass │ ├── compass.png │ ├── compass.html │ ├── compass.js │ └── compass.css ├── guiman │ ├── teleport.png │ ├── teleporthints.html │ ├── teleport.css │ ├── teleport.js │ └── teleportslideshow.html ├── changeme │ ├── changeme.png │ ├── flashdialog.png │ └── flashdialog.html ├── funfinder │ ├── funfinder.png │ ├── funfinder.html │ ├── funfinder.js │ └── funfinder.css ├── messagebar │ ├── messagebar.png │ ├── messagebar.html │ └── messagebar.css ├── volumecontrol │ ├── volume.png │ ├── volume_controls.html │ ├── volume.css │ └── volume.js ├── emotionsbar │ ├── emotionsbar.png │ ├── emotionsbar.html │ ├── emotionsbar.css │ └── emotionsbar.js ├── shortcutbar │ ├── shortcutbar.png │ ├── shortcutbar.html │ ├── shortcutbar.js │ └── shortcutbar.css ├── communicator │ ├── communicator.png │ ├── communicator.html │ └── communicator.css └── js │ ├── 5feb3e333de55f5e7413.wasm │ └── bridge.js ├── FlashProxy ├── FlashProxy.rc ├── packages.config ├── FlashProxy.def ├── platform.h ├── resource.h ├── FlashProxy.rgs ├── FlashProxy.vcxproj.filters ├── FlashRequestProxy.h └── FlashRequestProxy.cpp ├── .gitmodules ├── .gitignore ├── .github └── FUNDING.yml ├── README.md ├── SyncVersion.py └── ThereEdge.sln /BrowserProxy/.gitattributes: -------------------------------------------------------------------------------- 1 | *.html text eol=lf 2 | *.js text eol=lf -------------------------------------------------------------------------------- /SetupThereEdge/version.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | VERSION = '1.1.9' -------------------------------------------------------------------------------- /Resources/sg/hud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/hud.png -------------------------------------------------------------------------------- /SetupThereEdge/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | build/ 3 | dist/ 4 | obj/ 5 | bin/ 6 | *.spec 7 | *.txt -------------------------------------------------------------------------------- /FlashProxy/FlashProxy.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/FlashProxy/FlashProxy.rc -------------------------------------------------------------------------------- /Resources/sg/logo_gin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_gin.png -------------------------------------------------------------------------------- /Resources/trade/trade.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/trade/trade.png -------------------------------------------------------------------------------- /SetupThereEdge/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/SetupThereEdge/icon.ico -------------------------------------------------------------------------------- /Resources/sg/hud_holdem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/hud_holdem.png -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Extras"] 2 | path = Extras 3 | url = git@github.com:hmphus/there-edge-extras.git 4 | -------------------------------------------------------------------------------- /BrowserProxy/BrowserProxy.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/BrowserProxy/BrowserProxy.rc -------------------------------------------------------------------------------- /Resources/compass/compass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/compass/compass.png -------------------------------------------------------------------------------- /Resources/guiman/teleport.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/guiman/teleport.png -------------------------------------------------------------------------------- /Resources/sg/deck_motumotu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/deck_motumotu.png -------------------------------------------------------------------------------- /Resources/sg/deck_standard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/deck_standard.png -------------------------------------------------------------------------------- /Resources/sg/hud_cracked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/hud_cracked.png -------------------------------------------------------------------------------- /Resources/sg/logo_cracked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_cracked.png -------------------------------------------------------------------------------- /Resources/sg/logo_hearts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_hearts.png -------------------------------------------------------------------------------- /Resources/sg/logo_holdem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_holdem.png -------------------------------------------------------------------------------- /Resources/sg/logo_motumotu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_motumotu.png -------------------------------------------------------------------------------- /Resources/sg/logo_spades.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/logo_spades.png -------------------------------------------------------------------------------- /Resources/changeme/changeme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/changeme/changeme.png -------------------------------------------------------------------------------- /Resources/changeme/flashdialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/changeme/flashdialog.png -------------------------------------------------------------------------------- /Resources/funfinder/funfinder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/funfinder/funfinder.png -------------------------------------------------------------------------------- /Resources/messagebar/messagebar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/messagebar/messagebar.png -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_goth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_goth.png -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_reno.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_reno.png -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_tiki.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_tiki.png -------------------------------------------------------------------------------- /Resources/volumecontrol/volume.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/volumecontrol/volume.png -------------------------------------------------------------------------------- /Resources/emotionsbar/emotionsbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/emotionsbar/emotionsbar.png -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_celtic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_celtic.png -------------------------------------------------------------------------------- /Resources/shortcutbar/shortcutbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/shortcutbar/shortcutbar.png -------------------------------------------------------------------------------- /Resources/communicator/communicator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/communicator/communicator.png -------------------------------------------------------------------------------- /Resources/js/5feb3e333de55f5e7413.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/js/5feb3e333de55f5e7413.wasm -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_blueswirl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_blueswirl.png -------------------------------------------------------------------------------- /Resources/sg/cards_hud_bg_moroccan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hmphus/there-edge/HEAD/Resources/sg/cards_hud_bg_moroccan.png -------------------------------------------------------------------------------- /FlashProxy/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /BrowserProxy/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | packages/ 3 | **/Debug/ 4 | **/Develop/ 5 | **/Release/ 6 | *.aps 7 | *.vcxproj.user 8 | *_i.c 9 | *_i.h 10 | /*.bat 11 | /Resources/changeme/iconspng/ 12 | /WebView2/ -------------------------------------------------------------------------------- /FlashProxy/FlashProxy.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | 3 | EXPORTS 4 | DllCanUnloadNow PRIVATE 5 | DllGetClassObject PRIVATE 6 | DllRegisterServer PRIVATE 7 | DllUnregisterServer PRIVATE 8 | DllInstall PRIVATE -------------------------------------------------------------------------------- /BrowserProxy/BrowserProxy.def: -------------------------------------------------------------------------------- 1 | LIBRARY 2 | 3 | EXPORTS 4 | DllCanUnloadNow PRIVATE 5 | DllGetClassObject PRIVATE 6 | DllRegisterServer PRIVATE 7 | DllUnregisterServer PRIVATE 8 | DllInstall PRIVATE -------------------------------------------------------------------------------- /FlashProxy/platform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 4 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 5 | #include 6 | -------------------------------------------------------------------------------- /BrowserProxy/platform.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 4 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 5 | #include 6 | -------------------------------------------------------------------------------- /Resources/guiman/teleporthints.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Teleport Hints 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /FlashProxy/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by FlashProxy.rc 4 | // 5 | 6 | #define IDS_PROJNAME 100 7 | #define IDR_FLASHPROXY 101 8 | 9 | // Next default values for new objects 10 | // 11 | #ifdef APSTUDIO_INVOKED 12 | #ifndef APSTUDIO_READONLY_SYMBOLS 13 | #define _APS_NEXT_RESOURCE_VALUE 201 14 | #define _APS_NEXT_COMMAND_VALUE 32768 15 | #define _APS_NEXT_CONTROL_VALUE 201 16 | #define _APS_NEXT_SYMED_VALUE 106 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /Resources/compass/compass.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Compass 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /FlashProxy/FlashProxy.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | NoRemove CLSID 4 | { 5 | ForceRemove {71E05279-CB7A-496A-8EE9-D700955CA40C} = s 'There Edge Flash Proxy' 6 | { 7 | ForceRemove Programmable 8 | InprocServer32 = s '%MODULE%' 9 | { 10 | val ThreadingModel = s 'Apartment' 11 | } 12 | ProgID = s 'ThereEdge.FlashProxy.1' 13 | VersionIndependentProgID = s 'ThereEdge.FlashProxy' 14 | TypeLib = s '{682E7C31-6CE3-4FB3-9883-479ED34CB1B9}' 15 | Version = s '1.0' 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /BrowserProxy/BrowserProxy.rgs: -------------------------------------------------------------------------------- 1 | HKCR 2 | { 3 | NoRemove CLSID 4 | { 5 | ForceRemove {4D5AA1D8-B2D9-49D0-860E-8DAF2EC2CF0C} = s 'There Edge Browser Proxy' 6 | { 7 | ForceRemove Programmable 8 | InprocServer32 = s '%MODULE%' 9 | { 10 | val ThreadingModel = s 'Apartment' 11 | } 12 | ProgID = s 'ThereEdge.BrowserProxy.1' 13 | VersionIndependentProgID = s 'ThereEdge.BrowserProxy' 14 | TypeLib = s '{E792F884-FF4C-4563-92FE-ADAEA759F2EA}' 15 | Version = s '1.0' 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /BrowserProxy/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by BrowserProxy.rc 4 | // 5 | 6 | #define IDS_PROJNAME 100 7 | #define IDR_BROWSERPROXY 101 8 | #define IDR_COUPLING 102 9 | #define IDR_SETTINGS 103 10 | 11 | #define TEXTFILE 256 12 | 13 | // Next default values for new objects 14 | // 15 | #ifdef APSTUDIO_INVOKED 16 | #ifndef APSTUDIO_READONLY_SYMBOLS 17 | #define _APS_NEXT_RESOURCE_VALUE 201 18 | #define _APS_NEXT_COMMAND_VALUE 32768 19 | #define _APS_NEXT_CONTROL_VALUE 201 20 | #define _APS_NEXT_SYMED_VALUE 106 21 | #endif 22 | #endif 23 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: hmphus # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /Resources/emotionsbar/emotionsbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Action Bar 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ActiveX proxy to Edge WebView2 2 | 3 | This is a pair of ActiveX proxies to [Microsoft Edge WebView2](https://docs.microsoft.com/en-us/microsoft-edge/webview2/) for the [There](https://www.there.com/) client as a replacement for both the [Flash](https://www.adobe.com/products/flashplayer/end-of-life.html) controls and Internet Explorer WebBrowser control. 4 | 5 | The [Microsoft Edge WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) needs to be installed to use these controls. 6 | 7 | ## Building from source 8 | 9 | ### Visual Studio 10 | 11 | Install [Visual Studio 2022](https://visualstudio.microsoft.com/vs/) with the following: 12 | * Workloads 13 | * Desktop development with C++ 14 | * Python development 15 | * Individual components 16 | * Windows 10 SDK (10.0.19041.0) 17 | * Python language support 18 | * Python 3 64-bit (3.9.13) 19 | 20 | ![Screenshot](https://media.fotki.com/2v2aKZw88x3JhYT.png) -------------------------------------------------------------------------------- /Resources/communicator/communicator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Communicator 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | Communicator 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | 28 |
29 |
30 | 31 | -------------------------------------------------------------------------------- /SetupThereEdge/version.rs: -------------------------------------------------------------------------------- 1 | # UTF-8 2 | # 3 | VSVersionInfo( 4 | ffi=FixedFileInfo( 5 | filevers=(1, 1, 9, 0), 6 | prodvers=(1, 1, 9, 0), 7 | mask=0x3f, 8 | flags=0x0, 9 | OS=0x40004, 10 | fileType=0x1, 11 | subtype=0x0, 12 | date=(0, 0) 13 | ), 14 | kids=[ 15 | StringFileInfo([ 16 | StringTable(u'040904b0', [ 17 | StringStruct(u'CompanyName', u'Hmph!'), 18 | StringStruct(u'FileDescription', u'Setup helper for There Edge'), 19 | StringStruct(u'FileVersion', u'1.1.9.0'), 20 | StringStruct(u'InternalName', u'SetupThereEdge.exe'), 21 | StringStruct(u'LegalCopyright', u'(c) Hmph!'), 22 | StringStruct(u'OriginalFilename', u'SetupThereEdge.exe'), 23 | StringStruct(u'ProductName', u'There Edge Setup Helper'), 24 | StringStruct(u'ProductVersion', u'1.1.9.0') 25 | ]) 26 | ]), 27 | VarFileInfo([ 28 | VarStruct(u'Translation', [1033, 1200]) 29 | ]) 30 | ] 31 | ) 32 | -------------------------------------------------------------------------------- /SetupThereEdge/SetupThereEdge.pyproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | false 5 | dist\ 6 | 7 | 8 | {7467bc47-b250-4225-9d2d-7fbcfb8d9688} 9 | False 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Resources/messagebar/messagebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Message Bar 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /Resources/funfinder/funfinder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Fun Finder 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
What’s Happening
15 |
Who’s Saying What
16 |
Find a Cool Group
17 |
Explore the World
18 |
Go Shopping
19 |
Visitor’s Guide
20 |
21 |
22 |
23 |
24 |
25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /Resources/compass/compass.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | onReady: function() { 3 | There.fsCommand('setStageWidthHeight', { 4 | width: 86, 5 | height: 86, 6 | }); 7 | 8 | There.fsCommand('setWidthHeight', { 9 | width: 86, 10 | height: 86, 11 | }); 12 | 13 | There.fsCommand('setTextureBitDepth', { 14 | depth: 32, 15 | }); 16 | }, 17 | 18 | onVariable: function(name, value) { 19 | if (name == 'there_avheading') { 20 | $('.compass .face').css('transform', `rotate(${-value}deg)`); 21 | } 22 | 23 | if (name == 'there_teleporting') { 24 | $('.compass').attr(name.replace('there_', 'data-'), value); 25 | } 26 | }, 27 | }); 28 | 29 | $(document).ready(function() { 30 | $('.compass').on('mousedown', function(event) { 31 | if (event.which == 1) { 32 | There.fsCommand('beginDragWindow'); 33 | } 34 | event.preventDefault(); 35 | event.stopPropagation(); 36 | }); 37 | 38 | $('.compass .button[data-id="close"]').on('click', function() { 39 | There.fsCommand('closeWindow'); 40 | }).on('mouseover', function(event) { 41 | There.playSound('control rollover'); 42 | }).on('mousedown', function(event) { 43 | There.playSound('control down'); 44 | event.stopPropagation(); 45 | }).on('mouseup', function(event) { 46 | There.playSound('control up'); 47 | }); 48 | }); -------------------------------------------------------------------------------- /Resources/compass/compass.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:tahoma, sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .compass { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:86px; 18 | height:86px; 19 | background-color:#ffffff40; 20 | border-radius:5px; 21 | transition-property:opacity; 22 | transition-duration:250ms; 23 | } 24 | 25 | .compass[data-teleporting="1"] { 26 | opacity:0; 27 | pointer-events:none; 28 | } 29 | 30 | .compass .face { 31 | position:absolute; 32 | left:3px; 33 | top:3px; 34 | width:80px; 35 | height:80px; 36 | background-image:url(compass.png); 37 | } 38 | 39 | .compass .arrow { 40 | position:absolute; 41 | left:33px; 42 | top:29px; 43 | width:20px; 44 | height:26px; 45 | background-image:url(compass.png); 46 | background-position:-80px 0px; 47 | } 48 | 49 | .compass .button[data-id="close"] { 50 | position:absolute; 51 | left:71px; 52 | top:3px; 53 | width:13px; 54 | height:13px; 55 | background-image:url(compass.png); 56 | background-position:-86px -38px; 57 | } 58 | 59 | .compass .button[data-id="close"]:hover { 60 | background-position-y:-52px; 61 | } 62 | 63 | .compass .button[data-id="close"]:hover:active { 64 | background-position-y:-66px; 65 | } -------------------------------------------------------------------------------- /Resources/volumecontrol/volume_controls.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Volume 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | Volume 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Voice
24 |
25 |
26 |
27 |
Music
28 |
29 |
30 |
31 |
Environment
32 |
33 |
34 |
35 |
36 | 40 |
41 | 42 | -------------------------------------------------------------------------------- /Resources/guiman/teleport.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:verdana, sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .teleport { 14 | position:absolute; 15 | left:calc((100vw - 800px) / 2); 16 | top:0px; 17 | width:800px; 18 | height:600px; 19 | } 20 | 21 | .teleport:not([data-ready="1"]) { 22 | display:none; 23 | } 24 | 25 | .teleport svg.logo { 26 | background-color:#000; 27 | } 28 | 29 | .teleport .text { 30 | position:absolute; 31 | left:340px; 32 | top:268px; 33 | width:114px; 34 | height:24px; 35 | background-image:url(teleport.png); 36 | } 37 | 38 | .teleport .text .dots { 39 | position:absolute; 40 | left:113px; 41 | top:0px; 42 | width:17px; 43 | height:24px; 44 | background-image:url(teleport.png); 45 | background-position-x:-123px; 46 | animation-name:dots; 47 | animation-duration:2s; 48 | animation-timing-function:steps(1); 49 | animation-iteration-count:infinite; 50 | } 51 | 52 | @keyframes dots { 53 | 0% { 54 | width:0px; 55 | } 56 | 25% { 57 | width:5px; 58 | } 59 | 50% { 60 | width:11px; 61 | } 62 | 75% { 63 | width:17px; 64 | } 65 | } 66 | 67 | .teleport .hint { 68 | position:absolute; 69 | left:0px; 70 | top:400px; 71 | width:780px; 72 | height:80px; 73 | padding:0px 10px; 74 | color:#ffa85c; 75 | font-size:15px; 76 | font-weight:bold; 77 | text-align:center; 78 | } -------------------------------------------------------------------------------- /Resources/guiman/teleport.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | onReady: function() { 3 | There.fsCommand('setStageWidthHeight', { 4 | width: 800, 5 | height: 600, 6 | }); 7 | 8 | There.fsCommand('setWidthHeight', { 9 | width: 800, 10 | height: 600, 11 | }); 12 | 13 | There.fsCommand('setTextureBitDepth', { 14 | depth: 32, 15 | }); 16 | }, 17 | 18 | onVariable: function(name, value) { 19 | if (name == 'there_ready' && value == 1) { 20 | if (There.variables.there_pilotdoid == 0) { 21 | $('.hint').text('Welcome to There!'); 22 | } else { 23 | There.fetch({ 24 | path: '/VersionedXmlSvc/veilHints', 25 | query: { 26 | Oid: There.variables.there_pilotdoid, 27 | }, 28 | dataType: 'xml', 29 | success: function(xml) { 30 | const xmlAnswer = xml.getElementsByTagName('Answer')[0]; 31 | const xmlAvatarHints = xmlAnswer.getElementsByTagName('AvatarHints')[0]; 32 | const xmlHint = xmlAvatarHints.getElementsByTagName('Hint')[0]; 33 | $('.hint').text(xmlHint.childNodes[0].nodeValue); 34 | }, 35 | }); 36 | } 37 | if (There.isWindows()) { 38 | $('.teleport').attr('data-ready', '1'); 39 | } 40 | } 41 | if (There.isMacOS()) { 42 | if (name == 'viewportclientareawidth' || name == 'viewportclientareaheight') { 43 | const width = Number(There.variables.viewportclientareawidth ?? 0); 44 | const height = Number(There.variables.viewportclientareaheight ?? 0); 45 | if (width > 0 && height > 0) { 46 | There.fsCommand('setWidthHeight', { 47 | width: width, 48 | height: height, 49 | }); 50 | $('.teleport').attr('data-ready', '1'); 51 | } 52 | } 53 | } 54 | }, 55 | }); -------------------------------------------------------------------------------- /BrowserProxy/SettingsRequestHandler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace ATL; 4 | 5 | void Log(const WCHAR *format, ...); 6 | 7 | class SettingsRequestHandler: public IUnknown 8 | { 9 | public: 10 | SettingsRequestHandler(ICoreWebView2Environment *environment, const WCHAR *proxyVersion); 11 | virtual ~SettingsRequestHandler(); 12 | 13 | static BOOL Validate(const WCHAR *url); 14 | 15 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object) override; 16 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 17 | virtual ULONG STDMETHODCALLTYPE Release() override; 18 | 19 | public: 20 | HRESULT HandleRequest(const WCHAR *url, ICoreWebView2WebResourceRequestedEventArgs *args, HWND wnd); 21 | HRESULT ProcessMessage(const WCHAR *path, const WCHAR *query); 22 | 23 | protected: 24 | HRESULT HandleRedirect(const WCHAR *location); 25 | HRESULT HandleSettings(HWND wnd); 26 | HRESULT WriteHome(); 27 | HRESULT WriteAbout(HWND wnd); 28 | HRESULT GetStartPage(CHAR *mburl, DWORD &mblength, const WCHAR *path = nullptr); 29 | HRESULT SetStartPage(const WCHAR *url); 30 | HRESULT UrlUnescapeSpacesInPlace(WCHAR *text); 31 | HRESULT WriteEscapedContent(const WCHAR *text); 32 | 33 | protected: 34 | static BOOL CALLBACK InspectThreadWindow(HWND wnd, LPARAM lParam); 35 | static BOOL CALLBACK InspectChildWindow(HWND wnd, LPARAM lParam); 36 | 37 | protected: 38 | ULONG m_refCount; 39 | ULONG m_statusCode; 40 | CComBSTR m_reasonPhrase; 41 | CComBSTR m_contentType; 42 | CComBSTR m_location; 43 | CComBSTR m_proxyVersion; 44 | CComPtr m_environment; 45 | CComPtr m_content; 46 | }; -------------------------------------------------------------------------------- /Resources/trade/trade.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Trade 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | Trade Session 15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Add or remove items by clicking Trade in your
24 | My Things or ChangeMe menu. 25 |
26 |
27 |
I am giving:
28 |
29 |
Trade Status:
30 |
Trade Status: TRADING
31 |
Trade Status: OFFER
32 |
Trade Status: CONFIRMED
33 |
34 |
35 |
I am getting:
36 |
37 |
Trade Status:
38 |
Trade Status: TRADING
39 |
Trade Status: OFFER
40 |
Trade Status: CONFIRMED
41 |
42 | 48 |
49 |
50 | 51 | -------------------------------------------------------------------------------- /Resources/js/bridge.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | data: { 3 | queue: [], 4 | isReady: false, 5 | }, 6 | 7 | onVariable: function(name, value) { 8 | There.data.queue.push({name: name, value: value}); 9 | if (There.data.player == undefined) { 10 | if (name != 'there_ready') { 11 | return; 12 | } 13 | const ruffle = window.RufflePlayer.newest(); 14 | There.data.player = ruffle.createPlayer(); 15 | There.data.player.config = { 16 | autoplay: 'on', 17 | unmuteOverlay: 'hidden', 18 | contextMenu: false, 19 | backgroundColor: There.variables.there_translucencyenabled == 1 ? '#0000' : null, 20 | }; 21 | There.data.player.onFSCommand = function(command, query) { 22 | There.fsCommand(command, query); 23 | if (There.data.isReady == false) { 24 | There.data.isReady = true; 25 | setTimeout(There.forwardRuffleVariables, 0); 26 | } 27 | }; 28 | $('body').append(There.data.player); 29 | There.fsCommand('setStageWidthHeight', { 30 | width: $(There.data.player).innerWidth(), 31 | height: $(There.data.player).innerHeight(), 32 | }); 33 | There.fsCommand('setWidthHeight', { 34 | width: $(There.data.player).innerWidth(), 35 | height: $(There.data.player).innerHeight(), 36 | }); 37 | There.fsCommand('setTextureBitDepth', { 38 | depth: 32, 39 | }); 40 | There.data.player.load({ 41 | url: `http://${There.variables.there_resourceshost}/resources${$('body').attr('data-swf')}`, 42 | allowScriptAccess: true, 43 | }).then(function() { 44 | $('ruffle-player').attr('data-ready', '1'); 45 | }); 46 | return; 47 | } 48 | There.forwardRuffleVariables(); 49 | }, 50 | 51 | forwardRuffleVariables: function() { 52 | if (There.data.isReady) { 53 | while (There.data.queue.length > 0) { 54 | const entry = There.data.queue.shift(); 55 | There.data.player.instance.set_variable(`_root.${entry.name}`, entry.value); 56 | if (entry.name == 'there_teleporting') { 57 | $('ruffle-player').attr(entry.name.replace('there_', 'data-'), entry.value); 58 | } 59 | } 60 | } 61 | }, 62 | }); 63 | -------------------------------------------------------------------------------- /Resources/funfinder/funfinder.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | onReady: function() { 3 | There.fsCommand('setStageWidthHeight', { 4 | width: Number(There.variables.there_windowwidth ?? 800), 5 | height: 36, 6 | }); 7 | 8 | There.fsCommand('setWidthHeight', { 9 | width: Number(There.variables.there_windowwidth ?? 800), 10 | height: 36, 11 | }); 12 | 13 | There.fsCommand('setTextureBitDepth', { 14 | depth: 32, 15 | }); 16 | }, 17 | 18 | onVariable: function(name, value) { 19 | if (name == 'there_windowwidth') { 20 | There.fsCommand('setStageWidthHeight', { 21 | width: Number(value), 22 | height: 36, 23 | }); 24 | 25 | There.fsCommand('setWidthHeight', { 26 | width: Number(value), 27 | height: 36, 28 | }); 29 | } 30 | }, 31 | }); 32 | 33 | $(document).ready(function() { 34 | $('.funfinder .button').on('mouseover', function(event) { 35 | There.playSound('control rollover'); 36 | }).on('mousedown', function(event) { 37 | There.playSound('control down'); 38 | event.stopPropagation(); 39 | }).on('mouseup', function(event) { 40 | There.playSound('control up'); 41 | }); 42 | 43 | $('.funfinder .button[data-id="events"]').on('click', function() { 44 | There.guiCommand('happeningNow'); 45 | }); 46 | 47 | $('.funfinder .button[data-id="chats"]').on('click', function() { 48 | There.guiCommand('conversations'); 49 | }); 50 | 51 | $('.funfinder .button[data-id="clubs"]').on('click', function() { 52 | There.guiCommand('clubs'); 53 | }); 54 | 55 | $('.funfinder .button[data-id="map"]').on('click', function() { 56 | There.guiCommand('map'); 57 | }); 58 | 59 | $('.funfinder .button[data-id="shop"]').on('click', function() { 60 | There.guiCommand('shop'); 61 | }); 62 | 63 | $('.funfinder .button[data-id="guide"]').on('click', function() { 64 | There.guiCommand('guide'); 65 | }); 66 | 67 | $('.funfinder .button[data-id="help"]').on('click', function() { 68 | There.fsCommand('browser', { 69 | target: 'There_Help', 70 | urlGen: 'HelpFunFinderUrl', 71 | }); 72 | }); 73 | 74 | $('.funfinder .button[data-id="close"]').on('click', function() { 75 | There.fsCommand('closeWindow'); 76 | }); 77 | }); -------------------------------------------------------------------------------- /BrowserProxy/coupling.js: -------------------------------------------------------------------------------- 1 | if (window.VoiceTrainer != undefined) { 2 | VoiceTrainer.style.display = 'none'; 3 | VoiceTrainer.configState = 0; 4 | VoiceTrainer.recordLevel = 0; 5 | VoiceTrainer.configMessage = null; 6 | VoiceTrainer.configError = null; 7 | VoiceTrainer.events = {}; 8 | 9 | VoiceTrainer.attachEvent = function(name, callback) { 10 | VoiceTrainer.events[name] = callback; 11 | }; 12 | 13 | VoiceTrainer.Init = function() { 14 | window.chrome.webview.addEventListener('message', function(message) { 15 | if (message.data.name == 'VoiceTrainer') { 16 | if (message.data.data != undefined) { 17 | Object.assign(VoiceTrainer, message.data.data); 18 | } 19 | const event = VoiceTrainer.events[message.data.event]; 20 | if (event != undefined) { 21 | event(); 22 | } 23 | } 24 | }); 25 | window.chrome.webview.postMessage(`voiceTrainer/init`); 26 | }; 27 | 28 | VoiceTrainer.Config = function(state) { 29 | window.chrome.webview.postMessage(`voiceTrainer/put?configState=${state}`); 30 | }; 31 | 32 | VoiceTrainer.launchRecordingMixer = function(state) { 33 | window.chrome.webview.postMessage(`voiceTrainer/launchRecordingMixer`); 34 | }; 35 | 36 | const initialize = function() { 37 | VoiceTrainer.attachEvent('onconfigstatechange', VoiceTrainer_onconfigstatechange); 38 | VoiceTrainer.attachEvent('onbeginrecord', VoiceTrainer_onbeginrecord); 39 | VoiceTrainer.attachEvent('onendrecord', VoiceTrainer_onendrecord); 40 | VoiceTrainer.attachEvent('onlevelchange', VoiceTrainer_onlevelchange); 41 | VoiceTrainer.attachEvent('onconfigerror', VoiceTrainer_onconfigerror); 42 | VoiceTrainer.Init(); 43 | }; 44 | 45 | if (document.readyState == 'complete') { 46 | initialize(); 47 | } else { 48 | document.addEventListener('readystatechange', function(event) { 49 | initialize(); 50 | }); 51 | } 52 | } 53 | 54 | window.ActiveXObject = function(name) { 55 | this.name = name; 56 | }; 57 | 58 | ActiveXObject.prototype.load = function(url) { 59 | const self = this; 60 | const request = new XMLHttpRequest(); 61 | request.addEventListener('load', function() { 62 | self.readyState = 4; 63 | if (self.onreadystatechange != undefined) { 64 | self.onreadystatechange(this.responseXML); 65 | } 66 | }); 67 | request.open('GET', url); 68 | request.send(); 69 | }; 70 | 71 | console.log('There Edge compatibility coupling installed'); -------------------------------------------------------------------------------- /Resources/shortcutbar/shortcutbar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Shortcut Bar 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /FlashProxy/FlashProxy.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {9301c9ba-46a9-4651-a596-08497d2a0627} 18 | False 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Generated Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | 39 | 40 | Source Files 41 | 42 | 43 | Generated Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | 50 | 51 | Resource Files 52 | 53 | 54 | 55 | 56 | Resource Files 57 | 58 | 59 | Resource Files 60 | 61 | 62 | 63 | 64 | 65 | Resource Files 66 | 67 | 68 | -------------------------------------------------------------------------------- /BrowserProxy/BrowserProxy.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {9301c9ba-46a9-4651-a596-08497d2a0627} 18 | False 19 | 20 | 21 | 22 | 23 | Header Files 24 | 25 | 26 | Generated Files 27 | 28 | 29 | Header Files 30 | 31 | 32 | Header Files 33 | 34 | 35 | Header Files 36 | 37 | 38 | Header Files 39 | 40 | 41 | 42 | 43 | Source Files 44 | 45 | 46 | Generated Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | 56 | 57 | Resource Files 58 | 59 | 60 | 61 | 62 | Resource Files 63 | 64 | 65 | Resource Files 66 | 67 | 68 | Resource Files 69 | 70 | 71 | Resource Files 72 | 73 | 74 | 75 | 76 | 77 | Resource Files 78 | 79 | 80 | -------------------------------------------------------------------------------- /Resources/sg/ak_cracked_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Cracked 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Messages
19 |
20 |
21 |
22 | 23 |
New Game
24 |
Rules
25 |
Start
26 |
Submit
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | 81 | -------------------------------------------------------------------------------- /Resources/sg/ak_gin_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gin 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Messages
19 |
20 |
21 |
22 | 23 |
New Game
24 |
Rules
25 |
Deal
26 |
Draw Card
27 |
Discard
28 |
Knock
29 |
Show Melds
30 |
31 |
32 |
33 |
34 |
35 |
36 |
2-3-4
37 |
2-2-2
38 |
Group
39 |
40 |
Deck
41 |
42 |
43 |
44 |
My Hand
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
Game:--
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
Game:--
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 | 90 | -------------------------------------------------------------------------------- /Resources/sg/ak_hearts_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hearts 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Messages
19 |
Last Trick
20 |
21 |
22 |
23 | 24 |
New Game
25 |
Rules
26 |
Deal
27 |
Pass Cards
28 |
Play Card
29 |
Take Trick
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
My Hand
46 |
47 |
48 |
49 |
50 |
51 |
52 |
Hand:--
53 |
Game:--
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
Hand:--
62 |
Game:--
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
Hand:--
71 |
Game:--
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
Hand:--
80 |
Game:--
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | 97 | -------------------------------------------------------------------------------- /SyncVersion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import re 6 | import sys 7 | 8 | 9 | def get_version(): 10 | with open('Installer/Installer.vdproj', 'r', encoding='utf-8-sig') as file: 11 | lines = [l.strip() for l in file.readlines()] 12 | path = [''] 13 | for line in lines: 14 | if line == '{': 15 | path.append('') 16 | continue 17 | if line == '}': 18 | path.pop() 19 | continue 20 | match = re.search(r'"([^"]+)" = "([^"]+)"', line) 21 | if match is not None: 22 | path[-1] = match.group(1) 23 | if '.'.join(path) == 'DeployProject.Deployable.Product.ProductVersion': 24 | return match.group(2).split(':')[1] 25 | continue 26 | match = re.search(r'"([^"]+)"', line) 27 | if match is not None: 28 | path[-1] = match.group(1) 29 | continue 30 | return None 31 | 32 | 33 | def apply_version_rc(name, version): 34 | with open('%s/%s.rc' % (name, name), 'r', encoding='utf-16') as file: 35 | lines = [l.rstrip('\n') for l in file.readlines()] 36 | for (i, line) in enumerate(lines): 37 | match = re.match(r'^ ([A-Z]+?)VERSION ', line) 38 | if match is not None: 39 | line = ' %sVERSION %s' % ( 40 | match.group(1), 41 | ','.join(version.split('.') + ['0']), 42 | ) 43 | lines[i] = line 44 | continue 45 | match = re.match(r'^( +)VALUE "([A-Za-z]+)Version",', line) 46 | if match is not None: 47 | line = '%sVALUE "%sVersion", "%s.0"' % ( 48 | match.group(1), 49 | match.group(2), 50 | version, 51 | ) 52 | lines[i] = line 53 | continue 54 | with open('%s/%s.rc' % (name, name), 'w', encoding='utf-16') as file: 55 | file.write('\n'.join(lines) + '\n') 56 | 57 | 58 | def apply_version_py(name, version): 59 | lines = [ 60 | "# -*- coding: utf-8 -*-", 61 | "", 62 | "VERSION = '%s'" % version, 63 | ] 64 | with open('%s/version.py' % name, 'w') as file: 65 | file.write('\n'.join(lines)) 66 | 67 | 68 | def apply_version_rs(name, version): 69 | with open('%s/version.rs' % name, 'r') as file: 70 | lines = [l.rstrip('\n') for l in file.readlines()] 71 | for (i, line) in enumerate(lines): 72 | match = re.match(r'^( +(?:file|prod)vers=\()[0-9]+, [0-9]+, [0-9]+, [0-9]+(\).*$)', line) 73 | if match is not None: 74 | line = '%s%s%s' % ( 75 | match.group(1), 76 | ', '.join(version.split('.') + ['0']), 77 | match.group(2), 78 | ) 79 | lines[i] = line 80 | continue 81 | match = re.match(r'^( +StringStruct\(u\'(?:File|Product)Version\', u\')[.0-9]+(\'\).*$)', line) 82 | if match is not None: 83 | line = '%s%s.0%s' % ( 84 | match.group(1), 85 | version, 86 | match.group(2), 87 | ) 88 | lines[i] = line 89 | continue 90 | with open('%s/version.rs' % name, 'w') as file: 91 | file.write('\n'.join(lines) + '\n') 92 | 93 | 94 | if __name__ == '__main__': 95 | version = get_version() 96 | print('Version: %s' % version) 97 | apply_version_rc('BrowserProxy', version) 98 | apply_version_rc('FlashProxy', version) 99 | apply_version_py('SetupThereEdge', version) 100 | apply_version_rs('SetupThereEdge', version) -------------------------------------------------------------------------------- /BrowserProxy/VoiceTrainerProxy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace ATL; 4 | using namespace Microsoft::WRL; 5 | 6 | void Log(const WCHAR *format, ...); 7 | 8 | class IVoiceTrainer: public IDispatch 9 | { 10 | public: 11 | virtual HRESULT STDMETHODCALLTYPE Init() = 0; 12 | virtual HRESULT STDMETHODCALLTYPE put_ConfigState(long Config) = 0; 13 | virtual HRESULT STDMETHODCALLTYPE get_ConfigState(long *pVal) = 0; 14 | virtual HRESULT STDMETHODCALLTYPE get_RecordLevel(long *pVal) = 0; 15 | virtual HRESULT STDMETHODCALLTYPE get_ConfigMessage(BSTR *pVal) = 0; 16 | virtual HRESULT STDMETHODCALLTYPE get_ConfigError(BSTR *pVal) = 0; 17 | virtual HRESULT STDMETHODCALLTYPE Cancel() = 0; 18 | virtual HRESULT STDMETHODCALLTYPE get_Preprocess(long *pVal) = 0; 19 | virtual HRESULT STDMETHODCALLTYPE put_Preprocess(long pVal) = 0; 20 | virtual HRESULT STDMETHODCALLTYPE get_SupportsPreprocess(VARIANT_BOOL *pVal) = 0; 21 | virtual HRESULT STDMETHODCALLTYPE LaunchRecordingMixer() = 0; 22 | }; 23 | 24 | class IVoiceTrainerEvents: public IDispatch 25 | { 26 | public: 27 | virtual HRESULT STDMETHODCALLTYPE OnBeginRecord() = 0; 28 | virtual HRESULT STDMETHODCALLTYPE OnEndRecord() = 0; 29 | virtual HRESULT STDMETHODCALLTYPE OnLevelChange() = 0; 30 | virtual HRESULT STDMETHODCALLTYPE OnConfigStateChange() = 0; 31 | virtual HRESULT STDMETHODCALLTYPE OnConfigMessage() = 0; 32 | virtual HRESULT STDMETHODCALLTYPE OnConfigError() = 0; 33 | }; 34 | 35 | class VoiceTrainerProxy: public IVoiceTrainerEvents 36 | { 37 | public: 38 | static WCHAR g_WindowClassName[]; 39 | 40 | VoiceTrainerProxy(); 41 | virtual ~VoiceTrainerProxy(); 42 | 43 | static BOOL Validate(const WCHAR *url); 44 | 45 | HRESULT Init(HWND wnd, ICoreWebView2 *view); 46 | HRESULT Close(); 47 | 48 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object) override; 49 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 50 | virtual ULONG STDMETHODCALLTYPE Release() override; 51 | 52 | protected: 53 | virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo) override; 54 | virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override; 55 | virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) override; 56 | virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, 57 | VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) override; 58 | virtual HRESULT STDMETHODCALLTYPE OnBeginRecord() override; 59 | virtual HRESULT STDMETHODCALLTYPE OnEndRecord() override; 60 | virtual HRESULT STDMETHODCALLTYPE OnLevelChange() override; 61 | virtual HRESULT STDMETHODCALLTYPE OnConfigStateChange() override; 62 | virtual HRESULT STDMETHODCALLTYPE OnConfigMessage() override; 63 | virtual HRESULT STDMETHODCALLTYPE OnConfigError() override; 64 | 65 | public: 66 | HRESULT ProcessMessage(const WCHAR *path, const WCHAR *query); 67 | 68 | protected: 69 | HRESULT FormatBasicJson(WCHAR *json, size_t size, const WCHAR *event); 70 | HRESULT FormatBasicJson(WCHAR *json, size_t size, const WCHAR *event, const WCHAR *key, LONG value); 71 | HRESULT FormatBasicJson(WCHAR *json, size_t size, const WCHAR *event, const WCHAR *key, const WCHAR *value); 72 | 73 | protected: 74 | ULONG m_refCount; 75 | HWND m_wnd; 76 | CComPtr m_view; 77 | CComPtr m_voiceTrainer; 78 | CComPtr m_connectionPoint; 79 | DWORD m_connectionPointID; 80 | }; -------------------------------------------------------------------------------- /Resources/funfinder/funfinder.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:verdana, sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .funfinder { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:100%; 18 | height:34px; 19 | border-top:1px solid #666; 20 | background-color:#fff9; 21 | font-size:0px; 22 | } 23 | 24 | .funfinder .buttons.big { 25 | position:absolute; 26 | left:5px; 27 | top:5px; 28 | height:24px; 29 | } 30 | 31 | .funfinder .buttons.big .button { 32 | display:inline-block; 33 | margin-right:2px; 34 | width:121px; 35 | height:22px; 36 | border:1px solid #666; 37 | background-image:url(funfinder.png); 38 | border-radius:8px; 39 | text-align:center; 40 | overflow:hidden; 41 | } 42 | 43 | .funfinder .buttons.big .button:hover { 44 | background-position-y:-22px; 45 | } 46 | 47 | .funfinder .buttons.big .button:hover:active { 48 | background-position-y:-44px; 49 | } 50 | 51 | .funfinder .buttons.big .button .icon { 52 | display:inline-block; 53 | width:18px; 54 | height:22px; 55 | vertical-align:top; 56 | background-image:url(funfinder.png); 57 | } 58 | 59 | .funfinder .buttons.big .button[data-id="events"] .icon { 60 | background-position-x:-121px; 61 | } 62 | 63 | .funfinder .buttons.big .button[data-id="chats"] .icon { 64 | background-position-x:-139px; 65 | } 66 | 67 | .funfinder .buttons.big .button[data-id="clubs"] .icon { 68 | background-position-x:-157px; 69 | } 70 | 71 | .funfinder .buttons.big .button[data-id="map"] .icon { 72 | background-position-x:-175px; 73 | } 74 | 75 | .funfinder .buttons.big .button[data-id="shop"] .icon { 76 | background-position-x:-193px; 77 | } 78 | 79 | .funfinder .buttons.big .button[data-id="guide"] .icon { 80 | background-position-x:-211px; 81 | } 82 | 83 | .funfinder .buttons.big .button:hover .icon { 84 | background-position-y:-22px; 85 | } 86 | 87 | .funfinder .buttons.big .button:hover:active .icon { 88 | background-position-y:-44px; 89 | } 90 | 91 | .funfinder .buttons.big .button .title { 92 | display:inline-block; 93 | height:20px; 94 | line-height:20px; 95 | padding:1px 1px 1px 1px; 96 | vertical-align:top; 97 | font-size:9.5px; 98 | transform:scaley(1.2); 99 | color:#000; 100 | } 101 | 102 | .funfinder .buttons.big .button:hover .title { 103 | text-shadow:1px 1px 1px #0006; 104 | } 105 | 106 | .funfinder .buttons.big .button:hover:active .title { 107 | padding:2px 0px 0px 2px; 108 | text-shadow:0px 0px 2px #0006; 109 | } 110 | 111 | .funfinder .buttons.small { 112 | position:absolute; 113 | right:6px; 114 | top:10px; 115 | height:24px; 116 | } 117 | 118 | .funfinder .buttons.small .button { 119 | display:inline-block; 120 | margin-left:1px; 121 | width:14px; 122 | height:13px; 123 | border:1px solid #666; 124 | background-image:url(funfinder.png); 125 | background-position-x:-229px; 126 | border-radius:3px; 127 | } 128 | 129 | .funfinder .buttons.small .button[data-id="close"] { 130 | background-position-y:0px; 131 | } 132 | 133 | .funfinder .buttons.small .button[data-id="close"]:hover { 134 | background-position-y:-13px; 135 | } 136 | 137 | .funfinder .buttons.small .button[data-id="close"]:hover:active { 138 | background-position-y:-26px; 139 | } 140 | 141 | .funfinder .buttons.small .button[data-id="help"] { 142 | background-position-y:-39px; 143 | } 144 | 145 | .funfinder .buttons.small .button[data-id="help"]:hover { 146 | background-position-y:-52px; 147 | } 148 | 149 | .funfinder .buttons.small .button[data-id="help"]:hover:active { 150 | background-position-y:-65px; 151 | } -------------------------------------------------------------------------------- /Resources/sg/ak_motumotu_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Motu Motu 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Messages
19 |
20 |
21 |
22 |
23 | 24 |
New Game
25 |
Rules
26 |
Deal
27 |
Discard
28 |
Draw
29 |
Draw Cards
30 |
31 |
32 |
Please choose the wild color.
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
Discard this card or pass?
42 |
43 |
Discard
44 |
Pass
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
OneCard
54 |
55 |
Deck
56 |
57 |
58 |
My Hand
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | 107 | 108 | -------------------------------------------------------------------------------- /Resources/shortcutbar/shortcutbar.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | onReady: function() { 3 | There.fsCommand('setStageWidthHeight', { 4 | width: Number(There.variables.there_windowwidth ?? 800), 5 | height: 25, 6 | }); 7 | 8 | There.fsCommand('setWidthHeight', { 9 | width: Number(There.variables.there_windowwidth ?? 800), 10 | height: 25, 11 | }); 12 | 13 | There.fsCommand('setTextureBitDepth', { 14 | depth: 32, 15 | }); 16 | }, 17 | 18 | onVariable: function(name, value) { 19 | if (name == 'there_windowwidth') { 20 | There.fsCommand('setStageWidthHeight', { 21 | width: Number(value), 22 | height: 25, 23 | }); 24 | 25 | There.fsCommand('setWidthHeight', { 26 | width: Number(value), 27 | height: 25, 28 | }); 29 | } 30 | 31 | if (name == 'there_thisplaceenabled' || name == 'there_instandardview' || name == 'there_inbodyview' || 32 | name == 'there_aerialviewallowed' || name == 'there_emotionsflashing' || name == 'there_lastwindowavailable') { 33 | $('.shortcutbar').attr(name.replace('there_', 'data-'), value); 34 | } 35 | }, 36 | }); 37 | 38 | $(document).ready(function() { 39 | $('.shortcutbar .button').on('mouseover', function(event) { 40 | There.playSound('control rollover'); 41 | }).on('mousedown', function(event) { 42 | There.playSound('control down'); 43 | event.stopPropagation(); 44 | }).on('mouseup', function(event) { 45 | There.playSound('control up'); 46 | }); 47 | 48 | $('.shortcutbar .button[data-id="there"]').on('click', function() { 49 | There.guiCommand('thereCentral'); 50 | }); 51 | 52 | $('.shortcutbar .button[data-id="browser"]').on('click', function() { 53 | There.guiCommand('browse'); 54 | }); 55 | 56 | $('.shortcutbar .button[data-id="im"]').on('click', function() { 57 | There.guiCommand('im'); 58 | }); 59 | 60 | $('.shortcutbar .button[data-id="actions"]').on('click', function() { 61 | There.guiCommand('emotions'); 62 | }); 63 | 64 | $('.shortcutbar .button[data-id="happening"]').on('click', function() { 65 | There.guiCommand('happeningNow'); 66 | }); 67 | 68 | $('.shortcutbar .button[data-id="activities"]').on('click', function() { 69 | There.guiCommand('activities'); 70 | }); 71 | 72 | $('.shortcutbar .button[data-id="map"]').on('click', function() { 73 | There.guiCommand('map'); 74 | }); 75 | 76 | $('.shortcutbar .button[data-id="places"]').on('click', function() { 77 | There.guiCommand('places'); 78 | }); 79 | 80 | $('.shortcutbar .button[data-id="information"]').on('click', function() { 81 | There.guiCommand('thisPlaceInfo'); 82 | }); 83 | 84 | $('.shortcutbar .button[data-id="exit"]').on('click', function() { 85 | There.guiCommand('thisPlaceExit'); 86 | }); 87 | 88 | $('.shortcutbar .button[data-id="shop"]').on('click', function() { 89 | There.guiCommand('shop'); 90 | }); 91 | 92 | $('.shortcutbar .button[data-id="auctions"]').on('click', function() { 93 | There.guiCommand('auctions'); 94 | }); 95 | 96 | $('.shortcutbar .button[data-id="changeme"]').on('click', function() { 97 | There.guiCommand('changeMe'); 98 | }); 99 | 100 | $('.shortcutbar .button[data-id="organizer"]').on('click', function() { 101 | There.guiCommand({ 102 | action: 'organizer', 103 | folder: 'gear', 104 | }); 105 | }); 106 | 107 | $('.shortcutbar .button[data-id="aerial"]').on('click', function() { 108 | There.guiCommand({ 109 | action: 'setView', 110 | viewId: 'aerialMedium', 111 | }); 112 | }); 113 | 114 | $('.shortcutbar .button[data-id="mirror"]').on('click', function() { 115 | There.guiCommand({ 116 | action: 'setView', 117 | viewId: 'body', 118 | }); 119 | }); 120 | 121 | $('.shortcutbar .button[data-id="standard"]').on('click', function() { 122 | There.guiCommand({ 123 | action: 'setView', 124 | viewId: 'standard', 125 | }); 126 | }); 127 | 128 | $('.shortcutbar .button[data-id="topics"]').on('click', function() { 129 | There.guiCommand('help'); 130 | }); 131 | 132 | $('.shortcutbar .button[data-id="guide"]').on('click', function() { 133 | There.guiCommand('guide'); 134 | }); 135 | 136 | $('.shortcutbar .button[data-id="help"]').on('click', function() { 137 | There.fsCommand('browser', { 138 | target: 'There_Help', 139 | urlGen: 'HelpShortcutBarUrl', 140 | }); 141 | }); 142 | 143 | $('.shortcutbar .button[data-id="close"]').on('click', function() { 144 | There.fsCommand('closeWindow'); 145 | }); 146 | }); -------------------------------------------------------------------------------- /FlashProxy/FlashRequestProxy.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using namespace ATL; 4 | 5 | void Log(const WCHAR *format, ...); 6 | 7 | class FlashRequestProxy: public IBindCtx, 8 | public IBindStatusCallback, 9 | public IStream 10 | { 11 | public: 12 | FlashRequestProxy(ICoreWebView2Environment *environment, ICoreWebView2WebResourceRequestedEventArgs *args); 13 | virtual ~FlashRequestProxy(); 14 | 15 | HRESULT Init(IServiceProvider *serviceProvider, WCHAR *uri); 16 | 17 | virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **object) override; 18 | virtual ULONG STDMETHODCALLTYPE AddRef() override; 19 | virtual ULONG STDMETHODCALLTYPE Release() override; 20 | 21 | protected: 22 | virtual HRESULT STDMETHODCALLTYPE RegisterObjectBound(IUnknown *punk) override {return E_NOTIMPL;} 23 | virtual HRESULT STDMETHODCALLTYPE RevokeObjectBound(IUnknown *punk) override {return E_NOTIMPL;} 24 | virtual HRESULT STDMETHODCALLTYPE ReleaseBoundObjects() override {return E_NOTIMPL;} 25 | virtual HRESULT STDMETHODCALLTYPE SetBindOptions(BIND_OPTS *pbindopts) override {return E_NOTIMPL;} 26 | virtual HRESULT STDMETHODCALLTYPE GetBindOptions(BIND_OPTS *pbindopts) override {return E_NOTIMPL;} 27 | virtual HRESULT STDMETHODCALLTYPE GetRunningObjectTable(IRunningObjectTable **pprot) override {return E_NOTIMPL;} 28 | virtual HRESULT STDMETHODCALLTYPE RegisterObjectParam(LPOLESTR pszKey, IUnknown *punk) override {return E_NOTIMPL;} 29 | virtual HRESULT STDMETHODCALLTYPE GetObjectParam(LPOLESTR pszKey, IUnknown **ppunk) override; 30 | virtual HRESULT STDMETHODCALLTYPE EnumObjectParam(IEnumString **ppenum) override {return E_NOTIMPL;} 31 | virtual HRESULT STDMETHODCALLTYPE RevokeObjectParam(LPOLESTR pszKey) override {return E_NOTIMPL;} 32 | virtual HRESULT STDMETHODCALLTYPE OnStartBinding(DWORD dwReserved, IBinding *pib) override; 33 | virtual HRESULT STDMETHODCALLTYPE GetPriority(LONG *pnPriority) override {return E_NOTIMPL;} 34 | virtual HRESULT STDMETHODCALLTYPE OnLowResource(DWORD reserved) override {return E_NOTIMPL;} 35 | virtual HRESULT STDMETHODCALLTYPE OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) override; 36 | virtual HRESULT STDMETHODCALLTYPE OnStopBinding(HRESULT hresult, LPCWSTR szError) override; 37 | virtual HRESULT STDMETHODCALLTYPE GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo) override; 38 | virtual HRESULT STDMETHODCALLTYPE OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) override; 39 | virtual HRESULT STDMETHODCALLTYPE OnObjectAvailable(REFIID riid, IUnknown *punk) override {return E_NOTIMPL;} 40 | virtual HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead) override; 41 | virtual HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten) override {return E_NOTIMPL;} 42 | virtual HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) override; 43 | virtual HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) override {return E_NOTIMPL;} 44 | virtual HRESULT STDMETHODCALLTYPE CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) override {return E_NOTIMPL;} 45 | virtual HRESULT STDMETHODCALLTYPE Commit(DWORD grfCommitFlags) override {return E_NOTIMPL;} 46 | virtual HRESULT STDMETHODCALLTYPE Revert() override {return E_NOTIMPL;} 47 | virtual HRESULT STDMETHODCALLTYPE LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) override {return E_NOTIMPL;} 48 | virtual HRESULT STDMETHODCALLTYPE UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) override {return E_NOTIMPL;} 49 | virtual HRESULT STDMETHODCALLTYPE Stat(STATSTG *pstatstg, DWORD grfStatFlag) override {return E_NOTIMPL;} 50 | virtual HRESULT STDMETHODCALLTYPE Clone(IStream **ppstm) override {return E_NOTIMPL;} 51 | 52 | HRESULT DetermineContentType(const WCHAR *uri); 53 | 54 | protected: 55 | ULONG m_refCount; 56 | CComPtr m_environment; 57 | CComPtr m_args; 58 | CComPtr m_deferral; 59 | CComPtr m_stream; 60 | CComPtr m_binding; 61 | CComBSTR m_mimeType; 62 | CComBSTR m_contentType; 63 | ULONG m_size; 64 | ULONG m_position; 65 | }; -------------------------------------------------------------------------------- /Resources/changeme/flashdialog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ChangeMe Dialog 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | Welcome to the Spa 15 | Leave Treatments 16 | Save Lookset 17 | Rename Lookset 18 | Delete Lookset 19 | Save Outfit 20 | Rename Outfit 21 | Delete Outfit 22 | Thank you for using the Spa 23 | Error 24 |
25 |
26 |
27 |
    28 |
  • To Change your look, click a ChangeMe icon. Move the sliders to adjust that body part. 29 |
  • To See a new view, press an arrow key. 30 |
  • To Keep your new avatar look, click "Save" in ChangeMe. 31 |
  • To Leave the Spa, click the floating blue circle icon. 32 |
33 |
Don't show this message again.
34 |
35 |
36 | If you leave without clicking "Save" in ChangeMe, 37 | you will lose your new body settings. 38 |

39 | Leave anyway? 40 |
Don't show this message again.
41 |
42 |
43 |
44 |
Save
45 |
Save As...
46 |
47 |
48 | Your current body and face lookset is called "". 49 | Changes saved to this lookset are free. 50 |
51 |
52 | Name and save a new lookset for T? 53 | Please note that looksets are not refundable. 54 |
55 |
56 |
57 |
58 | Enter a new name for this lookset. 59 |
60 |
61 |
62 | You will lose this lookset permanently if you delete it. 63 |

64 | Delete the lookset ""? 65 |
66 |
67 | You can create an outfit from all of the items you are currently wearing. 68 |

69 | Enter a name for this outfit. 70 |
71 |
72 |
73 | Enter a new name for this outfit. 74 |
75 |
76 |
77 | You will lose this outfit if you delete it. 78 |

79 | However, you will not lose the individual items. 80 |

81 | Delete the outfit ""? 82 |
83 |
84 | Your changes to the lookset "" have been saved. 85 |
86 |
87 | Your new lookset "" has been saved 88 | and your account has been debited for the price of T. 89 |
90 |
91 | An error occurred while . Please try again later. 92 |
93 | 102 |
103 | 104 | 105 | -------------------------------------------------------------------------------- /Resources/guiman/teleportslideshow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Teleport Slideshow 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /Resources/emotionsbar/emotionsbar.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:tahoma, sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .emotionsbar { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:100%; 18 | height:21px; 19 | border-top:1px solid #808080; 20 | border-bottom:1px solid #808080; 21 | background-color:#bbeedd; 22 | font-size:0px; 23 | } 24 | 25 | .emotionsbar .buttons.big .banks, 26 | .emotionsbar .buttons.big .emotions { 27 | display:inline-block; 28 | } 29 | 30 | .emotionsbar .buttons.big .bank { 31 | display:inline-block; 32 | height:19px; 33 | line-height:19px; 34 | padding:1px 8px; 35 | vertical-align:top; 36 | border-left:1px solid #fff; 37 | border-right:1px solid #999; 38 | background-image:url(emotionsbar.png); 39 | background-position-y:-2px; 40 | font-size:11px; 41 | } 42 | 43 | .emotionsbar .buttons.big .bank:first-of-type { 44 | border-left:none; 45 | } 46 | 47 | .emotionsbar .buttons.big .bank:hover { 48 | background-position-y:-48px; 49 | text-shadow:1px 1px 1px #0006; 50 | } 51 | 52 | .emotionsbar .buttons.big .bank:hover:active { 53 | background-position-y:-48px; 54 | text-shadow:0px 0px 2px #0006; 55 | padding:2px 7px 0px 9px; 56 | } 57 | 58 | .emotionsbar .buttons.big .bank[data-selected="1"]:hover, 59 | .emotionsbar .buttons.big .bank[data-selected="1"]:active, 60 | .emotionsbar .buttons.big .bank[data-selected="1"] { 61 | background-position-y:-25px; 62 | text-shadow:none; 63 | padding:1px 8px; 64 | } 65 | 66 | .emotionsbar .buttons.big .button { 67 | display:inline-block; 68 | height:19px; 69 | line-height:19px; 70 | padding:1px 4px; 71 | vertical-align:top; 72 | font-size:11px; 73 | } 74 | 75 | .emotionsbar .buttons.big .button:hover { 76 | background-color:#88d4bb; 77 | } 78 | 79 | .emotionsbar .buttons.big .button:hover:active, 80 | .emotionsbar .buttons.big .button[data-id="talk"]:active, 81 | .emotionsbar[data-voicetoggle="1"][data-voiceisspeaking="1"] .buttons.big .button[data-id="talk"] { 82 | background-color:#88d4bb; 83 | padding:2px 3px 0px 5px; 84 | } 85 | 86 | .emotionsbar .buttons.big .button:not([data-enabled="1"]), 87 | .emotionsbar .buttons.big .button:not([data-enabled="1"]):hover, 88 | .emotionsbar .buttons.big .button:not([data-enabled="1"]):active, 89 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="talk"], 90 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="talk"]:hover, 91 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="talk"]:active, 92 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeon"], 93 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeon"]:hover, 94 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeon"]:active, 95 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeoff"], 96 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeoff"]:hover, 97 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnhandsfreeoff"]:active { 98 | padding:1px 4px; 99 | background-color:unset; 100 | color:#999; 101 | pointer-events:none; 102 | } 103 | 104 | .emotionsbar:not([data-voicehandfree="1"]) .buttons.big .button[data-id="turnhandsfreeoff"] { 105 | display:none; 106 | } 107 | 108 | .emotionsbar[data-voicehandfree="1"] .buttons.big .button[data-id="turnhandsfreeon"] { 109 | display:none; 110 | } 111 | 112 | .emotionsbar:not([data-voicetoggle="1"]) .buttons.big .button[data-id="turnvoiceoff"] { 113 | display:none; 114 | } 115 | 116 | .emotionsbar[data-voicetoggle="1"] .buttons.big .button[data-id="turnvoiceon"] { 117 | display:none; 118 | } 119 | 120 | .emotionsbar .buttons.small { 121 | position:absolute; 122 | right:6px; 123 | top:3px; 124 | } 125 | 126 | .emotionsbar .buttons.small .button { 127 | display:inline-block; 128 | margin-left:1px; 129 | width:14px; 130 | height:13px; 131 | border:1px solid #666; 132 | border-radius:3px; 133 | background-image:url(emotionsbar.png); 134 | } 135 | 136 | .emotionsbar .buttons.small .button[data-id="close"] { 137 | background-position-x:0px; 138 | background-position-y:-69px; 139 | } 140 | 141 | .emotionsbar .buttons.small .button[data-id="close"]:hover { 142 | background-position-y:-82px; 143 | } 144 | 145 | .emotionsbar .buttons.small .button[data-id="close"]:hover:active { 146 | background-position-y:-95px; 147 | } 148 | 149 | .emotionsbar .buttons.small .button[data-id="help"] { 150 | background-position-x:-14px; 151 | background-position-y:-69px; 152 | } 153 | 154 | .emotionsbar .buttons.small .button[data-id="help"]:hover { 155 | background-position-y:-82px; 156 | } 157 | 158 | .emotionsbar .buttons.small .button[data-id="help"]:hover:active { 159 | background-position-y:-95px; 160 | } -------------------------------------------------------------------------------- /Resources/sg/ak_spades_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spades 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Score
19 |
Messages
20 |
Last Trick
21 |
22 |
23 |
24 | 25 |
New Game
26 |
Rules
27 |
Deal
28 |
Play Card
29 |
Take Trick
30 |
31 |
32 |
Nil
33 |
1
34 |
2
35 |
3
36 |
4
37 |
5
38 |
6
39 |
40 |
41 |
7
42 |
8
43 |
9
44 |
10
45 |
11
46 |
12
47 |
13
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Points
56 |
Bags
57 |
58 |
59 |
60 |
61 |
62 |
Points
63 |
Bags
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
My Hand
82 |
83 |
84 |
85 |
86 |
87 |
88 |
Bid:--
89 |
Tricks:--
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
Bid:--
98 |
Tricks:--
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
Bid:--
107 |
Tricks:--
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
Bid:--
116 |
Tricks:--
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | 133 | 134 | -------------------------------------------------------------------------------- /BrowserProxy/settings.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ThereEdge Settings 5 | 6 | 151 | 152 | 198 | 199 | 200 | 203 |
204 |
Browser
205 |
Use the following URL when opening a new browser window:
206 |
207 | 208 | 209 |
210 |
211 |
212 |
UI Details
213 | 214 | 215 | @about@
NameTypeVersionAuthor
216 |
217 | 218 | -------------------------------------------------------------------------------- /Resources/sg/hud_hearts.css: -------------------------------------------------------------------------------- 1 | .left .panel[data-id="game"] .logo { 2 | position:absolute; 3 | left:5px; 4 | top:7px; 5 | width:52px; 6 | height:49px; 7 | background-image:url(logo_hearts.png); 8 | } 9 | 10 | .left .panel[data-id="game"] .button[data-id="newgame"] { 11 | position:absolute; 12 | left:67px; 13 | top:7px; 14 | } 15 | 16 | .left .panel[data-id="game"] .button[data-id="rules"] { 17 | position:absolute; 18 | left:67px; 19 | top:34px; 20 | } 21 | 22 | .left .panel[data-id="game"] .button[data-id="deal"], 23 | .left .panel[data-id="game"] .button[data-id="pass"], 24 | .left .panel[data-id="game"] .button[data-id="play"], 25 | .left .panel[data-id="game"] .button[data-id="taketrick"] { 26 | position:absolute; 27 | left:135px; 28 | top:7px; 29 | display:none; 30 | } 31 | 32 | .left .panel[data-id="tricks"] .players { 33 | position:absolute; 34 | left:0px; 35 | right:0px; 36 | top:5px; 37 | font-size:0px; 38 | display:flex; 39 | flex-direction:row; 40 | justify-content:space-around; 41 | } 42 | 43 | .left .panel[data-id="tricks"] .players .player { 44 | display:inline-block; 45 | width:47px; 46 | height:14px; 47 | padding:0px 2px; 48 | font-size:8px; 49 | color:#fff; 50 | text-align:center; 51 | white-space:nowrap; 52 | text-overflow:ellipsis; 53 | overflow:hidden; 54 | transform:scaleY(1.2) 55 | } 56 | 57 | .left .panel[data-id="tricks"] .cardset { 58 | position:absolute; 59 | left:0px; 60 | top:17px; 61 | width:100%; 62 | font-size:0px; 63 | display:flex; 64 | flex-direction:row; 65 | justify-content:space-around; 66 | } 67 | 68 | .left .panel[data-id="tricks"] .cardset .card { 69 | margin:0px; 70 | box-shadow:none; 71 | } 72 | 73 | .hud[data-gamestate="pregame"] .left .panel[data-id="game"] .button[data-id="deal"], 74 | .hud[data-gamestate="deal"] .left .panel[data-id="game"] .button[data-id="deal"] { 75 | display:inline-block; 76 | } 77 | 78 | .hud[data-gamestate="pass"] .left .panel[data-id="game"] .button[data-id="pass"], 79 | .hud[data-gamestate="passsend"] .left .panel[data-id="game"] .button[data-id="pass"] { 80 | display:inline-block; 81 | } 82 | 83 | .hud[data-gamestate="play"] .left .panel[data-id="game"] .button[data-id="play"], 84 | .hud[data-gamestate="playsend"] .left .panel[data-id="game"] .button[data-id="play"] { 85 | display:inline-block; 86 | } 87 | 88 | .hud[data-gamestate="taketrick"] .left .panel[data-id="game"] .button[data-id="taketrick"], 89 | .hud[data-gamestate="endgame"] .left .panel[data-id="game"] .button[data-id="taketrick"] { 90 | display:inline-block; 91 | } 92 | 93 | .middle { 94 | display:flex; 95 | flex-direction:row; 96 | height:100%; 97 | } 98 | 99 | .middle .table { 100 | position:relative; 101 | height:100%; 102 | } 103 | 104 | .middle .table::before { 105 | position:absolute; 106 | left:0px; 107 | right:0px; 108 | height:100%; 109 | border-left:1px solid rgba(255, 255, 255, 0.25); 110 | border-right:1px solid rgba(0, 0, 0, 0.5); 111 | content:' '; 112 | pointer-events:none; 113 | } 114 | 115 | .middle .table[data-player="1"] { 116 | width:340px; 117 | } 118 | 119 | .middle .table:not([data-player="1"]) { 120 | width:68px; 121 | border-left:1px solid #000; 122 | } 123 | 124 | .middle .table[data-player="1"] .title { 125 | position:absolute; 126 | left:7px; 127 | top:5px; 128 | width:250px; 129 | height:14px; 130 | line-height:14px; 131 | font-size:11px; 132 | font-weight:bold; 133 | color:#fff; 134 | text-align:center; 135 | } 136 | 137 | .middle .table[data-player="1"] .cardset[data-id^="hand"] { 138 | position:absolute; 139 | left:7px; 140 | top:20px; 141 | width:260px; 142 | height:37px; 143 | text-align:center; 144 | } 145 | 146 | .middle .table[data-player="1"] .message { 147 | position:absolute; 148 | left:11px; 149 | bottom:6px; 150 | width:250px; 151 | height:27px; 152 | line-height:12px; 153 | font-size:11px; 154 | color:#fff; 155 | display:flex; 156 | align-items:flex-end; 157 | justify-content:space-evenly; 158 | } 159 | 160 | .middle .table:not([data-player="1"]) { 161 | background-color:rgba(0, 0, 0, 0.15); 162 | } 163 | 164 | .middle .table .player { 165 | position:absolute; 166 | right:2px; 167 | top:5px; 168 | width:64px; 169 | height:14px; 170 | line-height:14px; 171 | font-size:11px; 172 | font-weight:bold; 173 | color:#fff; 174 | text-align:center; 175 | white-space:nowrap; 176 | text-overflow:ellipsis; 177 | overflow:hidden; 178 | } 179 | 180 | .middle .table .player[data-leader="1"] { 181 | font-style:italic; 182 | } 183 | 184 | .middle .table .turn { 185 | position:absolute; 186 | right:19px; 187 | top:20px; 188 | width:28px; 189 | height:26px; 190 | display:none; 191 | } 192 | 193 | .middle .table .turn[data-visible="1"] { 194 | display:inline-block; 195 | background-image:url(hud.png); 196 | background-position:0px -272px; 197 | } 198 | 199 | .middle .table .cardset[data-id^="played"] { 200 | position:absolute; 201 | right:20px; 202 | top:20px; 203 | width:27px; 204 | height:37px; 205 | text-align:center; 206 | } 207 | 208 | .middle .table .cardset[data-id^="played"] .card { 209 | box-shadow:none; 210 | } 211 | 212 | .middle .table .cardset[data-id^="played"][data-highlighted="1"] { 213 | margin:-2px -2px 0px 0px; 214 | border:2px solid #fa0; 215 | border-radius:6px; 216 | } 217 | 218 | .middle .table .stats { 219 | position:absolute; 220 | right:4px; 221 | bottom:6px; 222 | width:60px; 223 | line-height:12px; 224 | font-size:11px; 225 | color:#fff; 226 | } 227 | 228 | .middle .table .stats div { 229 | display:flex; 230 | flex-direction:row; 231 | justify-content:space-between; 232 | } 233 | -------------------------------------------------------------------------------- /ThereEdge.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35219.272 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FlashProxy", "FlashProxy\FlashProxy.vcxproj", "{9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BrowserProxy", "BrowserProxy\BrowserProxy.vcxproj", "{DBD14B66-F34F-4401-966B-E0F1073168D5}" 9 | EndProject 10 | Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "Installer", "Installer\Installer.vdproj", "{4EA03C29-5CC6-46CC-B2CC-E956A716A745}" 11 | EndProject 12 | Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "SetupThereEdge", "SetupThereEdge\SetupThereEdge.pyproj", "{7467BC47-B250-4225-9D2D-7FBCFB8D9688}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Develop|Any CPU = Develop|Any CPU 20 | Develop|x64 = Develop|x64 21 | Develop|x86 = Develop|x86 22 | Release|Any CPU = Release|Any CPU 23 | Release|x64 = Release|x64 24 | Release|x86 = Release|x86 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Debug|Any CPU.ActiveCfg = Debug|Win32 28 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Debug|x64.ActiveCfg = Debug|x64 29 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Debug|x64.Build.0 = Debug|x64 30 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Debug|x86.ActiveCfg = Debug|Win32 31 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Debug|x86.Build.0 = Debug|Win32 32 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Develop|Any CPU.ActiveCfg = Develop|Win32 33 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Develop|x64.ActiveCfg = Develop|x64 34 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Develop|x64.Build.0 = Develop|x64 35 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Develop|x86.ActiveCfg = Develop|Win32 36 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Develop|x86.Build.0 = Develop|Win32 37 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Release|Any CPU.ActiveCfg = Release|Win32 38 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Release|x64.ActiveCfg = Release|x64 39 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Release|x64.Build.0 = Release|x64 40 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Release|x86.ActiveCfg = Release|Win32 41 | {9B9EC2C9-8F0D-4320-9853-AAFDE83C42CD}.Release|x86.Build.0 = Release|Win32 42 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Debug|Any CPU.ActiveCfg = Debug|Win32 43 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Debug|x64.ActiveCfg = Debug|x64 44 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Debug|x64.Build.0 = Debug|x64 45 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Debug|x86.ActiveCfg = Debug|Win32 46 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Debug|x86.Build.0 = Debug|Win32 47 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Develop|Any CPU.ActiveCfg = Develop|Win32 48 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Develop|x64.ActiveCfg = Develop|x64 49 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Develop|x64.Build.0 = Develop|x64 50 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Develop|x86.ActiveCfg = Develop|Win32 51 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Develop|x86.Build.0 = Develop|Win32 52 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Release|Any CPU.ActiveCfg = Release|Win32 53 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Release|x64.ActiveCfg = Release|x64 54 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Release|x64.Build.0 = Release|x64 55 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Release|x86.ActiveCfg = Release|Win32 56 | {DBD14B66-F34F-4401-966B-E0F1073168D5}.Release|x86.Build.0 = Release|Win32 57 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Debug|Any CPU.ActiveCfg = Release 58 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Debug|Any CPU.Build.0 = Release 59 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Debug|x64.ActiveCfg = Release 60 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Debug|x64.Build.0 = Release 61 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Debug|x86.ActiveCfg = Release 62 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Develop|Any CPU.ActiveCfg = Release 63 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Develop|Any CPU.Build.0 = Release 64 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Develop|x64.ActiveCfg = Release 65 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Develop|x64.Build.0 = Release 66 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Develop|x86.ActiveCfg = Release 67 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Release|Any CPU.ActiveCfg = Release 68 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Release|Any CPU.Build.0 = Release 69 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Release|x64.ActiveCfg = Release 70 | {4EA03C29-5CC6-46CC-B2CC-E956A716A745}.Release|x86.ActiveCfg = Release 71 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 72 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Debug|x64.ActiveCfg = Debug|Any CPU 73 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Debug|x64.Build.0 = Debug|Any CPU 74 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Debug|x86.ActiveCfg = Release|Any CPU 75 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Develop|Any CPU.ActiveCfg = Debug|Any CPU 76 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Develop|x64.ActiveCfg = Debug|Any CPU 77 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Develop|x64.Build.0 = Debug|Any CPU 78 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Develop|x86.ActiveCfg = Release|Any CPU 79 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Release|Any CPU.ActiveCfg = Release|Any CPU 80 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Release|x64.ActiveCfg = Release|Any CPU 81 | {7467BC47-B250-4225-9D2D-7FBCFB8D9688}.Release|x86.ActiveCfg = Release|Any CPU 82 | EndGlobalSection 83 | GlobalSection(SolutionProperties) = preSolution 84 | HideSolutionNode = FALSE 85 | EndGlobalSection 86 | GlobalSection(ExtensibilityGlobals) = postSolution 87 | SolutionGuid = {D36760CA-9F66-4C07-AD48-C9F17ADB7A63} 88 | EndGlobalSection 89 | EndGlobal 90 | -------------------------------------------------------------------------------- /Resources/volumecontrol/volume.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .volume { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:128px; 18 | height:176px; 19 | background-color:rgba(200, 200, 200, 0.6); 20 | border-radius:5px; 21 | overflow:hidden; 22 | transition-property:opacity; 23 | transition-duration:250ms; 24 | } 25 | 26 | .volume[data-teleporting="1"] { 27 | opacity:0; 28 | pointer-events:none; 29 | } 30 | 31 | .volume[data-state="bar"] { 32 | height:25px; 33 | } 34 | 35 | .volume .titlebar { 36 | position:absolute; 37 | left:0px; 38 | right:0px; 39 | top:0px; 40 | height:23px; 41 | line-height:23px; 42 | font-size:0px; 43 | padding-left:5px; 44 | border-top-left-radius:5px; 45 | border-top-right-radius:5px; 46 | border:1px solid #808080; 47 | background-image:url(volume.png); 48 | background-position:0px 0px; 49 | } 50 | 51 | .volume[data-state="bar"] .titlebar { 52 | border-bottom-left-radius:5px; 53 | border-bottom-right-radius:5px; 54 | background-position:0px -23px; 55 | } 56 | 57 | .volume .titlebar span { 58 | font-size:13px; 59 | } 60 | 61 | .volume .titlebar .buttons { 62 | position:absolute; 63 | top:4px; 64 | right:5px; 65 | display:inline-block; 66 | font-size:0px; 67 | } 68 | 69 | .volume .titlebar .buttons .button { 70 | display:inline-block; 71 | margin-left:1px; 72 | width:14px; 73 | height:13px; 74 | border:1px solid #666; 75 | border-radius:3px; 76 | background-image:url(volume.png); 77 | background-position-x:-126px; 78 | z-index:2; 79 | } 80 | 81 | .volume[data-state="full"] .titlebar .buttons .button[data-id="close"] { 82 | background-position-y:0px; 83 | } 84 | 85 | .volume[data-state="bar"] .titlebar .buttons .button[data-id="close"] { 86 | background-position-y:-13px; 87 | } 88 | 89 | .volume .titlebar .buttons .button[data-id="bar"], 90 | .volume .titlebar .buttons .button[data-id="full"] { 91 | display:none; 92 | } 93 | 94 | .volume[data-state="full"] .titlebar .buttons .button[data-id="bar"] { 95 | display:inline-block; 96 | background-position-y:-26px; 97 | } 98 | 99 | .volume[data-state="bar"] .titlebar .buttons .button[data-id="full"] { 100 | display:inline-block; 101 | background-position-y:-39px; 102 | } 103 | 104 | .volume .titlebar .buttons .button:hover { 105 | background-position-x:-140px; 106 | } 107 | 108 | .volume .titlebar .buttons .button:hover:active { 109 | background-position-x:-154px; 110 | } 111 | 112 | .volume .panel { 113 | position:absolute; 114 | left:0px; 115 | right:0px; 116 | top:25px; 117 | display:flex; 118 | flex-direction:column; 119 | align-items:center; 120 | } 121 | 122 | .volume .panel .title { 123 | margin-top:6px; 124 | height:12px; 125 | line-height:12px; 126 | font-size:10px; 127 | text-align:center; 128 | color:#333; 129 | } 130 | 131 | .volume .panel .slider { 132 | position:relative; 133 | display:inline-block; 134 | top:-3px; 135 | width:83px; 136 | height:6px; 137 | padding:5px; 138 | margin:-5px; 139 | background-image:url(volume.png); 140 | background-position:5px -49px; 141 | background-clip:content-box; 142 | } 143 | 144 | .volume .panel .slider .knob { 145 | display:inline-block; 146 | position:absolute; 147 | margin-left:0px; 148 | left:0px; 149 | top:3px; 150 | width:8px; 151 | height:8px; 152 | background-image:url(volume.png); 153 | background-position:-126px -52px; 154 | border:1px solid #666; 155 | border-radius:5px; 156 | } 157 | 158 | .volume .panel .slider .knob:hover { 159 | background-position-x:-134px; 160 | } 161 | 162 | .volume .panel .slider .knob:active { 163 | background-position-x:-142px; 164 | } 165 | 166 | .volume .panel .item[data-enabled="0"] { 167 | opacity:0.5; 168 | pointer-events:none; 169 | } 170 | 171 | .volume .footer { 172 | position:absolute; 173 | left:0px; 174 | right:0px; 175 | bottom:0px; 176 | height:37px; 177 | padding-right:6px; 178 | font-size:0px; 179 | display:flex; 180 | justify-content:center; 181 | pointer-events:none; 182 | } 183 | 184 | .volume[data-state="bar"] .footer { 185 | display:none; 186 | } 187 | 188 | .volume .footer .button { 189 | margin-left:3px; 190 | height:18px; 191 | line-height:18px; 192 | padding:1px; 193 | border:1px solid #666; 194 | border-radius:6px; 195 | vertical-align:top; 196 | background-image:url(volume.png); 197 | font-size:11px; 198 | text-align:center; 199 | pointer-events:all; 200 | } 201 | 202 | .volume .footer .button:hover { 203 | text-shadow:1px 1px 1px #0006; 204 | } 205 | 206 | .volume .footer .button:hover:active { 207 | text-shadow:0px 0px 2px #0006; 208 | padding:2px 0px 0px 2px; 209 | } 210 | 211 | .volume .footer .button[data-enabled="0"], 212 | .volume .footer .button[data-enabled="0"]:hover, 213 | .volume .footer .button[data-enabled="0"]:active { 214 | color:#7dbbca; 215 | text-shadow:1px 1px 0px rgba(255, 255, 255, 0.5); 216 | pointer-events:none; 217 | } 218 | 219 | .volume .footer .button.medium { 220 | width:44px; 221 | background-position:-168px 0px; 222 | } 223 | 224 | .volume .footer .button.medium[data-engaged="1"] { 225 | background-position-x:-214px; 226 | } 227 | 228 | .volume .footer .button.medium:hover { 229 | background-position-y:-20px; 230 | } 231 | 232 | .volume .footer .button.medium:hover:active { 233 | background-position-y:-40px; 234 | } 235 | 236 | .volume .footer .bar { 237 | position:absolute; 238 | left:0px; 239 | right:0px; 240 | bottom:0px; 241 | height:8px; 242 | font-size:0px; 243 | border-bottom-left-radius:5px; 244 | border-bottom-right-radius:5px; 245 | border:1px solid #808080; 246 | background-image:url(volume.png); 247 | background-position:0px -46px; 248 | } -------------------------------------------------------------------------------- /Resources/volumecontrol/volume.js: -------------------------------------------------------------------------------- 1 | class VolumeSlider { 2 | constructor(element, callback) { 3 | let self = this; 4 | self.element = element; 5 | self.knob = $(self.element).find('.knob'); 6 | self.width = $(self.element).width(); 7 | let item = $(self.element).closest('.item'); 8 | self.id = $(item).attr('data-id'); 9 | self.name = $(item).attr('data-name'); 10 | self.value = 0; 11 | self.refresh(); 12 | self.callback = callback; 13 | self.active = false; 14 | $(self.knob).on('mousedown', function(event) { 15 | if (event.which == 1) { 16 | self.active = true; 17 | self.offsetX = event.pageX - $(self.knob).position().left; 18 | } 19 | }); 20 | $(document).on('mousemove', function(event) { 21 | if (self.active) { 22 | $(self.knob).css({ 23 | left: Math.min(Math.max(0, event.pageX - self.offsetX), self.width), 24 | }); 25 | } 26 | }).on('mouseup', function() { 27 | if (self.active) { 28 | self.active = false; 29 | self.obtainValue(); 30 | self.callback(self); 31 | } 32 | }); 33 | $(self.element).on('mousedown', function(event) { 34 | if (event.which == 1 && !self.active) { 35 | $(self.knob).animate({ 36 | left: Math.min(Math.max(0, event.offsetX - 5), self.width), 37 | }, 200, 'swing', function() { 38 | self.obtainValue(); 39 | self.callback(self); 40 | }); 41 | } 42 | }); 43 | } 44 | 45 | setValue(value) { 46 | let self = this; 47 | self.value = value; 48 | self.refresh(); 49 | } 50 | 51 | obtainValue() { 52 | let self = this; 53 | self.value = $(self.knob).position().left / self.width; 54 | } 55 | 56 | refresh() { 57 | let self = this; 58 | $(self.knob).css({ 59 | left: self.value * self.width, 60 | }); 61 | } 62 | } 63 | 64 | There.init({ 65 | data: { 66 | sliders: {}, 67 | }, 68 | 69 | onReady: function() { 70 | There.fsCommand('setStageWidthHeight', { 71 | width: 128, 72 | height: 176, 73 | }); 74 | 75 | There.fsCommand('setTextureBitDepth', { 76 | depth: 32, 77 | }); 78 | 79 | new ResizeObserver(function(entries) { 80 | const rect = entries[0].contentRect; 81 | There.fsCommand('setWidthHeight', { 82 | width: Math.ceil(rect.width), 83 | height: Math.ceil(rect.height), 84 | }); 85 | }).observe($('.volume')[0]); 86 | 87 | $('.slider').each(function(index, element) { 88 | const slider = new VolumeSlider(element, function(slider) { 89 | There.guiCommand({ 90 | action: 'setpreference', 91 | pref: slider.name, 92 | value: slider.value, 93 | }); 94 | }); 95 | There.data.sliders[slider.id] = slider; 96 | }); 97 | }, 98 | 99 | onVariable: function(name, value) { 100 | if (name == 'there_teleporting') { 101 | $('.volume').attr(name.replace('there_', 'data-'), value); 102 | } 103 | 104 | switch (name) { 105 | case 'there_voiceenabled': { 106 | $('.panel .item[data-id="voice"]').attr('data-enabled', value); 107 | break; 108 | } 109 | case 'there_musicenabled': { 110 | $('.panel .item[data-id="music"]').attr('data-enabled', value); 111 | break; 112 | } 113 | case 'there_muteallsound': { 114 | $('.footer .button[data-id="mute"]').attr('data-engaged', value); 115 | break; 116 | } 117 | case 'there_voicevolume': { 118 | There.data.sliders.voice.setValue(Number(value)); 119 | break; 120 | } 121 | case 'there_musicvolume': { 122 | There.data.sliders.music.setValue(Number(value)); 123 | break; 124 | } 125 | case 'there_environmentvolume': { 126 | There.data.sliders.environment.setValue(Number(value)); 127 | break; 128 | } 129 | } 130 | }, 131 | }); 132 | 133 | $(document).ready(function() { 134 | $('.titlebar').on('mousedown', function(event) { 135 | if (event.which == 1) { 136 | There.fsCommand('beginDragWindow'); 137 | } 138 | There.clearContextMenu(); 139 | event.preventDefault(); 140 | event.stopPropagation(); 141 | }); 142 | 143 | $('.titlebar .button').on('mouseover', function() { 144 | There.playSound('control rollover'); 145 | }).on('mousedown', function(event) { 146 | There.playSound('control down'); 147 | event.stopPropagation(); 148 | }).on('mouseup', function() { 149 | There.playSound('control up'); 150 | }); 151 | 152 | $('.slider').on('mousedown', function(event) { 153 | There.playSound('control down'); 154 | event.stopPropagation(); 155 | }); 156 | 157 | $('.slider .knob').on('mouseover', function() { 158 | There.playSound('control rollover'); 159 | }).on('mousedown', function(event) { 160 | There.playSound('control down'); 161 | event.stopPropagation(); 162 | }).on('mouseup', function() { 163 | There.playSound('control up'); 164 | }); 165 | 166 | $('.footer .button').on('mouseover', function() { 167 | There.playSound('control rollover'); 168 | }).on('mousedown', function(event) { 169 | There.playSound('control down'); 170 | event.stopPropagation(); 171 | }).on('mouseup', function() { 172 | There.playSound('control up'); 173 | }); 174 | 175 | $('.titlebar .buttons .button[data-id="bar"]').on('click', function() { 176 | $('.volume').attr('data-state', 'bar'); 177 | }).on('mousedown', function(event) { 178 | event.stopPropagation(); 179 | }); 180 | 181 | $('.titlebar .buttons .button[data-id="full"]').on('click', function() { 182 | $('.volume').attr('data-state', 'full'); 183 | }).on('mousedown', function(event) { 184 | event.stopPropagation(); 185 | }); 186 | 187 | $('.titlebar .buttons .button[data-id="close"]').on('click', function() { 188 | There.fsCommand('closeWindow'); 189 | }).on('mousedown', function(event) { 190 | event.stopPropagation(); 191 | }); 192 | 193 | $('.footer .button[data-id="mute"]').on('click', function() { 194 | if ($(this).attr('data-enabled') == 0) { 195 | return; 196 | } 197 | There.guiCommand({ 198 | action: 'togglepreference', 199 | pref: 'MuteAllSound', 200 | }); 201 | }); 202 | }); -------------------------------------------------------------------------------- /Resources/shortcutbar/shortcutbar.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .shortcutbar { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:100%; 18 | height:25px; 19 | background-image:url(shortcutbar.png); 20 | background-size:calc(100vw * 532) 100px; 21 | font-size:0px; 22 | } 23 | 24 | .shortcutbar .buttons.big .button { 25 | display:inline-block; 26 | margin-left:1px; 27 | width:26px; 28 | height:25px; 29 | background-image:url(shortcutbar.png); 30 | } 31 | 32 | .shortcutbar[data-emotionsflashing="1"] .buttons.big .button[data-id="actions"] { 33 | animation-name:blink; 34 | animation-duration:1s; 35 | animation-timing-function:steps(1); 36 | animation-iteration-count:5; 37 | } 38 | 39 | @keyframes blink { 40 | 0% { 41 | background-position-y:0px; 42 | } 43 | 50% { 44 | background-position-y:-25px; 45 | } 46 | } 47 | 48 | .shortcutbar .buttons.big .button:hover { 49 | background-position-y:-25px; 50 | } 51 | 52 | .shortcutbar .buttons.big .button:hover:active { 53 | background-position-y:-50px; 54 | } 55 | 56 | .shortcutbar .buttons.big .button[data-id="there"] { 57 | margin-left:7px; 58 | background-position-x:-52px; 59 | } 60 | 61 | .shortcutbar .buttons.big .button[data-id="browser"] { 62 | background-position-x:-78px; 63 | } 64 | 65 | .shortcutbar .buttons.big .button[data-id="im"] { 66 | background-position-x:-104px; 67 | } 68 | 69 | .shortcutbar .buttons.big .button[data-id="actions"] { 70 | background-position-x:-130px; 71 | } 72 | 73 | .shortcutbar .buttons.big .button[data-id="happening"] { 74 | background-position-x:-156px; 75 | } 76 | 77 | .shortcutbar .buttons.big .button[data-id="activities"] { 78 | background-position-x:-182px; 79 | } 80 | 81 | .shortcutbar .buttons.big .button[data-id="map"] { 82 | background-position-x:-208px; 83 | } 84 | 85 | .shortcutbar .buttons.big .button[data-id="places"] { 86 | background-position-x:-234px; 87 | } 88 | 89 | .shortcutbar .buttons.big .button[data-id="information"] { 90 | background-position-x:-260px; 91 | } 92 | 93 | .shortcutbar .buttons.big .button[data-id="exit"] { 94 | background-position-x:-286px; 95 | } 96 | 97 | .shortcutbar .buttons.big .button[data-id="shop"] { 98 | background-position-x:-312px; 99 | } 100 | 101 | .shortcutbar .buttons.big .button[data-id="auctions"] { 102 | background-position-x:-338px; 103 | } 104 | 105 | .shortcutbar .buttons.big .button[data-id="changeme"] { 106 | background-position-x:-364px; 107 | } 108 | 109 | .shortcutbar .buttons.big .button[data-id="organizer"] { 110 | background-position-x:-390px; 111 | } 112 | 113 | .shortcutbar .buttons.big .button[data-id="aerial"] { 114 | background-position-x:-26px; 115 | } 116 | 117 | .shortcutbar .buttons.big .button[data-id="mirror"] { 118 | background-position-x:-468px; 119 | } 120 | 121 | .shortcutbar .buttons.big .button[data-id="standard"] { 122 | background-position-x:0px; 123 | } 124 | 125 | .shortcutbar .buttons.big .button[data-id="topics"] { 126 | background-position-x:-416px; 127 | } 128 | 129 | .shortcutbar .buttons.big .button[data-id="guide"] { 130 | background-position-x:-442px; 131 | } 132 | 133 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="information"], 134 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="information"]:hover, 135 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="information"]:active, 136 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="exit"], 137 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="exit"]:hover, 138 | .shortcutbar[data-thisplaceenabled="0"] .buttons.big .button[data-id="exit"]:active { 139 | background-position-y:-75px; 140 | pointer-events:none; 141 | } 142 | 143 | .shortcutbar[data-instandardview="0"][data-inbodyview="0"] .buttons.big .button[data-id="aerial"] { 144 | display:none; 145 | } 146 | 147 | .shortcutbar:not([data-instandardview="0"][data-inbodyview="0"]) .buttons.big .button[data-id="standard"][data-index="0"] { 148 | display:none; 149 | } 150 | 151 | .shortcutbar[data-instandardview="0"][data-inbodyview="1"] .buttons.big .button[data-id="mirror"] { 152 | display:none; 153 | } 154 | 155 | .shortcutbar:not([data-instandardview="0"][data-inbodyview="1"]) .buttons.big .button[data-id="standard"][data-index="1"] { 156 | display:none; 157 | } 158 | 159 | .shortcutbar[data-aerialviewallowed="0"] .buttons.big .button[data-id="aerial"], 160 | .shortcutbar[data-aerialviewallowed="0"] .buttons.big .button[data-id="aerial"]:hover, 161 | .shortcutbar[data-aerialviewallowed="0"] .buttons.big .button[data-id="aerial"]:active { 162 | background-position-y:-75px; 163 | pointer-events:none; 164 | } 165 | 166 | .shortcutbar .buttons.big .separator { 167 | display:inline-block; 168 | margin-left:6px; 169 | margin-right:5px; 170 | width:3px; 171 | height:23px; 172 | background-color:#62848c; 173 | border:1px solid #62848c; 174 | border-right-color:#fff; 175 | box-sizing:border-box; 176 | } 177 | 178 | .shortcutbar .buttons.big .window { 179 | position:relative; 180 | display:inline-block; 181 | width:129px; 182 | height:25px; 183 | } 184 | 185 | .shortcutbar .buttons.big .window .icon { 186 | display:inline-block; 187 | margin-left:2px; 188 | width:24px; 189 | height:25px; 190 | background-image:url(shortcutbar.png); 191 | background-position-x:-494px; 192 | background-position-y:-75px; 193 | } 194 | 195 | .shortcutbar .buttons.big .window .text { 196 | display:inline-block; 197 | width:102px; 198 | height:25px; 199 | } 200 | 201 | .shortcutbar .buttons.small { 202 | position:absolute; 203 | right:6px; 204 | top:5px; 205 | height:24px; 206 | } 207 | 208 | .shortcutbar .buttons.small .button { 209 | display:inline-block; 210 | margin-left:1px; 211 | width:14px; 212 | height:13px; 213 | border:1px solid #666; 214 | border-radius:3px; 215 | background-image:url(shortcutbar.png); 216 | background-position-x:-518px; 217 | } 218 | 219 | .shortcutbar .buttons.small .button[data-id="close"] { 220 | background-position-y:0px; 221 | } 222 | 223 | .shortcutbar .buttons.small .button[data-id="close"]:hover { 224 | background-position-y:-13px; 225 | } 226 | 227 | .shortcutbar .buttons.small .button[data-id="close"]:hover:active { 228 | background-position-y:-26px; 229 | } 230 | 231 | .shortcutbar .buttons.small .button[data-id="help"] { 232 | background-position-y:-39px; 233 | } 234 | 235 | .shortcutbar .buttons.small .button[data-id="help"]:hover { 236 | background-position-y:-52px; 237 | } 238 | 239 | .shortcutbar .buttons.small .button[data-id="help"]:hover:active { 240 | background-position-y:-65px; 241 | } -------------------------------------------------------------------------------- /Resources/sg/hud_spades.css: -------------------------------------------------------------------------------- 1 | .left .panel[data-id="game"] .logo { 2 | position:absolute; 3 | left:2px; 4 | top:1px; 5 | width:60px; 6 | height:54px; 7 | background-image:url(logo_spades.png); 8 | } 9 | 10 | .left .panel[data-id="game"] .button[data-id="newgame"] { 11 | position:absolute; 12 | left:67px; 13 | top:7px; 14 | } 15 | 16 | .left .panel[data-id="game"] .button[data-id="rules"] { 17 | position:absolute; 18 | left:67px; 19 | top:34px; 20 | } 21 | 22 | .left .panel[data-id="game"] .button[data-id="deal"], 23 | .left .panel[data-id="game"] .button[data-id="play"], 24 | .left .panel[data-id="game"] .button[data-id="taketrick"] { 25 | position:absolute; 26 | left:135px; 27 | top:7px; 28 | display:none; 29 | } 30 | 31 | .left .panel[data-id="game"] .bid:first-of-type { 32 | position:absolute; 33 | left:7px; 34 | top:13px; 35 | font-size:0px; 36 | } 37 | 38 | .left .panel[data-id="game"] .bid:last-of-type { 39 | position:absolute; 40 | left:7px; 41 | top:33px; 42 | font-size:0px; 43 | } 44 | 45 | .left .panel[data-id="game"] .bid .button { 46 | margin-right:5px; 47 | } 48 | 49 | .left .panel[data-id="tricks"] .players { 50 | position:absolute; 51 | left:0px; 52 | right:0px; 53 | top:5px; 54 | font-size:0px; 55 | display:flex; 56 | flex-direction:row; 57 | justify-content:space-around; 58 | } 59 | 60 | .left .panel[data-id="score"] .section { 61 | position:absolute; 62 | top:5px; 63 | width:96px; 64 | height:50px; 65 | border:1px solid #000; 66 | font-size:0px; 67 | } 68 | 69 | .left .panel[data-id="score"] .section[data-team="1"] { 70 | left:5px; 71 | } 72 | 73 | .left .panel[data-id="score"] .section[data-team="2"] { 74 | right:5px; 75 | background-color:rgba(0, 0, 0, 0.15); 76 | } 77 | 78 | .left .panel[data-id="score"] .section .players { 79 | position:absolute; 80 | top:0px; 81 | width:100%; 82 | height:24px; 83 | line-height:12px; 84 | font-size:11px; 85 | text-align:center; 86 | color:#fff; 87 | display:flex; 88 | align-items:center; 89 | justify-content:center; 90 | } 91 | 92 | .left .panel[data-id="score"] .section .score { 93 | position:absolute; 94 | bottom:0px; 95 | width:100%; 96 | height:24px; 97 | line-height:12px; 98 | font-size:11px; 99 | text-align:center; 100 | color:#fff; 101 | display:flex; 102 | flex-direction:row; 103 | justify-content:space-around; 104 | } 105 | 106 | .left .panel[data-id="score"] .section .score div { 107 | display:inline-block; 108 | width:50%; 109 | } 110 | 111 | .left .panel[data-id="score"] .section .score div span { 112 | display:block; 113 | } 114 | 115 | .left .panel[data-id="tricks"] .players .player { 116 | display:inline-block; 117 | width:47px; 118 | height:14px; 119 | padding:0px 2px; 120 | font-size:8px; 121 | color:#fff; 122 | text-align:center; 123 | white-space:nowrap; 124 | text-overflow:ellipsis; 125 | overflow:hidden; 126 | transform:scaleY(1.2) 127 | } 128 | 129 | .left .panel[data-id="tricks"] .cardset { 130 | position:absolute; 131 | left:0px; 132 | top:17px; 133 | width:100%; 134 | font-size:0px; 135 | display:flex; 136 | flex-direction:row; 137 | justify-content:space-around; 138 | } 139 | 140 | .left .panel[data-id="tricks"] .cardset .card { 141 | margin:0px; 142 | box-shadow:none; 143 | } 144 | 145 | .hud[data-gamestate="bid"][data-isactiveplayer="1"] .left .panel[data-id="game"] .logo, 146 | .hud[data-gamestate="bid"][data-isactiveplayer="1"] .left .panel[data-id="game"] .button[data-id="newgame"], 147 | .hud[data-gamestate="bid"][data-isactiveplayer="1"] .left .panel[data-id="game"] .button[data-id="rules"] { 148 | display:none; 149 | } 150 | 151 | .hud:not([data-gamestate="bid"][data-isactiveplayer="1"]) .left .panel[data-id="game"] .bid { 152 | display:none; 153 | } 154 | 155 | .hud[data-gamestate="pregame"] .left .panel[data-id="game"] .button[data-id="deal"], 156 | .hud[data-gamestate="deal"] .left .panel[data-id="game"] .button[data-id="deal"] { 157 | display:inline-block; 158 | } 159 | 160 | .hud[data-gamestate="play"] .left .panel[data-id="game"] .button[data-id="play"], 161 | .hud[data-gamestate="playsend"] .left .panel[data-id="game"] .button[data-id="play"] { 162 | display:inline-block; 163 | } 164 | 165 | .hud[data-gamestate="taketrick"] .left .panel[data-id="game"] .button[data-id="taketrick"], 166 | .hud[data-gamestate="endgame"] .left .panel[data-id="game"] .button[data-id="taketrick"] { 167 | display:inline-block; 168 | } 169 | 170 | .middle { 171 | display:flex; 172 | flex-direction:row; 173 | height:100%; 174 | } 175 | 176 | .middle .table { 177 | position:relative; 178 | height:100%; 179 | } 180 | 181 | .middle .table::before { 182 | position:absolute; 183 | left:0px; 184 | right:0px; 185 | height:100%; 186 | border-left:1px solid rgba(255, 255, 255, 0.25); 187 | border-right:1px solid rgba(0, 0, 0, 0.5); 188 | content:' '; 189 | pointer-events:none; 190 | } 191 | 192 | .middle .table[data-player="1"] { 193 | width:340px; 194 | } 195 | 196 | .middle .table:not([data-player="1"]) { 197 | width:68px; 198 | border-left:1px solid #000; 199 | } 200 | 201 | .middle .table[data-player="1"] .title { 202 | position:absolute; 203 | left:7px; 204 | top:5px; 205 | width:250px; 206 | height:14px; 207 | line-height:14px; 208 | font-size:11px; 209 | font-weight:bold; 210 | color:#fff; 211 | text-align:center; 212 | } 213 | 214 | .middle .table[data-player="1"] .cardset[data-id^="hand"] { 215 | position:absolute; 216 | left:7px; 217 | top:20px; 218 | width:260px; 219 | height:37px; 220 | text-align:center; 221 | } 222 | 223 | .middle .table[data-player="1"] .message { 224 | position:absolute; 225 | left:11px; 226 | bottom:6px; 227 | width:250px; 228 | height:27px; 229 | line-height:12px; 230 | font-size:11px; 231 | color:#fff; 232 | display:flex; 233 | align-items:flex-end; 234 | justify-content:space-evenly; 235 | } 236 | 237 | .middle .table:not([data-player="1"]) { 238 | background-color:rgba(0, 0, 0, 0.15); 239 | } 240 | 241 | .middle .table .player { 242 | position:absolute; 243 | right:2px; 244 | top:5px; 245 | width:64px; 246 | height:14px; 247 | line-height:14px; 248 | font-size:11px; 249 | font-weight:bold; 250 | color:#fff; 251 | text-align:center; 252 | white-space:nowrap; 253 | text-overflow:ellipsis; 254 | overflow:hidden; 255 | } 256 | 257 | .middle .table .turn { 258 | position:absolute; 259 | right:19px; 260 | top:20px; 261 | width:28px; 262 | height:26px; 263 | display:none; 264 | } 265 | 266 | .middle .table .turn[data-visible="1"] { 267 | display:inline-block; 268 | background-image:url(hud.png); 269 | background-position:0px -272px; 270 | } 271 | 272 | .middle .table .cardset[data-id^="played"] { 273 | position:absolute; 274 | right:20px; 275 | top:20px; 276 | width:27px; 277 | height:37px; 278 | text-align:center; 279 | } 280 | 281 | .middle .table .cardset[data-id^="played"] .card { 282 | box-shadow:none; 283 | } 284 | 285 | .middle .table .cardset[data-id^="played"][data-highlighted="1"] { 286 | margin:-2px -2px 0px 0px; 287 | border:2px solid #fa0; 288 | border-radius:6px; 289 | } 290 | 291 | .middle .table .stats { 292 | position:absolute; 293 | right:4px; 294 | bottom:6px; 295 | width:60px; 296 | line-height:12px; 297 | font-size:11px; 298 | color:#fff; 299 | } 300 | 301 | .middle .table .stats div { 302 | display:flex; 303 | flex-direction:row; 304 | justify-content:space-between; 305 | } 306 | -------------------------------------------------------------------------------- /SetupThereEdge/SetupThereEdge.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | from version import VERSION 7 | from uuid import UUID 8 | from win32com.shell import shell, shellcon 9 | from win32com.client import pythoncom as com 10 | from argparse import ArgumentParser 11 | 12 | 13 | if __name__ == '__main__': 14 | print('ThereEdge %s\n' % VERSION) 15 | for i, argv in enumerate(sys.argv): 16 | if argv.startswith('--desktop='): 17 | if argv[10:] == '1': 18 | sys.argv[i] = '--desktop' 19 | else: 20 | del sys.argv[i] 21 | break 22 | parser = ArgumentParser() 23 | parser.add_argument('--path', type=str, default='.', help='client path') 24 | parser.add_argument('--pause', action='store_true', help='pause on error') 25 | parser.add_argument('--patch', action='store_true', help='patch the client') 26 | parser.add_argument('--register', action='store_true', help='register the libraries') 27 | parser.add_argument('--unregister', action='store_true', help='unregister the libraries') 28 | parser.add_argument('--startmenu', action='store_true', help='create a start menu shortcut') 29 | parser.add_argument('--desktop', action='store_true', help='create a desktop shortcut') 30 | parser.add_argument('--clean', action='store_true', help='clean up patched client and shortcuts') 31 | args = parser.parse_args() 32 | if not args.patch and not args.register and not args.unregister and not args.startmenu and not args.desktop and not args.clean: 33 | parser.print_usage() 34 | sys.exit(0) 35 | try: 36 | args.path = args.path.rstrip() 37 | if args.patch: 38 | uuid_pairs = [ 39 | [1, UUID('D27CDB6B-AE6D-11CF-96B8-444553540000'), UUID('682E7C31-6CE3-4FB3-9883-479ED34CB1B9')], # ShockwaveFlash TypeLib 40 | [1, UUID('D27CDB6C-AE6D-11CF-96B8-444553540000'), UUID('6B3DDCCB-B754-4D73-9E49-65B4AAD1EEAF')], # IShockwaveFlash 41 | [1, UUID('D27CDB6D-AE6D-11CF-96B8-444553540000'), UUID('543E9E91-C412-43DD-A12A-3F5AA34758D1')], # IShockwaveFlashEvents 42 | [1, UUID('D27CDB6E-AE6D-11CF-96B8-444553540000'), UUID('71E05279-CB7A-496A-8EE9-D700955CA40C')], # ShockwaveFlash CLSID 43 | [0, UUID('EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B'), UUID('E792F884-FF4C-4563-92FE-ADAEA759F2EA')], # WebBrowser TypeLib 44 | [0, UUID('EAB22AC1-30C1-11CF-A7EB-0000C05BAE0B'), UUID('2170EFE4-F488-4F5C-A844-469080351EC4')], # IWebBrowser 45 | [0, UUID('0002DF05-0000-0000-C000-000000000046'), UUID('825FAF08-F4AF-46BE-8F65-4D6F73185E60')], # IWebBrowserApp 46 | [2, UUID('D30C1661-CDAF-11d0-8A3E-00C04FC9E26E'), UUID('65CD626F-FDC0-417C-BAAC-CC90E4FEBA16')], # IWebBrowser2 47 | [0, UUID('EAB22AC2-30C1-11CF-A7EB-0000C05BAE0B'), UUID('DD68CD11-4932-435D-AE85-554A61B4D6F5')], # DWebBrowserEvents 48 | [1, UUID('34A715A0-6587-11D0-924A-0020AFC7AC4D'), UUID('A6601B01-4A9A-458A-A9D4-AA4207757056')], # DWebBrowserEvents2 49 | [2, UUID('8856F961-340A-11D0-A96B-00C04FD705A2'), UUID('4D5AA1D8-B2D9-49D0-860E-8DAF2EC2CF0C')], # WebBrowser CLSID 50 | ] 51 | with open(os.path.join(args.path, 'There.exe'), 'rb') as file: 52 | data = file.read() 53 | for uuid_pair in uuid_pairs: 54 | if data.find(uuid_pair[2].bytes_le) >= 0: 55 | raise RuntimeError('The patch has already been applied.') 56 | for uuid_pair in uuid_pairs: 57 | index = 0 58 | for i in range(uuid_pair[0]): 59 | f = data[index:].find(uuid_pair[1].bytes_le) 60 | if f < 0: 61 | raise RuntimeError('The patch cannot be used with this version of There.') 62 | index += f 63 | data = data[:index] + uuid_pair[2].bytes_le + data[index + 16:] 64 | index += 1 65 | if data[index:].find(uuid_pair[1].bytes_le) >= 0: 66 | raise RuntimeError('The patch cannot be used with this version of There.') 67 | with open(os.path.join(args.path, 'ThereEdge.exe'), 'wb') as file: 68 | file.write(data) 69 | print('The patch was applied successfully.') 70 | proxy_names = ['BrowserProxy', 'FlashProxy'] 71 | if args.register: 72 | for name in proxy_names: 73 | rc = os.system('regsvr32 /s "%s.dll"' % os.path.join(args.path, name)) 74 | if rc != 0: 75 | raise RuntimeError('Registration of %s failed (%s).' % (name, rc)) 76 | else: 77 | print('%s was registered successfully.' % name) 78 | if args.unregister: 79 | for name in proxy_names: 80 | rc = os.system('regsvr32 /u /s "%s.dll"' % os.path.join(args.path, name)) 81 | if rc != 0 and rc != 5: 82 | print('Unregistration of %s failed (%s).' % (name, rc)) 83 | else: 84 | print('%s was unregistered successfully.' % name) 85 | if args.startmenu or args.desktop: 86 | shortcut = com.CoCreateInstance(shell.CLSID_ShellLink, None, com.CLSCTX_INPROC_SERVER, shell.IID_IShellLink) 87 | file = shortcut.QueryInterface(com.IID_IPersistFile) 88 | file.Load(os.path.join(args.path, 'Sign on to There.lnk')) 89 | shortcut.SetWorkingDirectory(os.path.abspath(args.path)) 90 | shortcut.SetPath(os.path.join(os.path.abspath(args.path), 'ThereEdge.exe')) 91 | count = 0 92 | if args.startmenu: 93 | try: 94 | os.mkdir(os.path.join(shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAMS, 0, 0), 'There')) 95 | except FileExistsError: 96 | pass 97 | file.Save(os.path.join(shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAMS, 0, 0), 'There', 'There (Edge).lnk'), 0) 98 | count += 1 99 | if args.desktop: 100 | try: 101 | file.Save(os.path.join(shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0), 'There (Edge).lnk'), 0) 102 | count += 1 103 | except Exception as error: 104 | print(error) 105 | if count == 1: 106 | print('The shortcut was created successfully.') 107 | elif count > 1: 108 | print('The shortcuts were created successfully.') 109 | if args.clean: 110 | count = 0 111 | paths = [os.path.join(os.path.abspath(args.path), 'ThereEdge.exe')] 112 | try: 113 | paths.append(os.path.join(shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAMS, 0, 0), 'There', 'There (Edge).lnk')) 114 | except Exception: 115 | pass 116 | try: 117 | paths.append(os.path.join(shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0), 'There (Edge).lnk')) 118 | except Exception: 119 | pass 120 | for path in paths: 121 | if os.path.isfile(path): 122 | os.remove(path) 123 | count += 1 124 | if count == 1: 125 | print('1 file was removed successfully.') 126 | elif count > 1: 127 | print('%s files were removed successfully.' % count) 128 | except Exception as error: 129 | print(error) 130 | if args.pause: 131 | input('Press Enter to continue.\n') 132 | sys.exit(1) 133 | sys.exit(0) -------------------------------------------------------------------------------- /Resources/messagebar/messagebar.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:tahoma, sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .messagebar { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:800px; 18 | height:56px; 19 | font-size:0px; 20 | overflow:hidden; 21 | } 22 | 23 | .messagebar .animator { 24 | position:absolute; 25 | left:0px; 26 | top:56px; 27 | transition-property:top; 28 | } 29 | 30 | .messagebar[data-msgbaropened="0"] .animator { 31 | transition-duration:200ms; 32 | } 33 | 34 | .messagebar[data-msgbaropened="1"] .animator { 35 | top:0px; 36 | transition-duration:300ms; 37 | } 38 | 39 | .messagebar .left { 40 | position:relative; 41 | display:inline-block; 42 | width:44px; 43 | height:54px; 44 | border:1px solid #666; 45 | border-right-color:#999; 46 | border-bottom-color:#808080; 47 | border-top-left-radius:10px; 48 | background-image:url(messagebar.png); 49 | background-position:0px 0px; 50 | } 51 | 52 | .messagebar .middle { 53 | position:relative; 54 | display:inline-block; 55 | width:708px; 56 | height:54px; 57 | border-top:1px solid #666; 58 | border-bottom:1px solid #808080; 59 | background-color:#fffc; 60 | } 61 | 62 | .messagebar[data-flash="1"] .middle { 63 | animation-name:flash; 64 | animation-duration:200ms; 65 | animation-timing-function:steps(1); 66 | animation-iteration-count:2; 67 | } 68 | 69 | @keyframes flash { 70 | 0% { 71 | background-color:#fffc; 72 | } 73 | 50% { 74 | background-color:#fff; 75 | } 76 | } 77 | 78 | .messagebar .right { 79 | position:relative; 80 | display:inline-block; 81 | width:44px; 82 | height:54px; 83 | border:1px solid #666; 84 | border-left-color:#999; 85 | border-bottom-color:#808080; 86 | border-top-right-radius:10px; 87 | background-image:url(messagebar.png); 88 | background-position:-44px 0px; 89 | } 90 | 91 | .messagebar .left .icon { 92 | position:absolute; 93 | left:12px; 94 | top:16px; 95 | width:22px; 96 | height:22px; 97 | } 98 | 99 | .messagebar .left .icon[data-id="Receive"] { 100 | background-image:url(messagebar.png); 101 | background-position:0px -115px; 102 | } 103 | 104 | .messagebar .left .icon[data-id="QuestInfo"] { 105 | background-image:url(messagebar.png); 106 | background-position:0px -137px; 107 | } 108 | 109 | .messagebar .left .icon[data-id="Im"] { 110 | background-image:url(messagebar.png); 111 | background-position:0px -159px; 112 | } 113 | 114 | .messagebar .left .icon[data-id="PermDeny"] { 115 | background-image:url(messagebar.png); 116 | background-position:0px -181px; 117 | } 118 | 119 | .messagebar .left .icon[data-id="PermAllow"] { 120 | background-image:url(messagebar.png); 121 | background-position:0px -203px; 122 | } 123 | 124 | .messagebar .left .icon[data-id="Summon"] { 125 | background-image:url(messagebar.png); 126 | background-position:-44px -115px; 127 | } 128 | 129 | .messagebar .left .icon[data-id="Info"] { 130 | background-image:url(messagebar.png); 131 | background-position:-44px -137px; 132 | } 133 | 134 | .messagebar .left .icon[data-id="Error"] { 135 | background-image:url(messagebar.png); 136 | background-position:-44px -159px; 137 | } 138 | 139 | .messagebar .left .icon[data-state="0"] { 140 | background-position-x:-22px; 141 | } 142 | 143 | .messagebar .left .icon[data-id="information"][data-state="0"], 144 | .messagebar .left .icon[data-id="attention"][data-state="0"], 145 | .messagebar .left .icon[data-id="aral"][data-state="0"] { 146 | background-position-x:-66px; 147 | } 148 | 149 | .messagebar .left .icon[data-id="MktgInfo"] { 150 | left:3px; 151 | top:11px; 152 | width:41px; 153 | height:43px; 154 | background-image:url(messagebar.png); 155 | background-position:-47px -182px; 156 | } 157 | 158 | .messagebar .message { 159 | position:absolute; 160 | left:7px; 161 | top:3px; 162 | width:667px; 163 | height:48px; 164 | font-size:11px; 165 | font-weight:bold; 166 | line-height:15px; 167 | } 168 | 169 | .messagebar .message[data-buttoncount="1"] { 170 | width:615px; 171 | } 172 | 173 | .messagebar .message[data-buttoncount="2"] { 174 | width:563px; 175 | } 176 | 177 | .messagebar .message[data-buttoncount="3"] { 178 | width:512px; 179 | } 180 | 181 | .messagebar .buttons.big { 182 | position:absolute; 183 | right:22px; 184 | top:17px; 185 | } 186 | 187 | .messagebar .buttons.big .button { 188 | display:inline-block; 189 | margin-left:2px; 190 | width:49px; 191 | height:18px; 192 | line-height:18px; 193 | padding:1px; 194 | border:1px solid #666; 195 | border-radius:6px; 196 | vertical-align:top; 197 | background-image:url(messagebar.png); 198 | background-position:0px -55px; 199 | font-size:11px; 200 | text-align:center; 201 | } 202 | 203 | .messagebar .buttons.big .button:hover { 204 | background-position-y:-75px; 205 | text-shadow:1px 1px 1px #0006; 206 | } 207 | 208 | .messagebar .buttons.big .button:hover:active { 209 | background-position-y:-95px; 210 | text-shadow:0px 0px 2px #0006; 211 | padding:2px 0px 0px 2px; 212 | } 213 | 214 | .messagebar .buttons.big .button[data-id=""] { 215 | display:none; 216 | } 217 | 218 | .messagebar .buttons.arrows { 219 | position:absolute; 220 | right:0px; 221 | top:0px; 222 | width:15px; 223 | height:54px; 224 | border-left:1px solid #999; 225 | background-color:#fff; 226 | } 227 | 228 | .messagebar .buttons.arrows .button { 229 | position:absolute; 230 | left:0px; 231 | width:15px; 232 | height:26px; 233 | } 234 | 235 | .messagebar .buttons.arrows .button[data-id="up"] { 236 | top:0px; 237 | border-bottom:1px solid #999; 238 | } 239 | 240 | .messagebar .buttons.arrows .button[data-id="down"] { 241 | bottom:1px; 242 | } 243 | 244 | .messagebar .buttons.arrows .button svg { 245 | position:absolute; 246 | left:4px; 247 | top:11px; 248 | } 249 | 250 | .messagebar .buttons.arrows .button:hover svg { 251 | filter:drop-shadow(1px 1px 1px #0006); 252 | } 253 | 254 | .messagebar .buttons.arrows .button:hover:active svg { 255 | left:5px; 256 | top:12px; 257 | filter:drop-shadow(0px 0px 2px #0006); 258 | } 259 | 260 | .messagebar .buttons.arrows .button[data-enabled="0"], 261 | .messagebar .buttons.arrows .button[data-enabled="0"]:hover, 262 | .messagebar .buttons.arrows .button[data-enabled="0"]:active { 263 | pointer-events:none; 264 | } 265 | 266 | .messagebar .buttons.arrows .button[data-enabled="0"] svg, 267 | .messagebar .buttons.arrows .button[data-enabled="0"]:hover svg, 268 | .messagebar .buttons.arrows .button[data-enabled="0"]:active svg { 269 | left:4px; 270 | top:11px; 271 | filter:none; 272 | } 273 | 274 | .messagebar .buttons.arrows .button[data-enabled="0"] svg path, 275 | .messagebar .buttons.arrows .button[data-enabled="0"]:hover svg path, 276 | .messagebar .buttons.arrows .button[data-enabled="0"]:active svg path { 277 | fill:#aaa; 278 | } 279 | 280 | .messagebar .buttons.small { 281 | position:absolute; 282 | right:5px; 283 | top:20px; 284 | } 285 | 286 | .messagebar .buttons.small .button { 287 | display:inline-block; 288 | margin-left:1px; 289 | width:14px; 290 | height:13px; 291 | border:1px solid #666; 292 | border-radius:3px; 293 | background-image:url(messagebar.png); 294 | } 295 | 296 | .messagebar .buttons.small .button[data-id="close"] { 297 | background-position-x:-51px; 298 | background-position-y:-55px; 299 | } 300 | 301 | .messagebar .buttons.small .button[data-id="close"]:hover { 302 | background-position-y:-68px; 303 | } 304 | 305 | .messagebar .buttons.small .button[data-id="close"]:hover:active { 306 | background-position-y:-81px; 307 | } 308 | 309 | .messagebar .buttons.small .button[data-id="close"][data-enabled="0"], 310 | .messagebar .buttons.small .button[data-id="close"][data-enabled="0"]:hover, 311 | .messagebar .buttons.small .button[data-id="close"][data-enabled="0"]:active { 312 | background-position-y:-94px; 313 | pointer-events:none; 314 | } 315 | 316 | .messagebar .buttons.small .button[data-id="help"] { 317 | background-position-x:-65px; 318 | background-position-y:-55px; 319 | } 320 | 321 | .messagebar .buttons.small .button[data-id="help"]:hover { 322 | background-position-y:-68px; 323 | } 324 | 325 | .messagebar .buttons.small .button[data-id="help"]:hover:active { 326 | background-position-y:-81px; 327 | } 328 | 329 | .messagebar .buttons.small .button[data-id="help"][data-enabled="0"], 330 | .messagebar .buttons.small .button[data-id="help"][data-enabled="0"]:hover, 331 | .messagebar .buttons.small .button[data-id="help"][data-enabled="0"]:active { 332 | background-position-y:-94px; 333 | pointer-events:none; 334 | } -------------------------------------------------------------------------------- /FlashProxy/FlashRequestProxy.cpp: -------------------------------------------------------------------------------- 1 | #define _ATL_APARTMENT_THREADED 2 | #define _ATL_NO_AUTOMATIC_NAMESPACE 3 | #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS 4 | #define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW 5 | 6 | #pragma warning (disable:26812) 7 | #pragma warning (disable:28251) 8 | 9 | #include "platform.h" 10 | #include "resource.h" 11 | #include "shlwapi.h" 12 | #include "wininet.h" 13 | #include "atlbase.h" 14 | #include "atlcom.h" 15 | #include "atlctl.h" 16 | #include "atlstr.h" 17 | #include "atlsafe.h" 18 | #include "WebView2.h" 19 | #include "FlashRequestProxy.h" 20 | 21 | FlashRequestProxy::FlashRequestProxy(ICoreWebView2Environment *environment, ICoreWebView2WebResourceRequestedEventArgs *args): 22 | m_refCount(1), 23 | m_environment(environment), 24 | m_args(args), 25 | m_deferral(), 26 | m_stream(), 27 | m_binding(), 28 | m_mimeType(), 29 | m_contentType(), 30 | m_size(0), 31 | m_position(0) 32 | { 33 | } 34 | 35 | FlashRequestProxy::~FlashRequestProxy() 36 | { 37 | if (m_deferral != nullptr) 38 | m_deferral->Complete(); 39 | } 40 | 41 | HRESULT FlashRequestProxy::Init(IServiceProvider *serviceProvider, WCHAR *uri) 42 | { 43 | if (FAILED(m_args->GetDeferral(&m_deferral)) || m_deferral == nullptr) 44 | return E_FAIL; 45 | 46 | DetermineContentType(uri); 47 | 48 | CComPtr bindHost; 49 | if (FAILED(serviceProvider->QueryService(IID_IBindHost, &bindHost))) 50 | return E_FAIL; 51 | 52 | CComPtr moniker; 53 | if (FAILED(bindHost->CreateMoniker(uri, this, &moniker, 0))) 54 | return E_FAIL; 55 | 56 | if (FAILED(moniker->BindToStorage(this, nullptr, IID_IStream, (void**)&m_stream))) 57 | return E_FAIL; 58 | 59 | return S_OK; 60 | } 61 | 62 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::QueryInterface(REFIID riid, void **object) 63 | { 64 | if (IsEqualIID(riid, IID_IBindStatusCallback)) 65 | { 66 | AddRef(); 67 | *object = static_cast(this); 68 | return S_OK; 69 | } 70 | 71 | if (IsEqualIID(riid, IID_IStream)) 72 | { 73 | AddRef(); 74 | *object = static_cast(this); 75 | return S_OK; 76 | } 77 | 78 | if (IsEqualIID(riid, IID_IUnknown)) 79 | { 80 | AddRef(); 81 | *object = static_cast(this); 82 | return S_OK; 83 | } 84 | 85 | *object = nullptr; 86 | return E_NOINTERFACE; 87 | } 88 | 89 | ULONG STDMETHODCALLTYPE FlashRequestProxy::AddRef() 90 | { 91 | return ++m_refCount; 92 | } 93 | 94 | ULONG STDMETHODCALLTYPE FlashRequestProxy::Release() 95 | { 96 | ULONG refCount = m_refCount--; 97 | 98 | if (refCount == 0) 99 | delete this; 100 | 101 | return refCount; 102 | } 103 | 104 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::GetObjectParam(LPOLESTR pszKey, IUnknown **ppunk) 105 | { 106 | if (wcscmp(pszKey, L"_BSCB_Holder_") == 0) 107 | { 108 | *ppunk = static_cast(this); 109 | return S_OK; 110 | } 111 | 112 | return E_NOINTERFACE; 113 | } 114 | 115 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::OnStartBinding(DWORD dwReserved, IBinding *pib) 116 | { 117 | if (pib == nullptr) 118 | return E_INVALIDARG; 119 | 120 | m_binding = pib; 121 | return S_OK; 122 | } 123 | 124 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) 125 | { 126 | switch (ulStatusCode) 127 | { 128 | case BINDSTATUS_MIMETYPEAVAILABLE: 129 | { 130 | if (szStatusText == nullptr) 131 | return E_INVALIDARG; 132 | 133 | m_mimeType = szStatusText; 134 | break; 135 | } 136 | 137 | default: 138 | break; 139 | } 140 | 141 | return S_OK; 142 | } 143 | 144 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::OnStopBinding(HRESULT hresult, LPCWSTR szError) 145 | { 146 | if (FAILED(hresult) || m_deferral != nullptr) 147 | { 148 | if (m_environment == nullptr || m_args == nullptr) 149 | return E_FAIL; 150 | 151 | if (szError == nullptr) 152 | szError = L"Internal Server Error"; 153 | 154 | CComPtr response; 155 | if (FAILED(m_environment->CreateWebResourceResponse(nullptr, 500, szError, L"", &response)) || response == nullptr) 156 | return E_FAIL; 157 | 158 | if (FAILED(m_args->put_Response(response))) 159 | return E_FAIL; 160 | 161 | m_deferral->Complete(); 162 | m_deferral.Release(); 163 | } 164 | 165 | Release(); 166 | 167 | return S_OK; 168 | } 169 | 170 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::GetBindInfo(DWORD *grfBINDF, BINDINFO *pbindinfo) 171 | { 172 | if (grfBINDF == nullptr || pbindinfo == nullptr) 173 | return E_INVALIDARG; 174 | 175 | *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_NO_UI | BINDF_SILENTOPERATION; 176 | 177 | pbindinfo->dwBindVerb = BINDVERB_GET; 178 | pbindinfo->dwOptions = BINDINFO_OPTIONS_ENABLE_UTF8; 179 | pbindinfo->dwCodePage = CP_UTF8; 180 | 181 | return S_OK; 182 | } 183 | 184 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) 185 | { 186 | if (pformatetc == nullptr || pstgmed == nullptr) 187 | return E_INVALIDARG; 188 | 189 | if ((grfBSCF & BSCF_LASTDATANOTIFICATION) == 0) 190 | return S_OK; 191 | 192 | if ((grfBSCF & BSCF_DATAFULLYAVAILABLE) == 0) 193 | return S_OK; 194 | 195 | if (m_mimeType.Length() == 0) 196 | return E_FAIL; 197 | 198 | if (m_environment == nullptr || m_args == nullptr || m_deferral == nullptr || m_stream == nullptr) 199 | return E_FAIL; 200 | 201 | if (pformatetc->cfFormat == CF_TEXT) 202 | { 203 | m_size = dwSize - 1; 204 | m_contentType = m_mimeType; 205 | } 206 | else 207 | { 208 | m_size = dwSize; 209 | } 210 | 211 | CComPtr response; 212 | if (FAILED(m_environment->CreateWebResourceResponse(this, 200, L"OK", nullptr, &response)) || response == nullptr) 213 | return E_FAIL; 214 | 215 | CComPtr headers; 216 | if (FAILED(response->get_Headers(&headers)) || headers == nullptr) 217 | return E_FAIL; 218 | 219 | if (FAILED(headers->AppendHeader(L"Content-Type", m_contentType))) 220 | return E_FAIL; 221 | 222 | if (FAILED(m_args->put_Response(response))) 223 | return E_FAIL; 224 | 225 | m_deferral->Complete(); 226 | m_deferral.Release(); 227 | 228 | return S_OK; 229 | } 230 | 231 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::Read(void *pv, ULONG cb, ULONG *pcbRead) 232 | { 233 | if (pv == nullptr || pcbRead == nullptr || m_stream == nullptr) 234 | return E_INVALIDARG; 235 | 236 | HRESULT hr = m_stream->Read(pv, cb, pcbRead); 237 | if (SUCCEEDED(hr)) 238 | { 239 | if (*pcbRead > m_size) 240 | *pcbRead = m_size; 241 | 242 | m_size -= *pcbRead; 243 | m_position += *pcbRead; 244 | } 245 | 246 | return hr; 247 | } 248 | 249 | HRESULT STDMETHODCALLTYPE FlashRequestProxy::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) 250 | { 251 | if (dwOrigin == STREAM_SEEK_SET && dlibMove.QuadPart == 0 && m_position == 0) 252 | { 253 | if (plibNewPosition != nullptr) 254 | plibNewPosition->QuadPart = 0; 255 | 256 | return S_OK; 257 | } 258 | 259 | return E_NOTIMPL; 260 | } 261 | 262 | HRESULT FlashRequestProxy::DetermineContentType(const WCHAR *uri) 263 | { 264 | const WCHAR *ext = wcsrchr(uri, L'.'); 265 | if (ext == nullptr) 266 | return E_FAIL; 267 | 268 | ext++; 269 | 270 | if (_wcsicmp(ext, L"css") == 0) 271 | { 272 | m_contentType = L"text/css"; 273 | return S_OK; 274 | } 275 | 276 | if (_wcsicmp(ext, L"html") == 0) 277 | { 278 | m_contentType = L"text/html"; 279 | return S_OK; 280 | } 281 | 282 | if (_wcsicmp(ext, L"js") == 0) 283 | { 284 | m_contentType = L"application/javascript"; 285 | return S_OK; 286 | } 287 | 288 | if (_wcsicmp(ext, L"png") == 0) 289 | { 290 | m_contentType = L"image/png"; 291 | return S_OK; 292 | } 293 | 294 | if (_wcsicmp(ext, L"swf") == 0) 295 | { 296 | m_contentType = L"application/vnd.adobe.flash.movie"; 297 | return S_OK; 298 | } 299 | 300 | if (_wcsicmp(ext, L"wasm") == 0) 301 | { 302 | m_contentType = L"application/wasm"; 303 | return S_OK; 304 | } 305 | 306 | if (_wcsicmp(ext, L"xml") == 0) 307 | { 308 | m_contentType = L"text/xml"; 309 | return S_OK; 310 | } 311 | 312 | //Log(L"Content type unknown for .%s\n", ext); 313 | return E_FAIL; 314 | } -------------------------------------------------------------------------------- /Resources/sg/ak_texasholdem_hud.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Habanero Holdem 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 |
16 |
17 |
Game
18 |
Play
19 |
Messages
20 |
21 |
22 |
23 | 24 |
New Game
25 |
Rules
26 |
Options
27 |
Profile
28 |
29 |
30 |
31 | 32 |
Continue
33 |
Place Chips
34 |
Refill Stack
35 |
Deal
36 |
Deal Flop
37 |
Deal Turn
38 |
Deal River
39 |
Blind
40 |
Check
41 |
Call
42 |
Show Cards
43 |
Game Over
44 |
New Deal
45 |
Refill Stack
46 |
Go In
47 |
Sit Out
48 |
Bet
49 |
Bet
50 |
Raise
51 |
Raise
52 |
Buy Chips
53 |
All In
54 |
Go In
55 |
Sit Out
56 |
Buy Chips
57 |
Fold
58 |
New Game
59 |
60 |
61 |
Show your cards?
62 |
63 |
Yes
64 |
No
65 |
66 |
67 |
68 |
Are you sure?
69 |
70 |
Yes
71 |
No
72 |
73 |
74 |
75 |
Set bet amount
76 |
77 |
78 |
79 |
+
80 |
81 |
82 |
Bet
83 |
Cancel
84 |
85 |
86 |
87 |
Set raise amount
88 |
89 |
90 |
91 |
+
92 |
93 |
94 |
Raise
95 |
Cancel
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
Fold
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
Fold
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
Fold
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
Fold
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
Fold
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
Fold
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
Fold
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
Fold
199 |
200 |
201 |
202 |
203 |
Pot: --
204 |
Chips: --
205 |
Winnings: --
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 | 226 | -------------------------------------------------------------------------------- /Resources/sg/hud_cracked.css: -------------------------------------------------------------------------------- 1 | .left .panel[data-id="game"] .logo { 2 | position:absolute; 3 | left:5px; 4 | top:0px; 5 | width:54px; 6 | height:60px; 7 | background-image:url(logo_cracked.png); 8 | } 9 | 10 | .left .panel[data-id="game"] .button[data-id="newgame"] { 11 | position:absolute; 12 | left:67px; 13 | top:7px; 14 | } 15 | 16 | .left .panel[data-id="game"] .button[data-id="rules"] { 17 | position:absolute; 18 | left:67px; 19 | top:34px; 20 | } 21 | 22 | .left .panel[data-id="game"] .button[data-id="start"], 23 | .left .panel[data-id="game"] .button[data-id="submit"] { 24 | position:absolute; 25 | left:135px; 26 | top:7px; 27 | display:none; 28 | } 29 | 30 | .hud[data-gamestate="start"] .left .panel[data-id="game"] .button[data-id="start"] { 31 | display:inline-block; 32 | } 33 | 34 | .hud[data-gamestate="play"] .left .panel[data-id="game"] .button[data-id="submit"] { 35 | display:inline-block; 36 | } 37 | 38 | .middle { 39 | display:flex; 40 | flex-direction:row; 41 | height:100%; 42 | } 43 | 44 | .middle .section { 45 | position:relative; 46 | height:100%; 47 | font-size:0px; 48 | } 49 | 50 | .middle .section::before { 51 | position:absolute; 52 | left:0px; 53 | right:0px; 54 | height:100%; 55 | border-left:1px solid rgba(255, 255, 255, 0.25); 56 | border-right:1px solid rgba(0, 0, 0, 0.5); 57 | content:' '; 58 | pointer-events:none; 59 | } 60 | 61 | .middle .section:nth-of-type(1) { 62 | width:212px; 63 | } 64 | 65 | .middle .section:nth-of-type(1) .title { 66 | position:absolute; 67 | left:11px; 68 | right:11px; 69 | top:5px; 70 | height:17px; 71 | line-height:17px; 72 | font-size:11px; 73 | font-weight:bold; 74 | text-align:center; 75 | color:#000; 76 | display:none; 77 | } 78 | 79 | .hud[data-gamestate="start"] .middle .section:nth-of-type(1) .title { 80 | background-color:rgba(255, 255, 255, 0.45); 81 | display:inline-block; 82 | } 83 | 84 | .hud[data-gamestate="play"] .middle .section:nth-of-type(1) .title, 85 | .hud[data-gamestate="endgame"] .middle .section:nth-of-type(1) .title { 86 | background-color:var(--color, rgba(255, 255, 255, 0.45)); 87 | display:inline-block; 88 | } 89 | 90 | .middle .section:nth-of-type(1) input[type="text"] { 91 | position:absolute; 92 | left:11px; 93 | top:29px; 94 | width:calc(100% - 28px); 95 | height:21px; 96 | border:1px solid #000; 97 | border-radius:0px; 98 | font-size:14px; 99 | font-weight:bold; 100 | outline:none; 101 | color:#fff; 102 | background-color:rgba(0, 0, 0, 0.5); 103 | display:none; 104 | } 105 | 106 | .hud[data-gamestate="play"] .section:nth-of-type(1) input[type="text"] { 107 | display:block; 108 | } 109 | 110 | .hud[data-gamestate="play"] .section:nth-of-type(1) input[type="text"][data-status="1"] { 111 | background-color:rgba(0, 255, 0, 0.5); 112 | } 113 | 114 | .hud[data-gamestate="play"] .section:nth-of-type(1) input[type="text"][data-status="2"] { 115 | background-color:rgba(255, 0, 0, 0.5); 116 | } 117 | 118 | .middle .section:nth-of-type(1) input[type="text"]::placeholder { 119 | color:#fff; 120 | opacity:0.75; 121 | font-weight:normal; 122 | } 123 | 124 | .hud:not([data-isactiveplayer="1"]) .middle .section:nth-of-type(1) input[type="text"]::placeholder { 125 | visibility:hidden; 126 | } 127 | 128 | .middle .section:nth-of-type(1) .message { 129 | position:absolute; 130 | left:11px; 131 | right:11px; 132 | bottom:6px; 133 | height:27px; 134 | line-height:12px; 135 | font-size:11px; 136 | color:#fff; 137 | display:flex; 138 | align-items:flex-end; 139 | justify-content:space-evenly; 140 | } 141 | 142 | .middle .section:nth-of-type(2) { 143 | width:59px; 144 | border-left:1px solid #000; 145 | border-right:1px solid #000; 146 | } 147 | 148 | .middle .section:nth-of-type(2) .title { 149 | position:absolute; 150 | left:2px; 151 | right:2px; 152 | top:4px; 153 | font-size:11px; 154 | text-align:center; 155 | white-space:nowrap; 156 | color:#fff; 157 | } 158 | 159 | .middle .section:nth-of-type(2) .egg { 160 | position:absolute; 161 | left:12px; 162 | top:27px; 163 | width:35px; 164 | height:50px; 165 | transform-origin:bottom; 166 | background-image:url(hud_cracked.png); 167 | background-position-x:0px; 168 | display:none; 169 | } 170 | 171 | .hud[data-timer="1"] .middle .section:nth-of-type(2) .egg { 172 | background-position-y:0px; 173 | display:inline-block; 174 | } 175 | 176 | .hud[data-timer="2"] .middle .section:nth-of-type(2) .egg { 177 | background-position-y:-50px; 178 | display:inline-block; 179 | animation-name:shake; 180 | animation-duration:3s; 181 | animation-timing-function:ease-in-out; 182 | animation-iteration-count:infinite; 183 | } 184 | 185 | .hud[data-timer="3"] .middle .section:nth-of-type(2) .egg { 186 | background-position-y:-100px; 187 | display:inline-block; 188 | } 189 | 190 | @keyframes shake { 191 | 0% { 192 | transform:rotate(0deg); 193 | } 194 | 2% { 195 | transform:rotate(6deg); 196 | } 197 | 4% { 198 | transform:rotate(-5.4deg); 199 | } 200 | 6% { 201 | transform:rotate(4.8deg); 202 | } 203 | 8% { 204 | transform:rotate(-4.2deg); 205 | } 206 | 10% { 207 | transform:rotate(0deg); 208 | } 209 | 100% { 210 | transform:rotate(0deg); 211 | } 212 | } 213 | 214 | .middle .section:nth-of-type(3) { 215 | width:274px; 216 | display:flex; 217 | flex-direction:column; 218 | justify-content:space-evenly; 219 | } 220 | 221 | .middle .section:nth-of-type(3) .board { 222 | position:relative; 223 | width:100%; 224 | height:25%; 225 | border-bottom:1px solid #000; 226 | display:flex; 227 | flex-direction:row; 228 | justify-content:flex-start; 229 | } 230 | 231 | .middle .section:nth-of-type(3) .board::before { 232 | position:absolute; 233 | left:1px; 234 | right:1px; 235 | top:0px; 236 | bottom:0px; 237 | border-top:1px solid rgba(255, 255, 255, 0.25); 238 | border-bottom:1px solid rgba(0, 0, 0, 0.5); 239 | content:' '; 240 | pointer-events:none; 241 | } 242 | 243 | .middle .section:nth-of-type(3) .board:not([data-player="1"]) { 244 | background-color:rgba(0, 0, 0, 0.15); 245 | } 246 | 247 | .middle .section:nth-of-type(3) .board:last-of-type { 248 | border-bottom:none; 249 | } 250 | 251 | .middle .section:nth-of-type(3) .board .column { 252 | height:100%; 253 | display:flex; 254 | align-items:center; 255 | padding:0px 5px; 256 | } 257 | 258 | .middle .section:nth-of-type(3) .board .column span { 259 | font-size:11px; 260 | color:#fff; 261 | white-space:nowrap; 262 | text-overflow:ellipsis; 263 | overflow:hidden; 264 | } 265 | 266 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) { 267 | width:82px; 268 | justify-content:flex-start; 269 | border-right:1px solid rgba(0, 0, 0, 0.5); 270 | } 271 | 272 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .turn { 273 | width:14px; 274 | height:13px; 275 | flex-shrink:0; 276 | display:none; 277 | } 278 | 279 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .turn[data-visible="0"], 280 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .turn[data-visible="1"] { 281 | display:inline-block; 282 | margin-right:2px; 283 | } 284 | 285 | 286 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .turn[data-visible="1"] { 287 | background-image:url(hud.png); 288 | background-position:-52px -285px; 289 | } 290 | 291 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .icon[data-id="win"] { 292 | width:13px; 293 | height:12px; 294 | flex-shrink:0; 295 | margin-right:2px; 296 | background-image:url(hud_cracked.png); 297 | background-position:0px -150px; 298 | } 299 | 300 | .middle .section:nth-of-type(3) .board .column:nth-of-type(1) .player[data-leader="1"] { 301 | font-style:italic; 302 | } 303 | 304 | .middle .section:nth-of-type(3) .board .column:nth-of-type(2) { 305 | width:80px; 306 | justify-content:flex-start; 307 | border-left:1px solid rgba(255, 255, 255, 0.25); 308 | border-right:1px solid rgba(0, 0, 0, 0.5); 309 | } 310 | 311 | .middle .section:nth-of-type(3) .board .column:nth-of-type(3) { 312 | width:30px; 313 | justify-content:flex-end; 314 | border-left:1px solid rgba(255, 255, 255, 0.25); 315 | border-right:1px solid rgba(0, 0, 0, 0.5); 316 | } 317 | 318 | .middle .section:nth-of-type(3) .board .column:nth-of-type(4) { 319 | flex-grow:1; 320 | justify-content:flex-end; 321 | border-left:1px solid rgba(255, 255, 255, 0.25); 322 | } 323 | 324 | .middle .section:nth-of-type(3) .board[data-status="1"] .column:nth-of-type(2) span, 325 | .middle .section:nth-of-type(3) .board[data-status="1"] .column:nth-of-type(3) span { 326 | color:#0f0; 327 | } 328 | 329 | .middle .section:nth-of-type(3) .board[data-status="2"] .column:nth-of-type(2) span, 330 | .middle .section:nth-of-type(3) .board[data-status="2"] .column:nth-of-type(3) span { 331 | color:#f00; 332 | font-weight:bold; 333 | } 334 | 335 | .middle .section:nth-of-type(3) .board[data-status="3"] .column:nth-of-type(2) span, 336 | .middle .section:nth-of-type(3) .board[data-status="3"] .column:nth-of-type(3) span { 337 | color:#ffa500; 338 | } 339 | 340 | .button.mood { 341 | display:none; 342 | } -------------------------------------------------------------------------------- /Resources/communicator/communicator.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .communicator { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:200px; 18 | height:257px; 19 | background-color:rgba(200, 200, 200, 0.6); 20 | border-radius:5px; 21 | overflow:hidden; 22 | transition-property:opacity; 23 | transition-duration:250ms; 24 | } 25 | 26 | .communicator[data-teleporting="1"] { 27 | opacity:0; 28 | pointer-events:none; 29 | } 30 | 31 | .communicator[data-state="bar"] { 32 | height:25px; 33 | } 34 | 35 | .communicator .titlebar { 36 | position:absolute; 37 | left:0px; 38 | right:0px; 39 | top:0px; 40 | height:23px; 41 | line-height:23px; 42 | font-size:0px; 43 | padding-left:5px; 44 | border-top-left-radius:5px; 45 | border-top-right-radius:5px; 46 | border:1px solid #808080; 47 | background-image:url(communicator.png); 48 | background-position:0px 0px; 49 | } 50 | 51 | .communicator[data-state="bar"] .titlebar { 52 | border-bottom-left-radius:5px; 53 | border-bottom-right-radius:5px; 54 | background-position:0px -23px; 55 | } 56 | 57 | .communicator .titlebar span { 58 | font-size:13px; 59 | } 60 | 61 | .communicator .titlebar .buttons { 62 | position:absolute; 63 | top:4px; 64 | right:5px; 65 | display:inline-block; 66 | font-size:0px; 67 | } 68 | 69 | .communicator .titlebar .buttons .button { 70 | display:inline-block; 71 | margin-left:1px; 72 | width:14px; 73 | height:13px; 74 | border:1px solid #666; 75 | border-radius:3px; 76 | background-image:url(communicator.png); 77 | background-position-x:-198px; 78 | z-index:2; 79 | } 80 | 81 | .communicator .titlebar .buttons .button[data-id="close"] { 82 | background-position-y:0px; 83 | } 84 | 85 | .communicator .titlebar .buttons .button[data-id="help"] { 86 | background-position-y:-13px; 87 | } 88 | 89 | .communicator .titlebar .buttons .button[data-id="bar"], 90 | .communicator .titlebar .buttons .button[data-id="full"] { 91 | display:none; 92 | } 93 | 94 | .communicator[data-state="full"] .titlebar .buttons .button[data-id="bar"] { 95 | display:inline-block; 96 | background-position-y:-26px; 97 | } 98 | 99 | .communicator[data-state="bar"] .titlebar .buttons .button[data-id="full"] { 100 | display:inline-block; 101 | background-position-y:-39px; 102 | } 103 | 104 | .communicator .titlebar .buttons .button:hover { 105 | background-position-x:-212px; 106 | } 107 | 108 | .communicator .titlebar .buttons .button:hover:active { 109 | background-position-x:-226px; 110 | } 111 | 112 | .communicator .items { 113 | position:absolute; 114 | left:6px; 115 | right:6px; 116 | top:31px; 117 | bottom:43px; 118 | background-color:#fff; 119 | border:1px solid #666; 120 | overflow-y:scroll; 121 | } 122 | 123 | .communicator .items .item { 124 | position:relative; 125 | width:calc(100% + 7px * (var(--max-indent, 0) - var(--indent, 0))); 126 | height:20px; 127 | padding-left:calc(7px * var(--indent, 0)); 128 | display:flex; 129 | flex-direction:row; 130 | justify-content:flex-start; 131 | align-items:center; 132 | } 133 | 134 | .communicator .items .item[data-hover="1"], 135 | .communicator .items .item:hover { 136 | background-color:#f0f0f0; 137 | } 138 | 139 | .communicator .items .item .icon { 140 | width:17px; 141 | height:16px; 142 | margin-left:8px; 143 | box-sizing:border-box; 144 | } 145 | 146 | .communicator .items .item[data-type] .icon { 147 | background-image:url(communicator.png); 148 | background-clip:content-box; 149 | } 150 | 151 | .communicator .items .item[data-type="drawer"][data-drawer="open"] .icon { 152 | height:13px; 153 | background-position:0px -77px; 154 | } 155 | 156 | .communicator .items .item[data-type="drawer"][data-drawer="closed"] .icon { 157 | height:13px; 158 | padding-left:3px; 159 | background-position:-15px -77px; 160 | } 161 | 162 | .communicator .items .item[data-type="avatar"][data-client="3d"][data-status="available"] .icon { 163 | height:15px; 164 | padding-left:3px; 165 | background-position:-30px -75px; 166 | } 167 | 168 | .communicator .items .item[data-type="avatar"][data-client="3d"][data-status="away"] .icon { 169 | height:16px; 170 | padding-left:3px; 171 | background-position:-76px -74px; 172 | } 173 | 174 | .communicator .items .item[data-type="avatar"][data-client="3d"][data-status="dnd"] .icon { 175 | height:16px; 176 | padding-left:4px; 177 | padding-right:2px; 178 | background-position:-90px -74px; 179 | } 180 | 181 | .communicator .items .item[data-type="avatar"][data-client="3d"][data-status="offline"] .icon { 182 | height:14px; 183 | padding-left:3px; 184 | background-position:-103px -76px; 185 | } 186 | 187 | .communicator .items .item[data-type="avatar"][data-client="thereim"][data-status="available"] .icon { 188 | height:10px; 189 | padding-left:6px; 190 | padding-right:1px; 191 | background-position:-115px -80px; 192 | } 193 | 194 | .communicator .items .item[data-type="avatar"][data-client="thereim"][data-status="away"] .icon { 195 | height:10px; 196 | padding-left:6px; 197 | padding-right:1px; 198 | background-position:-148px -80px; 199 | } 200 | 201 | .communicator .items .item[data-type="avatar"][data-client="thereim"][data-status="dnd"] .icon { 202 | height:10px; 203 | padding-left:6px; 204 | padding-right:1px; 205 | background-position:-159px -80px; 206 | } 207 | 208 | .communicator .items .item[data-type="avatar"][data-client="thereim"][data-status="offline"] .icon { 209 | height:10px; 210 | padding-left:6px; 211 | padding-right:1px; 212 | background-position:-170px -80px; 213 | } 214 | 215 | .communicator .items .item .name { 216 | font-size:11px; 217 | margin:0px 8px; 218 | white-space:nowrap; 219 | } 220 | 221 | .communicator .footer { 222 | position:absolute; 223 | left:0px; 224 | right:0px; 225 | bottom:0px; 226 | height:37px; 227 | padding-right:6px; 228 | font-size:0px; 229 | display:flex; 230 | justify-content:flex-end; 231 | pointer-events:none; 232 | } 233 | 234 | .communicator[data-state="bar"] .footer { 235 | display:none; 236 | } 237 | 238 | .communicator .footer .button { 239 | margin-left:3px; 240 | height:18px; 241 | line-height:18px; 242 | padding:1px; 243 | border:1px solid #666; 244 | border-radius:6px; 245 | vertical-align:top; 246 | background-image:url(communicator.png); 247 | background-position-y:-31px; 248 | font-size:11px; 249 | text-align:center; 250 | pointer-events:all; 251 | } 252 | 253 | .communicator .footer .button:hover { 254 | text-shadow:1px 1px 1px #0006; 255 | } 256 | 257 | .communicator .footer .button:hover:active { 258 | text-shadow:0px 0px 2px #0006; 259 | padding:2px 0px 0px 2px; 260 | } 261 | 262 | .communicator .footer .button[data-enabled="0"], 263 | .communicator .footer .button[data-enabled="0"]:hover, 264 | .communicator .footer .button[data-enabled="0"]:active { 265 | color:#7dbbca; 266 | text-shadow:1px 1px 0px rgba(255, 255, 255, 0.5); 267 | pointer-events:none; 268 | } 269 | 270 | .communicator .footer .button.medium { 271 | width:57px; 272 | background-position:0px -54px; 273 | } 274 | 275 | .communicator .footer .button.medium:hover { 276 | background-position-x:-59px; 277 | } 278 | 279 | .communicator .footer .button.medium:hover:active { 280 | background-position-x:-118px; 281 | } 282 | 283 | .communicator .footer .button.medium[data-enabled="0"], 284 | .communicator .footer .button.medium[data-enabled="0"]:hover, 285 | .communicator .footer .button.medium[data-enabled="0"]:active { 286 | background-position-x:-177px; 287 | } 288 | 289 | .communicator .footer .bar { 290 | position:absolute; 291 | left:0px; 292 | right:0px; 293 | bottom:0px; 294 | height:8px; 295 | font-size:0px; 296 | border-bottom-left-radius:5px; 297 | border-bottom-right-radius:5px; 298 | border:1px solid #808080; 299 | background-image:url(communicator.png); 300 | background-position:0px -46px; 301 | } 302 | 303 | .contextmenu { 304 | display:none; 305 | position:absolute; 306 | left:105px; 307 | top:74px; 308 | box-shadow:2px 2px 3px #0006; 309 | z-index:5; 310 | } 311 | 312 | .communicator[data-state="full"] .contextmenu[data-active="1"] { 313 | display:block; 314 | } 315 | 316 | .contextmenu .item { 317 | margin-top:-1px; 318 | width:88px; 319 | height:14px; 320 | background-color:#fff; 321 | font-size:11px; 322 | border:1px solid #666; 323 | white-space:nowrap; 324 | overflow:hidden; 325 | } 326 | 327 | .contextmenu .item:first-of-type { 328 | margin-top:0px; 329 | } 330 | 331 | .contextmenu .item:hover { 332 | background-color:#f0f0f0; 333 | } 334 | 335 | .contextmenu .item:hover:active { 336 | background-color:#c4f0f8; 337 | } 338 | 339 | .contextmenu .item[data-enabled="0"]:hover, 340 | .contextmenu .item[data-enabled="0"]:active, 341 | .contextmenu .item[data-enabled="0"] { 342 | color:#ccc; 343 | background-color:#fff; 344 | pointer-events:none; 345 | } 346 | 347 | .contextmenu .item .sound { 348 | padding-left:6px; 349 | width:62px; 350 | height:14px; 351 | pointer-events:auto; 352 | } -------------------------------------------------------------------------------- /Resources/emotionsbar/emotionsbar.js: -------------------------------------------------------------------------------- 1 | There.init({ 2 | onReady: function() { 3 | There.fsCommand('setStageWidthHeight', { 4 | width: Number(There.variables.there_windowwidth ?? 800), 5 | height: 24, 6 | }); 7 | 8 | There.fsCommand('setWidthHeight', { 9 | width: Number(There.variables.there_windowwidth ?? 800), 10 | height: 24, 11 | }); 12 | 13 | There.fsCommand('setTextureBitDepth', { 14 | depth: 32, 15 | }); 16 | }, 17 | 18 | onVariable: function(name, value) { 19 | if (name == 'there_windowwidth') { 20 | There.fsCommand('setStageWidthHeight', { 21 | width: Number(value), 22 | height: 24, 23 | }); 24 | 25 | There.fsCommand('setWidthHeight', { 26 | width: Number(value), 27 | height: 24, 28 | }); 29 | } 30 | 31 | if (name == 'there_ready' && value == 1) { 32 | There.fetchEmotionsXml(); 33 | } 34 | 35 | if (name == 'there_voicetoggle' || name == 'there_voiceisspeaking' || name == 'there_voicehandfree') { 36 | $('.emotionsbar').attr(name.replace('there_', 'data-'), value); 37 | } 38 | }, 39 | 40 | fetchEmotionsXml: function() { 41 | There.data.ident = Math.random(); 42 | let query = { 43 | Oid: 0, 44 | request: There.data.ident, 45 | }; 46 | if (There.data.version != undefined) { 47 | query.lastVer = There.data.version; 48 | } 49 | There.fetch({ 50 | path: '/VersionedXmlSvc/emotionBarData', 51 | query: query, 52 | throttle: 60, 53 | dataType: 'xml', 54 | success: There.onEmotionsXml, 55 | complete: function() { 56 | There.setNamedTimer('fetch', 1000, There.fetchEmotionsXml); 57 | }, 58 | }); 59 | }, 60 | 61 | onEmotionsXml: function(xml) { 62 | const xmlAnswer = xml.getElementsByTagName('Answer')[0]; 63 | const xmlResult = xmlAnswer.getElementsByTagName('Result')[0]; 64 | if (xmlResult.childNodes[0].nodeValue != 1) { 65 | return; 66 | } 67 | const xmlVersion = xmlAnswer.getElementsByTagName('version')[0]; 68 | There.data.version = xmlVersion.childNodes[0].nodeValue; 69 | const divOrigSelected = $('.emotionsbar .bank[data-selected="1"]').first(); 70 | $('.emotionsbar .banks').empty(); 71 | $('.emotionsbar .emotions').empty(); 72 | const xmlData = xmlAnswer.getElementsByTagName('EmotionsBarData')[0]; 73 | for (let xmlBank of xmlData.getElementsByTagName('Bank')) { 74 | let divBank = $('
'); 75 | $(divBank).text(xmlBank.getElementsByTagName('Title')[0].childNodes[0].nodeValue); 76 | $(divBank).attr('data-id', xmlBank.getElementsByTagName('Title')[0].childNodes[0].nodeValue.toLowerCase()); 77 | $(divBank).attr('data-selected', xmlBank.getElementsByTagName('Selected')[0].childNodes[0].nodeValue); 78 | let emotions = []; 79 | for (let xmlEmotion of xmlBank.getElementsByTagName('Emotion')) { 80 | emotions.push({ 81 | id: 'emotion', 82 | text: xmlEmotion.getElementsByTagName('Text')[0].childNodes[0].nodeValue, 83 | enabled: xmlEmotion.getElementsByTagName('Enabled')[0].childNodes[0].nodeValue, 84 | }); 85 | } 86 | $(divBank).data('actions', emotions); 87 | $(divBank).on('click', function() { 88 | There.handleEmotionsBank(this); 89 | }).on('mouseover', function() { 90 | There.playSound('control rollover'); 91 | }).on('mousedown', function() { 92 | There.playSound('control down'); 93 | }).on('mouseup', function() { 94 | There.playSound('control up'); 95 | }); 96 | $('.emotionsbar .banks').append($(divBank)); 97 | } 98 | if(There.variables.there_voiceenabled == 1) { 99 | let divBank = $('
'); 100 | $(divBank).text('Voice'); 101 | $(divBank).attr('data-id', 'voice'); 102 | $(divBank).attr('data-selected', '0'); 103 | $(divBank).data('actions', [{ 104 | id: 'turnhandsfreeon', 105 | text: 'Turn Hands-free On', 106 | enabled: '1', 107 | }, { 108 | id: 'turnhandsfreeoff', 109 | text: 'Turn Hands-free Off', 110 | enabled: '1', 111 | }, { 112 | id: 'talk', 113 | text: 'Talk [PageDn]', 114 | enabled: '1', 115 | }, { 116 | id: 'turnvoiceon', 117 | text: 'Turn Voice On', 118 | enabled: '1', 119 | }, { 120 | id: 'turnvoiceoff', 121 | text: 'Turn Voice Off', 122 | enabled: '1', 123 | }, { 124 | id: 'voicetrainer', 125 | text: 'Voice Trainer', 126 | enabled: '1', 127 | }]); 128 | $(divBank).on('click', function() { 129 | There.handleEmotionsBank(this); 130 | }).on('mouseover', function() { 131 | There.playSound('control rollover'); 132 | }).on('mousedown', function() { 133 | There.playSound('control down'); 134 | }).on('mouseup', function() { 135 | There.playSound('control up'); 136 | }); 137 | $('.emotionsbar .banks').append($(divBank)); 138 | } 139 | const divNewSelected = $('.emotionsbar .bank[data-selected="1"]').first(); 140 | if (divNewSelected.length > 0) { 141 | $(divNewSelected).trigger('click'); 142 | } else if (divOrigSelected.length > 0) { 143 | const id = $(divOrigSelected).attr('data-id'); 144 | $(`.emotionsbar .bank[data-id="${id}"]`).trigger('click'); 145 | } 146 | }, 147 | 148 | handleEmotionsBank: function(divBank) { 149 | $('.emotionsbar .bank').attr('data-selected', '0'); 150 | $(divBank).attr('data-selected', '1'); 151 | $('.emotionsbar .emotions').empty(); 152 | for (let action of $(divBank).data('actions')) { 153 | let divButton = $('
'); 154 | $(divButton).text(action.text); 155 | $(divButton).attr('data-id', action.id); 156 | $(divButton).attr('data-enabled', action.enabled); 157 | if (action.id == 'talk') { 158 | $(divButton).on('mouseover', function() { 159 | There.playSound('control rollover'); 160 | }).on('mousedown', function() { 161 | There.playSound('control down'); 162 | There.guiCommand({ 163 | action: 'voiceTalk', 164 | toggle: '1', 165 | }); 166 | }); 167 | $(document).on('mouseup', function(event) { 168 | There.playSound('control up'); 169 | There.guiCommand({ 170 | action: 'voiceTalk', 171 | toggle: '0', 172 | }); 173 | }); 174 | } else { 175 | $(divButton).on('click', function() { 176 | There.handleEmotionsClick(this); 177 | }).on('mouseover', function() { 178 | There.playSound('control rollover'); 179 | }).on('mousedown', function() { 180 | There.playSound('control down'); 181 | }).on('mouseup', function() { 182 | There.playSound('control up'); 183 | }); 184 | } 185 | $('.emotionsbar .emotions').append($(divButton)); 186 | } 187 | }, 188 | 189 | handleEmotionsClick: function(divButton) { 190 | if ($(divButton).attr('data-enabled') != 1) { 191 | return; 192 | } 193 | switch($(divButton).attr('data-id')) { 194 | case 'emotion': { 195 | There.fsCommand('addChatText', { 196 | text: $(divButton).text(), 197 | }); 198 | break; 199 | } 200 | case 'turnhandsfreeon': { 201 | There.guiCommand({ 202 | action: 'setpreference', 203 | pref: 'VoiceHandsFree', 204 | value: '1', 205 | }); 206 | break; 207 | } 208 | case 'turnhandsfreeoff': { 209 | There.guiCommand({ 210 | action: 'setpreference', 211 | pref: 'VoiceHandsFree', 212 | value: '0', 213 | }); 214 | break; 215 | } 216 | case 'turnvoiceon': { 217 | There.guiCommand({ 218 | action: 'setpreference', 219 | pref: 'VoiceToggle', 220 | value: '1', 221 | }); 222 | break; 223 | } 224 | case 'turnvoiceoff': { 225 | There.guiCommand({ 226 | action: 'setpreference', 227 | pref: 'VoiceToggle', 228 | value: '0', 229 | }); 230 | break; 231 | } 232 | case 'voicetrainer': { 233 | if (There.isWindows()) { 234 | There.guiCommand({ 235 | action: 'outThereWindow', 236 | urlTag: 'VoiceTrainerUrl', 237 | targetName: 'There_Central', 238 | }); 239 | } 240 | if (There.isMacOS()) { 241 | There.guiCommand({ 242 | action: 'voiceTrainer', 243 | }); 244 | } 245 | break; 246 | } 247 | } 248 | }, 249 | }); 250 | 251 | $(document).ready(function() { 252 | $('.emotionsbar .button').on('mouseover', function(event) { 253 | There.playSound('control rollover'); 254 | }).on('mousedown', function(event) { 255 | There.playSound('control down'); 256 | event.stopPropagation(); 257 | }).on('mouseup', function(event) { 258 | There.playSound('control up'); 259 | }); 260 | 261 | $('.emotionsbar .button[data-id="help"]').on('click', function() { 262 | const id = $('.emotionsbar .bank[data-selected="1"]').first().attr('data-id'); 263 | There.fsCommand('browser', { 264 | target: 'There_Help', 265 | urlGen: id == 'voice' ? 'HelpVoiceUrl' : 'HelpEmotionsBarUrl', 266 | }); 267 | }); 268 | 269 | $('.emotionsbar .button[data-id="close"]').on('click', function() { 270 | There.fsCommand('closeWindow'); 271 | }); 272 | }); -------------------------------------------------------------------------------- /Resources/trade/trade.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin:0px; 3 | font-family:sans-serif; 4 | font-size:16px; 5 | color:#000; 6 | cursor:default; 7 | user-select:none; 8 | -webkit-user-select:none; 9 | text-size-adjust:none; 10 | overflow:hidden; 11 | } 12 | 13 | .trade { 14 | position:absolute; 15 | left:0px; 16 | top:0px; 17 | width:372px; 18 | height:256px; 19 | background-color:rgba(200, 200, 200, 0.6); 20 | border-radius:5px; 21 | overflow:hidden; 22 | transition-property:opacity; 23 | transition-duration:250ms; 24 | } 25 | 26 | .trade[data-teleporting="1"] { 27 | opacity:0; 28 | pointer-events:none; 29 | } 30 | 31 | .trade[data-state="bar"] { 32 | height:25px; 33 | } 34 | 35 | .trade .titlebar { 36 | position:absolute; 37 | left:0px; 38 | right:0px; 39 | top:0px; 40 | height:23px; 41 | line-height:23px; 42 | font-size:0px; 43 | padding-left:5px; 44 | border-top-left-radius:5px; 45 | border-top-right-radius:5px; 46 | border:1px solid #808080; 47 | background-image:url(trade.png); 48 | background-position:0px 0px; 49 | } 50 | 51 | .trade[data-state="bar"] .titlebar { 52 | border-bottom-left-radius:5px; 53 | border-bottom-right-radius:5px; 54 | background-position:0px -23px; 55 | } 56 | 57 | .trade .titlebar span { 58 | font-size:13px; 59 | } 60 | 61 | .trade .titlebar .buttons { 62 | position:absolute; 63 | top:4px; 64 | right:5px; 65 | display:inline-block; 66 | font-size:0px; 67 | } 68 | 69 | .trade .titlebar .buttons .button { 70 | display:inline-block; 71 | margin-left:1px; 72 | width:14px; 73 | height:13px; 74 | border:1px solid #666; 75 | border-radius:3px; 76 | background-image:url(trade.png); 77 | background-position-x:-328px; 78 | z-index:2; 79 | } 80 | 81 | .trade .titlebar .buttons .button[data-id="close"] { 82 | background-position-y:-54px; 83 | } 84 | 85 | .trade .titlebar .buttons .button[data-id="help"] { 86 | background-position-y:-67px; 87 | } 88 | 89 | .trade .titlebar .buttons .button[data-id="bar"], 90 | .trade .titlebar .buttons .button[data-id="full"] { 91 | display:none; 92 | } 93 | 94 | .trade[data-state="full"] .titlebar .buttons .button[data-id="bar"] { 95 | display:inline-block; 96 | background-position-y:-80px; 97 | } 98 | 99 | .trade[data-state="bar"] .titlebar .buttons .button[data-id="full"] { 100 | display:inline-block; 101 | background-position-y:-93px; 102 | } 103 | 104 | .trade .titlebar .buttons .button:hover { 105 | background-position-x:-342px; 106 | } 107 | 108 | .trade .titlebar .buttons .button:hover:active { 109 | background-position-x:-356px; 110 | } 111 | 112 | .trade .intro { 113 | position:absolute; 114 | left:0px; 115 | right:0px; 116 | top:28px; 117 | line-height:13px; 118 | font-size:12px; 119 | text-align:center; 120 | } 121 | 122 | .trade .panel { 123 | position:absolute; 124 | top:57px; 125 | width:178px; 126 | height:157px; 127 | border:1px solid #666; 128 | border-radius:4px; 129 | overflow:hidden; 130 | } 131 | 132 | .trade .panel[data-id="give"] { 133 | left:4px; 134 | } 135 | 136 | .trade .panel[data-id="take"] { 137 | right:4px; 138 | } 139 | 140 | .trade .panel .title { 141 | position:absolute; 142 | left:0px; 143 | right:0px; 144 | top:0px; 145 | height:14px; 146 | line-height:14px; 147 | padding:0px 4px; 148 | border-bottom:1px solid #666; 149 | background-color:#c4f0f8; 150 | font-size:11px; 151 | text-align:center; 152 | } 153 | 154 | .trade .panel .items { 155 | position:absolute; 156 | left:0px; 157 | right:0px; 158 | top:15px; 159 | bottom:15px; 160 | background-color:#fff; 161 | overflow-y:scroll; 162 | } 163 | 164 | .trade .panel .items .item { 165 | position:relative; 166 | width:100%; 167 | height:32px; 168 | border-bottom:1px dashed #999; 169 | display:flex; 170 | flex-direction:column; 171 | justify-content:center; 172 | } 173 | 174 | .trade .panel[data-id="give"] .items .item[data-hover="1"], 175 | .trade .panel[data-id="give"] .items .item:hover { 176 | background-color:#f0f0f0; 177 | } 178 | 179 | .trade .panel .items[data-count="2"] .item:last-of-type { 180 | border-bottom:none; 181 | } 182 | 183 | .trade .panel .items .item span { 184 | display:block; 185 | font-size:10px; 186 | margin:0px 8px; 187 | overflow:hidden; 188 | text-overflow:ellipsis; 189 | white-space:nowrap; 190 | } 191 | 192 | .trade .panel .status { 193 | position:absolute; 194 | left:0px; 195 | right:0px; 196 | bottom:0px; 197 | height:14px; 198 | line-height:14px; 199 | padding:0px 4px; 200 | border-top:1px solid #666; 201 | font-size:11px; 202 | text-align:left; 203 | display:none; 204 | } 205 | 206 | .trade:not([data-givestep="2"]):not([data-givestep="3"]):not([data-givestep="4"]) .panel[data-id="give"] .status[data-id="default"], 207 | .trade:not([data-takestep="2"]):not([data-takestep="3"]):not([data-takestep="4"]) .panel[data-id="take"] .status[data-id="default"], 208 | .trade[data-givestep="2"] .panel[data-id="give"] .status[data-id="trading"], 209 | .trade[data-takestep="2"] .panel[data-id="take"] .status[data-id="trading"] { 210 | background-color:#c4f0f8; 211 | display:inline-block; 212 | } 213 | 214 | .trade[data-givestep="3"] .panel[data-id="give"] .status[data-id="offer"], 215 | .trade[data-takestep="3"] .panel[data-id="take"] .status[data-id="offer"] { 216 | background-color:#9d7; 217 | display:inline-block; 218 | } 219 | 220 | .trade[data-givestep="4"] .panel[data-id="give"] .status[data-id="confirmed"], 221 | .trade[data-takestep="4"] .panel[data-id="take"] .status[data-id="confirmed"] { 222 | background-color:#fda; 223 | display:inline-block; 224 | } 225 | 226 | .trade .footer { 227 | position:absolute; 228 | left:0px; 229 | right:0px; 230 | bottom:0px; 231 | height:37px; 232 | padding-left:2px; 233 | font-size:0px; 234 | display:flex; 235 | justify-content:flex-start; 236 | pointer-events:none; 237 | } 238 | 239 | .trade[data-state="bar"] .footer { 240 | display:none; 241 | } 242 | 243 | .trade .footer .button { 244 | margin-left:2px; 245 | height:18px; 246 | line-height:18px; 247 | padding:1px; 248 | border:1px solid #666; 249 | border-radius:6px; 250 | vertical-align:top; 251 | background-image:url(trade.png); 252 | background-position-y:-31px; 253 | font-size:11px; 254 | text-align:center; 255 | pointer-events:all; 256 | display:none; 257 | } 258 | 259 | .trade .footer .button:hover { 260 | text-shadow:1px 1px 1px #0006; 261 | } 262 | 263 | .trade .footer .button:hover:active { 264 | text-shadow:0px 0px 2px #0006; 265 | padding:2px 0px 0px 2px; 266 | } 267 | 268 | .trade .footer .button[data-enabled="0"], 269 | .trade .footer .button[data-enabled="0"]:hover, 270 | .trade .footer .button[data-enabled="0"]:active { 271 | color:#7dbbca; 272 | text-shadow:1px 1px 0px rgba(255, 255, 255, 0.5); 273 | pointer-events:none; 274 | } 275 | 276 | .trade .footer .button.medium { 277 | width:56px; 278 | background-position:0px -54px; 279 | } 280 | 281 | .trade .footer .button.medium:hover { 282 | background-position-x:-58px; 283 | } 284 | 285 | .trade .footer .button.medium:hover:active { 286 | background-position-x:-116px; 287 | } 288 | 289 | .trade .footer .button.medium[data-enabled="0"], 290 | .trade .footer .button.medium[data-enabled="0"]:hover, 291 | .trade .footer .button.medium[data-enabled="0"]:active { 292 | background-position-x:-174px; 293 | } 294 | 295 | .trade .footer .button.huge { 296 | width:114px; 297 | background-position:0px -74px; 298 | } 299 | 300 | .trade .footer .button.huge:hover { 301 | background-position:-116px -74px; 302 | } 303 | 304 | .trade .footer .button.huge:hover:active { 305 | background-position:0px -94px; 306 | } 307 | 308 | .trade .footer .button.huge[data-enabled="0"], 309 | .trade .footer .button.huge[data-enabled="0"]:hover, 310 | .trade .footer .button.huge[data-enabled="0"]:active { 311 | background-position:-116px -94px; 312 | } 313 | 314 | .trade[data-givestep="2"] .footer .button[data-id="offer"] { 315 | display:inline-block; 316 | } 317 | 318 | .trade[data-givestep="3"] .footer .button[data-id="retract"], 319 | .trade[data-givestep="4"] .footer .button[data-id="retract"] { 320 | display:inline-block; 321 | } 322 | 323 | .trade[data-givestep="2"] .footer .button[data-id="confirm"], 324 | .trade[data-givestep="3"] .footer .button[data-id="confirm"], 325 | .trade[data-givestep="4"] .footer .button[data-id="confirm"] { 326 | display:inline-block; 327 | } 328 | 329 | .trade .footer .bar { 330 | position:absolute; 331 | left:0px; 332 | right:0px; 333 | bottom:0px; 334 | height:8px; 335 | font-size:0px; 336 | border-bottom-left-radius:5px; 337 | border-bottom-right-radius:5px; 338 | border:1px solid #808080; 339 | background-image:url(trade.png); 340 | background-position:0px -46px; 341 | } 342 | 343 | .contextmenu { 344 | display:none; 345 | position:absolute; 346 | left:110px; 347 | top:74px; 348 | box-shadow:2px 2px 3px #0006; 349 | z-index:5; 350 | } 351 | 352 | .trade[data-state="full"] .contextmenu[data-active="1"] { 353 | display:block; 354 | } 355 | 356 | .contextmenu .item { 357 | margin-top:-1px; 358 | width:68px; 359 | height:14px; 360 | background-color:#fff; 361 | font-size:11px; 362 | border:1px solid #666; 363 | } 364 | 365 | .contextmenu .item:first-of-type { 366 | margin-top:0px; 367 | } 368 | 369 | .contextmenu .item:hover { 370 | background-color:#f0f0f0; 371 | } 372 | 373 | .contextmenu .item:hover:active { 374 | background-color:#c4f0f8; 375 | } 376 | 377 | .contextmenu .item[data-enabled="0"]:hover, 378 | .contextmenu .item[data-enabled="0"]:active, 379 | .contextmenu .item[data-enabled="0"] { 380 | color:#ccc; 381 | background-color:#fff; 382 | pointer-events:none; 383 | } 384 | 385 | .contextmenu .item .sound { 386 | padding-left:6px; 387 | width:62px; 388 | height:14px; 389 | pointer-events:auto; 390 | } --------------------------------------------------------------------------------