Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
19ed45ac25 | |||
be7fda7c50 | |||
50ea4e61c6 | |||
82439911c6 | |||
0d24fabdf4 | |||
79eea99d19 | |||
c053b72f58 | |||
1a278528a2 | |||
c1a8899d02 | |||
b01d0a8af3 | |||
8cae35ea46 | |||
8307a1ad83 | |||
8af28e46be | |||
2af5adca3d | |||
7300d1caa8 | |||
7c3e28870e | |||
9130707086 | |||
49b23040c6 | |||
522c304b32 | |||
5d5bc82e26 | |||
49b7703334 | |||
706847dd47 | |||
2c566b208b | |||
95be02d4ce | |||
c834a2e6d9 | |||
6a963456ed | |||
c5d3481c47 | |||
2b248a6cef | |||
c9cf6b3f41 | |||
704c56d13f | |||
5085d23dd1 | |||
1675d5d2dc | |||
bf6e0fddd5 | |||
18f6d878e0 | |||
364606f7e9 | |||
b206dd44f0 | |||
d121bbe709 | |||
cfd6470946 | |||
f22f299330 | |||
767b15184f | |||
6e744d228f | |||
a1ab6c96f2 | |||
0ea7ddbd5a | |||
2f54e62c23 | |||
54abef2624 | |||
c5d70514ac | |||
57316cbaee | |||
9d4d145e7f |
@ -1,52 +1,71 @@
|
|||||||
---
|
---
|
||||||
Language: Cpp
|
|
||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
AlignAfterOpenBracket: true
|
AlignAfterOpenBracket: true
|
||||||
AlignEscapedNewlinesLeft: true
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Left
|
||||||
AlignOperands: false
|
AlignOperands: false
|
||||||
AlignTrailingComments: true
|
AlignTrailingComments: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
AllowShortBlocksOnASingleLine: false
|
AllowShortBlocksOnASingleLine: false
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: false
|
AllowShortLoopsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: Inline
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakAfterDefinitionReturnType: false
|
|
||||||
AlwaysBreakTemplateDeclarations: true
|
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
BreakBeforeBraces: Stroustrup
|
AlwaysBreakTemplateDeclarations: true
|
||||||
BreakBeforeBinaryOperators: None
|
|
||||||
BreakBeforeTernaryOperators: true
|
|
||||||
BreakConstructorInitializersBeforeComma: true
|
|
||||||
BinPackParameters: false
|
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Stroustrup
|
||||||
|
BreakBeforeInheritanceComma: true
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakStringLiterals: true
|
||||||
ColumnLimit: 100
|
ColumnLimit: 100
|
||||||
CommentPragmas: ''
|
CommentPragmas: ''
|
||||||
|
CompactNamespaces: false
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
ConstructorInitializerIndentWidth: 2
|
ConstructorInitializerIndentWidth: 2
|
||||||
ContinuationIndentWidth: 2
|
ContinuationIndentWidth: 2
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
FixNamespaceComments: true
|
||||||
ForEachMacros: [ foreach ]
|
ForEachMacros: []
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^("|<)stdafx\.h(pp)?("|>)'
|
||||||
|
Priority: -1
|
||||||
|
- Regex: '^<(W|w)indows.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '(_test|_win|_linux|_mac|_ios|_osx|_null)?$'
|
||||||
IndentCaseLabels: false
|
IndentCaseLabels: false
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
IndentWrappedFunctionNames: false
|
IndentWrappedFunctionNames: false
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
ObjCBlockIndentWidth: 4
|
PenaltyBreakAssignment: 0
|
||||||
ObjCSpaceAfterProperty: true
|
|
||||||
ObjCSpaceBeforeProtocolList: true
|
|
||||||
PenaltyBreakBeforeFirstCallParameter: 1
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
PenaltyBreakComment: 300
|
PenaltyBreakComment: 300
|
||||||
PenaltyBreakString: 1000
|
|
||||||
PenaltyBreakFirstLessLess: 120
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
PenaltyExcessCharacter: 1000000
|
PenaltyExcessCharacter: 1000000
|
||||||
PenaltyReturnTypeOnItsOwnLine: 9999999
|
PenaltyReturnTypeOnItsOwnLine: 9999999
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
@ -59,4 +78,15 @@ SpacesInSquareBrackets: false
|
|||||||
Standard: Cpp11
|
Standard: Cpp11
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
---
|
||||||
|
Language: ObjC
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
ObjCSpaceAfterProperty: true
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
---
|
||||||
|
Language: Java
|
||||||
|
BasedOnStyle: Google
|
||||||
|
BreakAfterJavaFieldAnnotations: true
|
||||||
...
|
...
|
||||||
|
47
.travis.yml
Normal file
47
.travis.yml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
language: cpp
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
- CLANG_FORMAT_SUFFIX="-dummy" # don't use formatting on Travis, this is
|
||||||
|
# needed not to use default 3.5 version
|
||||||
|
# which is too old.
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-5
|
||||||
|
- os: linux
|
||||||
|
env: MATRIX_EVAL="CC=clang-4.0 && CXX=clang++-4.0"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- llvm-toolchain-trusty-4.0
|
||||||
|
packages:
|
||||||
|
- clang-4.0
|
||||||
|
- os: linux
|
||||||
|
env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- llvm-toolchain-trusty-5.0
|
||||||
|
packages:
|
||||||
|
- clang-5.0
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode9
|
||||||
|
|
||||||
|
# prevent Travis from overwriting our CXX variables
|
||||||
|
before_install:
|
||||||
|
- eval "${MATRIX_EVAL}"
|
||||||
|
- echo $CXX
|
||||||
|
|
||||||
|
script:
|
||||||
|
- mkdir build
|
||||||
|
- cd build
|
||||||
|
- cmake -DCLANG_FORMAT_SUFFIX=$CLANG_FORMAT_SUFFIX --config Release ..
|
||||||
|
- cmake --build . -- -j2
|
@ -1,6 +1,10 @@
|
|||||||
cmake_minimum_required (VERSION 3.7.0)
|
cmake_minimum_required (VERSION 3.2.0)
|
||||||
project (DiscordRPC)
|
project (DiscordRPC)
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
option(BUILD_EXAMPLES "Build example apps" ON)
|
||||||
|
|
||||||
# format
|
# format
|
||||||
file(GLOB_RECURSE ALL_SOURCE_FILES
|
file(GLOB_RECURSE ALL_SOURCE_FILES
|
||||||
examples/*.cpp examples/*.h examples/*.c
|
examples/*.cpp examples/*.h examples/*.c
|
||||||
@ -8,22 +12,18 @@ file(GLOB_RECURSE ALL_SOURCE_FILES
|
|||||||
src/*.cpp src/*.h src/*.c
|
src/*.cpp src/*.h src/*.c
|
||||||
)
|
)
|
||||||
|
|
||||||
find_program(CLANG_FORMAT_CMD clang-format)
|
# Set CLANG_FORMAT_SUFFIX if you are using custom clang-format, e.g. clang-format-5.0
|
||||||
|
find_program(CLANG_FORMAT_CMD clang-format${CLANG_FORMAT_SUFFIX})
|
||||||
|
|
||||||
if (CLANG_FORMAT_CMD)
|
if (CLANG_FORMAT_CMD)
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
clangformat
|
clangformat
|
||||||
COMMAND clang-format
|
COMMAND ${CLANG_FORMAT_CMD}
|
||||||
-i -style=file -fallback-style=none
|
-i -style=file -fallback-style=none
|
||||||
${ALL_SOURCE_FILES}
|
${ALL_SOURCE_FILES}
|
||||||
DEPENDS
|
DEPENDS
|
||||||
${ALL_SOURCE_FILES}
|
${ALL_SOURCE_FILES}
|
||||||
)
|
)
|
||||||
else(CLANG_FORMAT_CMD)
|
|
||||||
add_custom_target(
|
|
||||||
clangformat
|
|
||||||
COMMENT "no clang format"
|
|
||||||
)
|
|
||||||
endif(CLANG_FORMAT_CMD)
|
endif(CLANG_FORMAT_CMD)
|
||||||
|
|
||||||
# thirdparty stuff
|
# thirdparty stuff
|
||||||
@ -32,7 +32,7 @@ execute_process(
|
|||||||
ERROR_QUIET
|
ERROR_QUIET
|
||||||
)
|
)
|
||||||
|
|
||||||
find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_SOURCE_DIR}/thirdparty)
|
find_file(RAPIDJSONTEST NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH)
|
||||||
if (NOT RAPIDJSONTEST)
|
if (NOT RAPIDJSONTEST)
|
||||||
message("no rapidjson, download")
|
message("no rapidjson, download")
|
||||||
set(RJ_TAR_FILE ${CMAKE_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz)
|
set(RJ_TAR_FILE ${CMAKE_SOURCE_DIR}/thirdparty/v1.1.0.tar.gz)
|
||||||
@ -44,11 +44,13 @@ if (NOT RAPIDJSONTEST)
|
|||||||
file(REMOVE ${RJ_TAR_FILE})
|
file(REMOVE ${RJ_TAR_FILE})
|
||||||
endif(NOT RAPIDJSONTEST)
|
endif(NOT RAPIDJSONTEST)
|
||||||
|
|
||||||
find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_SOURCE_DIR}/thirdparty)
|
find_file(RAPIDJSON NAMES rapidjson rapidjson-1.1.0 PATHS ${CMAKE_SOURCE_DIR}/thirdparty CMAKE_FIND_ROOT_PATH_BOTH)
|
||||||
|
|
||||||
add_library(rapidjson STATIC IMPORTED ${RAPIDJSON})
|
add_library(rapidjson STATIC IMPORTED ${RAPIDJSON})
|
||||||
|
|
||||||
# add subdirs
|
# add subdirs
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(examples/send-presence)
|
if (BUILD_EXAMPLES)
|
||||||
|
add_subdirectory(examples/send-presence)
|
||||||
|
endif(BUILD_EXAMPLES)
|
||||||
|
65
README.md
65
README.md
@ -1,35 +1,27 @@
|
|||||||
# Discord RPC
|
# Discord RPC
|
||||||
|
|
||||||
This is a lib and quick demos that implement the very minimal subset to show current status, and
|
This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs.
|
||||||
have callbacks for where a more complete game would do more things. You can use the lib directly
|
|
||||||
if you like, or use it as a guide to writing your own if it doesn't suit your game as is.
|
|
||||||
|
|
||||||
PRs/feedback welcome if you have an improvement everyone might want, or can describe how this
|
Included here are some quick demos that implement the very minimal subset to show current status, and
|
||||||
doesn't meet your needs.
|
have callbacks for where a more complete game would do more things (joining, spectating, etc).
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
The most up to date documentation for Rich Presence can always be found in our [developer site](https://discordapp.com/developers/docs/topics/rich-presence)!
|
The most up to date documentation for Rich Presence can always be found in our [developer site](https://discordapp.com/developers/docs/topics/rich-presence)!
|
||||||
|
|
||||||
## Usage
|
## Basic Usage
|
||||||
|
|
||||||
Zeroith, you should be set up to build things because you are a game developer, right?
|
Zeroith, you should be set up to build things because you are a game developer, right?
|
||||||
|
|
||||||
First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me)
|
First, head on over to the [Discord developers site](https://discordapp.com/developers/applications/me) and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init function.
|
||||||
and make yourself an app. Keep track of `Client ID` -- you'll need it here to pass to the init
|
|
||||||
function.
|
|
||||||
|
|
||||||
### From package
|
### From package
|
||||||
|
|
||||||
Download a release package, extract it, add `/include` to your compile includes, `/lib` to your
|
Download a release package for your platform(s) -- they have subdirs with various prebuilt options, select the one you need add `/include` to your compile includes, `/lib` to your linker paths, and link with `discord-rpc`. For the dynamically linked builds, you'll need to ship the associated file along with your game.
|
||||||
linker paths, and link with `discord-rpc`.
|
|
||||||
|
|
||||||
Note that the release packages were compiled using Visual Studio 2015, so the [Visual C++ Redistributable for VS2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145) will be a requirement for your game. If you wish to avoid this dependency, you should compile the libraries yourself using whatever dependencies are already in your game.
|
|
||||||
|
|
||||||
### From repo
|
### From repo
|
||||||
|
|
||||||
There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for
|
There's a [CMake](https://cmake.org/download/) file that should be able to generate the lib for you; Sometimes I use it like this:
|
||||||
you; I use it like this:
|
|
||||||
```sh
|
```sh
|
||||||
cd <path to discord-rpc>
|
cd <path to discord-rpc>
|
||||||
mkdir build
|
mkdir build
|
||||||
@ -37,25 +29,50 @@ you; I use it like this:
|
|||||||
cmake .. -DCMAKE_INSTALL_PREFIX=<path to install discord-rpc to>
|
cmake .. -DCMAKE_INSTALL_PREFIX=<path to install discord-rpc to>
|
||||||
cmake --build . --config Release --target install
|
cmake --build . --config Release --target install
|
||||||
```
|
```
|
||||||
Sometimes I use the generated project files. There are a couple of CMake options you might care about:
|
There is a wrapper build script `build.py` that runs `cmake` with a few different options.
|
||||||
|
|
||||||
|
Usually, I run `build.py` to get things started, then use the generated project files as I work on things.
|
||||||
|
|
||||||
|
There are some CMake options you might care about:
|
||||||
|
|
||||||
| flag | default | does |
|
| flag | default | does |
|
||||||
|------|---------|------|
|
|------|---------|------|
|
||||||
| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself.
|
| `ENABLE_IO_THREAD` | `ON` | When enabled, we start up a thread to do io processing, if disabled you should call `Discord_UpdateConnection` yourself.
|
||||||
| `BUILD_DYNAMIC_LIB` | `OFF` | Build library as a DLL
|
| `USE_STATIC_CRT` | `OFF` | (Windows) Enable to statically link the CRT, avoiding requiring users install the redistributable package. (The prebuilt binaries enable this option)
|
||||||
|
| [`BUILD_SHARED_LIBS`](https://cmake.org/cmake/help/v3.7/variable/BUILD_SHARED_LIBS.html) | `OFF` | Build library as a DLL
|
||||||
|
|
||||||
|
## Continuous Builds
|
||||||
|
|
||||||
|
Why do we have three of these? Three times the fun!
|
||||||
|
|
||||||
|
| CI | badge |
|
||||||
|
|----|-------|
|
||||||
|
| TravisCI | [](https://travis-ci.org/discordapp/discord-rpc)
|
||||||
|
| AppVeyor | [](https://ci.appveyor.com/project/crmarsh/discord-rpc)
|
||||||
|
| Buildkite (internal) | [](https://buildkite.com/discord/discord-rpc)
|
||||||
|
|
||||||
## Sample: send-presence
|
## Sample: send-presence
|
||||||
|
|
||||||
This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence
|
This is a text adventure "game" that inits/deinits the connection to Discord, and sends a presence update on each command.
|
||||||
update on each command.
|
|
||||||
|
|
||||||
## Sample: button-clicker
|
## Sample: button-clicker
|
||||||
|
|
||||||
This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and
|
This is a sample [Unity](https://unity3d.com/) project that wraps a DLL version of the library, and sends presence updates when you click on a button.
|
||||||
sends presence updates when you click on a button.
|
|
||||||
|
|
||||||
## Sample: unrealstatus
|
## Sample: unrealstatus
|
||||||
|
|
||||||
This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the
|
This is a sample [Unreal](https://www.unrealengine.com) project that wraps the DLL version of the library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to make a very simple UI.
|
||||||
library with an Unreal plugin, exposes a blueprint class for interacting with it, and uses that to
|
|
||||||
make a very simple UI.
|
## Wrappers and Implementations
|
||||||
|
|
||||||
|
Below is a table of unofficial, community-developed wrappers for and implementations of Rich Presence in various languages. If you would like to have yours added, please make a pull request adding your repository to the table. The repository should include:
|
||||||
|
|
||||||
|
- The code
|
||||||
|
- A brief ReadMe of how to use it
|
||||||
|
- A working example
|
||||||
|
|
||||||
|
###### Rich Presence Wrappers and Implementations
|
||||||
|
|
||||||
|
| Name | Language |
|
||||||
|
|------|----------|
|
||||||
|
| Be the first! | |
|
||||||
|
17
appveyor.yml
Normal file
17
appveyor.yml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
version: '{build}'
|
||||||
|
install:
|
||||||
|
- python -m pip install click
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
- mkdir examples\unrealstatus\Plugins\discordrpc\Binaries\ThirdParty\discordrpcLibrary\Win64
|
||||||
|
- python build.py
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: builds\install\win32-dynamic
|
||||||
|
name: win32-dynamic
|
||||||
|
- path: builds\install\win32-static
|
||||||
|
name: win32-static
|
||||||
|
- path: builds\install\win64-dynamic
|
||||||
|
name: win64-dynamic
|
||||||
|
- path: builds\install\win64-static
|
||||||
|
name: win64-static
|
210
build.py
210
build.py
@ -1,15 +1,39 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import click
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import shutil
|
import shutil
|
||||||
import zipfile
|
import zipfile
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import click
|
||||||
|
|
||||||
|
|
||||||
|
def get_platform():
|
||||||
|
""" a name for the platform """
|
||||||
|
if sys.platform.startswith('win'):
|
||||||
|
return 'win'
|
||||||
|
elif sys.platform == 'darwin':
|
||||||
|
return 'osx'
|
||||||
|
elif sys.platform.startswith('linux'):
|
||||||
|
return 'linux'
|
||||||
|
raise Exception('Unsupported platform ' + sys.platform)
|
||||||
|
|
||||||
|
|
||||||
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
# we use Buildkite which sets this env variable by default
|
||||||
|
IS_BUILD_MACHINE = os.environ.get('CI', '') == 'true'
|
||||||
|
PLATFORM = get_platform()
|
||||||
|
INSTALL_ROOT = os.path.join(SCRIPT_PATH, 'builds', 'install')
|
||||||
|
|
||||||
|
|
||||||
|
def get_signtool():
|
||||||
|
""" get path to code signing tool """
|
||||||
|
if PLATFORM == 'win':
|
||||||
|
sdk_dir = os.environ['WindowsSdkDir']
|
||||||
|
return os.path.join(sdk_dir, 'bin', 'x86', 'signtool.exe')
|
||||||
|
elif PLATFORM == 'osx':
|
||||||
|
return '/usr/bin/codesign'
|
||||||
|
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
@ -26,69 +50,185 @@ def cd(new_dir):
|
|||||||
def mkdir_p(path):
|
def mkdir_p(path):
|
||||||
""" mkdir -p """
|
""" mkdir -p """
|
||||||
if not os.path.isdir(path):
|
if not os.path.isdir(path):
|
||||||
|
click.secho('Making ' + path, fg='yellow')
|
||||||
os.makedirs(path)
|
os.makedirs(path)
|
||||||
|
|
||||||
|
|
||||||
def build_lib(build_name, generator, options):
|
@click.group(invoke_without_command=True)
|
||||||
|
@click.pass_context
|
||||||
|
@click.option('--clean', is_flag=True)
|
||||||
|
def cli(ctx, clean):
|
||||||
|
""" click wrapper for command line stuff """
|
||||||
|
if ctx.invoked_subcommand is None:
|
||||||
|
ctx.invoke(libs, clean=clean)
|
||||||
|
if IS_BUILD_MACHINE:
|
||||||
|
ctx.invoke(sign)
|
||||||
|
ctx.invoke(archive)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def unity():
|
||||||
|
""" todo: build unity project """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.pass_context
|
||||||
|
def for_unity(ctx):
|
||||||
|
""" build just dynamic libs for use in unity project """
|
||||||
|
ctx.invoke(
|
||||||
|
libs,
|
||||||
|
clean=False,
|
||||||
|
static=False,
|
||||||
|
shared=True,
|
||||||
|
skip_formatter=True,
|
||||||
|
just_release=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
def unreal():
|
||||||
|
""" todo: build unreal project """
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def build_lib(build_name, generator, options, just_release):
|
||||||
|
""" Create a dir under builds, run build and install in it """
|
||||||
build_path = os.path.join(SCRIPT_PATH, 'builds', build_name)
|
build_path = os.path.join(SCRIPT_PATH, 'builds', build_name)
|
||||||
install_path = os.path.join(SCRIPT_PATH, 'builds', 'install', build_name)
|
install_path = os.path.join(INSTALL_ROOT, build_name)
|
||||||
mkdir_p(build_path)
|
mkdir_p(build_path)
|
||||||
mkdir_p(install_path)
|
mkdir_p(install_path)
|
||||||
with cd(build_path):
|
with cd(build_path):
|
||||||
initial_cmake = ['cmake', SCRIPT_PATH, '-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)]
|
initial_cmake = [
|
||||||
|
'cmake',
|
||||||
|
SCRIPT_PATH,
|
||||||
|
'-DCMAKE_INSTALL_PREFIX=%s' % os.path.join('..', 'install', build_name)
|
||||||
|
]
|
||||||
if generator:
|
if generator:
|
||||||
initial_cmake.extend(['-G', generator])
|
initial_cmake.extend(['-G', generator])
|
||||||
for key in options:
|
for key in options:
|
||||||
val = 'ON' if options[key] else 'OFF'
|
val = options[key]
|
||||||
initial_cmake.append('-D%s=%s' %(key, val))
|
if type(val) is bool:
|
||||||
|
val = 'ON' if val else 'OFF'
|
||||||
|
initial_cmake.append('-D%s=%s' % (key, val))
|
||||||
|
click.echo('--- Building ' + build_name)
|
||||||
subprocess.check_call(initial_cmake)
|
subprocess.check_call(initial_cmake)
|
||||||
subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug'])
|
if not just_release:
|
||||||
|
subprocess.check_call(['cmake', '--build', '.', '--config', 'Debug'])
|
||||||
subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install'])
|
subprocess.check_call(['cmake', '--build', '.', '--config', 'Release', '--target', 'install'])
|
||||||
|
|
||||||
|
|
||||||
def create_archive():
|
@cli.command()
|
||||||
archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % sys.platform)
|
def archive():
|
||||||
|
""" create zip of install dir """
|
||||||
|
click.echo('--- Archiving')
|
||||||
|
archive_file_path = os.path.join(SCRIPT_PATH, 'builds', 'discord-rpc-%s.zip' % get_platform())
|
||||||
archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED)
|
archive_file = zipfile.ZipFile(archive_file_path, 'w', zipfile.ZIP_DEFLATED)
|
||||||
archive_src_base_path = os.path.join(SCRIPT_PATH, 'builds', 'install')
|
archive_src_base_path = INSTALL_ROOT
|
||||||
archive_dst_base_path = 'discord-rpc'
|
archive_dst_base_path = 'discord-rpc'
|
||||||
with cd(archive_src_base_path):
|
with cd(archive_src_base_path):
|
||||||
for path, subdirs, filenames in os.walk('.'):
|
for path, _, filenames in os.walk('.'):
|
||||||
for fname in filenames:
|
for fname in filenames:
|
||||||
fpath = os.path.join(path, fname)
|
fpath = os.path.join(path, fname)
|
||||||
archive_file.write(fpath, os.path.normpath(os.path.join(archive_dst_base_path, fpath)))
|
dst_path = os.path.normpath(os.path.join(archive_dst_base_path, fpath))
|
||||||
|
click.echo('Adding ' + dst_path)
|
||||||
|
archive_file.write(fpath, dst_path)
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
@cli.command()
|
||||||
|
def sign():
|
||||||
|
""" Do code signing within install directory using our cert """
|
||||||
|
tool = get_signtool()
|
||||||
|
signable_extensions = set()
|
||||||
|
if PLATFORM == 'win':
|
||||||
|
signable_extensions.add('.dll')
|
||||||
|
sign_command_base = [
|
||||||
|
tool,
|
||||||
|
'sign',
|
||||||
|
'/n', 'Hammer & Chisel Inc.',
|
||||||
|
'/a',
|
||||||
|
'/tr', 'http://timestamp.digicert.com/rfc3161',
|
||||||
|
'/as',
|
||||||
|
'/td', 'sha256',
|
||||||
|
'/fd', 'sha256',
|
||||||
|
]
|
||||||
|
elif PLATFORM == 'osx':
|
||||||
|
signable_extensions.add('.dylib')
|
||||||
|
sign_command_base = [
|
||||||
|
tool,
|
||||||
|
'--keychain', os.path.expanduser('~/Library/Keychains/login.keychain'),
|
||||||
|
'-vvvv',
|
||||||
|
'--deep',
|
||||||
|
'--force',
|
||||||
|
'--sign', 'Developer ID Application: Hammer & Chisel Inc. (53Q6R32WPB)',
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
click.secho('Not signing things on this platform yet', fg='red')
|
||||||
|
return
|
||||||
|
|
||||||
|
click.echo('--- Signing')
|
||||||
|
for path, _, filenames in os.walk(INSTALL_ROOT):
|
||||||
|
for fname in filenames:
|
||||||
|
ext = os.path.splitext(fname)[1]
|
||||||
|
if ext not in signable_extensions:
|
||||||
|
continue
|
||||||
|
fpath = os.path.join(path, fname)
|
||||||
|
click.echo('Sign ' + fpath)
|
||||||
|
sign_command = sign_command_base + [fpath]
|
||||||
|
subprocess.check_call(sign_command)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
@click.option('--clean', is_flag=True)
|
@click.option('--clean', is_flag=True)
|
||||||
def main(clean):
|
@click.option('--static', is_flag=True)
|
||||||
os.chdir(SCRIPT_PATH)
|
@click.option('--shared', is_flag=True)
|
||||||
|
@click.option('--skip_formatter', is_flag=True)
|
||||||
|
@click.option('--just_release', is_flag=True)
|
||||||
|
def libs(clean, static, shared, skip_formatter, just_release):
|
||||||
|
""" Do all the builds for this platform """
|
||||||
if clean:
|
if clean:
|
||||||
shutil.rmtree('builds', ignore_errors=True)
|
shutil.rmtree('builds', ignore_errors=True)
|
||||||
|
|
||||||
mkdir_p('builds')
|
mkdir_p('builds')
|
||||||
|
|
||||||
if sys.platform.startswith('win'):
|
if not (static or shared):
|
||||||
|
static = True
|
||||||
|
shared = True
|
||||||
|
|
||||||
|
static_options = {}
|
||||||
|
dynamic_options = {
|
||||||
|
'BUILD_SHARED_LIBS': True,
|
||||||
|
'USE_STATIC_CRT': True,
|
||||||
|
}
|
||||||
|
|
||||||
|
if skip_formatter or IS_BUILD_MACHINE:
|
||||||
|
static_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||||||
|
dynamic_options['CLANG_FORMAT_SUFFIX'] = 'none'
|
||||||
|
|
||||||
|
if IS_BUILD_MACHINE:
|
||||||
|
just_release = True
|
||||||
|
|
||||||
|
if PLATFORM == 'win':
|
||||||
generator32 = 'Visual Studio 14 2015'
|
generator32 = 'Visual Studio 14 2015'
|
||||||
generator64 = 'Visual Studio 14 2015 Win64'
|
generator64 = 'Visual Studio 14 2015 Win64'
|
||||||
|
if static:
|
||||||
build_lib('win32-static', generator32, {})
|
build_lib('win32-static', generator32, static_options, just_release)
|
||||||
build_lib('win32-dynamic', generator32, {'BUILD_DYNAMIC_LIB': True})
|
build_lib('win64-static', generator64, static_options, just_release)
|
||||||
build_lib('win64-static', generator64, {})
|
if shared:
|
||||||
build_lib('win64-dynamic', generator64, {'BUILD_DYNAMIC_LIB': True})
|
build_lib('win32-dynamic', generator32, dynamic_options, just_release)
|
||||||
|
build_lib('win64-dynamic', generator64, dynamic_options, just_release)
|
||||||
# todo: this in some better way
|
elif PLATFORM == 'osx':
|
||||||
src_dll = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release', 'discord-rpc.dll')
|
if static:
|
||||||
dst_dll = os.path.join(SCRIPT_PATH, 'examples', 'button-clicker', 'Assets', 'Resources', 'discord-rpc.dll')
|
build_lib('osx-static', None, static_options, just_release)
|
||||||
shutil.copy(src_dll, dst_dll)
|
if shared:
|
||||||
dst_dll = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc', 'Binaries', 'ThirdParty', 'discordrpcLibrary', 'Win64', 'discord-rpc.dll')
|
build_lib('osx-dynamic', None, dynamic_options, just_release)
|
||||||
shutil.copy(src_dll, dst_dll)
|
elif PLATFORM == 'linux':
|
||||||
elif sys.platform == 'darwin':
|
if static:
|
||||||
build_lib('osx-static', None, {})
|
build_lib('linux-static', None, static_options, just_release)
|
||||||
build_lib('osx-dynamic', None, {'BUILD_DYNAMIC_LIB': True})
|
if shared:
|
||||||
|
build_lib('linux-dynamic', None, dynamic_options, just_release)
|
||||||
create_archive()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main())
|
os.chdir(SCRIPT_PATH)
|
||||||
|
sys.exit(cli())
|
||||||
|
2
examples/button-clicker/.gitignore
vendored
2
examples/button-clicker/.gitignore
vendored
@ -1,6 +1,8 @@
|
|||||||
/Library/
|
/Library/
|
||||||
/Temp/
|
/Temp/
|
||||||
/obj/
|
/obj/
|
||||||
|
/Assets/Plugins/
|
||||||
|
/Assets/Plugins.meta
|
||||||
*.sln
|
*.sln
|
||||||
*.csproj
|
*.csproj
|
||||||
*.userprefs
|
*.userprefs
|
101
examples/button-clicker/Assets/BuildHelper.cs
Normal file
101
examples/button-clicker/Assets/BuildHelper.cs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
using UnityEditor;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
[InitializeOnLoad]
|
||||||
|
public class ScriptBatch
|
||||||
|
{
|
||||||
|
static ScriptBatch()
|
||||||
|
{
|
||||||
|
EnsureDLL();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool FileExists(string filename)
|
||||||
|
{
|
||||||
|
return new FileInfo(filename).Exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool RunRpcBuildScript()
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.Log("Try to run build script");
|
||||||
|
|
||||||
|
Process proc = new Process();
|
||||||
|
#if UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
|
||||||
|
proc.StartInfo.UseShellExecute = false;
|
||||||
|
// brew installs cmake in /usr/local/bin, which Unity seems to strip from PATH?
|
||||||
|
string newPath = proc.StartInfo.EnvironmentVariables["PATH"] + ":/usr/local/bin";
|
||||||
|
proc.StartInfo.EnvironmentVariables["PATH"] = newPath;
|
||||||
|
#endif
|
||||||
|
proc.StartInfo.FileName = "python";
|
||||||
|
proc.StartInfo.Arguments = "build.py for_unity";
|
||||||
|
proc.StartInfo.WorkingDirectory = "../..";
|
||||||
|
proc.Start();
|
||||||
|
proc.WaitForExit();
|
||||||
|
return proc.ExitCode == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EnsureDLL()
|
||||||
|
{
|
||||||
|
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
||||||
|
string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" };
|
||||||
|
string[] dstDlls = { "Assets/Plugins/x86/discord-rpc.dll", "Assets/Plugins/x86_64/discord-rpc.dll" };
|
||||||
|
string[] srcDlls = { "../../builds/install/win64-dynamic/bin/discord-rpc.dll", "../../builds/install/win64-dynamic/bin/discord-rpc.dll" };
|
||||||
|
#elif UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX
|
||||||
|
string[] dstDirs = { "Assets/Plugins" };
|
||||||
|
string[] dstDlls = { "Assets/Plugins/discord-rpc.bundle" };
|
||||||
|
string[] srcDlls = { "../../builds/install/osx-dynamic/lib/libdiscord-rpc.dylib" };
|
||||||
|
#else
|
||||||
|
string[] dstDirs = { "Assets/Plugins", "Assets/Plugins/x86", "Assets/Plugins/x86_64" };
|
||||||
|
string[] dstDlls = { "Assets/Plugins/x86/discord-rpc.so", "Assets/Plugins/x86_64/discord-rpc.so" };
|
||||||
|
string[] srcDlls = { "../../builds/install/linux-dynamic/bin/discord-rpc.dll", "../../builds/install/win64-dynamic/bin/discord-rpc.dll" };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Debug.Assert(dstDlls.Length == srcDlls.Length);
|
||||||
|
|
||||||
|
bool exists = true;
|
||||||
|
foreach (string fname in dstDlls)
|
||||||
|
{
|
||||||
|
if (!FileExists(fname))
|
||||||
|
{
|
||||||
|
exists = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
exists = true;
|
||||||
|
foreach (string fname in srcDlls)
|
||||||
|
{
|
||||||
|
if (!FileExists(fname))
|
||||||
|
{
|
||||||
|
exists = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
if (!RunRpcBuildScript())
|
||||||
|
{
|
||||||
|
UnityEngine.Debug.LogError("Build failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the dirs exist
|
||||||
|
foreach (string dirname in dstDirs)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(dirname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy dlls
|
||||||
|
for (int i = 0; i < dstDlls.Length; ++i)
|
||||||
|
{
|
||||||
|
FileUtil.CopyFileOrDirectory(srcDlls[i], dstDlls[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
examples/button-clicker/Assets/BuildHelper.cs.meta
Normal file
13
examples/button-clicker/Assets/BuildHelper.cs.meta
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e5aecc4633e5f594b85eaa39f49bb402
|
||||||
|
timeCreated: 1512071254
|
||||||
|
licenseType: Free
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -68,10 +68,10 @@ public class DiscordController : MonoBehaviour
|
|||||||
onSpectate.Invoke(secret);
|
onSpectate.Invoke(secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RequestCallback(DiscordRpc.JoinRequest request)
|
public void RequestCallback(ref DiscordRpc.JoinRequest request)
|
||||||
{
|
{
|
||||||
++callbackCalls;
|
++callbackCalls;
|
||||||
Debug.Log(string.Format("Discord: join request {0}: {1}", request.username, request.userId));
|
Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId));
|
||||||
onJoinRequest.Invoke(request);
|
onJoinRequest.Invoke(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ public class DiscordRpc
|
|||||||
public delegate void SpectateCallback(string secret);
|
public delegate void SpectateCallback(string secret);
|
||||||
|
|
||||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||||
public delegate void RequestCallback(JoinRequest request);
|
public delegate void RequestCallback(ref JoinRequest request);
|
||||||
|
|
||||||
public struct EventHandlers
|
public struct EventHandlers
|
||||||
{
|
{
|
||||||
@ -55,6 +55,7 @@ public class DiscordRpc
|
|||||||
{
|
{
|
||||||
public string userId;
|
public string userId;
|
||||||
public string username;
|
public string username;
|
||||||
|
public string discriminator;
|
||||||
public string avatar;
|
public string avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4ddcc1759a3a2394fa1fa376963639e0
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1501697278
|
|
||||||
licenseType: Free
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
Binary file not shown.
@ -1,27 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2aadd6305b09fa94dab94261a8bb8caf
|
|
||||||
timeCreated: 1501697340
|
|
||||||
licenseType: Free
|
|
||||||
PluginImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
iconMap: {}
|
|
||||||
executionOrder: {}
|
|
||||||
isPreloaded: 0
|
|
||||||
isOverridable: 0
|
|
||||||
platformData:
|
|
||||||
data:
|
|
||||||
first:
|
|
||||||
Any:
|
|
||||||
second:
|
|
||||||
enabled: 1
|
|
||||||
settings: {}
|
|
||||||
data:
|
|
||||||
first:
|
|
||||||
Editor: Editor
|
|
||||||
second:
|
|
||||||
enabled: 0
|
|
||||||
settings:
|
|
||||||
DefaultValueInitialized: true
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
@ -653,7 +653,7 @@ MonoBehaviour:
|
|||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
presence:
|
presence:
|
||||||
state: Button clicking
|
state: Button clicking
|
||||||
details:
|
details: Best game ever
|
||||||
startTimestamp: 0
|
startTimestamp: 0
|
||||||
endTimestamp: 0
|
endTimestamp: 0
|
||||||
largeImageKey: stable-large
|
largeImageKey: stable-large
|
||||||
@ -663,10 +663,10 @@ MonoBehaviour:
|
|||||||
partyId: abcdefg
|
partyId: abcdefg
|
||||||
partySize: 1
|
partySize: 1
|
||||||
partyMax: 10
|
partyMax: 10
|
||||||
matchSecret:
|
matchSecret: match_secret
|
||||||
joinSecret:
|
joinSecret: join_secret
|
||||||
spectateSecret:
|
spectateSecret: spectate_secret
|
||||||
instance: 0
|
instance: 1
|
||||||
applicationId: 345229890980937739
|
applicationId: 345229890980937739
|
||||||
optionalSteamId:
|
optionalSteamId:
|
||||||
callbackCalls: 0
|
callbackCalls: 0
|
||||||
|
@ -17,3 +17,4 @@ PhysicsManager:
|
|||||||
m_EnablePCM: 1
|
m_EnablePCM: 1
|
||||||
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||||
m_AutoSimulation: 1
|
m_AutoSimulation: 1
|
||||||
|
m_AutoSyncTransforms: 1
|
||||||
|
@ -4,4 +4,7 @@
|
|||||||
EditorBuildSettings:
|
EditorBuildSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Scenes: []
|
m_Scenes:
|
||||||
|
- enabled: 1
|
||||||
|
path: Assets/main.unity
|
||||||
|
guid: 3b03d21bb25fa494e8694cd6e4b6d769
|
||||||
|
@ -24,6 +24,7 @@ Physics2DSettings:
|
|||||||
m_QueriesStartInColliders: 1
|
m_QueriesStartInColliders: 1
|
||||||
m_ChangeStopsCallbacks: 0
|
m_ChangeStopsCallbacks: 0
|
||||||
m_CallbacksOnDisable: 1
|
m_CallbacksOnDisable: 1
|
||||||
|
m_AutoSyncTransforms: 1
|
||||||
m_AlwaysShowColliders: 0
|
m_AlwaysShowColliders: 0
|
||||||
m_ShowColliderSleep: 1
|
m_ShowColliderSleep: 1
|
||||||
m_ShowColliderContacts: 0
|
m_ShowColliderContacts: 0
|
||||||
|
@ -3,14 +3,15 @@
|
|||||||
--- !u!129 &1
|
--- !u!129 &1
|
||||||
PlayerSettings:
|
PlayerSettings:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
serializedVersion: 12
|
serializedVersion: 13
|
||||||
productGUID: 5eccc60d3e382a346a65f512d6b81b84
|
productGUID: 5eccc60d3e382a346a65f512d6b81b84
|
||||||
AndroidProfiler: 0
|
AndroidProfiler: 0
|
||||||
|
AndroidFilterTouchesWhenObscured: 0
|
||||||
defaultScreenOrientation: 4
|
defaultScreenOrientation: 4
|
||||||
targetDevice: 2
|
targetDevice: 2
|
||||||
useOnDemandResources: 0
|
useOnDemandResources: 0
|
||||||
accelerometerFrequency: 60
|
accelerometerFrequency: 60
|
||||||
companyName: DefaultCompany
|
companyName: Discord Inc.
|
||||||
productName: button-clicker
|
productName: button-clicker
|
||||||
defaultCursor: {fileID: 0}
|
defaultCursor: {fileID: 0}
|
||||||
cursorHotspot: {x: 0, y: 0}
|
cursorHotspot: {x: 0, y: 0}
|
||||||
@ -38,8 +39,6 @@ PlayerSettings:
|
|||||||
width: 1
|
width: 1
|
||||||
height: 1
|
height: 1
|
||||||
m_SplashScreenLogos: []
|
m_SplashScreenLogos: []
|
||||||
m_SplashScreenBackgroundLandscape: {fileID: 0}
|
|
||||||
m_SplashScreenBackgroundPortrait: {fileID: 0}
|
|
||||||
m_VirtualRealitySplashScreen: {fileID: 0}
|
m_VirtualRealitySplashScreen: {fileID: 0}
|
||||||
m_HolographicTrackingLossScreen: {fileID: 0}
|
m_HolographicTrackingLossScreen: {fileID: 0}
|
||||||
defaultScreenWidth: 1024
|
defaultScreenWidth: 1024
|
||||||
@ -49,7 +48,6 @@ PlayerSettings:
|
|||||||
m_StereoRenderingPath: 0
|
m_StereoRenderingPath: 0
|
||||||
m_ActiveColorSpace: 0
|
m_ActiveColorSpace: 0
|
||||||
m_MTRendering: 1
|
m_MTRendering: 1
|
||||||
m_MobileMTRendering: 0
|
|
||||||
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
|
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
|
||||||
iosShowActivityIndicatorOnLoading: -1
|
iosShowActivityIndicatorOnLoading: -1
|
||||||
androidShowActivityIndicatorOnLoading: -1
|
androidShowActivityIndicatorOnLoading: -1
|
||||||
@ -64,8 +62,10 @@ PlayerSettings:
|
|||||||
useOSAutorotation: 1
|
useOSAutorotation: 1
|
||||||
use32BitDisplayBuffer: 1
|
use32BitDisplayBuffer: 1
|
||||||
disableDepthAndStencilBuffers: 0
|
disableDepthAndStencilBuffers: 0
|
||||||
|
androidBlitType: 0
|
||||||
defaultIsFullScreen: 1
|
defaultIsFullScreen: 1
|
||||||
defaultIsNativeResolution: 1
|
defaultIsNativeResolution: 1
|
||||||
|
macRetinaSupport: 1
|
||||||
runInBackground: 0
|
runInBackground: 0
|
||||||
captureSingleScreen: 0
|
captureSingleScreen: 0
|
||||||
muteOtherAudioSources: 0
|
muteOtherAudioSources: 0
|
||||||
@ -95,6 +95,7 @@ PlayerSettings:
|
|||||||
xboxEnableHeadOrientation: 0
|
xboxEnableHeadOrientation: 0
|
||||||
xboxEnableGuest: 0
|
xboxEnableGuest: 0
|
||||||
xboxEnablePIXSampling: 0
|
xboxEnablePIXSampling: 0
|
||||||
|
metalFramebufferOnly: 0
|
||||||
n3dsDisableStereoscopicView: 0
|
n3dsDisableStereoscopicView: 0
|
||||||
n3dsEnableSharedListOpt: 1
|
n3dsEnableSharedListOpt: 1
|
||||||
n3dsEnableVSync: 0
|
n3dsEnableVSync: 0
|
||||||
@ -103,6 +104,7 @@ PlayerSettings:
|
|||||||
xboxOneMonoLoggingLevel: 0
|
xboxOneMonoLoggingLevel: 0
|
||||||
xboxOneLoggingLevel: 1
|
xboxOneLoggingLevel: 1
|
||||||
xboxOneDisableEsram: 0
|
xboxOneDisableEsram: 0
|
||||||
|
xboxOnePresentImmediateThreshold: 0
|
||||||
videoMemoryForVertexBuffers: 0
|
videoMemoryForVertexBuffers: 0
|
||||||
psp2PowerMode: 0
|
psp2PowerMode: 0
|
||||||
psp2AcquireBGM: 1
|
psp2AcquireBGM: 1
|
||||||
@ -134,12 +136,17 @@ PlayerSettings:
|
|||||||
daydream:
|
daydream:
|
||||||
depthFormat: 0
|
depthFormat: 0
|
||||||
useSustainedPerformanceMode: 0
|
useSustainedPerformanceMode: 0
|
||||||
|
enableVideoLayer: 0
|
||||||
|
useProtectedVideoMemory: 0
|
||||||
hololens:
|
hololens:
|
||||||
depthFormat: 1
|
depthFormat: 1
|
||||||
protectGraphicsMemory: 0
|
protectGraphicsMemory: 0
|
||||||
useHDRDisplay: 0
|
useHDRDisplay: 0
|
||||||
|
m_ColorGamuts: 00000000
|
||||||
targetPixelDensity: 0
|
targetPixelDensity: 0
|
||||||
resolutionScalingMode: 0
|
resolutionScalingMode: 0
|
||||||
|
androidSupportedAspectRatio: 1
|
||||||
|
androidMaxAspectRatio: 2.1
|
||||||
applicationIdentifier: {}
|
applicationIdentifier: {}
|
||||||
buildNumber: {}
|
buildNumber: {}
|
||||||
AndroidBundleVersionCode: 1
|
AndroidBundleVersionCode: 1
|
||||||
@ -160,10 +167,10 @@ PlayerSettings:
|
|||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Bits: 238
|
m_Bits: 238
|
||||||
iPhoneSdkVersion: 988
|
iPhoneSdkVersion: 988
|
||||||
iOSTargetOSVersionString:
|
iOSTargetOSVersionString: 7.0
|
||||||
tvOSSdkVersion: 0
|
tvOSSdkVersion: 0
|
||||||
tvOSRequireExtendedGameController: 0
|
tvOSRequireExtendedGameController: 0
|
||||||
tvOSTargetOSVersionString:
|
tvOSTargetOSVersionString: 9.0
|
||||||
uIPrerenderedIcon: 0
|
uIPrerenderedIcon: 0
|
||||||
uIRequiresPersistentWiFi: 0
|
uIRequiresPersistentWiFi: 0
|
||||||
uIRequiresFullScreen: 1
|
uIRequiresFullScreen: 1
|
||||||
@ -220,7 +227,9 @@ PlayerSettings:
|
|||||||
AndroidKeyaliasName:
|
AndroidKeyaliasName:
|
||||||
AndroidTVCompatibility: 1
|
AndroidTVCompatibility: 1
|
||||||
AndroidIsGame: 1
|
AndroidIsGame: 1
|
||||||
|
AndroidEnableTango: 0
|
||||||
androidEnableBanner: 1
|
androidEnableBanner: 1
|
||||||
|
androidUseLowAccuracyLocation: 0
|
||||||
m_AndroidBanners:
|
m_AndroidBanners:
|
||||||
- width: 320
|
- width: 320
|
||||||
height: 180
|
height: 180
|
||||||
@ -231,10 +240,14 @@ PlayerSettings:
|
|||||||
m_BuildTargetBatching: []
|
m_BuildTargetBatching: []
|
||||||
m_BuildTargetGraphicsAPIs: []
|
m_BuildTargetGraphicsAPIs: []
|
||||||
m_BuildTargetVRSettings: []
|
m_BuildTargetVRSettings: []
|
||||||
|
m_BuildTargetEnableVuforiaSettings: []
|
||||||
openGLRequireES31: 0
|
openGLRequireES31: 0
|
||||||
openGLRequireES31AEP: 0
|
openGLRequireES31AEP: 0
|
||||||
webPlayerTemplate: APPLICATION:Default
|
|
||||||
m_TemplateCustomTags: {}
|
m_TemplateCustomTags: {}
|
||||||
|
mobileMTRendering:
|
||||||
|
Android: 1
|
||||||
|
iPhone: 1
|
||||||
|
tvOS: 1
|
||||||
wiiUTitleID: 0005000011000000
|
wiiUTitleID: 0005000011000000
|
||||||
wiiUGroupID: 00010000
|
wiiUGroupID: 00010000
|
||||||
wiiUCommonSaveSize: 4096
|
wiiUCommonSaveSize: 4096
|
||||||
@ -368,6 +381,9 @@ PlayerSettings:
|
|||||||
switchUdpSendBufferSize: 9
|
switchUdpSendBufferSize: 9
|
||||||
switchUdpReceiveBufferSize: 42
|
switchUdpReceiveBufferSize: 42
|
||||||
switchSocketBufferEfficiency: 4
|
switchSocketBufferEfficiency: 4
|
||||||
|
switchSocketInitializeEnabled: 1
|
||||||
|
switchNetworkInterfaceManagerInitializeEnabled: 1
|
||||||
|
switchPlayerConnectionEnabled: 1
|
||||||
ps4NPAgeRating: 12
|
ps4NPAgeRating: 12
|
||||||
ps4NPTitleSecret:
|
ps4NPTitleSecret:
|
||||||
ps4NPTrophyPackPath:
|
ps4NPTrophyPackPath:
|
||||||
|
@ -1 +1 @@
|
|||||||
m_EditorVersion: 2017.1.1f1
|
m_EditorVersion: 2017.2.0f3
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
@ -12,6 +12,7 @@ public class discordrpcLibrary : ModuleRules
|
|||||||
if (Target.Platform == UnrealTargetPlatform.Win64)
|
if (Target.Platform == UnrealTargetPlatform.Win64)
|
||||||
{
|
{
|
||||||
// Add the import library
|
// Add the import library
|
||||||
|
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Include"));
|
||||||
PublicLibraryPaths.Add(Path.Combine(ModuleDirectory, "x64", "Release"));
|
PublicLibraryPaths.Add(Path.Combine(ModuleDirectory, "x64", "Release"));
|
||||||
PublicAdditionalLibraries.Add("discord-rpc.lib");
|
PublicAdditionalLibraries.Add("discord-rpc.lib");
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
DEFINE_LOG_CATEGORY(Discord)
|
DEFINE_LOG_CATEGORY(Discord)
|
||||||
|
|
||||||
static UDiscordRpc* self = nullptr;
|
static UDiscordRpc* self = nullptr;
|
||||||
|
|
||||||
static void ReadyHandler()
|
static void ReadyHandler()
|
||||||
{
|
{
|
||||||
UE_LOG(Discord, Log, TEXT("Discord connected"));
|
UE_LOG(Discord, Log, TEXT("Discord connected"));
|
||||||
@ -53,6 +54,19 @@ static void SpectateGameHandler(const char* spectateSecret)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void JoinRequestHandler(const DiscordJoinRequest* request)
|
||||||
|
{
|
||||||
|
FDiscordJoinRequestData jr;
|
||||||
|
jr.userId = ANSI_TO_TCHAR(request->userId);
|
||||||
|
jr.username = ANSI_TO_TCHAR(request->username);
|
||||||
|
jr.discriminator = ANSI_TO_TCHAR(request->discriminator);
|
||||||
|
jr.avatar = ANSI_TO_TCHAR(request->avatar);
|
||||||
|
UE_LOG(Discord, Log, TEXT("Discord join request from %s#%s"), *jr.username, *jr.discriminator);
|
||||||
|
if (self) {
|
||||||
|
self->OnJoinRequest.Broadcast(jr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UDiscordRpc::Initialize(const FString& applicationId,
|
void UDiscordRpc::Initialize(const FString& applicationId,
|
||||||
bool autoRegister,
|
bool autoRegister,
|
||||||
const FString& optionalSteamId)
|
const FString& optionalSteamId)
|
||||||
@ -69,6 +83,9 @@ void UDiscordRpc::Initialize(const FString& applicationId,
|
|||||||
if (OnSpectate.IsBound()) {
|
if (OnSpectate.IsBound()) {
|
||||||
handlers.spectateGame = SpectateGameHandler;
|
handlers.spectateGame = SpectateGameHandler;
|
||||||
}
|
}
|
||||||
|
if (OnJoinRequest.IsBound()) {
|
||||||
|
handlers.joinRequest = JoinRequestHandler;
|
||||||
|
}
|
||||||
auto appId = StringCast<ANSICHAR>(*applicationId);
|
auto appId = StringCast<ANSICHAR>(*applicationId);
|
||||||
auto steamId = StringCast<ANSICHAR>(*optionalSteamId);
|
auto steamId = StringCast<ANSICHAR>(*optionalSteamId);
|
||||||
Discord_Initialize(
|
Discord_Initialize(
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
#include "discordrpc.h"
|
#include "discordrpc.h"
|
||||||
#include "Core.h"
|
#include "Core.h"
|
||||||
#include "ModuleManager.h"
|
|
||||||
#include "IPluginManager.h"
|
#include "IPluginManager.h"
|
||||||
|
#include "ModuleManager.h"
|
||||||
|
|
||||||
#define LOCTEXT_NAMESPACE "FdiscordrpcModule"
|
#define LOCTEXT_NAMESPACE "FdiscordrpcModule"
|
||||||
|
|
||||||
|
@ -2,13 +2,31 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Engine.h"
|
|
||||||
#include "CoreMinimal.h"
|
#include "CoreMinimal.h"
|
||||||
|
#include "Engine.h"
|
||||||
#include "DiscordRpcBlueprint.generated.h"
|
#include "DiscordRpcBlueprint.generated.h"
|
||||||
|
|
||||||
// unreal's header tool hates clang-format
|
// unreal's header tool hates clang-format
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask to join callback data
|
||||||
|
*/
|
||||||
|
USTRUCT(BlueprintType)
|
||||||
|
struct FDiscordJoinRequestData {
|
||||||
|
GENERATED_USTRUCT_BODY()
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FString userId;
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FString username;
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FString discriminator;
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FString avatar;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
|
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
|
||||||
|
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDiscordConnected);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDiscordConnected);
|
||||||
@ -16,6 +34,7 @@ DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordDisconnected, int, errorCod
|
|||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, int, errorCode, const FString&, errorMessage);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, int, errorCode, const FString&, errorMessage);
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoin, const FString&, joinSecret);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoin, const FString&, joinSecret);
|
||||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret);
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret);
|
||||||
|
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoinRequest, const FDiscordJoinRequestData&, joinRequest);
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@ -119,6 +138,12 @@ public:
|
|||||||
Category = "Discord")
|
Category = "Discord")
|
||||||
FDiscordSpectate OnSpectate;
|
FDiscordSpectate OnSpectate;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintAssignable,
|
||||||
|
meta = (DisplayName = "When Discord another user sends a join request",
|
||||||
|
Keywords = "Discord rpc"),
|
||||||
|
Category = "Discord")
|
||||||
|
FDiscordJoinRequest OnJoinRequest;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite,
|
UPROPERTY(BlueprintReadWrite,
|
||||||
meta = (DisplayName = "Rich presence info", Keywords = "Discord rpc"),
|
meta = (DisplayName = "Rich presence info", Keywords = "Discord rpc"),
|
||||||
Category = "Discord")
|
Category = "Discord")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"FileVersion": 3,
|
"FileVersion": 3,
|
||||||
"EngineAssociation": "4.16",
|
"EngineAssociation": "4.18",
|
||||||
"Category": "",
|
"Category": "",
|
||||||
"Description": "",
|
"Description": "",
|
||||||
"Modules": [
|
"Modules": [
|
||||||
|
@ -44,6 +44,7 @@ typedef struct DiscordRichPresence {
|
|||||||
typedef struct DiscordJoinRequest {
|
typedef struct DiscordJoinRequest {
|
||||||
const char* userId;
|
const char* userId;
|
||||||
const char* username;
|
const char* username;
|
||||||
|
const char* discriminator;
|
||||||
const char* avatar;
|
const char* avatar;
|
||||||
} DiscordJoinRequest;
|
} DiscordJoinRequest;
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
include_directories(${PROJECT_SOURCE_DIR}/include)
|
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON)
|
option(ENABLE_IO_THREAD "Start up a separate I/O thread, otherwise I'd need to call an update function" ON)
|
||||||
option(BUILD_DYNAMIC_LIB "Build library as a DLL" OFF)
|
option(USE_STATIC_CRT "Use /MT[d] for dynamic library" OFF)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
|
||||||
set(BASE_RPC_SRC
|
set(BASE_RPC_SRC
|
||||||
${PROJECT_SOURCE_DIR}/include/discord-rpc.h
|
${PROJECT_SOURCE_DIR}/include/discord-rpc.h
|
||||||
@ -16,34 +18,42 @@ set(BASE_RPC_SRC
|
|||||||
msg_queue.h
|
msg_queue.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if (${BUILD_DYNAMIC_LIB})
|
if (${BUILD_SHARED_LIBS})
|
||||||
set(RPC_LIBRARY_TYPE SHARED)
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp)
|
set(BASE_RPC_SRC ${BASE_RPC_SRC} dllmain.cpp)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
else(${BUILD_DYNAMIC_LIB})
|
endif(${BUILD_SHARED_LIBS})
|
||||||
set(RPC_LIBRARY_TYPE STATIC)
|
|
||||||
endif(${BUILD_DYNAMIC_LIB})
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_definitions(-DDISCORD_WINDOWS)
|
add_definitions(-DDISCORD_WINDOWS)
|
||||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp)
|
set(BASE_RPC_SRC ${BASE_RPC_SRC} connection_win.cpp discord_register_win.cpp)
|
||||||
add_library(discord-rpc ${RPC_LIBRARY_TYPE} ${BASE_RPC_SRC})
|
add_library(discord-rpc ${BASE_RPC_SRC})
|
||||||
target_compile_options(discord-rpc PRIVATE /EHsc
|
if (MSVC)
|
||||||
/MT
|
set(CRT_FLAGS)
|
||||||
/Wall
|
if(USE_STATIC_CRT)
|
||||||
/wd4100 # unreferenced formal parameter
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
/wd4514 # unreferenced inline
|
set(CRT_FLAGS /MTd)
|
||||||
/wd4625 # copy constructor deleted
|
else()
|
||||||
/wd5026 # move constructor deleted
|
set(CRT_FLAGS /MT)
|
||||||
/wd4626 # move assignment operator deleted
|
endif()
|
||||||
/wd4668 # not defined preprocessor macro
|
endif(USE_STATIC_CRT)
|
||||||
/wd4710 # function not inlined
|
target_compile_options(discord-rpc PRIVATE /EHsc
|
||||||
/wd4711 # function was inlined
|
${CRT_FLAGS}
|
||||||
/wd4820 # structure padding
|
/Wall
|
||||||
/wd4946 # reinterpret_cast used between related classes
|
/wd4100 # unreferenced formal parameter
|
||||||
/wd5027 # move assignment operator was implicitly defined as deleted
|
/wd4514 # unreferenced inline
|
||||||
)
|
/wd4625 # copy constructor deleted
|
||||||
|
/wd5026 # move constructor deleted
|
||||||
|
/wd4626 # move assignment operator deleted
|
||||||
|
/wd4668 # not defined preprocessor macro
|
||||||
|
/wd4710 # function not inlined
|
||||||
|
/wd4711 # function was inlined
|
||||||
|
/wd4820 # structure padding
|
||||||
|
/wd4946 # reinterpret_cast used between related classes
|
||||||
|
/wd5027 # move assignment operator was implicitly defined as deleted
|
||||||
|
)
|
||||||
|
endif(MSVC)
|
||||||
|
target_link_libraries(discord-rpc PRIVATE psapi)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
if(UNIX)
|
if(UNIX)
|
||||||
@ -57,7 +67,7 @@ if(UNIX)
|
|||||||
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp)
|
set(BASE_RPC_SRC ${BASE_RPC_SRC} discord_register_linux.cpp)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
add_library(discord-rpc ${RPC_LIBRARY_TYPE} ${BASE_RPC_SRC})
|
add_library(discord-rpc ${BASE_RPC_SRC})
|
||||||
target_link_libraries(discord-rpc PUBLIC pthread)
|
target_link_libraries(discord-rpc PUBLIC pthread)
|
||||||
target_compile_options(discord-rpc PRIVATE
|
target_compile_options(discord-rpc PRIVATE
|
||||||
-g
|
-g
|
||||||
@ -75,7 +85,10 @@ if(UNIX)
|
|||||||
-Wno-exit-time-destructors # not sure about these
|
-Wno-exit-time-destructors # not sure about these
|
||||||
-Wno-global-constructors
|
-Wno-global-constructors
|
||||||
)
|
)
|
||||||
target_compile_options(discord-rpc PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-std=c++14>)
|
|
||||||
|
if (${BUILD_SHARED_LIBS})
|
||||||
|
target_compile_options(discord-rpc PRIVATE -fPIC)
|
||||||
|
endif (${BUILD_SHARED_LIBS})
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
target_link_libraries(discord-rpc PRIVATE "-framework AppKit")
|
target_link_libraries(discord-rpc PRIVATE "-framework AppKit")
|
||||||
@ -85,15 +98,17 @@ endif(UNIX)
|
|||||||
target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include)
|
target_include_directories(discord-rpc PRIVATE ${RAPIDJSON}/include)
|
||||||
|
|
||||||
if (NOT ${ENABLE_IO_THREAD})
|
if (NOT ${ENABLE_IO_THREAD})
|
||||||
add_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD)
|
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DISABLE_IO_THREAD)
|
||||||
endif (NOT ${ENABLE_IO_THREAD})
|
endif (NOT ${ENABLE_IO_THREAD})
|
||||||
|
|
||||||
if (${BUILD_DYNAMIC_LIB})
|
if (${BUILD_SHARED_LIBS})
|
||||||
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB)
|
target_compile_definitions(discord-rpc PUBLIC -DDISCORD_DYNAMIC_LIB)
|
||||||
target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK)
|
target_compile_definitions(discord-rpc PRIVATE -DDISCORD_BUILDING_SDK)
|
||||||
endif(${BUILD_DYNAMIC_LIB})
|
endif(${BUILD_SHARED_LIBS})
|
||||||
|
|
||||||
add_dependencies(discord-rpc clangformat)
|
if (CLANG_FORMAT_CMD)
|
||||||
|
add_dependencies(discord-rpc clangformat)
|
||||||
|
endif(CLANG_FORMAT_CMD)
|
||||||
|
|
||||||
# install
|
# install
|
||||||
|
|
||||||
@ -101,16 +116,13 @@ install(
|
|||||||
TARGETS discord-rpc
|
TARGETS discord-rpc
|
||||||
EXPORT "discord-rpc"
|
EXPORT "discord-rpc"
|
||||||
RUNTIME
|
RUNTIME
|
||||||
DESTINATION "bin"
|
DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||||
CONFIGURATIONS Release
|
|
||||||
LIBRARY
|
LIBRARY
|
||||||
DESTINATION "lib"
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
CONFIGURATIONS Release
|
|
||||||
ARCHIVE
|
ARCHIVE
|
||||||
DESTINATION "lib"
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
CONFIGURATIONS Release
|
|
||||||
INCLUDES
|
INCLUDES
|
||||||
DESTINATION "include"
|
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include <stdint.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
struct Backoff {
|
struct Backoff {
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#define NOMCX
|
#define NOMCX
|
||||||
#define NOSERVICE
|
#define NOSERVICE
|
||||||
#define NOIME
|
#define NOIME
|
||||||
#include <windows.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
int GetProcessId()
|
int GetProcessId()
|
||||||
{
|
{
|
||||||
|
@ -35,13 +35,15 @@ struct QueuedMessage {
|
|||||||
struct JoinRequest {
|
struct JoinRequest {
|
||||||
// snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null
|
// snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null
|
||||||
// terminator = 21
|
// terminator = 21
|
||||||
char userId[22];
|
char userId[32];
|
||||||
// 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null
|
// 32 unicode glyphs is max name size => 4 bytes per glyph in the worst case, +1 for null
|
||||||
// terminator = 129
|
// terminator = 129
|
||||||
char username[130];
|
char username[344];
|
||||||
|
// 4 decimal digits + 1 null terminator = 5
|
||||||
|
char discriminator[8];
|
||||||
// optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35
|
// optional 'a_' + md5 hex digest (32 bytes) + null terminator = 35
|
||||||
char avatar[36];
|
char avatar[128];
|
||||||
// +1 on each because: it's even / I'm paranoid
|
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
|
||||||
};
|
};
|
||||||
|
|
||||||
static RpcConnection* Connection{nullptr};
|
static RpcConnection* Connection{nullptr};
|
||||||
@ -65,16 +67,55 @@ static MsgQueue<JoinRequest, JoinQueueSize> JoinAskQueue;
|
|||||||
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential
|
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential
|
||||||
// backoff from 0.5 seconds to 1 minute
|
// backoff from 0.5 seconds to 1 minute
|
||||||
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
static Backoff ReconnectTimeMs(500, 60 * 1000);
|
||||||
static auto NextConnect{std::chrono::system_clock::now()};
|
static auto NextConnect = std::chrono::system_clock::now();
|
||||||
static int Pid{0};
|
static int Pid{0};
|
||||||
static int Nonce{1};
|
static int Nonce{1};
|
||||||
|
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
#ifndef DISCORD_DISABLE_IO_THREAD
|
||||||
static std::atomic_bool KeepRunning{true};
|
static void Discord_UpdateConnection(void);
|
||||||
static std::mutex WaitForIOMutex;
|
class IoThreadHolder {
|
||||||
static std::condition_variable WaitForIOActivity;
|
private:
|
||||||
static std::thread IoThread;
|
std::atomic_bool keepRunning{true};
|
||||||
|
std::mutex waitForIOMutex;
|
||||||
|
std::condition_variable waitForIOActivity;
|
||||||
|
std::thread ioThread;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Start()
|
||||||
|
{
|
||||||
|
keepRunning.store(true);
|
||||||
|
ioThread = std::thread([&]() {
|
||||||
|
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
||||||
|
while (keepRunning.load()) {
|
||||||
|
Discord_UpdateConnection();
|
||||||
|
std::unique_lock<std::mutex> lock(waitForIOMutex);
|
||||||
|
waitForIOActivity.wait_for(lock, maxWait);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notify() { waitForIOActivity.notify_all(); }
|
||||||
|
|
||||||
|
void Stop()
|
||||||
|
{
|
||||||
|
keepRunning.exchange(false);
|
||||||
|
Notify();
|
||||||
|
if (ioThread.joinable()) {
|
||||||
|
ioThread.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~IoThreadHolder() { Stop(); }
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
class IoThreadHolder {
|
||||||
|
public:
|
||||||
|
void Start() {}
|
||||||
|
void Stop() {}
|
||||||
|
void Notify() {}
|
||||||
|
};
|
||||||
#endif // DISCORD_DISABLE_IO_THREAD
|
#endif // DISCORD_DISABLE_IO_THREAD
|
||||||
|
static IoThreadHolder IoThread;
|
||||||
|
|
||||||
static void UpdateReconnectTime()
|
static void UpdateReconnectTime()
|
||||||
{
|
{
|
||||||
@ -127,8 +168,9 @@ static void Discord_UpdateConnection(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto data = GetObjMember(&message, "data");
|
||||||
|
|
||||||
if (strcmp(evtName, "ACTIVITY_JOIN") == 0) {
|
if (strcmp(evtName, "ACTIVITY_JOIN") == 0) {
|
||||||
auto data = GetObjMember(&message, "data");
|
|
||||||
auto secret = GetStrMember(data, "secret");
|
auto secret = GetStrMember(data, "secret");
|
||||||
if (secret) {
|
if (secret) {
|
||||||
StringCopy(JoinGameSecret, secret);
|
StringCopy(JoinGameSecret, secret);
|
||||||
@ -136,7 +178,6 @@ static void Discord_UpdateConnection(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) {
|
else if (strcmp(evtName, "ACTIVITY_SPECTATE") == 0) {
|
||||||
auto data = GetObjMember(&message, "data");
|
|
||||||
auto secret = GetStrMember(data, "secret");
|
auto secret = GetStrMember(data, "secret");
|
||||||
if (secret) {
|
if (secret) {
|
||||||
StringCopy(SpectateGameSecret, secret);
|
StringCopy(SpectateGameSecret, secret);
|
||||||
@ -144,7 +185,6 @@ static void Discord_UpdateConnection(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) {
|
else if (strcmp(evtName, "ACTIVITY_JOIN_REQUEST") == 0) {
|
||||||
auto data = GetObjMember(&message, "data");
|
|
||||||
auto user = GetObjMember(data, "user");
|
auto user = GetObjMember(data, "user");
|
||||||
auto userId = GetStrMember(user, "id");
|
auto userId = GetStrMember(user, "id");
|
||||||
auto username = GetStrMember(user, "username");
|
auto username = GetStrMember(user, "username");
|
||||||
@ -153,6 +193,10 @@ static void Discord_UpdateConnection(void)
|
|||||||
if (userId && username && joinReq) {
|
if (userId && username && joinReq) {
|
||||||
StringCopy(joinReq->userId, userId);
|
StringCopy(joinReq->userId, userId);
|
||||||
StringCopy(joinReq->username, username);
|
StringCopy(joinReq->username, username);
|
||||||
|
auto discriminator = GetStrMember(user, "discriminator");
|
||||||
|
if (discriminator) {
|
||||||
|
StringCopy(joinReq->discriminator, discriminator);
|
||||||
|
}
|
||||||
if (avatar) {
|
if (avatar) {
|
||||||
StringCopy(joinReq->avatar, avatar);
|
StringCopy(joinReq->avatar, avatar);
|
||||||
}
|
}
|
||||||
@ -188,25 +232,9 @@ static void Discord_UpdateConnection(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
|
||||||
static void DiscordRpcIo(void)
|
|
||||||
{
|
|
||||||
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
|
|
||||||
|
|
||||||
while (KeepRunning.load()) {
|
|
||||||
Discord_UpdateConnection();
|
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(WaitForIOMutex);
|
|
||||||
WaitForIOActivity.wait_for(lock, maxWait);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void SignalIOActivity()
|
static void SignalIOActivity()
|
||||||
{
|
{
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
IoThread.Notify();
|
||||||
WaitForIOActivity.notify_all();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool RegisterForEvent(const char* evtName)
|
static bool RegisterForEvent(const char* evtName)
|
||||||
@ -273,10 +301,7 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
|||||||
UpdateReconnectTime();
|
UpdateReconnectTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
IoThread.Start();
|
||||||
KeepRunning.store(true);
|
|
||||||
IoThread = std::thread(DiscordRpcIo);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" DISCORD_EXPORT void Discord_Shutdown()
|
extern "C" DISCORD_EXPORT void Discord_Shutdown()
|
||||||
@ -287,13 +312,7 @@ extern "C" DISCORD_EXPORT void Discord_Shutdown()
|
|||||||
Connection->onConnect = nullptr;
|
Connection->onConnect = nullptr;
|
||||||
Connection->onDisconnect = nullptr;
|
Connection->onDisconnect = nullptr;
|
||||||
Handlers = {};
|
Handlers = {};
|
||||||
#ifndef DISCORD_DISABLE_IO_THREAD
|
IoThread.Stop();
|
||||||
KeepRunning.exchange(false);
|
|
||||||
SignalIOActivity();
|
|
||||||
if (IoThread.joinable()) {
|
|
||||||
IoThread.join();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
RpcConnection::Destroy(Connection);
|
RpcConnection::Destroy(Connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +384,7 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks()
|
|||||||
while (JoinAskQueue.HavePendingSends()) {
|
while (JoinAskQueue.HavePendingSends()) {
|
||||||
auto req = JoinAskQueue.GetNextSendMessage();
|
auto req = JoinAskQueue.GetNextSendMessage();
|
||||||
if (Handlers.joinRequest) {
|
if (Handlers.joinRequest) {
|
||||||
DiscordJoinRequest djr{req->userId, req->username, req->avatar};
|
DiscordJoinRequest djr{req->userId, req->username, req->discriminator, req->avatar};
|
||||||
Handlers.joinRequest(&djr);
|
Handlers.joinRequest(&djr);
|
||||||
}
|
}
|
||||||
JoinAskQueue.CommitSend();
|
JoinAskQueue.CommitSend();
|
||||||
|
@ -85,12 +85,14 @@ extern "C" void Discord_Register(const char* applicationId, const char* command)
|
|||||||
"xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s",
|
"xdg-mime default discord-%s.desktop x-scheme-handler/discord-%s",
|
||||||
applicationId,
|
applicationId,
|
||||||
applicationId);
|
applicationId);
|
||||||
system(xdgMimeCommand);
|
if (system(xdgMimeCommand) < 0) {
|
||||||
|
fprintf(stderr, "Failed to register mime handler\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
extern "C" void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
||||||
{
|
{
|
||||||
char command[256];
|
char command[256];
|
||||||
sprintf(command, "xdg-open steam://run/%s", steamId);
|
sprintf(command, "xdg-open steam://rungameid/%s", steamId);
|
||||||
Discord_Register(applicationId, command);
|
Discord_Register(applicationId, command);
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,6 @@ void Discord_Register(const char* applicationId, const char* command)
|
|||||||
void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
void Discord_RegisterSteamGame(const char* applicationId, const char* steamId)
|
||||||
{
|
{
|
||||||
char command[256];
|
char command[256];
|
||||||
sprintf(command, "steam://run/%s", steamId);
|
sprintf(command, "steam://rungameid/%s", steamId);
|
||||||
Discord_Register(applicationId, command);
|
Discord_Register(applicationId, command);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* MinGW defaults to WINNT 5.1 (aka XP), however some of functions used here
|
||||||
|
* require WINNT >= 6.0 APIs, which are only visible when WINVER and
|
||||||
|
* _WIN32_WINNT defines are set properly before including any system headers.
|
||||||
|
* Such API is e.g. RegSetKeyValueW.
|
||||||
|
*/
|
||||||
|
#ifdef __MINGW32__
|
||||||
|
// 0x0600 == vista
|
||||||
|
#define WINVER 0x0600
|
||||||
|
#define _WIN32_WINNT 0x0600
|
||||||
|
#endif // __MINGW32__
|
||||||
|
|
||||||
#include "discord-rpc.h"
|
#include "discord-rpc.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
@ -6,9 +18,8 @@
|
|||||||
#define NOSERVICE
|
#define NOSERVICE
|
||||||
#define NOIME
|
#define NOIME
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <Psapi.h>
|
#include <psapi.h>
|
||||||
#include <Strsafe.h>
|
#include <strsafe.h>
|
||||||
#pragma comment(lib, "Psapi.lib")
|
|
||||||
|
|
||||||
void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
||||||
{
|
{
|
||||||
@ -17,14 +28,14 @@ void Discord_RegisterW(const wchar_t* applicationId, const wchar_t* command)
|
|||||||
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
// Update the HKEY_CURRENT_USER, because it doesn't seem to require special permissions.
|
||||||
|
|
||||||
wchar_t exeFilePath[MAX_PATH];
|
wchar_t exeFilePath[MAX_PATH];
|
||||||
DWORD exeLen = GetModuleFileNameExW(GetCurrentProcess(), nullptr, exeFilePath, MAX_PATH);
|
DWORD exeLen = GetModuleFileNameW(nullptr, exeFilePath, MAX_PATH);
|
||||||
wchar_t openCommand[1024];
|
wchar_t openCommand[1024];
|
||||||
|
|
||||||
if (command && command[0]) {
|
if (command && command[0]) {
|
||||||
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command);
|
StringCbPrintfW(openCommand, sizeof(openCommand), L"%s", command);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lstrcpyW(openCommand, exeFilePath);
|
StringCbCopyW(openCommand, sizeof(openCommand), exeFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t protocolName[64];
|
wchar_t protocolName[64];
|
||||||
@ -121,7 +132,7 @@ extern "C" void Discord_RegisterSteamGame(const char* applicationId, const char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
wchar_t command[1024];
|
wchar_t command[1024];
|
||||||
StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://run/%s", steamPath, wSteamId);
|
StringCbPrintfW(command, sizeof(command), L"\"%s\" steam://rungameid/%s", steamPath, wSteamId);
|
||||||
|
|
||||||
Discord_RegisterW(appId, command);
|
Discord_RegisterW(appId, command);
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
#pragma warning(disable : 6313) // Incorrect operator
|
#pragma warning(disable : 6313) // Incorrect operator
|
||||||
|
|
||||||
#include "rapidjson/document.h"
|
#include "rapidjson/document.h"
|
||||||
#include "rapidjson/writer.h"
|
|
||||||
#include "rapidjson/stringbuffer.h"
|
#include "rapidjson/stringbuffer.h"
|
||||||
|
#include "rapidjson/writer.h"
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
@ -79,6 +79,9 @@ public:
|
|||||||
}
|
}
|
||||||
// allocate how much you need in the first place
|
// allocate how much you need in the first place
|
||||||
assert(!originalPtr && !originalSize);
|
assert(!originalPtr && !originalSize);
|
||||||
|
// unused parameter warning
|
||||||
|
(void)(originalPtr);
|
||||||
|
(void)(originalSize);
|
||||||
return Malloc(newSize);
|
return Malloc(newSize);
|
||||||
}
|
}
|
||||||
static void Free(void* ptr)
|
static void Free(void* ptr)
|
||||||
|
Reference in New Issue
Block a user