diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e4983d5..53e94d1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -21,19 +21,19 @@ jobs: run: zig build - name: Test run: zig build test - ubuntu-build: - timeout-minutes: 15 - continue-on-error: true - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: goto-bus-stop/setup-zig@v2 - - name: Install OpenGL - run: apt-get libglu1-mesa-dev freeglut3-dev mesa-common-dev - - name: Build - run: zig build - - name: Test - run: zig build test + # ubuntu-build: + # timeout-minutes: 15 + # continue-on-error: true + # runs-on: ubuntu-latest + # steps: + # - uses: actions/checkout@v2 + # - uses: goto-bus-stop/setup-zig@v2 + # - name: Install OpenGL + # run: apt-get libglu1-mesa-dev freeglut3-dev mesa-common-dev + # - name: Build + # run: zig build + # - name: Test + # run: zig build test lint: needs: build timeout-minutes: 15 diff --git a/Client/AUTHORS b/Client/AUTHORS deleted file mode 100644 index 256626b..0000000 --- a/Client/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Fatbag \ No newline at end of file diff --git a/Client/Audio/Audio.hpp b/Client/Audio/Audio.hpp deleted file mode 100644 index 78ab719..0000000 --- a/Client/Audio/Audio.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Audio/Audio.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "windows/xaudio2.hpp" -#ifdef PlaySound //defined by the Windows API - #undef PlaySound -#endif - -struct PlayableSound_t { - bool Playing; - uint8_t * Data; - IXAudio2SourceVoice* pSourceVoice; -}; - -namespace Audio { - int Initialize(); - PlayableSound_t * LoadSound(const Sound_t * Sound); - bool PlaySound(PlayableSound_t * Sound); - bool StopSound(PlayableSound_t * Sound); - void DeleteSound(PlayableSound_t * Sound); - void Shutdown(); -} \ No newline at end of file diff --git a/Client/Audio/Startup.cpp b/Client/Audio/Startup.cpp deleted file mode 100644 index 93496b6..0000000 --- a/Client/Audio/Startup.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Audio/Startup.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -namespace Audio { - -IXAudio2 *pXAudio2 = NULL; -IXAudio2MasteringVoice *MasterVoice = NULL; - -int Initialize(){ - HRESULT result; - - result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE | COINIT_SPEED_OVER_MEMORY); - if(result != S_OK){ - MessageBox(Window::hWnd, "Failed to initialize Microsoft COM.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_AUDIO_INIT_COM; - } - - result = XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR); - if(result != S_OK){ - MessageBox(Window::hWnd, "Failed to initialize XAudio2. Please download the latest DirectX runtime for your system.", - NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_AUDIO_INIT_XAUDIO2; - } - - result = pXAudio2->CreateMasteringVoice(&MasterVoice, 2, 44100, 0, 0, NULL); - if(result != S_OK){ - MessageBox(Window::hWnd, "Failed to create the mastering voice for XAudio2.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_AUDIO_CREATE_VOICE; - } - return 0; -} - -PlayableSound_t * LoadSound(const Sound_t * Sound){ - const WAVEFORMATEX wfx = { - WAVE_FORMAT_PCM, //wFormatTag - Sound->Channels, //nChannels - Sound->SamplingRate, //nSamplesPerSec - ((Sound->Channels * Sound->BitDepth) >> 3) * Sound->SamplingRate, //nAvgBytesPerSec - ((Sound->Channels * Sound->BitDepth) >> 3), //nBlockAlign - Sound->BitDepth, //wBitsPerSample - 0 //cbSize - }; - - const XAUDIO2_BUFFER buffer = { - 0, //Flags - Sound->Duration * wfx.nBlockAlign, //AudioBytes - Sound->Data, //pAudioData - 0, //PlayBegin - 0, //PlayLength - 0, //LoopBegin - 0, //LoopLength - XAUDIO2_LOOP_INFINITE, //LoopCount - NULL, //pContext - }; - - IXAudio2SourceVoice* pSourceVoice; - if(FAILED(pXAudio2->CreateSourceVoice(&pSourceVoice, &wfx))) - return NULL; - if(FAILED(pSourceVoice->SubmitSourceBuffer(&buffer))) - return NULL; - - PlayableSound_t * PlayableSound = (PlayableSound_t*) malloc(sizeof(PlayableSound_t)); - if(!PlayableSound) - return NULL; - PlayableSound->pSourceVoice = pSourceVoice; - PlayableSound->Playing = false; - PlayableSound->Data = Sound->Data; - return PlayableSound; -} - -bool PlaySound(PlayableSound_t * Sound){ - if(!Sound->Playing && !FAILED(Sound->pSourceVoice->Start(0))){ - Sound->Playing = true; - return true; - } - return false; -} - -bool StopSound(PlayableSound_t * Sound){ - int success = false; - if(Sound->Playing && !FAILED(Sound->pSourceVoice->Stop(0))) - success = true; - Sound->Playing = false; - return success; -} - -void DeleteSound(PlayableSound_t * Sound){ - StopSound(Sound); - //Sound->pSourceVoice->Release(); -} - -void Shutdown(){ - if(MasterVoice){ - MasterVoice->DestroyVoice(); - MasterVoice = NULL; - } - if(pXAudio2){ - pXAudio2->Release(); - pXAudio2 = NULL; - } -} - -} \ No newline at end of file diff --git a/Client/Audio/windows/xaudio2.cpp b/Client/Audio/windows/xaudio2.cpp deleted file mode 100644 index 669d706..0000000 --- a/Client/Audio/windows/xaudio2.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -DEFINE_GUID(CLSID_XAudio2, 0xe21a7345, 0xeb21, 0x468e, 0xbe, 0x50, 0x80, 0x4d, 0xb9, 0x7c, 0xf7, 0x08); -DEFINE_GUID(CLSID_XAudio2_Debug, 0xf7a76c21, 0x53d4, 0x46bb, 0xac, 0x53, 0x8b, 0x45, 0x9c, 0xae, 0x46, 0xbd); -DEFINE_GUID(IID_IXAudio2, 0x8bcf1f58, 0x9fe7, 0x4583, 0x8a, 0xc6, 0xe2, 0xad, 0xc4, 0x65, 0xc8, 0xbb); \ No newline at end of file diff --git a/Client/Audio/windows/xaudio2.hpp b/Client/Audio/windows/xaudio2.hpp deleted file mode 100644 index 758539e..0000000 --- a/Client/Audio/windows/xaudio2.hpp +++ /dev/null @@ -1,271 +0,0 @@ -/* - xaudio2.hpp (2010-08-14) - author: OV2 - - ruby-specific header to provide mingw-friendly xaudio2 interfaces -*/ - -#include -#include - -DEFINE_GUID(CLSID_XAudio2, 0xe21a7345, 0xeb21, 0x468e, 0xbe, 0x50, 0x80, 0x4d, 0xb9, 0x7c, 0xf7, 0x08); -DEFINE_GUID(CLSID_XAudio2_Debug, 0xf7a76c21, 0x53d4, 0x46bb, 0xac, 0x53, 0x8b, 0x45, 0x9c, 0xae, 0x46, 0xbd); -DEFINE_GUID(IID_IXAudio2, 0x8bcf1f58, 0x9fe7, 0x4583, 0x8a, 0xc6, 0xe2, 0xad, 0xc4, 0x65, 0xc8, 0xbb); - -DECLARE_INTERFACE(IXAudio2Voice); - -#define XAUDIO2_COMMIT_NOW 0 -#define XAUDIO2_DEFAULT_CHANNELS 0 -#define XAUDIO2_DEFAULT_SAMPLERATE 0 -#define XAUDIO2_DEFAULT_FREQ_RATIO 4.0f -#define XAUDIO2_DEBUG_ENGINE 0x0001 -#define XAUDIO2_LOOP_INFINITE 255 -#define XAUDIO2_VOICE_NOSRC 0x0004 - -enum XAUDIO2_DEVICE_ROLE -{ - NotDefaultDevice = 0x0, - DefaultConsoleDevice = 0x1, - DefaultMultimediaDevice = 0x2, - DefaultCommunicationsDevice = 0x4, - DefaultGameDevice = 0x8, - GlobalDefaultDevice = 0xf, - InvalidDeviceRole = ~GlobalDefaultDevice -}; - -struct XAUDIO2_DEVICE_DETAILS -{ - WCHAR DeviceID[256]; - WCHAR DisplayName[256]; - XAUDIO2_DEVICE_ROLE Role; - WAVEFORMATEXTENSIBLE OutputFormat; -}; - -struct XAUDIO2_VOICE_DETAILS -{ - UINT32 CreationFlags; - UINT32 InputChannels; - UINT32 InputSampleRate; -}; - -typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER -{ - Processor1 = 0x00000001, - Processor2 = 0x00000002, - Processor3 = 0x00000004, - Processor4 = 0x00000008, - Processor5 = 0x00000010, - Processor6 = 0x00000020, - Processor7 = 0x00000040, - Processor8 = 0x00000080, - Processor9 = 0x00000100, - Processor10 = 0x00000200, - Processor11 = 0x00000400, - Processor12 = 0x00000800, - Processor13 = 0x00001000, - Processor14 = 0x00002000, - Processor15 = 0x00004000, - Processor16 = 0x00008000, - Processor17 = 0x00010000, - Processor18 = 0x00020000, - Processor19 = 0x00040000, - Processor20 = 0x00080000, - Processor21 = 0x00100000, - Processor22 = 0x00200000, - Processor23 = 0x00400000, - Processor24 = 0x00800000, - Processor25 = 0x01000000, - Processor26 = 0x02000000, - Processor27 = 0x04000000, - Processor28 = 0x08000000, - Processor29 = 0x10000000, - Processor30 = 0x20000000, - Processor31 = 0x40000000, - Processor32 = 0x80000000, - XAUDIO2_ANY_PROCESSOR = 0xffffffff, - XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR -} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR; - -struct XAUDIO2_VOICE_SENDS -{ - UINT32 OutputCount; - IXAudio2Voice* *pOutputVoices; -}; - -struct XAUDIO2_EFFECT_DESCRIPTOR -{ - IUnknown *pEffect; - BOOL InitialState; - UINT32 OutputChannels; -}; - -struct XAUDIO2_EFFECT_CHAIN -{ - UINT32 EffectCount; - const XAUDIO2_EFFECT_DESCRIPTOR *pEffectDescriptors; -}; - -enum XAUDIO2_FILTER_TYPE -{ - LowPassFilter, - BandPassFilter, - HighPassFilter -}; - -struct XAUDIO2_FILTER_PARAMETERS -{ - XAUDIO2_FILTER_TYPE Type; - float Frequency; - float OneOverQ; -}; - -struct XAUDIO2_BUFFER -{ - UINT32 Flags; - UINT32 AudioBytes; - const BYTE *pAudioData; - UINT32 PlayBegin; - UINT32 PlayLength; - UINT32 LoopBegin; - UINT32 LoopLength; - UINT32 LoopCount; - void *pContext; -}; - -struct XAUDIO2_BUFFER_WMA -{ - const UINT32 *pDecodedPacketCumulativeBytes; - UINT32 PacketCount; -}; - -struct XAUDIO2_VOICE_STATE -{ - void *pCurrentBufferContext; - UINT32 BuffersQueued; - UINT64 SamplesPlayed; -}; - -struct XAUDIO2_PERFORMANCE_DATA -{ - UINT64 AudioCyclesSinceLastQuery; - UINT64 TotalCyclesSinceLastQuery; - UINT32 MinimumCyclesPerQuantum; - UINT32 MaximumCyclesPerQuantum; - UINT32 MemoryUsageInBytes; - UINT32 CurrentLatencyInSamples; - UINT32 GlitchesSinceEngineStarted; - UINT32 ActiveSourceVoiceCount; - UINT32 TotalSourceVoiceCount; - UINT32 ActiveSubmixVoiceCount; - UINT32 TotalSubmixVoiceCount; - UINT32 ActiveXmaSourceVoices; - UINT32 ActiveXmaStreams; -}; - -struct XAUDIO2_DEBUG_CONFIGURATION -{ - UINT32 TraceMask; - UINT32 BreakMask; - BOOL LogThreadID; - BOOL LogFileline; - BOOL LogFunctionName; - BOOL LogTiming; -}; - -DECLARE_INTERFACE(IXAudio2EngineCallback) -{ - STDMETHOD_(void, OnProcessingPassStart) (void); - STDMETHOD_(void, OnProcessingPassEnd) (void); - STDMETHOD_(void, OnCriticalError) (HRESULT Error); -}; - -DECLARE_INTERFACE(IXAudio2VoiceCallback) -{ - STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32 BytesRequired); - STDMETHOD_(void, OnVoiceProcessingPassEnd) (void); - STDMETHOD_(void, OnStreamEnd) (void); - STDMETHOD_(void, OnBufferStart) (void *pBufferContext); - STDMETHOD_(void, OnBufferEnd) (void *pBufferContext); - STDMETHOD_(void, OnLoopEnd) (void *pBufferContext); - STDMETHOD_(void, OnVoiceError) (void *pBufferContext, HRESULT Error); -}; - -DECLARE_INTERFACE(IXAudio2Voice) -{ - STDMETHOD_(void, GetVoiceDetails) (XAUDIO2_VOICE_DETAILS *pVoiceDetails); - STDMETHOD(SetOutputVoices) (const XAUDIO2_VOICE_SENDS *pSendList); - STDMETHOD(SetEffectChain) (const XAUDIO2_EFFECT_CHAIN *pEffectChain); - STDMETHOD(EnableEffect) (UINT32 EffectIndex, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD(DisableEffect) (UINT32 EffectIndex, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetEffectState) (UINT32 EffectIndex, BOOL *pEnabled); - STDMETHOD(SetEffectParameters) (UINT32 EffectIndex, const void *pParameters, UINT32 ParametersByteSize, - UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD(GetEffectParameters) (UINT32 EffectIndex, void *pParameters, UINT32 ParametersByteSize); - STDMETHOD(SetFilterParameters) (const XAUDIO2_FILTER_PARAMETERS *pParameters, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetFilterParameters) (XAUDIO2_FILTER_PARAMETERS *pParameters); - STDMETHOD(SetVolume) (float Volume, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetVolume) (float *pVolume); - STDMETHOD(SetChannelVolumes) (UINT32 Channels, const float *pVolumes, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetChannelVolumes) (UINT32 Channels, float *pVolumes); - STDMETHOD(SetOutputMatrix) (IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels, UINT32 DestinationChannels, - const float *pLevelMatrix, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetOutputMatrix) (IXAudio2Voice *pDestinationVoice, UINT32 SourceChannels, - UINT32 DestinationChannels, float *pLevelMatrix); - STDMETHOD_(void, DestroyVoice) (void); -}; - -DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice){}; - -DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice){}; - -DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice) -{ - STDMETHOD(Start) (UINT32 Flags, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD(Stop) (UINT32 Flags, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD(SubmitSourceBuffer) (const XAUDIO2_BUFFER *pBuffer, const XAUDIO2_BUFFER_WMA *pBufferWMA = NULL); - STDMETHOD(FlushSourceBuffers) (void); - STDMETHOD(Discontinuity) (void); - STDMETHOD(ExitLoop) (UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetState) (XAUDIO2_VOICE_STATE *pVoiceState); - STDMETHOD(SetFrequencyRatio) (float Ratio, UINT32 OperationSet = XAUDIO2_COMMIT_NOW); - STDMETHOD_(void, GetFrequencyRatio) (float *pRatio); -}; - -DECLARE_INTERFACE_(IXAudio2, IUnknown) -{ - STDMETHOD(GetDeviceCount) (UINT32 *pCount); - STDMETHOD(GetDeviceDetails) (UINT32 Index, XAUDIO2_DEVICE_DETAILS *pDeviceDetails); - STDMETHOD(Initialize) (UINT32 Flags = 0, XAUDIO2_PROCESSOR XAudio2Processor = XAUDIO2_DEFAULT_PROCESSOR); - STDMETHOD(RegisterForCallbacks) (IXAudio2EngineCallback *pCallback); - STDMETHOD_(void, UnregisterForCallbacks) (IXAudio2EngineCallback *pCallback); - STDMETHOD(CreateSourceVoice) (IXAudio2SourceVoice* *ppSourceVoice, const WAVEFORMATEX *pSourceFormat, UINT32 Flags = 0, - float MaxFrequencyRatio = XAUDIO2_DEFAULT_FREQ_RATIO, IXAudio2VoiceCallback *pCallback = NULL, - const XAUDIO2_VOICE_SENDS *pSendList = NULL, const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL); - STDMETHOD(CreateSubmixVoice) (IXAudio2SubmixVoice* *ppSubmixVoice, UINT32 InputChannels, UINT32 InputSampleRate, - UINT32 Flags = 0, UINT32 ProcessingStage = 0, const XAUDIO2_VOICE_SENDS *pSendList = NULL, - const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL); - STDMETHOD(CreateMasteringVoice) (IXAudio2MasteringVoice* *ppMasteringVoice, - UINT32 InputChannels = XAUDIO2_DEFAULT_CHANNELS, UINT32 InputSampleRate = XAUDIO2_DEFAULT_SAMPLERATE, - UINT32 Flags = 0, UINT32 DeviceIndex = 0, const XAUDIO2_EFFECT_CHAIN *pEffectChain = NULL); - STDMETHOD(StartEngine) (void); - STDMETHOD_(void, StopEngine) (void); - STDMETHOD(CommitChanges) (UINT32 OperationSet); - STDMETHOD_(void, GetPerformanceData) (XAUDIO2_PERFORMANCE_DATA *pPerfData); - STDMETHOD_(void, SetDebugConfiguration) (const XAUDIO2_DEBUG_CONFIGURATION *pDebugConfiguration, void *pReserved = NULL); -}; - -inline HRESULT XAudio2Create(IXAudio2* *ppXAudio2, UINT32 Flags = 0, - XAUDIO2_PROCESSOR XAudio2Processor = XAUDIO2_DEFAULT_PROCESSOR) -{ - IXAudio2 *pXAudio2; - HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2, NULL, - CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2); - if(SUCCEEDED(hr)){ - hr = pXAudio2->Initialize(Flags, XAudio2Processor); - if(SUCCEEDED(hr)) - *ppXAudio2 = pXAudio2; - else - pXAudio2->Release(); - } - return hr; -} \ No newline at end of file diff --git a/Client/CHANGES b/Client/CHANGES deleted file mode 100644 index aacc0cb..0000000 --- a/Client/CHANGES +++ /dev/null @@ -1,2 +0,0 @@ -Technical Preview 1 - * Initial release \ No newline at end of file diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt deleted file mode 100644 index fc096e0..0000000 --- a/Client/CMakeLists.txt +++ /dev/null @@ -1,22 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(NiotsoClient) - -include_directories(${FILEHANDLER_INCLUDE} ${FREETYPE_INCLUDE}) - -if(WIN32) - set(NIOTSOCLIENT_SOURCES - Client.cpp - Audio/Startup.cpp - Audio/windows/XAudio2.cpp - Graphics/Font.cpp - Graphics/Startup.cpp - Graphics/Viewport.cpp - Resources/Resource.rc - Scene/LoginScreen/LoginScreen.cpp - System/System.cpp - Window/Window.cpp - ) - add_executable(TSO WIN32 ${NIOTSOCLIENT_SOURCES}) - target_link_libraries(TSO ole32 opengl32) - target_link_libraries(TSO FileHandler_shared ${FREETYPE_LINK}) -endif() \ No newline at end of file diff --git a/Client/COPYING b/Client/COPYING deleted file mode 100644 index acdc1dc..0000000 --- a/Client/COPYING +++ /dev/null @@ -1,642 +0,0 @@ -IMPORTANT: -Niotso is distributed under the terms of the GNU GPLv3. - -While this license does permit others to compile, distribute, change, -and distribute changes to Niotso, in reality, many of these freedoms -cannot legally be enacted by anybody. - -Specifically, if you make changes to Niotso such that it significantly -changes the "game experience as presented to the player", it cannot -be distributed to others. You also may not distribute a version of -Niotso that has stripped the EA or Maxis trademarked names or logos -anywhere from the game. Personal use of these modifications is okay. - -These restrictions are not enforced by us, but may potentially be used -by EA in attempt to take down your game. - -If you have any questions, you may visit - - ---- - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/Client/Client.cpp b/Client/Client.cpp deleted file mode 100644 index 15c8d70..0000000 --- a/Client/Client.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Client.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "EngineInterface.hpp" - -static void Shutdown(); -Scene * CurrentScene; - -#ifdef _WIN32 - -/* MinGW bonus feature; saves 66 kB in the binary :) */ -/* */ void* __CRTDECL operator new(unsigned size){return malloc(size);} -/* */ void __CRTDECL operator delete(void *ptr){free(ptr);} -/* */ extern "C" void __CRTDECL __cxa_pure_virtual(){} - -int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) -{ - int result; - - //Disallow multiple instances of the game from running - CreateMutex(NULL, TRUE, "Global\\TSO_NIOTSO_MUTEX"); - if(GetLastError() == ERROR_ALREADY_EXISTS){ - HWND hWnd = FindWindow("TSO_NIOTSO", "The Sims Online"); - if(hWnd != NULL){ - ShowWindow(hWnd, SW_RESTORE); - SetForegroundWindow(hWnd); - SetFocus(hWnd); - } - return ERROR_INIT_ANOTHERINSTRUNNING; - } - - Window::Width = 800; - Window::Height = 600; - Window::Fullscreen = false; - System::hInst = hInstance; - - result = Window::Initialize(); - if(result != 0){ - Shutdown(); - return ERROR_INIT | ERROR_INIT_WINDOW | result; - } - - result = System::Initialize(); - if(result != 0){ - Shutdown(); - return ERROR_INIT | ERROR_INIT_SYSTEM | result; - } - - result = Graphics::Initialize(); - if(result != 0){ - Shutdown(); - return ERROR_INIT | ERROR_INIT_GRAPHICS | result; - } - - result = Audio::Initialize(); - if(result != 0){ - Shutdown(); - return ERROR_INIT | ERROR_INIT_AUDIO | result; - } - - CurrentScene = new LoginScreen(); - if(CurrentScene == NULL || System::SceneFailed){ - Shutdown(); - return ERROR_INIT | ERROR_INIT_LOGIC | ERROR_LOGIC_CREATE_SCENE; - } - - ShowWindow(Window::hWnd, SW_SHOW); - SetForegroundWindow(Window::hWnd); - SetFocus(Window::hWnd); - - LARGE_INTEGER PreviousTime; - QueryPerformanceCounter(&PreviousTime); - - while(true){ - LARGE_INTEGER CurrentTime; - QueryPerformanceCounter(&CurrentTime); - float TimeDelta = (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/System::ClockFreq.QuadPart; - PreviousTime = CurrentTime; - if(TimeDelta < 0 || TimeDelta >= 5) //Safe-guard in case of system delay - continue; - - memcpy(&System::UserInput, (const void*) &System::UserInput_v, sizeof(System::UserInput_t)); - - int result = CurrentScene->RunFor(TimeDelta); - if(result == System::SHUTDOWN) - break; - if(result > 0){ - glClear(GL_COLOR_BUFFER_BIT); - CurrentScene->Render(); - SwapBuffers(Graphics::hDC); - } - - //Sleep for the remainder of the frame - PreviousTime.QuadPart = CurrentTime.QuadPart; - QueryPerformanceCounter(&CurrentTime); - float SleepDuration = - (System::FramePeriod - (float)(CurrentTime.QuadPart-PreviousTime.QuadPart)/System::ClockFreq.QuadPart) * 1000; - if(SleepDuration > 1 && SleepDuration < 100) Sleep((unsigned) SleepDuration); - } - - ShowWindow(Window::hWnd, SW_HIDE); - delete CurrentScene; - - Shutdown(); - return 0; -} - -static void Shutdown() -{ - Audio::Shutdown(); - Graphics::Shutdown(); - System::Shutdown(); - Window::Shutdown(); -} - -#endif \ No newline at end of file diff --git a/Client/EngineInterface.hpp b/Client/EngineInterface.hpp deleted file mode 100644 index 17dce67..0000000 --- a/Client/EngineInterface.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - EngineInterface.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -//Compiler/platform constants -#ifdef _WIN32 - #define WINVER 0x0502 - #define _WIN32_WINNT 0x0502 - #define _CRT_SECURE_NO_WARNINGS -#endif - -//Standard libraries -#include -#include -#include -#include -#ifdef _WIN32 - #define WIN32_LEAN_AND_MEAN - #include - #undef NULL - #define NULL 0 -#endif - -//Codebase libraries -#include "FileHandler.hpp" -#include "ft2build.h" -#include FT_FREETYPE_H - -//Macro definitions -#ifndef min - #define min(x,y) ((x)<(y)?(x):(y)) -#endif -#ifndef max - #define max(x,y) ((x)>(y)?(x):(y)) -#endif - -//Codebase version, branding, linker resources -#include "version.h" -#include "Resources/Resource.h" - -//Components -#include "Audio/Audio.hpp" -#include "Graphics/Graphics.hpp" -#include "System/System.hpp" -#include "Window/Window.hpp" - -#include "Scene/Scene.hpp" \ No newline at end of file diff --git a/Client/Graphics/Font.cpp b/Client/Graphics/Font.cpp deleted file mode 100644 index 10941d6..0000000 --- a/Client/Graphics/Font.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Graphics/Font.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -namespace Graphics { - -FT_Library FreeTypeLibrary; -FT_Face FontFace; - -static void FindStringSize(const wchar_t * String, unsigned * width, unsigned * height, int * xoffset, int * yoffset, int font){ - int x = 0, y = 0; - int lowestx = 0, lowesty = 0, highestx = 0, highesty = 0; - - for(wchar_t letter=*String; letter!='\0'; letter=*(++String)){ - int error = FT_Load_Char(FontFace, letter, FT_LOAD_RENDER); - if(error) continue; - - int bottomx = x + FontFace->glyph->bitmap_left; - int bottomy = y + FontFace->glyph->bitmap_top - FontFace->glyph->bitmap.rows; - if(bottomx < lowestx) lowestx = bottomx; - if(bottomy < lowesty) lowesty = bottomy; - - int topx = x + FontFace->glyph->bitmap_left + FontFace->glyph->bitmap.width; - int topy = y + FontFace->glyph->bitmap_top; - if(topx > highestx) highestx = topx; - if(topy > highesty) highesty = topy; - - x += FontFace->glyph->advance.x >> 6; - y += FontFace->glyph->advance.y >> 6; - } - - *width = highestx-lowestx, *height = highesty-lowesty; - *xoffset = -lowestx, *yoffset = -lowesty; -} - -void DrawText(Image_t * Image, const wchar_t * String, int x, int y, unsigned width, unsigned height, - TextAlignment Alignment, int font, COLORREF Color){ - //x, y, width, height form the bounding rectangle into which the text should be drawn. - //(x,y) defines the offset to the top-left of the rectangle from the top left of the background. - //The destination image must be stored in bottom-up order. - - if(x >= (signed)Image->Width || y >= (signed)Image->Height) return; - - //(stringx,stringy) will refer to the top-left of the string in bottom-up coordinates - int stringx, stringy; - unsigned StringWidth, StringHeight; - FindStringSize(String, &StringWidth, &StringHeight, &stringx, &stringy, font); - - //Horizontal alignment - if(Alignment < 2) stringx = x; //Left - else if(Alignment < 4) stringx = x+(width-StringWidth+1)/2; //Middle - else stringx = x+width-StringWidth; //Right - //Vertical alignment - if(!(Alignment&1)) stringy = y; //Top - else stringy = y+(height-StringHeight+1)/2; //Middle - stringy = Image->Height-stringy-StringHeight; - - //Now that we've done the alignment, we can crop the bounding box within the limits of the background image - if(x < 0){ Image->Width += x; x = 0; } - if(y < 0){ Image->Height += y; y = 0; } - if(width > Image->Width) width = Image->Width; - if(height > Image->Height) height = Image->Height; - - for(wchar_t letter=*String; letter!='\0'; letter=*(++String)){ - int error = FT_Load_Char(FontFace, letter, FT_LOAD_RENDER); - if(error) continue; - - int cWidth = FontFace->glyph->bitmap.width, cHeight = FontFace->glyph->bitmap.rows; - if(cWidth && cHeight){ - uint8_t * cRender; /* Convert to Bottom-up */ - uint8_t * OriginalRender = FontFace->glyph->bitmap.buffer; - if(FontFace->glyph->bitmap.pitch > 0){ - cRender = (uint8_t *) malloc(cWidth * cHeight); - for(int i=0; iglyph->bitmap_left; - stringy += FontFace->glyph->bitmap_top-cHeight; - for(int i=max(-stringy, 0); iData + 3*((stringy+i)*width + (stringx+j)); - - int originalcolor; - originalcolor = *ptr; - *ptr++ = (uint8_t) (originalcolor + (int)((GetBValue(Color)-originalcolor)*2*value+255)/510); - originalcolor = *ptr; - *ptr++ = (uint8_t) (originalcolor + (int)((GetGValue(Color)-originalcolor)*2*value+255)/510); - originalcolor = *ptr; - *ptr++ = (uint8_t) (originalcolor + (int)((GetRValue(Color)-originalcolor)*2*value+255)/510); - } - } - stringx -= FontFace->glyph->bitmap_left; - stringy -= FontFace->glyph->bitmap_top-cHeight; - - if(FontFace->glyph->bitmap.pitch > 0) free(cRender); - } - stringx += FontFace->glyph->advance.x >> 6; - stringy += FontFace->glyph->advance.y >> 6; - } -} - -Image_t * StringImage(const wchar_t * String, int font, COLORREF Color){ - Image_t * Image = (Image_t*) malloc(sizeof(Image_t)); - if(Image == NULL) return NULL; - - unsigned StringWidth, StringHeight; - int stringx, stringy; - FindStringSize(String, &StringWidth, &StringHeight, &stringx, &stringy, font); - - Image->Data = (uint8_t*) malloc(4 * StringWidth * StringHeight); - if(Image->Data == NULL){ - free(Image); - return NULL; - } - for(unsigned i=0; i<4*StringWidth*StringHeight;){ - Image->Data[i++] = GetBValue(Color); - Image->Data[i++] = GetGValue(Color); - Image->Data[i++] = GetRValue(Color); - Image->Data[i++] = 0; - } - - for(wchar_t letter=*String; letter!='\0'; letter=*(++String)){ - int error = FT_Load_Char(FontFace, letter, FT_LOAD_RENDER); - if(error) continue; - - int cWidth = FontFace->glyph->bitmap.width, cHeight = FontFace->glyph->bitmap.rows; - if(cWidth && cHeight){ - uint8_t * cRender; /* Convert to Bottom-up */ - uint8_t * OriginalRender = FontFace->glyph->bitmap.buffer; - if(FontFace->glyph->bitmap.pitch > 0){ - cRender = (uint8_t *) malloc(cWidth * cHeight); - for(int i=0; iglyph->bitmap_left; - stringy += FontFace->glyph->bitmap_top-cHeight; - for(int i=0; iData + 4*((stringy+i)*StringWidth + (stringx+j)); - ptr[3] = cRender[i*cWidth + j]; - } - } - stringx -= FontFace->glyph->bitmap_left; - stringy -= FontFace->glyph->bitmap_top-cHeight; - - if(FontFace->glyph->bitmap.pitch > 0) free(cRender); - } - stringx += FontFace->glyph->advance.x >> 6; - stringy += FontFace->glyph->advance.y >> 6; - } - - Image->Width = StringWidth; - Image->Height = StringHeight; - Image->Format = FIMG_BGRA32; - return Image; -} - -} \ No newline at end of file diff --git a/Client/Graphics/Graphics.hpp b/Client/Graphics/Graphics.hpp deleted file mode 100644 index f9e5a85..0000000 --- a/Client/Graphics/Graphics.hpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Graphics/Graphics.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include - -//Graphics/Startup.cpp -namespace Graphics { - int Initialize(); - void Shutdown(); - extern HDC hDC; - extern HGLRC hRC; - - int InitGL(); - void ResizeViewport(unsigned width, unsigned height); - - enum TextAlignment { - ALIGN_LEFT_TOP, - ALIGN_LEFT_CENTER, - ALIGN_CENTER_TOP, - ALIGN_CENTER_CENTER, - ALIGN_RIGHT_TOP, - ALIGN_RIGHT_CENTER - }; - - //Font.cpp - extern FT_Library FreeTypeLibrary; - extern FT_Face FontFace; - void DrawText(Image_t * Image, const wchar_t * String, int x, int y, unsigned width, unsigned height, - TextAlignment Alignment, int font, COLORREF Color); - Image_t * StringImage(const wchar_t * String, int font, COLORREF Color); -} \ No newline at end of file diff --git a/Client/Graphics/Startup.cpp b/Client/Graphics/Startup.cpp deleted file mode 100644 index 35f44ae..0000000 --- a/Client/Graphics/Startup.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Graphics/Startup.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -namespace Graphics { - -HDC hDC; -HGLRC hRC; - -int Initialize(){ - hDC = GetDC(Window::hWnd); - if(hDC == NULL){ - MessageBox(Window::hWnd, "Failed to obtain the device context.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_GRAPHICS_OBTAIN_DC; - } - - const PIXELFORMATDESCRIPTOR pfd = { - sizeof(PIXELFORMATDESCRIPTOR), 1, //Size and version - PFD_DRAW_TO_WINDOW | //dwFlags - PFD_SUPPORT_OPENGL | - PFD_DOUBLEBUFFER, - PFD_TYPE_RGBA, //iPixelType - 24, //cColorBits - 0, 0, 0, 0, 0, 0, 0, 0, //R,G,B,A bits - 0, 0, 0, 0, 0, //Accumulation buffer bits - 16, //cDepthBits - 0, //cStencilBits - 0, //cAuxBuffers - PFD_MAIN_PLANE, //iLayerType - 0, //Reserved - 0, 0, 0 //Masks - }; - - unsigned PixelFormat = ChoosePixelFormat(hDC, &pfd); - if(!PixelFormat){ - MessageBox(Window::hWnd, "Failed to find a suitable pixel format for the device context.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_GRAPHICS_FIND_PIXELFORMAT; - } - - if(!SetPixelFormat(hDC, PixelFormat, &pfd)){ - MessageBox(Window::hWnd, "Failed to set the pixel format for the device context.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_GRAPHICS_SET_PIXELFORMAT; - } - - hRC = wglCreateContext(hDC); - if(!hRC){ - MessageBox(Window::hWnd, "Failed to create an OpenGL rendering context.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_GRAPHICS_CREATE_GLRC; - } - - if(!wglMakeCurrent(hDC, hRC)){ - MessageBox(Window::hWnd, "Failed to activate the OpenGL device context.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_GRAPHICS_ACTIVATE_GLRC; - } - - BOOL (WINAPI *wglSwapIntervalEXT)(int) = (BOOL (WINAPI *)(int)) wglGetProcAddress("wglSwapIntervalEXT"); - if(wglSwapIntervalEXT) wglSwapIntervalEXT(1); - int (WINAPI *wglGetSwapIntervalEXT)(void) = (int (WINAPI *)(void)) wglGetProcAddress("wglGetSwapIntervalEXT"); - if(wglGetSwapIntervalEXT) wglGetSwapIntervalEXT(); //Seems necessary on some cards - - int result = InitGL(); - if(result != 0){ - Shutdown(); - return ERROR_GRAPHICS_INIT_GLSCENE | result; - } - - ResizeViewport(Window::Width, Window::Height); - return 0; -} - -int InitGL(){ - glShadeModel(GL_SMOOTH); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - glClearDepth(1.0f); - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); - glEnable(GL_RESCALE_NORMAL); - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - return 0; -} - -void Shutdown(){ - if(Graphics::hRC){ - wglMakeCurrent(NULL, NULL); - wglDeleteContext(Graphics::hRC); - Graphics::hRC = NULL; - } - if(Graphics::hDC){ - ReleaseDC(Window::hWnd, Graphics::hDC); - Graphics::hDC = NULL; - } -} - -} \ No newline at end of file diff --git a/Client/Graphics/Viewport.cpp b/Client/Graphics/Viewport.cpp deleted file mode 100644 index c39c9b0..0000000 --- a/Client/Graphics/Viewport.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Graphics/Viewport.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -void Graphics::ResizeViewport(unsigned width, unsigned height){ - if(width == 0) width++; - if(height == 0) height++; - - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - glOrtho(0, width, 0, height, 0.0, 1.0); -} \ No newline at end of file diff --git a/Client/README b/Client/README deleted file mode 100644 index e69de29..0000000 diff --git a/Client/Resources/Resource.h b/Client/Resources/Resource.h deleted file mode 100644 index 04d4a13..0000000 --- a/Client/Resources/Resource.h +++ /dev/null @@ -1,2 +0,0 @@ -#define ID_VERSIONINFO 1 -#define IDI_TSO 2 diff --git a/Client/Resources/Resource.rc b/Client/Resources/Resource.rc deleted file mode 100644 index 574970b..0000000 --- a/Client/Resources/Resource.rc +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include "../version.h" -#include "Resource.h" - -IDI_TSO ICON "TSO.ico" - -ID_VERSIONINFO VERSIONINFO -FILEVERSION VERSION_A,VERSION_B,VERSION_C,VERSION_D -PRODUCTVERSION VERSION_A,VERSION_B,VERSION_C,VERSION_D -FILEOS 0x00040000L //Windows 32-bit+ -FILETYPE 1 //1 is exe, 2 is dll, and so on. - //The list can be found at -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904B0" - BEGIN - VALUE "CompanyName", "Maxis™" - VALUE "FileDescription", "The Sims Online" - VALUE "FileVersion", VERSIONSTR - VALUE "InternalName", "TSO_NIOTSO" - VALUE "LegalCopyright", "Copyright © 2002-2005 Maxis™" - VALUE "OriginalFilename", "TSO.exe" - VALUE "ProductName", "The Sims Online" - VALUE "ProductVersion", VERSIONSTR - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x0409, 0x04B0 - END -END diff --git a/Client/Resources/TSO.ico b/Client/Resources/TSO.ico deleted file mode 100644 index ee94659..0000000 Binary files a/Client/Resources/TSO.ico and /dev/null differ diff --git a/Client/Scene/LoginScreen/LoginScreen.cpp b/Client/Scene/LoginScreen/LoginScreen.cpp deleted file mode 100644 index 7e7c9bc..0000000 --- a/Client/Scene/LoginScreen/LoginScreen.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Scene/LoginScreen/LoginScreen.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../../EngineInterface.hpp" - -static const wchar_t * const StatusStrings[] = { - L"Extruding Terrain Web", - L"Adjusting Emotional Weights", - L"Calibrating Personality Matrix", - - L"Calculating Domestic Coefficients", - L"Readjusting Career Ladder", - L"Accessing Money Supply", - L"Hacking the Social Network", - L"Tweaking Chaos Control", - L"Downloading Reticulated Splines" -}; -static const char * const images[] = {"eagames.bmp", "maxis.png", "setup.bmp"}; - -static const char * const sounds[] = {"loadloop.wav"}; - -LoginScreen::LoginScreen() : Scene(0){ - Screen = Screen_EAGames; - Time = 0; - ScrollPos = -1; - memset(image, 0, IMG_COUNT * sizeof(Image_t *)); - memset(texture, 0, TEX_COUNT * sizeof(GLuint)); - memset(sound, 0, SND_COUNT * sizeof(PlayableSound_t *)); - - glMatrixMode(GL_TEXTURE); - glGenTextures(TEX_COUNT, texture); - - FT_Set_Char_Size(Graphics::FontFace, 0, 22*64, 0, 0); - - for(int i=TEX_EAGAMES; i<=TEX_SETUP; i++){ - Image_t * Image = File::ReadImageFile(images[i]); - if(!Image){ - const char * Message; - switch(File::Error){ - case FERR_NOT_FOUND: - Message = "%s does not exist."; - break; - case FERR_OPEN: - Message = "%s could not be opened for reading."; - break; - case FERR_BLANK: - case FERR_UNRECOGNIZED: - case FERR_INVALIDDATA: - Message = "%s is corrupt or invalid."; - break; - case FERR_MEMORY: - Message = "Memory for %s could not be allocated."; - break; - default: - Message = "%s could not be read."; - } - - char Buffer[1024]; - sprintf(Buffer, Message, images[i]); - MessageBox(Window::hWnd, Buffer, NULL, MB_OK | MB_ICONERROR); - EXIT_SCENE(); - } - - if(i == TEX_MAXIS){ - Graphics::DrawText(Image, L"Maxis\x2122 is an Electronic Arts\x2122 brand.", 0, 600-146, 800, 146, - Graphics::ALIGN_CENTER_CENTER, 0, RGB(0xef, 0xe3, 0x8c)); - } - - glBindTexture(GL_TEXTURE_2D, texture[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, Image->Width, Image->Height, 0, GL_BGR, GL_UNSIGNED_BYTE, Image->Data); - free(Image->Data); - free(Image); - } - - image[IMG_COPYRIGHT] = Graphics::StringImage(L"(c) 2002, 2003 Electronic Arts Inc. All rights reserved.", - 0, RGB(0xef, 0xe3, 0x8c)); - if(image[IMG_COPYRIGHT] == NULL){ - EXIT_SCENE(); - } - glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_COPYRIGHT]->Width, image[IMG_COPYRIGHT]->Height, 0, GL_BGRA, - GL_UNSIGNED_BYTE, image[IMG_COPYRIGHT]->Data); - free(image[IMG_COPYRIGHT]->Data); - - for(int i=0; i<9; i++){ - image[IMG_STATUS+i] = Graphics::StringImage(StatusStrings[i], 0, RGB(0xef, 0xe3, 0x8c)); - if(image[IMG_STATUS+i] == NULL){ - EXIT_SCENE(); - } - glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image[IMG_STATUS+i]->Width, image[IMG_STATUS+i]->Height, 0, GL_BGRA, - GL_UNSIGNED_BYTE, image[IMG_STATUS+i]->Data); - free(image[IMG_STATUS+i]->Data); - } - - for(int i=0; iData); - free(sound[i]); - } - } -} - -int LoginScreen::Run(float TimeDelta){ - Time += TimeDelta; - if(ScrollPos != 8){ - ScrollPos += TimeDelta*0.75; - if(ScrollPos > 8) ScrollPos = 8; - } - - if(Screen != Screen_Setup && Time >= 4.0){ - Screen = (Screen==Screen_EAGames) ? Screen_Maxis : Screen_Setup; - Time = 0; - } - - if(System::UserInput.CloseWindow){ - return SCENE_EXIT; - } - return SCENE_NEED_REDRAW; -} - -void LoginScreen::Render(){ - glMatrixMode(GL_TEXTURE); - - //Background - glBindTexture(GL_TEXTURE_2D, texture[Screen]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i(0,0); - glTexCoord2i(1,0); glVertex2i(800,0); - glTexCoord2i(1,1); glVertex2i(800,600); - glTexCoord2i(0,1); glVertex2i(0,600); - glEnd(); - - if(Screen != Screen_Setup) return; - - glBindTexture(GL_TEXTURE_2D, texture[TEX_COPYRIGHT]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,58); - glTexCoord2i(1,0); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,58); - glTexCoord2i(1,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2 + image[IMG_COPYRIGHT]->Width,image[IMG_COPYRIGHT]->Height + 58); - glTexCoord2i(0,1); glVertex2i((800-image[IMG_COPYRIGHT]->Width)/2,image[IMG_COPYRIGHT]->Height + 58); - glEnd(); - - for(int i=0; i<9; i++){ - glBindTexture(GL_TEXTURE_2D, texture[TEX_STATUS+i]); - glBegin(GL_QUADS); - glTexCoord2i(0,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,20); - glTexCoord2i(1,0); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,20); - glTexCoord2i(1,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2 + image[IMG_STATUS+i]->Width,image[IMG_STATUS+i]->Height + 20); - glTexCoord2i(0,1); glVertex2i(((float)i - ScrollPos)*800 + (800-image[IMG_STATUS+i]->Width)/2,image[IMG_STATUS+i]->Height + 20); - glEnd(); - } -} \ No newline at end of file diff --git a/Client/Scene/LoginScreen/LoginScreen.hpp b/Client/Scene/LoginScreen/LoginScreen.hpp deleted file mode 100644 index a3d30a0..0000000 --- a/Client/Scene/LoginScreen/LoginScreen.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Scene/LoginScreen/LoginScreen.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -class LoginScreen : public Scene { - enum { - IMG_COPYRIGHT, - IMG_STATUS, //value = 1..9 - IMG_COUNT = 10 - }; - - enum { - TEX_EAGAMES, - TEX_MAXIS, - TEX_SETUP, - TEX_COPYRIGHT, - TEX_STATUS, //value = 4..12 - TEX_COUNT = 13 - }; - - enum { - SND_LOADLOOP, - SND_COUNT - }; - - enum { Screen_EAGames, Screen_Maxis, Screen_Setup } Screen; - float Time; - float ScrollPos; - Image_t * image[IMG_COUNT]; - GLuint texture[TEX_COUNT]; - PlayableSound_t * sound[SND_COUNT]; - - public: - LoginScreen(); - ~LoginScreen(); - void Render(); - - private: - int Run(float TimeDelta); -}; \ No newline at end of file diff --git a/Client/Scene/Scene.hpp b/Client/Scene/Scene.hpp deleted file mode 100644 index 97133b5..0000000 --- a/Client/Scene/Scene.hpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Scene/Scene.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#define EXIT_SCENE() do { System::SceneFailed = true; delete this; return; } while(0) -#define SCENE_EXIT 0 -#define SCENE_NEED_REDRAW 1 -#define SCENE_NO_REDRAW -1 - -class Scene { - const float TickPeriod; - float RealTimeDelta; - virtual int Run(float TimeDelta) = 0; - - protected: - float TimeDelta; - Scene(float c) : TickPeriod(c), RealTimeDelta(0) {} - - public: - int RunFor(float TimeDelta) { - if(TickPeriod == 0){ - return Run(TimeDelta); - } - - bool Redraw = false; - RealTimeDelta += TimeDelta; - while(RealTimeDelta >= 0){ - int result = Run(TickPeriod); - if(result == System::SHUTDOWN) - return System::SHUTDOWN; - if(result > 0) Redraw = true; - RealTimeDelta -= TickPeriod; - } - return (Redraw) ? 1 : -1; - } - - virtual void Render() = 0; - virtual ~Scene() {}; -}; - -/**** -** Scenes -*/ - -#include "LoginScreen/LoginScreen.hpp" \ No newline at end of file diff --git a/Client/System/System.cpp b/Client/System/System.cpp deleted file mode 100644 index 1ebf8c3..0000000 --- a/Client/System/System.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - System/System.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -namespace System { - -HINSTANCE hInst = NULL; -LARGE_INTEGER ClockFreq; -volatile float FramePeriod; -UserInput_t UserInput = UserInput_t(); -volatile UserInput_t UserInput_v; -bool SceneFailed = false; - -int Initialize(){ - QueryPerformanceFrequency(&ClockFreq); - - DEVMODE dm; - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); - System::FramePeriod = 1.0f/dm.dmDisplayFrequency; - - if(FT_Init_FreeType(&Graphics::FreeTypeLibrary)){ - MessageBox(Window::hWnd, "Failed to initialize FreeType.", NULL, MB_OK | MB_ICONERROR); - Graphics::FreeTypeLibrary = NULL; - Shutdown(); - return ERROR_SYSTEM_INIT_FREETYPE; - }; - if(FT_New_Face(Graphics::FreeTypeLibrary, "simdialogue-uni-game.ttf", 0, &Graphics::FontFace)){ - MessageBox(Window::hWnd, "simdialogue-uni-game.ttf does not exist or is corrupt or invalid.", - NULL, MB_OK | MB_ICONERROR); - Graphics::FontFace = NULL; - Shutdown(); - return ERROR_SYSTEM_MISSING_FONT; - } - - return 0; -} - -void Shutdown(){ - if(Graphics::FontFace){ - FT_Done_Face(Graphics::FontFace); - Graphics::FontFace = NULL; - } - if(Graphics::FreeTypeLibrary){ - FT_Done_FreeType(Graphics::FreeTypeLibrary); - Graphics::FreeTypeLibrary = NULL; - } -} - -} \ No newline at end of file diff --git a/Client/System/System.hpp b/Client/System/System.hpp deleted file mode 100644 index 9306529..0000000 --- a/Client/System/System.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - System/System.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -namespace System { - int Initialize(); - void Shutdown(); - - extern HINSTANCE hInst; - extern LARGE_INTEGER ClockFreq; - extern volatile float FramePeriod; - - struct UserInput_t { - bool Keys[256]; - bool MouseDown; - bool CloseWindow; - }; - extern UserInput_t UserInput; - extern volatile UserInput_t UserInput_v; - - extern bool SceneFailed; - - //Constants - enum { - SHUTDOWN = 0 - }; -} - -/**** -** Program exit codes -** (Return 0 for success) -*/ - -#define ERROR_INIT 0x1000 -#define ERROR_INIT_ANOTHERINSTRUNNING 0x1001 - -//Engine errors -//Use: return ERROR_INIT | result; -#define ERROR_INIT_WINDOW 0x0100 - enum { - ERROR_WINDOW_SYNCOBJECT = 1, - ERROR_WINDOW_CREATE_THREAD, - ERROR_WINDOW_SYNCHRONIZE, - ERROR_WINDOW_REGISTER_CLASS, - ERROR_WINDOW_CREATE, - ERROR_WINDOW_HANDLE - }; -#define ERROR_INIT_SYSTEM 0x0200 - enum { - ERROR_SYSTEM_INIT_FREETYPE = 1, - ERROR_SYSTEM_MISSING_FONT - }; -#define ERROR_INIT_GRAPHICS 0x0300 - enum { - ERROR_GRAPHICS_OBTAIN_DC = 1, - ERROR_GRAPHICS_FIND_PIXELFORMAT, - ERROR_GRAPHICS_SET_PIXELFORMAT, - ERROR_GRAPHICS_CREATE_GLRC, - ERROR_GRAPHICS_ACTIVATE_GLRC, - ERROR_GRAPHICS_INIT_GLSCENE - }; -#define ERROR_INIT_AUDIO 0x0400 - enum { - ERROR_AUDIO_INIT_COM = 1, - ERROR_AUDIO_INIT_XAUDIO2, - ERROR_AUDIO_CREATE_VOICE - }; -#define ERROR_INIT_LOGIC 0x0500 - enum { - ERROR_LOGIC_CREATE_SCENE = 1 - }; \ No newline at end of file diff --git a/Client/TODO b/Client/TODO deleted file mode 100644 index 8f37171..0000000 --- a/Client/TODO +++ /dev/null @@ -1,21 +0,0 @@ -Because there are too many long-term things to list that we still have "to do" to reach the next development phase (e.g. -alpha to beta), this file contains only the things that are worked on currently or that will be in the very near future. - -While anybody is free to work on _anything_ at any point during Niotso's time, this list shall ONLY contain those relevant -to complete the criteria for the next development phase, which can be found here: - - -//----------// - -Development Phase: Planning - -Technical Preview 1 -Schedule: (Not very subject to change) - 1. Implement cst, uis, ini, and xml parsers with support for UTF-8 [20%] - 2. Replicate functionality up until the login dialog [90%] - 3. Implement the audio engine - 4. Implement the OpenGL-based windowing system - 5. Replicate character selection and creation features and the city selection dialog - 6. Implement debug logging and support for configuration files - 7. Implement the code needed to allow the game to read all necessary files from the TSOClient folder - 8. Port the client to Linux \ No newline at end of file diff --git a/Client/Window/SetCursor.cpp b/Client/Window/SetCursor.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Client/Window/Window.cpp b/Client/Window/Window.cpp deleted file mode 100644 index e7add39..0000000 --- a/Client/Window/Window.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Window/Window.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "../EngineInterface.hpp" - -namespace Window { - -unsigned Width, Height; -bool Fullscreen; -HWND hWnd; - -static HANDLE Response = NULL; -static HANDLE Thread = NULL; -static DWORD ThreadID = NULL; -static volatile int Result = NULL; - -static DWORD WINAPI Procedure(LPVOID); -static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); -static int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen); - -int Initialize(){ - Response = CreateEvent(NULL, FALSE, FALSE, NULL); - if(Response == NULL){ - MessageBox(NULL, "Failed to create the message loop synchronization object.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_WINDOW_SYNCOBJECT; - } - - Thread = CreateThread(NULL, 1024 /* very tiny stack size is needed */, Window::Procedure, NULL, 0, &ThreadID); - if(Thread == NULL){ - MessageBox(NULL, "Failed to create the message loop thread.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_WINDOW_CREATE_THREAD; - } - - if(WaitForSingleObject(Window::Response, INFINITE) != WAIT_OBJECT_0){ - MessageBox(NULL, "Failed to synchronize with the message loop thread.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_WINDOW_SYNCHRONIZE; - } - - if(Result != 0){ - Shutdown(); - return Result; - } - - hWnd = FindWindow("TSO_NIOTSO", "The Sims Online"); - if(hWnd == NULL){ - MessageBox(NULL, "Failed to obtain a handle for the window.", NULL, MB_OK | MB_ICONERROR); - Shutdown(); - return ERROR_WINDOW_HANDLE; - } - - return 0; -} - -void Shutdown(){ - if(hWnd){ - DestroyWindow(hWnd); - hWnd = NULL; - } - if(Thread){ - DWORD value; - while(GetExitCodeThread(Thread, &value) && value){ - PostThreadMessage(ThreadID, WM_QUIT, 0, 0); - Sleep(1); - } - Thread = NULL; - } - if(Response){ - CloseHandle(Response); - Response = NULL; - } - - UnregisterClass("TSO_NIOTSO", System::hInst); -} - -static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){ - switch(uMsg){ - - case WM_SETCURSOR: - SetCursor(NULL); - break; - - case WM_KEYDOWN: - case WM_KEYUP: - System::UserInput_v.Keys[wParam] = (uMsg == WM_KEYDOWN); - return 0; - - case WM_CLOSE: - System::UserInput_v.CloseWindow = true; - return 0; - - case WM_DEVMODECHANGE: { - DEVMODE dm; - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm); - System::FramePeriod = 1.0f/dm.dmDisplayFrequency; - } return 0; - - } - return DefWindowProc(hWnd, uMsg, wParam, lParam); -} - -static DWORD WINAPI Procedure(LPVOID){ - int result = CreateWindowInvisible(System::hInst, Window::Width, Window::Height, Window::Fullscreen); - if(result != 0){ - Window::Result = result; - SetEvent(Window::Response); - return 0; - } - SetEvent(Window::Response); - - MSG msg; - while(GetMessage(&msg, NULL, 0, 0)){ - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - return 0; -} - -static int CreateWindowInvisible(HINSTANCE hInst, unsigned Width, unsigned Height, bool Fullscreen) -{ - const WNDCLASS wc = { - CS_OWNDC, //style - WndProc, //lpfnWndProc - 0, //cbClsExtra - 0, //cbWndExtra - hInst, //hInstance - (HICON) LoadImage(hInst, MAKEINTRESOURCE(IDI_TSO), //hIcon - IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE), - NULL, //hCursor - NULL, //hbrBackground - NULL, //lpszMenuName - "TSO_NIOTSO" //lpszClassName - }; - - if(!RegisterClass(&wc)){ - MessageBox(NULL, "Failed to register the window class.", NULL, MB_OK | MB_ICONERROR); - return ERROR_WINDOW_REGISTER_CLASS; - } - SetCursor(NULL); - - HWND hWnd = NULL; - if(Fullscreen){ - DEVMODE dmScreenSettings; - dmScreenSettings.dmSize = sizeof(dmScreenSettings); - dmScreenSettings.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL; - dmScreenSettings.dmPelsWidth = Width; - dmScreenSettings.dmPelsHeight = Height; - dmScreenSettings.dmBitsPerPel = 32; - - if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL){ - MessageBox(NULL, "Fullscreen mode is not supported by your setup. It has been turned off.", NULL, - MB_OK | MB_ICONERROR); - Fullscreen = 0; - }else{ - hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online", WS_POPUP, - 0, 0, Width, Height, 0, 0, hInst, NULL); - } - } - if(hWnd == NULL){ - Fullscreen = false; - RECT WindowRect = {0, 0, Width, Height}; - - //Use a style of WS_OVERLAPPEDWINDOW to allow resizing - AdjustWindowRectEx(&WindowRect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE, - WS_EX_APPWINDOW); //This finds the dimensions of a window with a client area of our specified dimensions - - //Note: Windows can be positioned anywhere, even outside the visible workspace, - //but their sizes are limited to the size of the workspace on the primary display. - unsigned WindowWidth = WindowRect.right-WindowRect.left, WindowHeight = WindowRect.bottom-WindowRect.top; - RECT WorkspaceRect; - SystemParametersInfo(SPI_GETWORKAREA, 0, &WorkspaceRect, 0); - - hWnd = CreateWindowEx(WS_EX_APPWINDOW, "TSO_NIOTSO", "The Sims Online", - WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, - ((WorkspaceRect.right-WorkspaceRect.left - WindowWidth)>>1) + WorkspaceRect.left, - ((WorkspaceRect.bottom-WorkspaceRect.top - WindowHeight)>>1) + WorkspaceRect.top, - WindowWidth, WindowHeight, 0, 0, hInst, NULL); - } - - if(hWnd == NULL){ - MessageBox(NULL, "Failed to create the window.", NULL, MB_OK | MB_ICONERROR); - return ERROR_WINDOW_CREATE; - } - - return 0; -} - -} \ No newline at end of file diff --git a/Client/Window/Window.hpp b/Client/Window/Window.hpp deleted file mode 100644 index 08fd040..0000000 --- a/Client/Window/Window.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - Niotso - The New Implementation of The Sims Online - Window/Window.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -namespace Window { - int Initialize(); - void Shutdown(); - - extern unsigned Width, Height; - extern bool Fullscreen; - extern HWND hWnd; -} \ No newline at end of file diff --git a/Client/version.h b/Client/version.h deleted file mode 100644 index 27ce87a..0000000 --- a/Client/version.h +++ /dev/null @@ -1,10 +0,0 @@ -#define VERSION_A 0 -#define VERSION_B 0 -#define VERSION_C 0 -#define VERSION_D 0 - -//You don't have to touch the following -#define xstr(x) str(x) -#define str(x) #x //Yes, double levels is required. See -#define VERSIONSTR "" \ - xstr(VERSION_A) "." xstr(VERSION_B) "." xstr(VERSION_C) "." xstr(VERSION_D) diff --git a/Server/AUTHORS b/Server/AUTHORS deleted file mode 100644 index 256626b..0000000 --- a/Server/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Fatbag \ No newline at end of file diff --git a/Server/CHANGES b/Server/CHANGES deleted file mode 100644 index aacc0cb..0000000 --- a/Server/CHANGES +++ /dev/null @@ -1,2 +0,0 @@ -Technical Preview 1 - * Initial release \ No newline at end of file diff --git a/Server/CMakeLists.txt b/Server/CMakeLists.txt deleted file mode 100644 index 46c3647..0000000 --- a/Server/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -project(NiotsoServer) - -if(WIN32) -else() - set(NIOTSOSERVER_SOURCES - Server.cpp - ) - add_executable(niotsod-vanilla ${NIOTSOSERVER_SOURCES}) - target_link_libraries(niotsod-vanilla) -endif() diff --git a/Server/COPYING b/Server/COPYING deleted file mode 100644 index acdc1dc..0000000 --- a/Server/COPYING +++ /dev/null @@ -1,642 +0,0 @@ -IMPORTANT: -Niotso is distributed under the terms of the GNU GPLv3. - -While this license does permit others to compile, distribute, change, -and distribute changes to Niotso, in reality, many of these freedoms -cannot legally be enacted by anybody. - -Specifically, if you make changes to Niotso such that it significantly -changes the "game experience as presented to the player", it cannot -be distributed to others. You also may not distribute a version of -Niotso that has stripped the EA or Maxis trademarked names or logos -anywhere from the game. Personal use of these modifications is okay. - -These restrictions are not enforced by us, but may potentially be used -by EA in attempt to take down your game. - -If you have any questions, you may visit - - ---- - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS \ No newline at end of file diff --git a/Server/README b/Server/README deleted file mode 100644 index e69de29..0000000 diff --git a/Server/Server.cpp b/Server/Server.cpp deleted file mode 100644 index 82b38be..0000000 --- a/Server/Server.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - Niotso Server - Niotso daemon based on PostgreSQL - Server.cpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Server.hpp" - -#define SHUTDOWN(X) do { syslog(LOG_INFO, " Could not recover from errors. Shutting down."); \ - exitval = EXIT_FAILURE; goto X; } while(0) -#define SHUTDOWN_M(X, Y) do { syslog(LOG_ERR, " %s (%s)", X, strerror(errno)); \ - SHUTDOWN(Y); } while(0) - -//IPV6_V6ONLY - -static void term(int) -{ -} - -int main(int, char **) -{ - const pid_t pid = fork(); - if(pid < 0){ - const char *msg1 = " Failed to create child process (%s).", *msg2 = strerror(errno); - openlog(SERVER_NAME, 0, LOG_DAEMON); - syslog(LOG_ERR, msg1, msg2); - closelog(); - fprintf(stderr, msg1, msg2); - fprintf(stderr, "\n"); - return EXIT_FAILURE; - }else if(pid > 0) - return EXIT_SUCCESS; - - int exitval = EXIT_SUCCESS, sockfd, epollfd; - { //New scope required for error handling - int ret; - FILE * fd; - - umask(0); - - openlog(SERVER_NAME, LOG_PID, LOG_DAEMON); - - if(setsid() < 0) - SHUTDOWN_M("Failed to create session", close_msg); - - if(chdir(CONFIG_DIR) < 0) - SHUTDOWN_M("Failed to change into \""CONFIG_DIR"\"", close_msg); - - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - struct sigaction sigact; - sigact.sa_handler = term; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGINT, &sigact, NULL); - - syslog(LOG_INFO, " "SERVER_NAME" (version "VERSIONSTR") is starting..."); - - fd = fopen("network.conf", "r"); - if(!fd) - SHUTDOWN_M("Failed to open \""CONFIG_DIR"/network.conf\"", close_msg); - unsigned int port = 0; - ret = fscanf(fd, "%u", &port); - fclose(fd); - if(ret < 0) - SHUTDOWN_M("Failed to read \""CONFIG_DIR"/network.conf\"", close_msg); - if(port > 65535){ - syslog(LOG_ERR, " Invalid port '%u' specified in \""CONFIG_DIR"/network.conf\".", port); - SHUTDOWN(close_msg); - } - - sockfd = socket(AF_INET6, SOCK_DGRAM, 0); - if(sockfd < 0) - SHUTDOWN_M("Failed to open socket", close_msg); - - int flags = fcntl(sockfd, F_GETFL, 0); - if(flags < 0) - SHUTDOWN_M("Failed to read socket flags", close_socket); - if(fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) < 0) - SHUTDOWN_M("Failed to set socket flags", close_socket); - - sockaddr_in6 server_addr, client_addr; - memset(&server_addr, 0, sizeof(sockaddr_in6)); - memset(&client_addr, 0, sizeof(sockaddr_in6)); - server_addr.sin6_family = AF_INET6; - server_addr.sin6_port = htons((uint16_t) port); - server_addr.sin6_addr = in6addr_any; - client_addr.sin6_family = AF_INET6; - client_addr.sin6_addr = in6addr_any; - - if(bind(sockfd, (const sockaddr*) &server_addr, sizeof(sockaddr_in6)) < 0) - SHUTDOWN_M("Failed to bind to socket", close_socket); - - epollfd = epoll_create(1); - if(epollfd < 0) - SHUTDOWN_M("Failed to create an epoll handle", close_socket); - - epoll_event epev[1]; - epev[0].events = EPOLLIN | EPOLLPRI; - epev[0].data.fd = sockfd; - if(epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, epev) < 0) - SHUTDOWN_M("Failed to register the socket to the epoll handle", close_epoll); - - //Now that we're running, stop being terminate-on-failure-happy - syslog(LOG_INFO, " Running."); - - /**** - ** Listen loop - */ - - int eventcount; - while((eventcount = epoll_wait(epollfd, epev, 1, -1)) >= 0){ - if(eventcount == 0) - continue; - else if(epev[0].events & EPOLLERR) - SHUTDOWN_M("Socket closed unexpectedly with EPOLLERR", close_epoll); - else if(epev[0].events & EPOLLHUP) - SHUTDOWN_M("Socket closed unexpectedly with EPOLLHUP", close_epoll); - else if(!(epev[0].events & EPOLLIN) && !(epev[0].events & EPOLLPRI)) - continue; - - uint8_t packetdata[1500]; - socklen_t addrlen = sizeof(sockaddr_in6); - ssize_t packetsize = recvfrom(epev[0].data.fd, packetdata, 1500, 0, (sockaddr*) &client_addr, &addrlen); - if(packetsize < 0){ - if(errno == EINTR || errno == ECONNRESET || errno == ENOTCONN || errno == ETIMEDOUT || - errno == EAGAIN || errno == EWOULDBLOCK) - continue; - - SHUTDOWN_M("Socket closed unexpectedly on call to recvfrom", close_epoll); - } - - //Pass the packet down (even zero-length packets might be meaningful in the protocol) - //... - } - - /**** - ** Shutdown - */ - - } - close_epoll: close(epollfd); - close_socket: close(sockfd); - close_msg: syslog(LOG_INFO, " Shut down gracefully."); - closelog(); - - return exitval; -} diff --git a/Server/Server.hpp b/Server/Server.hpp deleted file mode 100644 index 77e83f9..0000000 --- a/Server/Server.hpp +++ /dev/null @@ -1,24 +0,0 @@ -/* - Niotso Server - Niotso daemon based on PostgreSQL - Server.hpp - Copyright (c) 2012 Niotso Project - Author(s): Fatbag - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#define SERVER_NAME "niotsod-vanilla" -#define CONFIG_DIR "/etc/"SERVER_NAME - -#define VERSIONSTR "0.0.0" diff --git a/Server/TODO b/Server/TODO deleted file mode 100644 index 7bb4f49..0000000 --- a/Server/TODO +++ /dev/null @@ -1,10 +0,0 @@ -Because there are too many long-term things to list that we still have "to do" to reach the next development phase (e.g. -alpha to beta), this file contains only the things that are worked on currently or that will be in the very near future. - -While anybody is free to work on _anything_ at any point during Niotso's time, this list shall ONLY contain those relevant -to complete the criteria for the next development phase, which can be found here: - - -//----------// - -Tasks will be added for the server when the development phase reaches Alpha. \ No newline at end of file diff --git a/code_of_conduct.md b/code_of_conduct.md new file mode 100644 index 0000000..cc9508f --- /dev/null +++ b/code_of_conduct.md @@ -0,0 +1,77 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at \[INSERT CONTACT METHOD\]. All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1\. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2\. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3\. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4\. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.0, available at . + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +For answers to common questions about this code of conduct, see the FAQ at . Translations are available at . \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Api.cs b/server/FSO.Server.Api.Core/Api.cs new file mode 100755 index 0000000..1da36e4 --- /dev/null +++ b/server/FSO.Server.Api.Core/Api.cs @@ -0,0 +1,281 @@ +using FSO.Server.Api.Core.Services; +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Common.Config; +using FSO.Server.Database.DA; +using FSO.Server.Domain; +using FSO.Server.Servers.Api.JsonWebToken; +using Microsoft.AspNetCore.Http; +using System; +using System.Collections.Specialized; +using System.Linq; +using System.Security; + +namespace FSO.Server.Api.Core +{ + public class Api : ApiAbstract + { + public static Api INSTANCE; + + public IDAFactory DAFactory; + public ApiConfig Config; + public JWTFactory JWT; + public Shards Shards; + public IGluonHostPool HostPool; + public IUpdateUploader UpdateUploader; + public IUpdateUploader UpdateUploaderClient; + public GithubConfig Github; + + public Api() + { + INSTANCE = this; + } + + public void Init(NameValueCollection appSettings) + { + Config = new ApiConfig(); + Config.Maintainance = bool.Parse(appSettings["maintainance"]); + Config.AuthTicketDuration = int.Parse(appSettings["authTicketDuration"]); + Config.Regkey = appSettings["regkey"]; + Config.Secret = appSettings["secret"]; + Config.UpdateUrl = appSettings["updateUrl"]; + Config.CDNUrl = appSettings["cdnUrl"]; + Config.NFSdir = appSettings["nfsdir"]; + Config.UseProxy = bool.Parse(appSettings["useProxy"]); + Config.UpdateID = (appSettings["updateID"] == "") ? (int?)null : int.Parse(appSettings["updateID"]); + Config.BranchName = appSettings["branchName"] ?? "beta"; + + // new smtp config vars + if (appSettings["smtpHost"]!=null&& + appSettings["smtpUser"]!=null&& + appSettings["smtpPassword"]!=null&& + appSettings["smtpPort"]!=null) + { + Config.SmtpEnabled = true; + Config.SmtpHost = appSettings["smtpHost"]; + Config.SmtpUser = appSettings["smtpUser"]; + Config.SmtpPassword = appSettings["smtpPassword"]; + Config.SmtpPort = int.Parse(appSettings["smtpPort"]); + } + + JWT = new JWTFactory(new JWTConfiguration() + { + Key = System.Text.UTF8Encoding.UTF8.GetBytes(Config.Secret) + }); + + DAFactory = new MySqlDAFactory(new Database.DatabaseConfiguration() + { + ConnectionString = appSettings["connectionString"] + }); + + Shards = new Shards(DAFactory); + Shards.AutoUpdate(); + } + + public JWTUser RequireAuthentication(HttpRequest request) + { + JWTUser result; + + if (!string.IsNullOrEmpty(request.Headers["Authorization"])) + { + result = JWT.DecodeToken(GetAuthParam(request.Headers["Authorization"])); + } + else + { + var cookies = request.Cookies; + if (cookies == null) + throw new SecurityException("Unable to find cookie"); + + + var cookie = cookies["fso"]; + if (string.IsNullOrEmpty(cookie)) + { + throw new SecurityException("Unable to find cookie"); + } + result = JWT.DecodeToken(cookie); + } + if (result == null) + { + throw new SecurityException("Invalid token"); + } + + return result; + } + + public string GetAuthParam(string auth) + { + var ind = auth.IndexOf(' '); + if (ind == -1) return auth; + return auth.Substring(ind + 1); + } + + /// + /// Sends an email to a user to tell them that they're banned. ;( + /// + /// + /// + /// + public void SendBanMail(string username, string email, uint end_date) + { + ApiMail banMail = new ApiMail("MailBan"); + + var date = end_date == 0 ? "Permanent ban" : Epoch.ToDate(end_date).ToString(); + + banMail.AddString("username", username); + banMail.AddString("end", date); + + banMail.Send(email, "Banned from ingame"); + } + + /// + /// Sends an email to a user saying that the registration went OK. + /// + /// + /// + public void SendEmailConfirmationOKMail(string username, string email) + { + ApiMail confirmOKMail = new ApiMail("MailRegistrationOK"); + + confirmOKMail.AddString("username", username); + + confirmOKMail.Send(email, "Welcome to FreeSO, " + username + "!"); + } + + /// + /// Sends an email to a a new user with a token to create their user. + /// + /// + /// + /// + /// + /// + public bool SendEmailConfirmationMail(string email, string token, string confirmation_url, uint expires) + { + ApiMail confirmMail = new ApiMail("MailRegistrationToken"); + + confirmation_url = confirmation_url.Replace("%token%", token); + confirmMail.AddString("token", token); + confirmMail.AddString("expires", Epoch.HMSRemaining(expires)); + confirmMail.AddString("confirmation_url", confirmation_url); + + return confirmMail.Send(email, "Verify your FreeSO account"); + } + + /// + /// Sends an email to a user with a token to reset their password. + /// + /// + /// + /// + /// + /// + /// + public bool SendPasswordResetMail(string email, string username, string token, string confirmation_url, uint expires) + { + ApiMail confirmMail = new ApiMail("MailPasswordReset"); + + confirmation_url = confirmation_url.Replace("%token%", token); + confirmMail.AddString("token", token); + confirmMail.AddString("expires", Epoch.HMSRemaining(expires)); + confirmMail.AddString("confirmation_url", confirmation_url); + + return confirmMail.Send(email, "Password Reset for " + username); + } + + /// + /// Sends a password change success email to a user. + /// + /// + /// + /// + public bool SendPasswordResetOKMail(string email, string username) + { + ApiMail confirmMail = new ApiMail("MailPasswordResetOK"); + + confirmMail.AddString("username", username); + + return confirmMail.Send(email, "Your account password was reset"); + } + + public void DemandModerator(JWTUser user) + { + if (!user.Claims.Contains("moderator")) throw new Exception("Requires Moderator level status"); + } + + public void DemandAdmin(JWTUser user) + { + if (!user.Claims.Contains("admin")) throw new Exception("Requires Admin level status"); + } + + public void DemandModerator(HttpRequest request) + { + DemandModerator(RequireAuthentication(request)); + } + + public void DemandAdmin(HttpRequest request) + { + DemandAdmin(RequireAuthentication(request)); + } + + /// + /// Changes a user's password. + /// + /// + /// + public void ChangePassword(uint user_id, string new_password) + { + using (var da = DAFactory.Get()) + { + var passhash = PasswordHasher.Hash(new_password); + var authSettings = new Database.DA.Users.UserAuthenticate(); + authSettings.scheme_class = passhash.scheme; + authSettings.data = passhash.data; + authSettings.user_id = user_id; + + da.Users.UpdateAuth(authSettings); + } + } + + /// + /// Inserts a brand new user in db. + /// + /// + /// + /// + /// + /// + public Database.DA.Users.User CreateUser(string username, string email, string password, string ip) + { + using (var da = DAFactory.Get()) + { + var userModel = new Database.DA.Users.User(); + userModel.username = username; + userModel.email = email; + userModel.is_admin = false; + userModel.is_moderator = false; + userModel.user_state = Database.DA.Users.UserState.valid; + userModel.register_date = Epoch.Now; + userModel.is_banned = false; + userModel.register_ip = ip; + userModel.last_ip = ip; + + var passhash = PasswordHasher.Hash(password); + var authSettings = new Database.DA.Users.UserAuthenticate(); + authSettings.scheme_class = passhash.scheme; + authSettings.data = passhash.data; + + try + { + var userId = da.Users.Create(userModel); + authSettings.user_id = userId; + da.Users.CreateAuth(authSettings); + return da.Users.GetById(userId); + } + catch (Exception) + { + return null; + } + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/ApiConfig.cs b/server/FSO.Server.Api.Core/ApiConfig.cs new file mode 100755 index 0000000..80dd4e5 --- /dev/null +++ b/server/FSO.Server.Api.Core/ApiConfig.cs @@ -0,0 +1,42 @@ +using FSO.Server.Api.Core.Services; + +namespace FSO.Server.Api.Core +{ + public class ApiConfig + { + /// + /// How long an auth ticket is valid for + /// + public int AuthTicketDuration = 300; + + /// + /// If non-null, the user must provide this key to register an account. + /// + public string Regkey { get; set; } + + /// + /// If true, only authentication from moderators and admins will be accepted + /// + public bool Maintainance { get; set; } + + public string Secret { get; set; } + + public string UpdateUrl { get; set; } + public string CDNUrl { get; set; } + + public string NFSdir { get; set; } + + public string SmtpHost { get; set; } + public int SmtpPort { get; set; } + public string SmtpPassword { get; set; } + public string SmtpUser { get; set; } + + public bool SmtpEnabled { get; set; } + public bool UseProxy { get; set; } + + public int? UpdateID { get; set; } + + public string BranchName { get; set; } = "dev"; + public IUpdateUploader UpdateUploader { get; set; } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminEventsController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminEventsController.cs new file mode 100755 index 0000000..45ca1bb --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminEventsController.cs @@ -0,0 +1,157 @@ +using System; +using System.Linq; +using System.Net; +using FSO.Server.Api.Core.Models; +using FSO.Server.Api.Core.Utils; +using FSO.Server.Database.DA.DbEvents; +using FSO.Server.Database.DA.Tuning; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling MVC for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/events")] + [ApiController] + public class AdminEventsController : ControllerBase + { + //List events + [HttpGet] + public IActionResult Get(int limit, int offset, string order) + { + if (limit == 0) limit = 20; + if (order == null) order = "start_day"; + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + + if (limit > 100) + { + limit = 100; + } + + var result = da.Events.All((int)offset, (int)limit, order); + return ApiResponse.PagedList(Request, HttpStatusCode.OK, result); + } + } + + [HttpGet("presets")] + public IActionResult GetPresets() + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + return new JsonResult(da.Tuning.GetAllPresets().ToList()); + } + } + + [HttpPost("presets")] + public IActionResult CreatePreset([FromBody]PresetCreateModel request) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + //make the preset first + var preset_id = da.Tuning.CreatePreset( + new DbTuningPreset() + { + name = request.name, + description = request.description, + flags = request.flags + }); + + foreach (var item in request.items) + { + da.Tuning.CreatePresetItem(new DbTuningPresetItem() + { + preset_id = preset_id, + tuning_type = item.tuning_type, + tuning_table = item.tuning_table, + tuning_index = item.tuning_index, + value = item.value + }); + } + return new JsonResult(da.Tuning.GetAllPresets().ToList()); + } + } + + [HttpGet("presets/{preset_id}")] + public IActionResult GetPresetEntries(int preset_id) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + return new JsonResult(da.Tuning.GetPresetItems(preset_id).ToList()); + } + } + + [HttpDelete("presets/{preset_id}")] + public IActionResult DeletePreset(int preset_id) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + return da.Tuning.DeletePreset(preset_id) ? (IActionResult)Ok() : NotFound(); + } + } + + // POST admin/updates (start update generation) + [HttpPost] + public IActionResult Post([FromBody]EventCreateModel request) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + DbEventType type; + try + { + type = Enum.Parse(request.type); + } + catch + { + return BadRequest("Event type must be one of:" + string.Join(", ", Enum.GetNames(typeof(DbEventType)))); + } + var model = new DbEvent() + { + title = request.title, + description = request.description, + start_day = request.start_day, + end_day = request.end_day, + type = type, + value = request.value, + value2 = request.value2, + mail_subject = request.mail_subject, + mail_message = request.mail_message, + mail_sender = request.mail_sender, + mail_sender_name = request.mail_sender_name + }; + return new JsonResult(new { id = da.Events.Add(model) }); + } + } + + [HttpDelete] + [Route("{id}")] + public IActionResult Delete(int id) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + if (!da.Events.Delete(id)) return NotFound(); + } + + return Ok(); + } + + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminHostsController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminHostsController.cs new file mode 100755 index 0000000..781c25d --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminHostsController.cs @@ -0,0 +1,30 @@ +using FSO.Server.Api.Core.Utils; +using System.Net; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Cors; + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/hosts")] + [ApiController] + public class AdminHostsController : ControllerBase + { + public IActionResult Get() + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + var hosts = api.HostPool.GetAll(); + + return ApiResponse.Json(HttpStatusCode.OK, hosts.Select(x => new { + role = x.Role, + call_sign = x.CallSign, + internal_host = x.InternalHost, + public_host = x.PublicHost, + connected = x.Connected, + time_boot = x.BootTime + })); + } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminOAuthController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminOAuthController.cs new file mode 100755 index 0000000..aa52623 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminOAuthController.cs @@ -0,0 +1,129 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Servers.Api.JsonWebToken; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/oauth/token")] + [ApiController] + public class AdminOAuthController : ControllerBase + { + [HttpPost] + public IActionResult Post([FromForm] AuthRequest auth) + { + if (auth == null) Ok(); + if (auth.grant_type == "password") + { + var api = Api.INSTANCE; + using (var da = api.DAFactory.Get()) + { + var user = da.Users.GetByUsername(auth.username); + if (user == null || user.is_banned || !(user.is_admin || user.is_moderator)) + { + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError + { + error = "unauthorized_client", + error_description = "user_credentials_invalid" + }); + } + + var ip = ApiUtils.GetIP(Request); + var accLock = da.Users.GetRemainingAuth(user.user_id, ip); + if (accLock != null && (accLock.active || accLock.count >= AuthLoginController.LockAttempts) && accLock.expire_time > Epoch.Now) + { + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError + { + error = "unauthorized_client", + error_description = "account_locked" + }); + } + + var authSettings = da.Users.GetAuthenticationSettings(user.user_id); + var isPasswordCorrect = PasswordHasher.Verify(auth.password, new PasswordHash + { + data = authSettings.data, + scheme = authSettings.scheme_class + }); + + if (!isPasswordCorrect) + { + var durations = AuthLoginController.LockDuration; + var failDelay = 60 * durations[Math.Min(durations.Length - 1, da.Users.FailedConsecutive(user.user_id, ip))]; + if (accLock == null) + { + da.Users.NewFailedAuth(user.user_id, ip, (uint)failDelay); + } + else + { + var remaining = da.Users.FailedAuth(accLock.attempt_id, (uint)failDelay, AuthLoginController.LockAttempts); + } + + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError + { + error = "unauthorized_client", + error_description = "user_credentials_invalid" + }); + } + + da.Users.SuccessfulAuth(user.user_id, ip); + + JWTUser identity = new JWTUser(); + identity.UserName = user.username; + var claims = new List(); + if (user.is_admin || user.is_moderator) + { + claims.Add("moderator"); + } + if (user.is_admin) + { + claims.Add("admin"); + } + + identity.Claims = claims; + identity.UserID = user.user_id; + + var token = api.JWT.CreateToken(identity); + + var response = ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthSuccess + { + access_token = token.Token, + expires_in = token.ExpiresIn + }); + + return response; + } + } + + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new OAuthError + { + error = "invalid_request", + error_description = "unknown grant_type" + }); + } + } + + + public class OAuthError + { + public string error_description { get; set; } + public string error { get; set; } + } + + public class OAuthSuccess + { + public string access_token { get; set; } + public int expires_in { get; set; } + } + + public class AuthRequest + { + public string grant_type { get; set; } + public string username { get; set; } + public string password { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminShardsController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminShardsController.cs new file mode 100755 index 0000000..5a277e8 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminShardsController.cs @@ -0,0 +1,69 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/shards")] + [ApiController] + public class AdminShardsController : ControllerBase + { + [HttpGet] + public IActionResult Get() + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + + using (var db = api.DAFactory.Get()) + { + var shards = db.Shards.All(); + return ApiResponse.Json(HttpStatusCode.OK, shards); + } + } + + [HttpPost("shutdown")] + public IActionResult shutdown(ShutdownModel sd) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + + ShutdownType type = ShutdownType.SHUTDOWN; + if (sd.update) type = ShutdownType.UPDATE; + else if (sd.restart) type = ShutdownType.RESTART; + + api.RequestShutdown((uint)sd.timeout, type); + + return ApiResponse.Json(HttpStatusCode.OK, true); + } + + [HttpPost("announce")] + public IActionResult announce(AnnouncementModel an) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + api.BroadcastMessage(an.sender, an.subject, an.message); + + return ApiResponse.Json(HttpStatusCode.OK, true); + } + } + + public class AnnouncementModel + { + public string sender; + public string subject; + public string message; + public int[] shard_ids; + } + + public class ShutdownModel + { + public int timeout; + public bool restart; + public bool update; + public int[] shard_ids; + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminTasksController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminTasksController.cs new file mode 100755 index 0000000..608cf59 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminTasksController.cs @@ -0,0 +1,73 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Database.DA.Tasks; +using FSO.Server.Protocol.Gluon.Packets; +using Newtonsoft.Json; +using System; +using System.Net; +using System.Linq; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Cors; + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/tasks")] + [ApiController] + public class AdminTasksController : ControllerBase + { + [HttpGet] + public IActionResult Get(int limit, int offset) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + + using (var da = api.DAFactory.Get()) + { + + if (limit > 100) + { + limit = 100; + } + + var result = da.Tasks.All((int)offset, (int)limit); + return ApiResponse.PagedList(Request, HttpStatusCode.OK, result); + } + } + + [HttpPost("request")] + public IActionResult request([FromBody] TaskRequest task) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + + var taskServer = api.HostPool.GetByRole(Database.DA.Hosts.DbHostRole.task).FirstOrDefault(); + if (taskServer == null) + { + return ApiResponse.Json(HttpStatusCode.OK, -1); + } + else + { + try + { + var id = taskServer.Call(new RequestTask() + { + TaskType = task.task_type.ToString(), + ParameterJson = JsonConvert.SerializeObject(task.parameter), + ShardId = (task.shard_id == null || !task.shard_id.HasValue) ? -1 : task.shard_id.Value + }).Result; + return ApiResponse.Json(HttpStatusCode.OK, id); + } + catch (Exception ex) + { + return ApiResponse.Json(HttpStatusCode.OK, -1); + } + } + } + } + public class TaskRequest + { + public DbTaskType task_type; + public int? shard_id; + public dynamic parameter; + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminUpdatesController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminUpdatesController.cs new file mode 100755 index 0000000..e9c31bb --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminUpdatesController.cs @@ -0,0 +1,172 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using FSO.Server.Api.Core.Models; +using FSO.Server.Api.Core.Services; +using FSO.Server.Api.Core.Utils; +using FSO.Server.Database.DA.Updates; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/updates")] + public class AdminUpdatesController : ControllerBase + { + //List updates + [HttpGet] + public IActionResult Get(int limit, int offset, string order) + { + if (limit == 0) limit = 20; + if (order == null) order = "date"; + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + + if (limit > 100) + { + limit = 100; + } + + var result = da.Updates.All((int)offset, (int)limit); + return ApiResponse.PagedList(Request, HttpStatusCode.OK, result); + } + } + + + // GET all branches + [HttpGet("branches")] + public IActionResult GetBranches() + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + using (var da = api.DAFactory.Get()) + { + return new JsonResult(da.Updates.GetBranches().ToList()); + } + } + + // GET all addons + [HttpGet("addons")] + public IActionResult GetAddons() + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + using (var da = api.DAFactory.Get()) + { + return new JsonResult(da.Updates.GetAddons(20).ToList()); + } + } + + // POST create a branch. + [HttpPost("branches")] + public IActionResult AddBranch(DbUpdateBranch branch) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + using (var da = api.DAFactory.Get()) + { + if (da.Updates.AddBranch(branch)) return Ok(); + else return NotFound(); + } + } + + // POST update a branch. + [HttpPost("branches/{id}")] + public IActionResult UpdateBranch(DbUpdateBranch branch) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + using (var da = api.DAFactory.Get()) + { + if (da.Updates.UpdateBranchInfo(branch)) return Ok(); + else return NotFound(); + } + } + + public class AddonUploadModel + { + public string name { get; set; } + public string description { get; set; } + public IFormFile clientAddon { get; set; } + public IFormFile serverAddon { get; set; } + } + + static int AddonRequestID = 0; + [HttpPost("uploadaddon")] + [DisableRequestSizeLimit] + [RequestFormLimits(MultipartBodyLengthLimit = 500000000)] + public async Task UploadAddon(AddonUploadModel upload) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + var reqID = ++AddonRequestID; + + var info = new DbUpdateAddon(); + if (upload.name == null || upload.name.Length > 128) return BadRequest("Invalid name."); + if (upload.description == null || upload.description.Length > 1024) return BadRequest("Invalid description."); + info.name = upload.name; + info.description = upload.description; + info.date = DateTime.UtcNow; + + if (upload.clientAddon == null && upload.serverAddon == null) + return BadRequest("client or server addon binary must be uploaded."); + + var addonID = DateTime.UtcNow.Ticks; + Directory.CreateDirectory("updateTemp/addons/"); + if (upload.clientAddon != null) + { + using (var file = System.IO.File.Open($"updateTemp/addons/client{reqID}.zip", FileMode.Create, FileAccess.Write, FileShare.None)) + { + await upload.clientAddon.CopyToAsync(file); + } + info.addon_zip_url = await api.UpdateUploader.UploadFile($"addons/client{addonID}.zip", $"updateTemp/addons/client{reqID}.zip", $"addon-{addonID}"); + System.IO.File.Delete($"updateTemp/addons/client{reqID}.zip"); + } + + if (upload.serverAddon != null) + { + using (var file = System.IO.File.Open($"updateTemp/addons/server{reqID}.zip", FileMode.Create, FileAccess.Write, FileShare.None)) + { + await upload.serverAddon.CopyToAsync(file); + } + info.server_zip_url = await api.UpdateUploader.UploadFile($"addons/server{addonID}.zip", $"updateTemp/addons/server{reqID}.zip", $"addon-{addonID}"); + System.IO.File.Delete($"updateTemp/addons/server{reqID}.zip"); + } + + using (var da = api.DAFactory.Get()) + { + da.Updates.AddAddon(info); + return new JsonResult(info); + } + } + + // GET status for ongoing update generation + [HttpGet("updateTask/{id}")] + public IActionResult GetTask(int id) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + var task = GenerateUpdateService.INSTANCE.GetTask(id); + if (task == null) return NotFound(); + else return new JsonResult(task); + } + + // POST admin/updates (start update generation) + [HttpPost] + public IActionResult Post([FromBody]UpdateCreateModel request) + { + var api = Api.INSTANCE; + api.DemandAdmin(Request); + var task = GenerateUpdateService.INSTANCE.CreateTask(request); + return new JsonResult(task); + } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/Admin/AdminUsersController.cs b/server/FSO.Server.Api.Core/Controllers/Admin/AdminUsersController.cs new file mode 100755 index 0000000..0ed6a9d --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/Admin/AdminUsersController.cs @@ -0,0 +1,334 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Database.DA.Inbox; +using FSO.Server.Database.DA.Users; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers.Admin +{ + [EnableCors("AdminAppPolicy")] + [Route("admin/users")] + [ApiController] + public class AdminUsersController : ControllerBase + { + //Get information about me, useful for the admin user interface to disable UI based on who you login as + public IActionResult current() + { + var api = Api.INSTANCE; + + var user = api.RequireAuthentication(Request); + + using (var da = api.DAFactory.Get()) + { + var userModel = da.Users.GetById(user.UserID); + if (userModel == null) + { + throw new Exception("Unable to find user"); + } + return ApiResponse.Json(HttpStatusCode.OK, userModel); + } + } + + + //Get the attributes of a specific user + [HttpGet("{id}")] + public IActionResult Get(string id) + { + if (id == "current") return current(); + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + var userModel = da.Users.GetById(uint.Parse(id)); + if (userModel == null) { throw new Exception("Unable to find user"); } + return ApiResponse.Json(HttpStatusCode.OK, userModel); + } + } + + /// + /// Unbans a user by IP and user. + /// + /// ID of user to unban. + /// + [HttpPost] + [Route("admin/unban")] + public IActionResult UnbanUser([FromBody] string user_id) + { + Api api = Api.INSTANCE; + + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + User userModel = da.Users.GetById(uint.Parse(user_id)); + + if(userModel.is_banned) + { + da.Users.UpdateBanned(uint.Parse(user_id), false); + } + + var ban = da.Bans.GetByIP(userModel.last_ip); + + if (ban!=null) + { + da.Bans.Remove(userModel.user_id); + } + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + } + + /// + /// Sends an in-game email message to a player. + /// + /// + /// + [HttpPost] + [Route("admin/mail")] + public IActionResult SendMail(MailCreateModel mail) + { + Api api = Api.INSTANCE; + + api.DemandAdmin(Request); + + using (var da = api.DAFactory.Get()) + { + User recipient = da.Users.GetById(uint.Parse(mail.target_id)); + + if (recipient == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "invalid_target_id" + }); + } + + if (mail.subject.Trim() == "") + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "subject_empty" + }); + } + + if (mail.body.Trim() == "") + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "body_empty" + }); + } + + // Save mail in db + int message_id = da.Inbox.CreateMessage(new DbInboxMsg + { + sender_id = 2147483648, + target_id = uint.Parse(mail.target_id), + subject = mail.subject, + body = mail.body, + sender_name = "FreeSO Staff", + time = DateTime.UtcNow, + msg_type = 4, + msg_subtype = 0, + read_state = 0, + }); + + // Try and notify the user ingame + api.RequestMailNotify(message_id, mail.subject, mail.body, uint.Parse(mail.target_id)); + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + } + + /// + /// Kicks a user out the current session. + /// + /// + /// + [HttpPost] + [Route("admin/kick")] + public IActionResult KickUser([FromBody] string user_id) + { + Api api = Api.INSTANCE; + + api.DemandModerator(Request); + + api.RequestUserDisconnect(uint.Parse(user_id)); + + return ApiResponse.Json(HttpStatusCode.OK, new { + status = "success" + }); + } + + /// + /// Bans a user and kicks them. + /// + /// + /// + [HttpPost] + [Route("admin/ban")] + public IActionResult BanUser(BanCreateModel ban) + { + Api api = Api.INSTANCE; + + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + User userModel = da.Users.GetById(uint.Parse(ban.user_id)); + + if (userModel == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "invalid_id" + }); + } + + if (ban.ban_type == "ip") + { + if (da.Bans.GetByIP(userModel.last_ip) != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "already_banned" + }); + } + + if (userModel.last_ip == "127.0.0.1") + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "invalid_ip" + }); + } + + da.Bans.Add(userModel.last_ip, userModel.user_id, ban.reason, int.Parse(ban.end_date), userModel.client_id); + + api.RequestUserDisconnect(userModel.user_id); + + api.SendBanMail(userModel.username, userModel.email, uint.Parse(ban.end_date)); + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + else if (ban.ban_type == "user") + { + if (userModel.is_banned) + { + return ApiResponse.Json(HttpStatusCode.NotFound, new + { + status = "already_banned" + }); + } + + da.Users.UpdateBanned(userModel.user_id, true); + + api.RequestUserDisconnect(userModel.user_id); + + api.SendBanMail(userModel.username, userModel.email, uint.Parse(ban.end_date)); + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "invalid_ban_type" + }); + } + } + + //List users + [HttpGet] + public IActionResult Get(int limit, int offset, string order) + { + if (limit == 0) limit = 20; + if (order == null) order = "register_date"; + var api = Api.INSTANCE; + api.DemandModerator(Request); + using (var da = api.DAFactory.Get()) + { + + if (limit > 100) + { + limit = 100; + } + + var result = da.Users.All((int)offset, (int)limit); + return ApiResponse.PagedList(Request, HttpStatusCode.OK, result); + } + } + + //Create a new user + [HttpPost] + public IActionResult Post(UserCreateModel user) + { + var api = Api.INSTANCE; + var nuser = api.RequireAuthentication(Request); + api.DemandModerator(nuser); + + if (user.is_admin) + { + //I need admin claim to do this + api.DemandAdmin(nuser); + } + + using (var da = api.DAFactory.Get()) + { + var userModel = new User(); + userModel.username = user.username; + userModel.email = user.email; + userModel.is_admin = user.is_admin; + userModel.is_moderator = user.is_moderator; + userModel.user_state = UserState.valid; + userModel.register_date = Epoch.Now; + userModel.is_banned = false; + + var userId = da.Users.Create(userModel); + + userModel = da.Users.GetById(userId); + if (userModel == null) { throw new Exception("Unable to find user"); } + return ApiResponse.Json(HttpStatusCode.OK, userModel); + } + } + } + + public class UserCreateModel + { + public string username { get; set; } + public string email { get; set; } + public string password { get; set; } + public bool is_admin { get; set; } + public bool is_moderator { get; set; } + } + + public class BanCreateModel + { + public string ban_type { get; set; } + public string user_id { get; set; } + public string reason { get; set; } + public string end_date { get; set; } + } + + public class MailCreateModel + { + public string target_id { get; set; } + public string subject { get; set; } + public string body { get; set; } + public string sender_name { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/AuthLoginController.cs b/server/FSO.Server.Api.Core/Controllers/AuthLoginController.cs new file mode 100755 index 0000000..1a0ced7 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/AuthLoginController.cs @@ -0,0 +1,134 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Database.DA.AuthTickets; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; +using System.Text; + +namespace FSO.Server.Api.Core.Controllers +{ + [Route("AuthLogin")] + [ApiController] + public class AuthLoginController : ControllerBase + { + private static Func ERROR_020 = printError("INV-020", "Please enter your member name and password."); + private static Func ERROR_110 = printError("INV-110", "The member name or password you have entered is incorrect. Please try again."); + private static Func ERROR_302 = printError("INV-302", "The game has experienced an internal error. Please try again."); + private static Func ERROR_160 = printError("INV-160", "The server is currently down for maintainance. Please try again later."); + private static Func ERROR_150 = printError("INV-150", "We're sorry, but your account has been suspended or cancelled."); + private static string LOCK_MESSAGE = "Your account has been locked due to too many incorrect login attempts. " + + "If you cannot remember your password, it can be reset at https://beta.freeso.org/forgot. Locked for: "; + + public static int LockAttempts = 5; + + public static int[] LockDuration = new int[] { + 5, + 15, + 30, + 60, + 120, + 720, + 1440 + }; + + // GET api/ + [HttpGet] + public IActionResult Get(string username, string password, string version, string clientid) + { + if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) + { + return ERROR_020(); + } + + AuthTicket ticket = null; + + var api = Api.INSTANCE; + + using (var db = api.DAFactory.Get()) + { + var user = db.Users.GetByUsername(username); + if (user == null) + { + return ERROR_110(); + } + + if (user.is_banned) + { + return ERROR_150(); + } + + if (api.Config.Maintainance && !(user.is_admin || user.is_moderator)) + { + return ERROR_160(); + } + + var ip = ApiUtils.GetIP(Request); + + var accLock = db.Users.GetRemainingAuth(user.user_id, ip); + if (accLock != null && (accLock.active || accLock.count >= LockAttempts) && accLock.expire_time > Epoch.Now) + { + return printError("INV-170", LOCK_MESSAGE + Epoch.HMSRemaining(accLock.expire_time))(); + } + + var authSettings = db.Users.GetAuthenticationSettings(user.user_id); + var isPasswordCorrect = PasswordHasher.Verify(password, new PasswordHash + { + data = authSettings.data, + scheme = authSettings.scheme_class + }); + + if (!isPasswordCorrect) + { + var failDelay = 60 * LockDuration[Math.Min(LockDuration.Length - 1, db.Users.FailedConsecutive(user.user_id, ip))]; + if (accLock == null) + { + db.Users.NewFailedAuth(user.user_id, ip, (uint)failDelay); + } else + { + var remaining = db.Users.FailedAuth(accLock.attempt_id, (uint)failDelay, LockAttempts); + if (remaining == 0) + return printError("INV-170", LOCK_MESSAGE + Epoch.HMSRemaining(Epoch.Now + (uint)failDelay))(); + } + return ERROR_110(); + } + + var ban = db.Bans.GetByIP(ip); + if (ban != null) + { + return ERROR_110(); + } + + db.Users.SuccessfulAuth(user.user_id, ip); + db.Users.UpdateClientID(user.user_id, clientid ?? "0"); + + /** Make a ticket **/ + ticket = new AuthTicket(); + ticket.ticket_id = Guid.NewGuid().ToString().Replace("-", ""); + ticket.user_id = user.user_id; + ticket.date = Epoch.Now; + ticket.ip = ip; + + db.AuthTickets.Create(ticket); + db.Users.UpdateLastLogin(user.user_id, Epoch.Now); + } + var content = "Valid=TRUE\r\nTicket=" + ticket.ticket_id.ToString() + "\r\n"; + return ApiResponse.Plain(HttpStatusCode.OK, content); + } + + + public static Func printError(String code, String message) + { + StringBuilder result = new StringBuilder(); + result.AppendLine("Valid=FALSE"); + result.AppendLine("Ticket=0"); + result.AppendLine("reasontext=" + code + ";" + message); + result.AppendLine("reasonurl="); + + return () => + { + return ApiResponse.Plain(HttpStatusCode.OK, result.ToString()); + }; + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/AvatarDataController.cs b/server/FSO.Server.Api.Core/Controllers/AvatarDataController.cs new file mode 100755 index 0000000..80f620b --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/AvatarDataController.cs @@ -0,0 +1,48 @@ +using FSO.Common.Utils; +using FSO.Server.Api.Core.Utils; +using FSO.Server.Protocol.CitySelector; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [Route("cityselector/app/AvatarDataServlet")] + [ApiController] + public class AvatarDataController : ControllerBase + { + public IActionResult Get() + { + var api = Api.INSTANCE; + var user = api.RequireAuthentication(Request); + + var result = new XMLList("The-Sims-Online"); + + using (var db = api.DAFactory.Get()) + { + var avatars = db.Avatars.GetSummaryByUserId(user.UserID); + + foreach (var avatar in avatars) + { + result.Add(new AvatarData + { + ID = avatar.avatar_id, + Name = avatar.name, + ShardName = api.Shards.GetById(avatar.shard_id).Name, + HeadOutfitID = avatar.head, + BodyOutfitID = avatar.body, + AppearanceType = (AvatarAppearanceType)Enum.Parse(typeof(AvatarAppearanceType), avatar.skin_tone.ToString()), + Description = avatar.description, + LotId = avatar.lot_id, + LotName = avatar.lot_name, + LotLocation = avatar.lot_location + }); + } + } + + return ApiResponse.Xml(HttpStatusCode.OK, result); + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/AvatarInfoController.cs b/server/FSO.Server.Api.Core/Controllers/AvatarInfoController.cs new file mode 100755 index 0000000..5c122b2 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/AvatarInfoController.cs @@ -0,0 +1,321 @@ +using FSO.Server.Api.Core.Utils; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using FSO.Server.Database.DA.Avatars; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class AvatarInfoController : ControllerBase + { + //get the avatars by user_id + [Route("userapi/user/avatars")] + public IActionResult GetByUser() + { + var api = Api.INSTANCE; + var user = api.RequireAuthentication(Request); + if (!user.Claims.Contains("userReadPermissions")) return ApiResponse.Json(HttpStatusCode.OK, new JSONAvatarError("No read premissions found.")); + + using (var da = api.DAFactory.Get()) + { + var avatars = da.Avatars.GetByUserId(user.UserID); + List avatarJson = new List(); + foreach (var avatar in avatars) + { + avatarJson.Add(new JSONAvatar + { + avatar_id = avatar.avatar_id, + shard_id = avatar.shard_id, + name = avatar.name, + gender = avatar.gender, + date = avatar.date, + description = avatar.description, + current_job = avatar.current_job, + mayor_nhood = avatar.mayor_nhood + }); + } + var avatarsJson = new JSONAvatars(); + avatarsJson.avatars = avatarJson; + return ApiResponse.Json(HttpStatusCode.OK, avatarsJson); + } + } + //get the avatar by id + [HttpGet] + [Route("userapi/avatars/{avartarId}")] + public IActionResult GetByID(uint avartarId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var avatar = da.Avatars.Get(avartarId); + if (avatar == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Avatar not found")); + + var avatarJson = new JSONAvatar + { + avatar_id = avatar.avatar_id, + shard_id = avatar.shard_id, + name = avatar.name, + gender = avatar.gender, + date = avatar.date, + description = avatar.description, + current_job = avatar.current_job, + mayor_nhood = avatar.mayor_nhood + + }; + + return ApiResponse.Json(HttpStatusCode.OK, avatarJson); + } + } + //get the avatars by ids + [Route("userapi/avatars")] + public IActionResult GetByIDs([FromQuery(Name = "ids")]string idsString) + { + var api = Api.INSTANCE; + try + { + uint[] ids = Array.ConvertAll(idsString.Split(","), uint.Parse); + using (var da = api.DAFactory.Get()) + { + var avatars = da.Avatars.GetMultiple(ids); + List avatarJson = new List(); + foreach (var avatar in avatars) + { + avatarJson.Add(new JSONAvatar + { + avatar_id = avatar.avatar_id, + shard_id = avatar.shard_id, + name = avatar.name, + gender = avatar.gender, + date = avatar.date, + description = avatar.description, + current_job = avatar.current_job, + mayor_nhood = avatar.mayor_nhood + }); + } + var avatarsJson = new JSONAvatars(); + avatarsJson.avatars = avatarJson; + return ApiResponse.Json(HttpStatusCode.OK, avatarsJson); + } + } + catch + { + return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Error during cast. (invalid_value)")); + } + } + //gets all the avatars from one city + [HttpGet] + [Route("userapi/city/{shardId}/avatars/page/{pageNum}")] + public IActionResult GetAll(int shardId,int pageNum, [FromQuery(Name = "avatars_on_page")]int perPage) + { + var api = Api.INSTANCE; + if(perPage == 0) + { + perPage = 100; + } + if (perPage > 500) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("The max amount of avatars per page is 500")); + using (var da = api.DAFactory.Get()) + { + pageNum = pageNum - 1; + + var avatars = da.Avatars.AllByPage(shardId, pageNum * perPage, perPage,"avatar_id"); + var avatarCount = avatars.Total; + var totalPages = (avatars.Total - 1)/perPage + 1; + + var pageAvatarsJson = new JSONAvatarsPage(); + pageAvatarsJson.total_avatars = avatarCount; + pageAvatarsJson.page = pageNum + 1; + pageAvatarsJson.total_pages = (int)totalPages; + pageAvatarsJson.avatars_on_page = avatars.Count(); + + if (pageNum < 0 || pageNum >= (int)totalPages) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Page not found")); + if (avatars == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Avatar not found")); + + List avatarJson = new List(); + foreach (var avatar in avatars) + { + avatarJson.Add(new JSONAvatar + { + avatar_id = avatar.avatar_id, + shard_id = avatar.shard_id, + name = avatar.name, + gender = avatar.gender, + date = avatar.date, + description = avatar.description, + current_job = avatar.current_job, + mayor_nhood = avatar.mayor_nhood + }); + + } + + pageAvatarsJson.avatars = avatarJson; + return ApiResponse.Json(HttpStatusCode.OK, pageAvatarsJson); + } + } + //gets avatar by name + [HttpGet] + [Route("userapi/city/{shardId}/avatars/name/{name}")] + public IActionResult GetByName(int shardId, string name) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var avatar = da.Avatars.SearchExact(shardId, name, 1).FirstOrDefault(); + if (avatar == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Avatar not found")); + + var avatarJson = new JSONAvatar(); + var avatarById = da.Avatars.Get(avatar.avatar_id); + if (avatarById == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Avatar not found")); + avatarJson = (new JSONAvatar + { + avatar_id = avatarById.avatar_id, + shard_id = avatarById.shard_id, + name = avatarById.name, + gender = avatarById.gender, + date = avatarById.date, + description = avatarById.description, + current_job = avatarById.current_job, + mayor_nhood = avatarById.mayor_nhood + }); + return ApiResponse.Json(HttpStatusCode.OK, avatarJson); + } + } + //gets all the avatars that live in a specific neighbourhood + [HttpGet] + [Route("userapi/city/{shardId}/avatars/neighborhood/{nhoodId}")] + public IActionResult GetByNhood(int shardId, uint nhoodId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lots = da.Lots.All(shardId).Where(x => x.neighborhood_id == nhoodId); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Lots not found")); + + List avatarJson = new List(); + foreach (var lot in lots) + { + if(lot.category != FSO.Common.Enum.LotCategory.community) + { + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id); + var avatars = da.Avatars.GetMultiple(roomies.ToArray()); + foreach (var avatar in avatars) + { + avatarJson.Add(new JSONAvatar + { + avatar_id = avatar.avatar_id, + shard_id = avatar.shard_id, + name = avatar.name, + gender = avatar.gender, + date = avatar.date, + description = avatar.description, + current_job = avatar.current_job, + mayor_nhood = avatar.mayor_nhood + }); + } + } + + } + var avatarsJson = new JSONAvatars(); + avatarsJson.avatars = avatarJson; + return ApiResponse.Json(HttpStatusCode.OK, avatarsJson); + } + } + //get all online Avatars + [HttpGet] + [Route("userapi/avatars/online")] + public IActionResult GetOnline([FromQuery(Name = "compact")]bool compact) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + List avatarSmallJson = new List(); + var avatarJson = new JSONAvatarOnline(); + if (compact) + { + var avatarStatus = da.AvatarClaims.GetAllActiveAvatarsCount(); + if (avatarStatus == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("ammount not found")); + avatarJson.avatars_online_count = avatarStatus; + } + + + if (!compact) + { + var avatarStatus = da.AvatarClaims.GetAllActiveAvatars(); + if (avatarStatus == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONAvatarError("Avatars not found")); + + foreach (var avatar in avatarStatus) + { + uint location = 0; + if (avatar.privacy_mode == 0) + { + location = avatar.location; + } + avatarSmallJson.Add(new JSONAvatarSmall + { + avatar_id = avatar.avatar_id, + name = avatar.name, + privacy_mode = avatar.privacy_mode, + location = location + }); + + } + avatarJson.avatars_online_count = avatarStatus.Count(); + } + + avatarJson.avatars = avatarSmallJson; + return ApiResponse.Json(HttpStatusCode.OK, avatarJson); + } + } + } + public class JSONAvatarError + { + public string error; + public JSONAvatarError(string errorString) + { + error = errorString; + } + } + public class JSONAvatarsPage + { + public int page { get; set; } + public int total_pages { get; set; } + public int total_avatars { get; set; } + public int avatars_on_page { get; set; } + public List avatars { get; set; } + } + public class JSONAvatarOnline + { + public int? avatars_online_count { get; set; } + public List avatars { get; set; } + } + public class JSONAvatarSmall + { + public uint avatar_id { get; set; } + public string name { get; set; } + public byte privacy_mode { get; set; } + public uint location { get; set; } + } + public class JSONAvatars + { + public List avatars { get; set; } + } + public class JSONAvatar + { + public uint avatar_id { get; set; } + public int shard_id { get; set; } + public string name { get; set; } + public DbAvatarGender gender { get; set; } + public uint date { get; set; } + public string description { get; set; } + public ushort current_job { get; set; } + public int? mayor_nhood { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/BulletinInfoController.cs b/server/FSO.Server.Api.Core/Controllers/BulletinInfoController.cs new file mode 100755 index 0000000..4d94202 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/BulletinInfoController.cs @@ -0,0 +1,134 @@ +using FSO.Server.Api.Core.Utils; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using FSO.Server.Database.DA.Bulletin; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class BulletinInfoController : ControllerBase + { + [HttpGet("nhoodId")] + [Route("userapi/neighborhood/{nhoodId}/bulletins")] + public IActionResult GetByNhoodAndAfter(uint nhoodId, [FromQuery(Name = "after")]uint after) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + if (after == null) after = 0; + var bulletins = da.BulletinPosts.GetByNhoodId(nhoodId, after); + if (bulletins == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONBulletinError("Bulletins not found")); + + List bulletinJson = new List(); + foreach (var bulletin in bulletins) + { + bulletinJson.Add(new JSONBulletin + { + bulletin_id = bulletin.bulletin_id, + neighborhood_id = bulletin.neighborhood_id, + avatar_id = bulletin.avatar_id, + title = bulletin.title, + body = bulletin.body, + date = bulletin.date, + flags = bulletin.flags, + lot_id = bulletin.lot_id, + type = bulletin.type + }); + + } + var bulletinsJson = new JSONBulletins(); + bulletinsJson.bulletins = bulletinJson; + return ApiResponse.Json(HttpStatusCode.OK, bulletinsJson); + } + } + [HttpGet] + [Route("userapi/neighborhood/{nhoodid}/bulletins/{bulletinId}")] + public IActionResult GetByID(uint bulletinId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var bulletin = da.BulletinPosts.Get(bulletinId); + if (bulletin == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONBulletinError("Bulletin not found")); + + var bulletinJson = new JSONBulletin(); + bulletinJson = new JSONBulletin + { + bulletin_id = bulletin.bulletin_id, + neighborhood_id = bulletin.neighborhood_id, + avatar_id = bulletin.avatar_id, + title = bulletin.title, + body = bulletin.body, + date = bulletin.date, + flags = bulletin.flags, + lot_id = bulletin.lot_id, + type = bulletin.type + }; + return ApiResponse.Json(HttpStatusCode.OK, bulletinJson); + } + } + [HttpGet] + [Route("userapi/neighborhood/{nhoodId}/bulletins/type/{bulletinType}")] + public IActionResult GetByNhoodAndType(uint nhoodId,DbBulletinType bulletinType) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var bulletins = da.BulletinPosts.GetByNhoodId(nhoodId, 0).Where(x => x.type == bulletinType); + if (bulletins == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONBulletinError("Bulletins not found")); + + List bulletinJson = new List(); + foreach (var bulletin in bulletins) + { + bulletinJson.Add(new JSONBulletin + { + bulletin_id = bulletin.bulletin_id, + neighborhood_id = bulletin.neighborhood_id, + avatar_id = bulletin.avatar_id, + title = bulletin.title, + body = bulletin.body, + date = bulletin.date, + flags = bulletin.flags, + lot_id = bulletin.lot_id, + type = bulletin.type + }); + + } + var bulletinsJson = new JSONBulletins(); + bulletinsJson.bulletins = bulletinJson; + return ApiResponse.Json(HttpStatusCode.OK, bulletinsJson); + } + } + } + public class JSONBulletinError + { + public string error; + public JSONBulletinError(string errorString) + { + error = errorString; + } + } + public class JSONBulletins + { + public List bulletins { get; set; } + } + public class JSONBulletin + { + public uint bulletin_id { get; set; } + public int neighborhood_id { get; set; } + public uint? avatar_id { get; set; } + public string title { get; set; } + public string body { get; set; } + public uint date { get; set; } + public uint flags { get; set; } + public int? lot_id { get; set; } + public DbBulletinType type { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/CityJSONController.cs b/server/FSO.Server.Api.Core/Controllers/CityJSONController.cs new file mode 100755 index 0000000..d89d67a --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/CityJSONController.cs @@ -0,0 +1,73 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class CityJSONController : ControllerBase + { + private static object ModelLock = new object { }; + private static CityInfoModel LastModel = new CityInfoModel(); + private static uint LastModelUpdate; + + [HttpGet] + [Route("userapi/city/{shardid}/city.json")] + public IActionResult Get(int shardid) + { + var api = Api.INSTANCE; + + var now = Epoch.Now; + if (LastModelUpdate < now - 15) + { + LastModelUpdate = now; + lock (ModelLock) + { + LastModel = new CityInfoModel(); + using (var da = api.DAFactory.Get()) + { + var lots = da.Lots.AllLocations(shardid); + var lotstatus = da.LotClaims.AllLocations(shardid); + LastModel.reservedLots = lots.ConvertAll(x => x.location).ToArray(); + LastModel.names = lots.ConvertAll(x => x.name).ToArray(); + LastModel.activeLots = lotstatus.ConvertAll(x => x.location).ToArray(); + LastModel.onlineCount = lotstatus.ConvertAll(x => x.active).ToArray(); + } + } + } + lock (ModelLock) + { + return ApiResponse.Json(HttpStatusCode.OK, LastModel); + } + } + + [HttpGet] + [Route("userapi/city/thumbwork.json")] + public IActionResult ThumbWork() + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + var work = da.Lots.Get3DWork(); + if (work == null) return ApiResponse.Plain(HttpStatusCode.OK, ""); + else + { + return ApiResponse.Json(HttpStatusCode.OK, work); + } + } + } + } + + class CityInfoModel + { + public string[] names; + public uint[] reservedLots; + public uint[] activeLots; + public int[] onlineCount; + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/ElectionInfoController.cs b/server/FSO.Server.Api.Core/Controllers/ElectionInfoController.cs new file mode 100755 index 0000000..b2990c4 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/ElectionInfoController.cs @@ -0,0 +1,79 @@ +using FSO.Server.Api.Core.Utils; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Net; +using FSO.Server.Database.DA.Elections; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class ElectionController : ControllerBase + { + [HttpGet] + [Route("userapi/neighborhood/{nhoodId}/elections")] + public IActionResult GetByNhood(uint nhoodId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var nhood = da.Neighborhoods.Get(nhoodId); + if (nhood.election_cycle_id == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONElectionError("Election cycle not found")); + + var electionCycle = da.Elections.GetCycle((uint)nhood.election_cycle_id); + + var electionCandidates = new List(); + if (electionCycle.current_state == Database.DA.Elections.DbElectionCycleState.election) + electionCandidates = da.Elections.GetCandidates(electionCycle.cycle_id, Database.DA.Elections.DbCandidateState.running); + + if (electionCycle.current_state == Database.DA.Elections.DbElectionCycleState.ended) + electionCandidates = da.Elections.GetCandidates(electionCycle.cycle_id, Database.DA.Elections.DbCandidateState.won); + + if (electionCycle == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONElectionError("Election cycle not found")); + + List candidatesJson = new List(); + foreach (var candidate in electionCandidates) + { + candidatesJson.Add(new JSONCandidates + { + candidate_avatar_id = candidate.candidate_avatar_id, + comment = candidate.comment, + state = candidate.state + }); + + } + var electionJson = new JSONElections(); + electionJson.candidates = candidatesJson; + electionJson.current_state = electionCycle.current_state; + electionJson.neighborhood_id = nhood.neighborhood_id; + electionJson.start_date = electionCycle.start_date; + electionJson.end_date = electionCycle.end_date; + return ApiResponse.Json(HttpStatusCode.OK, electionJson); + } + } + } + public class JSONElectionError + { + public string error; + public JSONElectionError(string errorString) + { + error = errorString; + } + } + public class JSONElections + { + public DbElectionCycleState current_state { get; set; } + public int neighborhood_id { get; set; } + public uint start_date { get; set; } + public uint end_date { get; set; } + public List candidates { get; set; } + } + public class JSONCandidates + { + public uint candidate_avatar_id { get; set; } + public string comment { get; set; } + public DbCandidateState state { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/GameAPI/UpdateController.cs b/server/FSO.Server.Api.Core/Controllers/GameAPI/UpdateController.cs new file mode 100755 index 0000000..ad6beb9 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/GameAPI/UpdateController.cs @@ -0,0 +1,38 @@ +using System.Linq; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; + +namespace FSO.Server.Api.Core.Controllers.GameAPI +{ + [EnableCors] + [Route("userapi/update")] + public class UpdateController : ControllerBase + { + + // GET userapi/update + // get recent PUBLISHED updates for the active branch, ordered by publish date + [HttpGet()] + public IActionResult Get(int id) + { + var api = Api.INSTANCE; + using (var da = api.DAFactory.Get()) + { + var recents = da.Updates.GetRecentUpdatesForBranchByName(api.Config.BranchName, 20); + return new JsonResult(recents.ToList()); + } + } + + // GET: userapi/update/ + // get recent PUBLISHED updates for a specific branch, ordered by publish date + [HttpGet("{branch}")] + public IActionResult Get(string branch) + { + var api = Api.INSTANCE; + using (var da = api.DAFactory.Get()) + { + var recents = da.Updates.GetRecentUpdatesForBranchByName(branch, 20); + return new JsonResult(recents.ToList()); + } + } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/GithubController.cs b/server/FSO.Server.Api.Core/Controllers/GithubController.cs new file mode 100755 index 0000000..8aad74b --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/GithubController.cs @@ -0,0 +1,77 @@ +using System; +using System.Security.Cryptography; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using Octokit; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class GithubController : ControllerBase + { + readonly GitHubClient client = + new GitHubClient(new ProductHeaderValue(Api.INSTANCE.Github.AppName), new Uri("https://github.com/")); + + private string StoredToken; + private static string CSRF; + + // GET: // + [HttpGet] + [Route("github/")] + public IActionResult Index() + { + if (Api.INSTANCE.Github == null) return NotFound(); + if (Api.INSTANCE.Github.AccessToken != null) return NotFound(); + + return Redirect(GetOauthLoginUrl()); + } + + [HttpGet] + [Route("github/callback")] + public async Task Callback(string code, string state) + { + if (Api.INSTANCE.Github == null) return NotFound(); + if (Api.INSTANCE.Github.AccessToken != null) return NotFound(); + + if (!String.IsNullOrEmpty(code)) + { + var expectedState = CSRF; + if (state != expectedState) throw new InvalidOperationException("SECURITY FAIL!"); + //CSRF = null; + + var token = await client.Oauth.CreateAccessToken( + new OauthTokenRequest(Api.INSTANCE.Github.ClientID, Api.INSTANCE.Github.ClientSecret, code) + { + RedirectUri = new Uri("http://localhost:80/github/callback") + }); + StoredToken = token.AccessToken; + } + + return Ok(StoredToken); + } + + private string GetOauthLoginUrl() + { + var rngCsp = new RNGCryptoServiceProvider(); + string csrf = ""; + var random = new byte[24]; + rngCsp.GetBytes(random); + for (int i=0; i<24; i++) + { + csrf += (char)('?' + random[i]/4); + } + CSRF = csrf; + + // 1. Redirect users to request GitHub access + var request = new OauthLoginRequest(Api.INSTANCE.Github.ClientID) + { + Scopes = { "admin:org", "repo" }, + State = csrf + }; + var oauthLoginUrl = client.Oauth.GetGitHubLoginUrl(request); + return oauthLoginUrl.ToString(); + } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/InitialConnectController.cs b/server/FSO.Server.Api.Core/Controllers/InitialConnectController.cs new file mode 100755 index 0000000..900a029 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/InitialConnectController.cs @@ -0,0 +1,93 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Protocol.CitySelector; +using FSO.Server.Servers.Api.JsonWebToken; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [Route("cityselector/app/InitialConnectServlet")] + [ApiController] + public class InitialConnectController : ControllerBase + { + private static Func ERROR_MISSING_TOKEN = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("501", "Token not found")); + private static Func ERROR_EXPIRED_TOKEN = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("502", "Token has expired")); + + [HttpGet] + public IActionResult Get(string ticket, string version) + { + var api = Api.INSTANCE; + + if (ticket == null || ticket == "" || version == null){ + return ERROR_MISSING_TOKEN(); + } + + using (var db = api.DAFactory.Get()) + { + var dbTicket = db.AuthTickets.Get(ticket); + if (dbTicket == null){ + return ERROR_MISSING_TOKEN(); + } + + db.AuthTickets.Delete((string)ticket); + if (dbTicket.date + api.Config.AuthTicketDuration < Epoch.Now){ + return ERROR_EXPIRED_TOKEN(); + } + + /** Is it a valid account? **/ + var user = db.Users.GetById(dbTicket.user_id); + if (user == null){ + return ERROR_MISSING_TOKEN(); + } + + //Use JWT to create and sign an auth cookies + var session = new JWTUser() + { + UserID = user.user_id, + UserName = user.username + }; + + //TODO: This assumes 1 shard, when using multiple need to either have version download occour after + //avatar select, or rework the tables + var shardOne = api.Shards.GetById(1); + + var token = api.JWT.CreateToken(session); + + IActionResult response; + if (shardOne.UpdateID != null) + { + var update = db.Updates.GetUpdate(shardOne.UpdateID.Value); + response = ApiResponse.Xml(HttpStatusCode.OK, new UserAuthorized() + { + FSOBranch = shardOne.VersionName, + FSOVersion = shardOne.VersionNumber, + FSOUpdateUrl = update.full_zip, + FSOCDNUrl = api.Config.CDNUrl + }); + } + else + { + response = ApiResponse.Xml(HttpStatusCode.OK, new UserAuthorized() + { + FSOBranch = shardOne.VersionName, + FSOVersion = shardOne.VersionNumber, + FSOUpdateUrl = api.Config.UpdateUrl, + FSOCDNUrl = api.Config.CDNUrl + }); + } + Response.Cookies.Append("fso", token.Token, new Microsoft.AspNetCore.Http.CookieOptions() + { + Expires = DateTimeOffset.Now.AddDays(1), + Domain = Request.Host.Host, + Path = "/" + }); + //HttpContext.Current.Response.SetCookie(new HttpCookie("fso", token.Token)); + return response; + } + } + + } +} + \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/LotInfoController.cs b/server/FSO.Server.Api.Core/Controllers/LotInfoController.cs new file mode 100755 index 0000000..eaae56a --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/LotInfoController.cs @@ -0,0 +1,705 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using FSO.Server.Api.Core.Utils; +using FSO.Common.Enum; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Cors; + +namespace FSO.Server.Api.Core.Controllers +{ + + public static class MemoryCacher + { + public static MemoryCache Default = new MemoryCache(new MemoryCacheOptions()); + public static object GetValue(string key) + { + MemoryCache memoryCache = Default; + return memoryCache.Get(key); + } + + public static bool Add(string key, object value, DateTimeOffset absExpiration) + { + MemoryCache memoryCache = Default; + return memoryCache.Set(key, value, absExpiration) == value; + } + + public static void Delete(string key) + { + MemoryCache memoryCache = Default; + memoryCache.Remove(key); + } + } + + [EnableCors] + [ApiController] + public class LotInfoController : ControllerBase + { + public static ConcurrentDictionary LotLocationCache = new ConcurrentDictionary(); + + public static int? IDForLocation(int shardid, uint loc) + { + var api = Api.INSTANCE; + var locToID = LotLocationCache.GetOrAdd(shardid, (ikey) => + { + using (var da = api.DAFactory.Get()) + { + return new ShardLocationCache( + new ConcurrentDictionary(da.Lots.All(ikey).Select(x => new KeyValuePair(x.location, x.lot_id))) + ); + } + }); + if (DateTime.UtcNow - locToID.CreateTime > TimeSpan.FromMinutes(15)) + { + ShardLocationCache removed; + LotLocationCache.TryRemove(shardid, out removed); + } + + try + { + return locToID.Dict.GetOrAdd(loc, (ikey) => + { + using (var da = api.DAFactory.Get()) + { + return da.Lots.GetByLocation(shardid, ikey).lot_id; + } + }); + } catch (NullReferenceException e) + { + return null; + } + } + + [HttpGet] + [Route("userapi/city/{shardid}/{id}.png")] + [ResponseCache(Duration = 60 * 60, Location = ResponseCacheLocation.Any)] + public IActionResult Get(int shardid, uint id) + { + var dat = (byte[])MemoryCacher.GetValue("lt" + shardid + ":" + id); + if (dat != null) + { + return File(dat, "image/png"); + } + + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = IDForLocation(shardid, id); + if (lot == null) return NotFound(); + + FileStream stream; + try + { + var ndat = System.IO.File.ReadAllBytes(Path.Combine(api.Config.NFSdir, "Lots/" + lot.Value.ToString("x8") + "/thumb.png")); + MemoryCacher.Add("lt" + shardid + ":" + id, ndat, DateTime.Now.Add(new TimeSpan(1, 0, 0))); + + return File(ndat, "image/png"); + } + catch (Exception e) + { + return NotFound(); + } + } + } + + [HttpGet] + [Route("userapi/city/{shardid}/i{id}.json")] + public IActionResult GetJSON(int shardid, uint id) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByLocation(shardid, id); + if (lot == null) return NotFound(); + + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id).ToArray(); + + var jlot = new JSONLot + { + admit_mode = lot.admit_mode, + category = lot.category, + created_date = lot.created_date, + description = lot.description, + location = lot.location, + name = lot.name, + neighborhood_id = lot.neighborhood_id, + owner_id = lot.owner_id, + shard_id = lot.shard_id, + skill_mode = lot.skill_mode, + roommates = roomies + }; + + return ApiResponse.Json(HttpStatusCode.OK, jlot); + } + } + + //New user API calls might replace old once later + //get lot information by location + [HttpGet] + [Route("userapi/lots/{lotId}")] + public IActionResult GetByID(int lotId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.Get(lotId); + if (lot == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lot not found")); + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id).ToArray(); + + var lotJson = new JSONLot + { + admit_mode = lot.admit_mode, + category = lot.category, + created_date = lot.created_date, + description = lot.description, + location = lot.location, + name = lot.name, + neighborhood_id = lot.neighborhood_id, + owner_id = lot.owner_id, + shard_id = lot.shard_id, + skill_mode = lot.skill_mode, + roommates = roomies, + lot_id = lot.lot_id + }; + + return ApiResponse.Json(HttpStatusCode.OK, lotJson); + } + } + //get the lots by ids + [Route("userapi/lots")] + public IActionResult GetByIDs([FromQuery(Name = "ids")]string idsString) + { + var api = Api.INSTANCE; + try + { + int[] ids = Array.ConvertAll(idsString.Split(","), int.Parse); + using (var da = api.DAFactory.Get()) + { + var lots = da.Lots.GetMultiple(ids); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lot not found")); + + List lotJson = new List(); + foreach (var lot in lots) + { + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id).ToArray(); + lotJson.Add(new JSONLot + { + admit_mode = lot.admit_mode, + category = lot.category, + created_date = lot.created_date, + description = lot.description, + location = lot.location, + name = lot.name, + neighborhood_id = lot.neighborhood_id, + owner_id = lot.owner_id, + shard_id = lot.shard_id, + skill_mode = lot.skill_mode, + roommates = roomies, + lot_id = lot.lot_id + }); + } + var lotsJson = new JSONLots(); + lotsJson.lots = lotJson; + return ApiResponse.Json(HttpStatusCode.OK, lotsJson); + } + } + catch + { + return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Error during cast. (invalid_value)")); + } + } + //gets all the lots from one city + [HttpGet] + [Route("userapi/city/{shardId}/lots/page/{pageNum}")] + public IActionResult GetAll(int shardId, int pageNum, [FromQuery(Name = "lots_on_page")]int perPage) + { + var api = Api.INSTANCE; + if (perPage == 0) + { + perPage = 100; + } + if (perPage > 500) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("The max amount of lots per page is 500")); + using (var da = api.DAFactory.Get()) + { + pageNum = pageNum - 1; + + var lots = da.Lots.AllByPage(shardId, pageNum * perPage, perPage,"lot_id"); + var lotCount = lots.Total; + var totalPages = (lots.Total - 1) / perPage + 1; + + var pageLotsJson = new JSONLotsPage(); + pageLotsJson.total_lots = lotCount; + pageLotsJson.page = pageNum + 1; + pageLotsJson.total_pages = (int)totalPages; + pageLotsJson.lots_on_page = lots.Count(); + + if (pageNum < 0 || pageNum >= (int)totalPages) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Page not found")); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lots not found")); + + List lotJson = new List(); + foreach (var lot in lots) + { + lotJson.Add(new JSONLotSmall + { + location = lot.location, + name = lot.name, + description = lot.description, + category = lot.category, + admit_mode = lot.admit_mode, + neighborhood_id = lot.neighborhood_id, + lot_id = lot.lot_id + }); + } + + pageLotsJson.lots = lotJson; + return ApiResponse.Json(HttpStatusCode.OK, pageLotsJson); + } + } + //get lot information by location + [HttpGet] + [Route("userapi/city/{shardId}/lots/location/{locationId}")] + public IActionResult GetByLocation(int shardId, uint locationId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByLocation(shardId, locationId); + if (lot == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lot not found")); + + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id).ToArray(); + + var LotJSON = new JSONLot + { + admit_mode = lot.admit_mode, + category = lot.category, + created_date = lot.created_date, + description = lot.description, + location = lot.location, + name = lot.name, + neighborhood_id = lot.neighborhood_id, + owner_id = lot.owner_id, + shard_id = lot.shard_id, + skill_mode = lot.skill_mode, + roommates = roomies, + lot_id = lot.lot_id + }; + + return ApiResponse.Json(HttpStatusCode.OK, LotJSON); + } + } + //get lot information By neighbourhood + [HttpGet] + [Route("userapi/city/{shardId}/lots/neighborhood/{nhoodId}")] + public IActionResult GetByNhood(int shardId, uint nhoodId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lots = da.Lots.All(shardId).Where(x => x.neighborhood_id == nhoodId); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("lots not found")); + List lotJson = new List(); + foreach (var lot in lots) + { + lotJson.Add(new JSONLotSmall + { + location = lot.location, + name = lot.name, + description = lot.description, + category = lot.category, + admit_mode = lot.admit_mode, + neighborhood_id = lot.neighborhood_id, + lot_id = lot.lot_id + }); + } + var lotsJson = new JSONLotsSmall(); + lotsJson.lots = lotJson; + return ApiResponse.Json(HttpStatusCode.OK, lotsJson); + } + } + //get lot information by name + [HttpGet] + [Route("userapi/city/{shardId}/lots/name/{lotName}")] + public IActionResult GetByName(int shardId, string lotName) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByName(shardId, lotName); + if (lot == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lot not found")); + + var roomies = da.Roommates.GetLotRoommates(lot.lot_id).Where(x => x.is_pending == 0).Select(x => x.avatar_id).ToArray(); + + var lotJson = new JSONLot + { + lot_id = lot.lot_id, + admit_mode = lot.admit_mode, + category = lot.category, + created_date = lot.created_date, + description = lot.description, + location = lot.location, + name = lot.name, + neighborhood_id = lot.neighborhood_id, + owner_id = lot.owner_id, + shard_id = lot.shard_id, + skill_mode = lot.skill_mode, + roommates = roomies + }; + + return ApiResponse.Json(HttpStatusCode.OK, lotJson); + } + } + //get online lots + [HttpGet] + [Route("userapi/city/{shardId}/lots/online")] + public IActionResult GetOnline(int shardId, [FromQuery(Name = "compact")]bool compact) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + List lotSmallJson = new List(); + var lotsOnlineJson = new JSONLotsOnline(); + + if (!compact) + { + var activeLots = da.LotClaims.AllActiveLots(shardId); + if (activeLots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lots not found")); + var totalAvatars = 0; + foreach (var lot in activeLots) + { + lotSmallJson.Add(new JSONLotSmall + { + location = lot.location, + name = lot.name, + description = lot.description, + category = lot.category, + admit_mode = lot.admit_mode, + neighborhood_id = lot.neighborhood_id, + avatars_in_lot = lot.active, + lot_id = lot.lot_id + }); + totalAvatars += lot.active; + } + lotsOnlineJson.total_lots_online = activeLots.Count(); + lotsOnlineJson.total_avatars_in_lots_online = totalAvatars; + } + else + { + var activeLots = da.LotClaims.AllLocations(shardId); + if (activeLots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lots not found")); + var totalAvatars = 0; + foreach (var lot in activeLots) + { + totalAvatars += lot.active; + } + + lotsOnlineJson.total_lots_online = activeLots.Count(); + lotsOnlineJson.total_avatars_in_lots_online = totalAvatars; + } + + lotsOnlineJson.lots = lotSmallJson; + return ApiResponse.Json(HttpStatusCode.OK, lotsOnlineJson); + } + } + //get Top-100 lots by category + [HttpGet] + [Route("userapi/city/{shardId}/lots/top100/category/{lotCategory}")] + public IActionResult GetTop100ByCategory(int shardId, LotCategory lotCategory) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lots = da.LotTop100.GetByCategory(shardId, lotCategory).Take(100); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Top100 lots not found")); + + List top100Lots = new List(); + foreach (var top100Lot in lots) + { + top100Lots.Add(new JSONTop100Lot + { + category = top100Lot.category, + rank = top100Lot.rank, + shard_id = top100Lot.shard_id, + lot_location = top100Lot.lot_location, + lot_name = top100Lot.lot_name, + lot_id = top100Lot.lot_id + }); + } + var top100Json = new JSONTop100Lots(); + top100Json.lots = top100Lots; + return ApiResponse.Json(HttpStatusCode.OK, top100Json); + } + } + //get Top-100 lots by shard + [HttpGet] + [Route("userapi/city/{shardId}/lots/top100/all")] + public IActionResult GetTop100ByShard(int shardId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lots = da.LotTop100.GetAllByShard(shardId); + if (lots == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONLotError("Lots not found")); + + List top100Lots = new List(); + foreach (var top100Lot in lots) + { + top100Lots.Add(new JSONTop100Lot + { + category = top100Lot.category, + rank = top100Lot.rank, + shard_id = top100Lot.shard_id, + lot_location = top100Lot.lot_location, + lot_name = top100Lot.lot_name, + lot_id = top100Lot.lot_id + }); + } + var top100Json = new JSONTop100Lots(); + top100Json.lots = top100Lots; + return ApiResponse.Json(HttpStatusCode.OK, top100Json); + } + } + + //moderation only functions, such as downloading lot state + [HttpGet] + [Route("userapi/city/{shardid}/{id}.fsov")] + public IActionResult GetFSOV(int shardid, uint id) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByLocation(shardid, id); + if (lot == null) return NotFound(); + + FileStream stream; + try + { + var path = Path.Combine(api.Config.NFSdir, "Lots/" + lot.lot_id.ToString("x8") + "/state_" + lot.ring_backup_num.ToString() + ".fsov"); + + + stream = System.IO.File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read); + return File(stream, "application/octet-stream"); + } + catch (Exception e) + { + return NotFound(); + } + } + } + + [HttpGet] + [Route("userapi/city/{shardid}/{id}.fsof")] + [ResponseCache(Duration = 60 * 60, Location = ResponseCacheLocation.Any)] + public IActionResult GetFSOF(int shardid, uint id) + { + var dat = (byte[])MemoryCacher.GetValue("lf" + shardid + ":" + id); + if (dat != null) + { + return File(dat, "application/octet-stream"); + } + + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var lot = IDForLocation(shardid, id); + if (lot == null) return NotFound(); + + FileStream stream; + try + { + var path = Path.Combine(api.Config.NFSdir, "Lots/" + lot.Value.ToString("x8") + "/thumb.fsof"); + + var ndat = System.IO.File.ReadAllBytes(path); + MemoryCacher.Add("lf" + shardid + ":" + id, ndat, DateTime.Now.Add(new TimeSpan(1, 0, 0))); + return File(ndat, "application/octet-stream"); + } + catch (Exception e) + { + return NotFound(); + } + } + } + + [HttpPost] + [Route("userapi/city/{shardid}/uploadfacade/{id}")] + public IActionResult UploadFacade(int shardid, uint id, List files) + { + var api = Api.INSTANCE; + api.DemandModerator(Request); + + if (files == null) + return NotFound(); + + byte[] data = null; + foreach (var file in files) + { + var filename = file.FileName.Trim('\"'); + using (var memoryStream = new MemoryStream()) + { + file.CopyTo(memoryStream); + data = memoryStream.ToArray(); + } + } + + if (data == null) return NotFound(); + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByLocation(shardid, id); + if (lot == null) return NotFound(); + + FileStream stream; + try + { + var path = Path.Combine(api.Config.NFSdir, "Lots/" + lot.lot_id.ToString("x8") + "/thumb.fsof"); + stream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Write); + stream.Write(data, 0, data.Length); + return Ok(); + } + catch (Exception e) + { + return NotFound(); + } + } + + /* + var api = Api.INSTANCE; + api.DemandModerator(Request); + + if (!Request.Content.IsMimeMultipartContent()) + return new HttpResponseMessage(HttpStatusCode.UnsupportedMediaType); + + var provider = new MultipartMemoryStreamProvider(); + var files = Request.Content.ReadAsMultipartAsync(provider).Result; + + byte[] data = null; + foreach (var file in provider.Contents) + { + var filename = file.Headers.ContentDisposition.FileName.Trim('\"'); + data = file.ReadAsByteArrayAsync().Result; + } + + if (data == null) return new HttpResponseMessage(HttpStatusCode.NotFound); + + using (var da = api.DAFactory.Get()) + { + var lot = da.Lots.GetByLocation(shardid, id); + if (lot == null) return new HttpResponseMessage(HttpStatusCode.NotFound); + + FileStream stream; + try + { + var path = Path.Combine(api.Config.NFSdir, "Lots/" + lot.lot_id.ToString("x8") + "/thumb.fsof"); + stream = System.IO.File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Write); + stream.Write(data, 0, data.Length); + + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = new StringContent("", Encoding.UTF8, "text/plain"); + return response; + } + catch (Exception e) + { + return new HttpResponseMessage(HttpStatusCode.NotFound); + } + } + */ + } + } + + + public class ShardLocationCache + { + public ConcurrentDictionary Dict = new ConcurrentDictionary(); + public DateTime CreateTime = DateTime.UtcNow; + + public ShardLocationCache(ConcurrentDictionary dict) + { + Dict = dict; + } + } + public class JSONLotError + { + public string error; + public JSONLotError(string errorString) + { + error = errorString; + } + } + public class JSONLotsSmall + { + public List lots { get; set; } + } + public class JSONLots + { + public List lots { get; set; } + } + public class JSONLotsPage + { + public int page { get; set; } + public int total_pages { get; set; } + public int total_lots { get; set; } + public int lots_on_page { get; set; } + public List lots { get; set; } + } + public class JSONLotsOnline + { + public int total_lots_online { get; set; } + public int total_avatars_in_lots_online { get; set; } + public List lots { get; set; } + } + public class JSONLotSmall + { + public int lot_id { get; set; } + public uint location { get; set; } + public string name { get; set; } + public string description { get; set; } + public LotCategory category { get; set; } + public uint admit_mode { get; set; } + public uint neighborhood_id { get; set; } + public int avatars_in_lot { get; set; } + } + public class JSONLot + { + public int lot_id { get; set; } + public int shard_id { get; set; } + public uint? owner_id { get; set; } + public uint[] roommates { get; set; } + public string name { get; set; } + public string description { get; set; } + public uint location { get; set; } + public uint neighborhood_id { get; set; } + public uint created_date { get; set; } + public LotCategory category { get; set; } + public byte skill_mode { get; set; } + public byte admit_mode { get; set; } + } + public class JSONTop100Lots + { + public List lots { get; set; } + } + public class JSONTop100Lot + { + public LotCategory category { get; set; } + public byte rank { get; set; } + public int shard_id { get; set; } + public string lot_name { get; set; } + public uint? lot_location { get; set; } + public int? lot_id { get; set; } + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/NhoodInfoController.cs b/server/FSO.Server.Api.Core/Controllers/NhoodInfoController.cs new file mode 100755 index 0000000..db3d2d8 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/NhoodInfoController.cs @@ -0,0 +1,128 @@ +using FSO.Server.Api.Core.Utils; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Linq; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [ApiController] + public class NhoodInfoController : ControllerBase + { + [HttpGet] + [Route("userapi/city/{shardId}/neighborhoods/all")] + public IActionResult GetAll(int shardId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var nhoods = da.Neighborhoods.All(shardId); + if (nhoods == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONNhoodError("Neighborhoods not found")); + + List nhoodJson = new List(); + foreach (var nhood in nhoods) + { + nhoodJson.Add(new JSONNhood + { + neighborhood_id = nhood.neighborhood_id, + name = nhood.name, + description = nhood.description, + color = nhood.color, + town_hall_id = nhood.town_hall_id, + icon_url = nhood.icon_url, + mayor_id = nhood.mayor_id, + mayor_elected_date = nhood.mayor_elected_date, + election_cycle_id = nhood.election_cycle_id + }); + + } + var nhoodsJson = new JSONNhoods(); + nhoodsJson.neighborhoods = nhoodJson; + return ApiResponse.Json(HttpStatusCode.OK, nhoodsJson); + } + } + [HttpGet] + [Route("userapi/neighborhoods/{nhoodId}")] + public IActionResult GetByID(uint nhoodId) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var nhood = da.Neighborhoods.Get(nhoodId); + if (nhood == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONNhoodError("Neighborhood not found")); + + var nhoodJson = new JSONNhood + { + neighborhood_id = nhood.neighborhood_id, + name = nhood.name, + description = nhood.description, + color = nhood.color, + town_hall_id = nhood.town_hall_id, + icon_url = nhood.icon_url, + mayor_id = nhood.mayor_id, + mayor_elected_date = nhood.mayor_elected_date, + election_cycle_id = nhood.election_cycle_id + }; + return ApiResponse.Json(HttpStatusCode.OK, nhoodJson); + } + } + [HttpGet] + [Route("userapi/city/{shardId}/neighborhoods/name/{nhoodName}")] + public IActionResult GetByName(int shardId, string nhoodName) + { + var api = Api.INSTANCE; + + using (var da = api.DAFactory.Get()) + { + var searchNhood = da.Neighborhoods.SearchExact(shardId, nhoodName, 1).FirstOrDefault(); + if (searchNhood == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONNhoodError("Neighborhood not found")); + + var nhood = da.Neighborhoods.Get((uint)searchNhood.neighborhood_id); + if (nhood == null) return ApiResponse.Json(HttpStatusCode.NotFound, new JSONNhoodError("Neighborhood not found")); + + var nhoodJson = new JSONNhood + { + neighborhood_id = nhood.neighborhood_id, + name = nhood.name, + description = nhood.description, + color = nhood.color, + town_hall_id = nhood.town_hall_id, + icon_url = nhood.icon_url, + mayor_id = nhood.mayor_id, + mayor_elected_date = nhood.mayor_elected_date, + election_cycle_id = nhood.election_cycle_id + }; + return ApiResponse.Json(HttpStatusCode.OK, nhoodJson); + } + } + } + public class JSONNhoodError + { + public string error; + public JSONNhoodError(string errorString) + { + error = errorString; + } + } + public class JSONNhoods + { + public List neighborhoods { get; set; } + } + public class JSONNhood + { + public int neighborhood_id { get; set; } + public string name { get; set; } + public string description { get; set; } + public uint color { get; set; } + public int? town_hall_id { get; set; } + public string icon_url { get; set; } + public uint? mayor_id { get; set; } + public uint mayor_elected_date { get; set; } + public uint? election_cycle_id { get; set; } + + } +} diff --git a/server/FSO.Server.Api.Core/Controllers/RegistrationController.cs b/server/FSO.Server.Api.Core/Controllers/RegistrationController.cs new file mode 100755 index 0000000..d950c6a --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/RegistrationController.cs @@ -0,0 +1,616 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Database.DA.EmailConfirmation; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Linq; +using System.Net; +using System.Text.RegularExpressions; + +namespace FSO.Server.Api.Core.Controllers +{ + /// + /// Controller for user registrations. + /// Supports email confirmation if enabled in config.json. + /// + + [EnableCors] + [Route("userapi/registration")] + [ApiController] + public class RegistrationController : ControllerBase + { + private const int REGISTER_THROTTLE_SECS = 60; + private const int EMAIL_CONFIRMATION_EXPIRE = 2 * 60 * 60; // 2 hrs + + /// + /// Alphanumeric (lowercase), no whitespace or special chars, cannot start with an underscore. + /// + private static Regex USERNAME_VALIDATION = new Regex("^([a-z0-9]){1}([a-z0-9_]){2,23}$"); + + #region Registration + [HttpPost] + public IActionResult CreateUser([FromForm] RegistrationModel user) + { + var api = Api.INSTANCE; + + if(api.Config.SmtpEnabled) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "missing_confirmation_token" + }); + } + + var ip = ApiUtils.GetIP(Request); + + user.username = user.username ?? ""; + user.username = user.username.ToLowerInvariant(); + user.email = user.email ?? ""; + //user.key = user.key ?? ""; + + string failReason = null; + if (user.username.Length < 3) failReason = "user_short"; + else if (user.username.Length > 24) failReason = "user_long"; + else if (!USERNAME_VALIDATION.IsMatch(user.username ?? "")) failReason = "user_invalid"; + else if ((user.password?.Length ?? 0) == 0) failReason = "pass_required"; + + try + { + var addr = new System.Net.Mail.MailAddress(user.email); + } + catch + { + failReason = "email_invalid"; + } + + if (failReason != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "bad_request", + error_description = failReason + }); + } + + /* + if (!string.IsNullOrEmpty(api.Config.Regkey) && api.Config.Regkey != user.key) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "key_wrong", + error_description = failReason + }); + } + */ + + using (var da = api.DAFactory.Get()) + { + //has this ip been banned? + var ban = da.Bans.GetByIP(ip); + if (ban != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "ip_banned" + }); + } + + //has this user registered a new account too soon after their last? + var now = Epoch.Now; + var prev = da.Users.GetByRegisterIP(ip); + if (now - (prev.FirstOrDefault()?.register_date ?? 0) < REGISTER_THROTTLE_SECS) + { + //cannot create a new account this soon. + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "registrations_too_frequent" + }); + } + + var userModel = api.CreateUser(user.username, user.email, user.password, ip); + + if(userModel==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "user_exists" + }); + } else { + api.SendEmailConfirmationOKMail(user.username, user.email); + return ApiResponse.Json(HttpStatusCode.OK, userModel); + } + } + } + + /// + /// Create a confirmation token and send email. + /// + /// + /// + [HttpPost] + [Route("userapi/registration/request")] + public IActionResult CreateToken(ConfirmationCreateTokenModel model) + { + Api api = Api.INSTANCE; + + // smtp needs to be configured for this + if(!api.Config.SmtpEnabled) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "smtp_disabled" + }); + } + + if(model.confirmation_url==null||model.email==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "missing_fields" + }); + } + + // verify email syntax + // To do: check if email address is disposable. + try + { + var addr = new System.Net.Mail.MailAddress(model.email); + } + catch + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "email_invalid" + }); + } + + using (var da = api.DAFactory.Get()) + { + // email is taken + if(da.Users.GetByEmail(model.email)!=null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "email_taken" + }); + } + + EmailConfirmation confirm = da.EmailConfirmations.GetByEmail(model.email, ConfirmationType.email); + + // already waiting for confirmation + if(confirm!=null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "confirmation_pending" + }); + } + + uint expires = Epoch.Now + EMAIL_CONFIRMATION_EXPIRE; + + // create new email confirmation + string token = da.EmailConfirmations.Create(new EmailConfirmation + { + type = ConfirmationType.email, + email = model.email, + expires = expires + }); + + // send email with recently generated token + bool sent = api.SendEmailConfirmationMail(model.email, token, model.confirmation_url, expires); + + if(sent) + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "email_failed" + }); + + } + } + + /// + /// Create a user with a valid email confirmation token. + /// + /// + /// + [HttpPost] + [Route("userapi/registration/confirm")] + public IActionResult CreateUserWithToken(RegistrationUseTokenModel user) + { + Api api = Api.INSTANCE; + + if (user == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "invalid_token" + }); + } + + using (var da = api.DAFactory.Get()) + { + EmailConfirmation confirmation = da.EmailConfirmations.GetByToken(user.token); + + if(confirmation == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "invalid_token" + }); + } + + var ip = ApiUtils.GetIP(Request); + + user.username = user.username ?? ""; + user.username = user.username.ToLowerInvariant(); + user.email = user.email ?? ""; + user.key = user.key ?? ""; + + string failReason = null; + if (user.username.Length < 3) failReason = "user_short"; + else if (user.username.Length > 24) failReason = "user_long"; + else if (!USERNAME_VALIDATION.IsMatch(user.username ?? "")) failReason = "user_invalid"; + else if ((user.password?.Length ?? 0) == 0) failReason = "pass_required"; + + try + { + var addr = new System.Net.Mail.MailAddress(user.email); + } + catch + { + failReason = "email_invalid"; + } + + if (failReason != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "bad_request", + error_description = failReason + }); + } + + if (!string.IsNullOrEmpty(api.Config.Regkey) && api.Config.Regkey != user.key) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "key_wrong", + error_description = failReason + }); + } + + //has this ip been banned? + var ban = da.Bans.GetByIP(ip); + if (ban != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "ip_banned" + }); + } + + //has this user registered a new account too soon after their last? + var prev = da.Users.GetByRegisterIP(ip); + if (Epoch.Now - (prev.FirstOrDefault()?.register_date ?? 0) < REGISTER_THROTTLE_SECS) + { + //cannot create a new account this soon. + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "registrations_too_frequent" + }); + } + + //create user in db + var userModel = api.CreateUser(user.username, user.email, user.password, ip); + + if (userModel == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "user_exists" + }); + } + else + { + //send OK email + api.SendEmailConfirmationOKMail(user.username, user.email); + da.EmailConfirmations.Remove(user.token); + return ApiResponse.Json(HttpStatusCode.OK, userModel); + } + } + } + + #endregion + + #region Password reset + [HttpPost] + [Route("userapi/password")] + public IActionResult ChangePassword(PasswordResetModel model) + { + Api api = Api.INSTANCE; + + if (api.Config.SmtpEnabled) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "missing_confirmation_token" + }); + } + + // No empty fields + if (model.username==null||model.new_password==null||model.old_password==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "missing_fields" + }); + } + + using (var da = api.DAFactory.Get()) + { + var user = da.Users.GetByUsername(model.username); + + if(user==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "user_invalid" + }); + } + + var authSettings = da.Users.GetAuthenticationSettings(user.user_id); + var correct = PasswordHasher.Verify(model.old_password, new PasswordHash + { + data = authSettings.data, + scheme = authSettings.scheme_class + }); + + if (!correct) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "incorrect_password" + }); + } + + api.ChangePassword(user.user_id, model.new_password); + api.SendPasswordResetOKMail(user.email, user.username); + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + } + + /// + /// Resets a user's password using a confirmation token. + /// + /// + /// + [HttpPost] + [Route("userapi/password/confirm")] + public IActionResult ConfirmPwd(PasswordResetUseTokenModel model) + { + Api api = Api.INSTANCE; + + if(model.token==null||model.new_password==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "missing_fields" + }); + } + + using (var da = api.DAFactory.Get()) + { + EmailConfirmation confirmation = da.EmailConfirmations.GetByToken(model.token); + + if(confirmation==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "invalid_token" + }); + } + + var user = da.Users.GetByEmail(confirmation.email); + + api.ChangePassword(user.user_id, model.new_password); + api.SendPasswordResetOKMail(user.email, user.username); + da.EmailConfirmations.Remove(model.token); + + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + } + + /// + /// Creates a password reset token and mails it to the user. + /// + /// + /// + [HttpPost] + [Route("userapi/password/request")] + public IActionResult CreatePwdToken(ConfirmationCreateTokenModel model) + { + Api api = Api.INSTANCE; + + if (model.confirmation_url == null || model.email == null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "missing_fields" + }); + } + + // verify email syntax + // To do: check if email address is disposable. + try + { + var addr = new System.Net.Mail.MailAddress(model.email); + } + catch + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "email_invalid" + }); + } + + using (var da = api.DAFactory.Get()) + { + + var user = da.Users.GetByEmail(model.email); + + if(user==null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "password_reset_failed", + error_description = "email_invalid" + }); + } + + EmailConfirmation confirm = da.EmailConfirmations.GetByEmail(model.email, ConfirmationType.password); + + // already awaiting a confirmation + // to-do: resend? + if (confirm != null) + { + return ApiResponse.Json(HttpStatusCode.OK, new RegistrationError() + { + error = "registration_failed", + error_description = "confirmation_pending" + }); + } + + uint expires = Epoch.Now + EMAIL_CONFIRMATION_EXPIRE; + + // create new email confirmation + string token = da.EmailConfirmations.Create(new EmailConfirmation + { + type = ConfirmationType.password, + email = model.email, + expires = expires + }); + + // send confirmation email with generated token + bool sent = api.SendPasswordResetMail(model.email, user.username, token, model.confirmation_url, expires); + + if (sent) + { + return ApiResponse.Json(HttpStatusCode.OK, new + { + status = "success" + }); + } + + return ApiResponse.Json(HttpStatusCode.OK, new + { + // success but email shitfaced + status = "email_failed" + }); + } + } + + #endregion + } + + #region Models + public class RegistrationError + { + public string error_description { get; set; } + public string error { get; set; } + } + + public class RegistrationModel + { + public string username { get; set; } + public string email { get; set; } + public string password { get; set; } + } + + /// + /// Expected request data when trying to create a token to register. + /// + public class ConfirmationCreateTokenModel + { + public string email { get; set; } + /// + /// The link the user will have to go to in order to confirm their token. + /// If %token% is present in the url, it will be replaced with the user's token. + /// + public string confirmation_url { get; set; } + } + + public class PasswordResetModel + { + public string username { get; set; } + public string old_password { get; set; } + public string new_password { get; set; } + } + + /// + /// Expected request data when trying to register with a token. + /// + public class RegistrationUseTokenModel + { + public string username { get; set; } + /// + /// User email. + /// + public string email { get; set; } + /// + /// User password. + /// + public string password { get; set; } + /// + /// Registration key. + /// + public string key { get; set; } + /// + /// The unique GUID. + /// + public string token { get; set; } + } + + public class PasswordResetUseTokenModel + { + public string token { get; set; } + public string new_password { get; set; } + } + + #endregion +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/ShardSelectorController.cs b/server/FSO.Server.Api.Core/Controllers/ShardSelectorController.cs new file mode 100755 index 0000000..c632562 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/ShardSelectorController.cs @@ -0,0 +1,98 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Database.DA.Shards; +using FSO.Server.Protocol.CitySelector; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [Route("cityselector/app/ShardSelectorServlet")] + [ApiController] + public class ShardSelectorController : ControllerBase + { + private static Func ERROR_SHARD_NOT_FOUND = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("503", "Shard not found")); + private static Func ERROR_AVATAR_NOT_FOUND = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("504", "Avatar not found")); + private static Func ERROR_AVATAR_NOT_YOURS = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("505", "You do not own this avatar!")); + private static Func ERROR_BANNED = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("506", "Your account has been banned.")); + private static Func ERROR_MAINTAINANCE = ApiResponse.XmlFuture(HttpStatusCode.OK, new XMLErrorMessage("507", "The server is currently undergoing maintainance. Please try again later.")); + + public IActionResult Get(string shardName, string avatarId) + { + var api = Api.INSTANCE; + + var user = api.RequireAuthentication(Request); + if (avatarId == null){ + //Using 0 to mean no avatar for CAS + avatarId = "0"; + } + + using (var db = api.DAFactory.Get()) + { + ShardStatusItem shard = api.Shards.GetByName(shardName); + if (shard != null) + { + var ip = ApiUtils.GetIP(Request); + uint avatarDBID = uint.Parse(avatarId); + + if (avatarDBID != 0) + { + var avatar = db.Avatars.Get(avatarDBID); + if (avatar == null) + { + //can't join server with an avatar that doesn't exist + return ERROR_AVATAR_NOT_FOUND(); + } + if (avatar.user_id != user.UserID || avatar.shard_id != shard.Id) + { + //make sure we own the avatar we're trying to connect with + return ERROR_AVATAR_NOT_YOURS(); + } + } + + var ban = db.Bans.GetByIP(ip); + var dbuser = db.Users.GetById(user.UserID); + if (dbuser == null || ban != null || dbuser.is_banned != false) + { + return ERROR_BANNED(); + } + + if (api.Config.Maintainance && !(dbuser.is_admin || dbuser.is_moderator)) + { + return ERROR_MAINTAINANCE(); + } + + /** Make an auth ticket **/ + var ticket = new ShardTicket + { + ticket_id = Guid.NewGuid().ToString().Replace("-", ""), + user_id = user.UserID, + avatar_id = avatarDBID, + date = Epoch.Now, + ip = ip + }; + + db.Users.UpdateConnectIP(ticket.user_id, ip); + db.Shards.CreateTicket(ticket); + + var result = new ShardSelectorServletResponse(); + result.PreAlpha = false; + + result.Address = shard.PublicHost; + result.PlayerID = user.UserID; + result.AvatarID = avatarId; + result.Ticket = ticket.ticket_id; + result.ConnectionID = ticket.ticket_id; + result.AvatarID = avatarId; + + return ApiResponse.Xml(HttpStatusCode.OK, result); + } + else + { + return ERROR_SHARD_NOT_FOUND(); + } + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/ShardStatusController.cs b/server/FSO.Server.Api.Core/Controllers/ShardStatusController.cs new file mode 100755 index 0000000..c4f4d73 --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/ShardStatusController.cs @@ -0,0 +1,29 @@ +using FSO.Common.Utils; +using FSO.Server.Api.Core.Utils; +using FSO.Server.Protocol.CitySelector; +using Microsoft.AspNetCore.Cors; +using Microsoft.AspNetCore.Mvc; +using System.Net; + +namespace FSO.Server.Api.Core.Controllers +{ + [EnableCors] + [Route("cityselector/shard-status.jsp")] + [ApiController] + public class ShardStatusController : ControllerBase + { + [HttpGet] + public IActionResult Get() + { + var api = Api.INSTANCE; + + var result = new XMLList("Shard-Status-List"); + var shards = api.Shards.All; + foreach (var shard in shards) + { + result.Add(shard); + } + return ApiResponse.Xml(HttpStatusCode.OK, result); + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Controllers/UserOAuthController.cs b/server/FSO.Server.Api.Core/Controllers/UserOAuthController.cs new file mode 100755 index 0000000..d4101da --- /dev/null +++ b/server/FSO.Server.Api.Core/Controllers/UserOAuthController.cs @@ -0,0 +1,122 @@ +using FSO.Server.Api.Core.Utils; +using FSO.Server.Common; +using FSO.Server.Servers.Api.JsonWebToken; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Api.Core.Controllers +{ + [Route("userapi/oauth/token")] + [ApiController] + public class UserOAuthController : ControllerBase + { + [HttpPost] + public IActionResult CreateToken([FromForm] UserOAuthRequest userAuthRequest) + { + if (userAuthRequest == null) BadRequest(); + var api = Api.INSTANCE; + using (var da = api.DAFactory.Get()) + { + var user = da.Users.GetByUsername(userAuthRequest.username); + if (user == null || user.is_banned) return ApiResponse.Json(System.Net.HttpStatusCode.Unauthorized, new UserOAuthError("unauthorized_client", "user_credentials_invalid")); + var ip = ApiUtils.GetIP(Request); + var hashSettings = da.Users.GetAuthenticationSettings(user.user_id); + var isPasswordCorrect = PasswordHasher.Verify(userAuthRequest.password, new PasswordHash + { + data = hashSettings.data, + scheme = hashSettings.scheme_class + }); + //check if account is locked due to failed attempts + var accLock = da.Users.GetRemainingAuth(user.user_id, ip); + if (accLock != null && (accLock.active || accLock.count >= AuthLoginController.LockAttempts) && accLock.expire_time > Epoch.Now) + { + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthError("unauthorized_client", "account_locked")); + } + //if the password is incorrect and check if user failed muli times and set a time out till next try. + if (!isPasswordCorrect) + { + var durations = AuthLoginController.LockDuration; + var failDelay = 60 * durations[Math.Min(durations.Length - 1, da.Users.FailedConsecutive(user.user_id, ip))]; + if (accLock == null) + { + da.Users.NewFailedAuth(user.user_id, ip, (uint)failDelay); + } + else + { + var remaining = da.Users.FailedAuth(accLock.attempt_id, (uint)failDelay, AuthLoginController.LockAttempts); + } + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthError("unauthorized_client", "user_credentials_invalid")); + } + + //user passed the password check, and now creates the claim/token + da.Users.SuccessfulAuth(user.user_id, ip); + var claims = new List(); + + //set the permission level in the claim + switch (userAuthRequest.permission_level) + { + case 1: + claims.Add("userReadPermissions"); + break; + case 2: + claims.Add("userReadPermissions"); + claims.Add("userWritePermissions"); + break; + case 3: + claims.Add("userReadPermissions"); + claims.Add("userWritePermissions"); + claims.Add("userUpdatePermissions"); + break; + case 4: + claims.Add("userReadPermissions"); + claims.Add("userWritePermissions"); + claims.Add("userUpdatePermissions"); + claims.Add("userDeletePermissions"); + break; + default: + break; + } + + //set the user identity + JWTUser identity = new JWTUser + { + UserID = user.user_id, + UserName = user.username, + Claims = claims + }; + + //generate the the tokenen and send it in a JSON format as response + var generatedToken = api.JWT.CreateToken(identity); + return ApiResponse.Json(System.Net.HttpStatusCode.OK, new UserOAuthSuccess + { + access_token = generatedToken.Token, + expires_in = generatedToken.ExpiresIn + }); + } + + } + } + public class UserOAuthRequest + { + public int permission_level { get; set; } + public string username { get; set; } + public string password { get; set; } + } + public class UserOAuthError + { + public string error; + public string error_description; + public UserOAuthError(string errorString,string errorDescriptionString) + { + error = errorString; + error_description = errorDescriptionString; + } + } + public class UserOAuthSuccess + { + public string access_token { get; set; } + public int expires_in { get; set; } + } + +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj b/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj new file mode 100755 index 0000000..8ecab64 --- /dev/null +++ b/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj @@ -0,0 +1,66 @@ + + + + netcoreapp2.2 + true + false + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailBan.html b/server/FSO.Server.Api.Core/MailTemplates/MailBan.html new file mode 100755 index 0000000..65918cf --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailBan.html @@ -0,0 +1,13 @@ +Account Suspended. +
One of your FreeSO accounts has been suspended for not following the rules. +
Banned account username: +%username%. +
+
+Expiration date: +%end% +
+
Official Discord: +https://discord.gg/xveESFj +
Forums: +http://forum.freeso.org \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailBase.html b/server/FSO.Server.Api.Core/MailTemplates/MailBase.html new file mode 100755 index 0000000..f27f443 --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailBase.html @@ -0,0 +1,9 @@ +
+
+ + Official Game Server +
+
+ %content% +
+
\ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailPasswordReset.html b/server/FSO.Server.Api.Core/MailTemplates/MailPasswordReset.html new file mode 100755 index 0000000..c66c8b6 --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailPasswordReset.html @@ -0,0 +1,11 @@ +Password Reset Request +
You requested a password reset. Good news, it's here! +
Click here to change your password. The link will expire in %expires%. +
Just in case, your token is: %token%. +
+
Official Discord: https://discord.gg/xveESFj +
Forums: http://forum.freeso.org +
Twitter: http://twitter.com/FreeSOGame +
+
Download the FreeSO Installer +
Get the installer from FreeSO.org. After confirming your account by clicking the link above, you will be able to create an account and login. \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailPasswordResetOK.html b/server/FSO.Server.Api.Core/MailTemplates/MailPasswordResetOK.html new file mode 100755 index 0000000..b0455b1 --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailPasswordResetOK.html @@ -0,0 +1,10 @@ +Your account password was just changed. +
The password for your account with username %username% was just changed. +
+
Official Discord: https://discord.gg/xveESFj +
Forums: http://forum.freeso.org +
Twitter: http://twitter.com/FreeSOGame +
+
+Learn how to get started: +
Check out TSOMania's guide at TSOMania.net. \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationOK.html b/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationOK.html new file mode 100755 index 0000000..c9ee86b --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationOK.html @@ -0,0 +1,12 @@ +Welcome to Sunrise Crater! +
You can now login in-game. Here are your details: +
Your username is: %username%. If you need any further support message us on one of our platforms. +
Please check out the rules if you haven't already! +
+
Official Discord: https://discord.gg/xveESFj +
Forums: http://forum.freeso.org +
Twitter: http://twitter.com/FreeSOGame +
+
+Learn how to get started: +
Check out TSOMania's guide at TSOMania.net. \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationToken.html b/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationToken.html new file mode 100755 index 0000000..7bd0de0 --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailRegistrationToken.html @@ -0,0 +1,11 @@ +You are almost here... +
One last step! Verify your email address: +
Click here finish your registration. The link will expire in %expires%. +
Just in case, your token is: %token%. +
+
Official Discord: https://discord.gg/xveESFj +
Forums: http://forum.freeso.org +
Twitter: http://twitter.com/FreeSOGame +
+
Download the FreeSO Installer +
Get the installer from FreeSO.org. After confirming your account by clicking the link above, you will be able to create an account and login. \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/MailTemplates/MailUnban.html b/server/FSO.Server.Api.Core/MailTemplates/MailUnban.html new file mode 100755 index 0000000..843c7d8 --- /dev/null +++ b/server/FSO.Server.Api.Core/MailTemplates/MailUnban.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Models/EventCreateModel.cs b/server/FSO.Server.Api.Core/Models/EventCreateModel.cs new file mode 100755 index 0000000..b9b607b --- /dev/null +++ b/server/FSO.Server.Api.Core/Models/EventCreateModel.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Server.Api.Core.Models +{ + public class EventCreateModel + { + public string title; + public string description; + public DateTime start_day; + public DateTime end_day; + public string type; + public int value; + public int value2; + public string mail_subject; + public string mail_message; + public int mail_sender; + public string mail_sender_name; + } + + public class PresetCreateModel + { + public string name; + public string description; + public int flags; + public List items; + } + + public class PresetItemModel + { + public string tuning_type; + public int tuning_table; + public int tuning_index; + public float value; + } +} diff --git a/server/FSO.Server.Api.Core/Models/FSOUpdateManifest.cs b/server/FSO.Server.Api.Core/Models/FSOUpdateManifest.cs new file mode 100755 index 0000000..40127fc --- /dev/null +++ b/server/FSO.Server.Api.Core/Models/FSOUpdateManifest.cs @@ -0,0 +1,10 @@ +using FSO.Files.Utils; +using System.Collections.Generic; + +namespace FSO.Server.Api.Core.Models +{ + public class FSOUpdateManifest { + public string Version; + public List Diffs; + } +} diff --git a/server/FSO.Server.Api.Core/Models/UpdateCreateModel.cs b/server/FSO.Server.Api.Core/Models/UpdateCreateModel.cs new file mode 100755 index 0000000..eb16ef4 --- /dev/null +++ b/server/FSO.Server.Api.Core/Models/UpdateCreateModel.cs @@ -0,0 +1,14 @@ +namespace FSO.Server.Api.Core.Models +{ + public class UpdateCreateModel + { + public int branchID; + public uint scheduledEpoch; + public string catalog; + + public bool contentOnly; + public bool includeMonogameDelta; + public bool disableIncremental; + public bool minorVersion; + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Models/UpdateGenerationStatus.cs b/server/FSO.Server.Api.Core/Models/UpdateGenerationStatus.cs new file mode 100755 index 0000000..c9e9f58 --- /dev/null +++ b/server/FSO.Server.Api.Core/Models/UpdateGenerationStatus.cs @@ -0,0 +1,69 @@ +using FSO.Server.Database.DA.Updates; + +namespace FSO.Server.Api.Core.Models +{ + public class UpdateGenerationStatus + { + public int TaskID; + public UpdateCreateModel Request; + public UpdateGenerationStatusCode Code; + public float EstimatedProgress; + + public DbUpdate Result; + public string Failure; + + public UpdateGenerationStatus(int taskID, UpdateCreateModel request) + { + TaskID = taskID; + Request = request; + } + + public void UpdateStatus(UpdateGenerationStatusCode code, float progress) + { + Code = code; + EstimatedProgress = progress; + } + + public void UpdateStatus(UpdateGenerationStatusCode code) + { + UpdateStatus(code, ((float)code - 1) / ((float)UpdateGenerationStatusCode.SUCCESS - 1)); + } + + public void SetResult(DbUpdate result) + { + UpdateStatus(UpdateGenerationStatusCode.SUCCESS); + Result = result; + } + + public void SetFailure(string failure) + { + UpdateStatus(UpdateGenerationStatusCode.FAILURE, 0); + Failure = failure; + } + } + + public enum UpdateGenerationStatusCode + { + FAILURE = 0, + + PREPARING = 1, + DOWNLOADING_CLIENT, + DOWNLOADING_SERVER, + DOWNLOADING_CLIENT_ADDON, + DOWNLOADING_SERVER_ADDON, + EXTRACTING_CLIENT, + EXTRACTING_CLIENT_ADDON, + BUILDING_DIFF, + BUILDING_INCREMENTAL_UPDATE, + BUILDING_CLIENT, + PUBLISHING_CLIENT, + + EXTRACTING_SERVER, + EXTRACTING_SERVER_ADDON, + BUILDING_SERVER, + PUBLISHING_SERVER, + + SCHEDULING_UPDATE, + SUCCESS + } +} diff --git a/server/FSO.Server.Api.Core/Program.cs b/server/FSO.Server.Api.Core/Program.cs new file mode 100755 index 0000000..4e8932f --- /dev/null +++ b/server/FSO.Server.Api.Core/Program.cs @@ -0,0 +1,53 @@ +using FSO.Server.Common; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; + +namespace FSO.Server.Api.Core +{ + public class Program + { + public static void Main(string[] args) + { + var host = CreateWebHostBuilder(args).Build(); + host.Run(); + } + + public static IAPILifetime RunAsync(string[] args) + { + var host = CreateWebHostBuilder(args).Build(); + var lifetime = new APIControl((IApplicationLifetime)host.Services.GetService(typeof(IApplicationLifetime))); + host.Start(); + return lifetime; + } + + public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseUrls(args[0]) + .ConfigureLogging(x => + { + x.SetMinimumLevel(LogLevel.None); + }) + .UseKestrel(options => + { + options.Limits.MaxRequestBodySize = 500000000; + }) + .SuppressStatusMessages(true) + .UseStartup(); + } + + public class APIControl : IAPILifetime + { + private IApplicationLifetime Lifetime; + + public APIControl(IApplicationLifetime lifetime) + { + Lifetime = lifetime; + } + + public void Stop() + { + Lifetime.StopApplication(); + } + } +} diff --git a/server/FSO.Server.Api.Core/Properties/launchSettings.json b/server/FSO.Server.Api.Core/Properties/launchSettings.json new file mode 100755 index 0000000..880a95e --- /dev/null +++ b/server/FSO.Server.Api.Core/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:61113", + "sslPort": 44333 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "api/values", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "FSO.Server.Api.Core": { + "commandName": "Project", + "launchBrowser": true, + "launchUrl": "api/values", + "applicationUrl": "https://localhost:5001;http://localhost:5000", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Services/AWSUpdateUploader.cs b/server/FSO.Server.Api.Core/Services/AWSUpdateUploader.cs new file mode 100755 index 0000000..a050a6c --- /dev/null +++ b/server/FSO.Server.Api.Core/Services/AWSUpdateUploader.cs @@ -0,0 +1,54 @@ +using Amazon; +using Amazon.Runtime; +using Amazon.S3; +using Amazon.S3.Model; +using FSO.Server.Common.Config; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace FSO.Server.Api.Core.Services +{ + public class AWSUpdateUploader : IUpdateUploader + { + private AWSConfig Config; + public AWSUpdateUploader(AWSConfig config) + { + Config = config; + } + + public async Task UploadFile(string destPath, string fileName, string groupName) + { + var region = Config.Region; + var bucket = Config.Bucket; + var s3config = new AmazonS3Config() + { + RegionEndpoint = RegionEndpoint.GetBySystemName(region), + Timeout = new TimeSpan(1, 0, 0), + ReadWriteTimeout = new TimeSpan(1, 0, 0), + MaxErrorRetry = 512 + }; + + using (var aws = new AmazonS3Client(new BasicAWSCredentials(Config.AccessKeyID, Config.SecretAccessKey), s3config)) + { + PutObjectRequest request = new PutObjectRequest() + { + InputStream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), + BucketName = bucket, + CannedACL = S3CannedACL.PublicRead, + Key = destPath + }; + PutObjectResponse response = await aws.PutObjectAsync(request); + + if (response.HttpStatusCode == System.Net.HttpStatusCode.OK) + { + return $"https://s3.{region}.amazonaws.com/{bucket}/" + destPath; + } + else + { + throw new Exception("Uploading file " + destPath + " failed with code " + response.HttpStatusCode + "!"); + } + } + } + } +} diff --git a/server/FSO.Server.Api.Core/Services/GenerateUpdateService.cs b/server/FSO.Server.Api.Core/Services/GenerateUpdateService.cs new file mode 100755 index 0000000..82240e7 --- /dev/null +++ b/server/FSO.Server.Api.Core/Services/GenerateUpdateService.cs @@ -0,0 +1,324 @@ +using FSO.Server.Api.Core.Models; +using FSO.Server.Database.DA.Updates; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using FSO.Files.Utils; +using FSO.Server.Common; +using System.Diagnostics; + +namespace FSO.Server.Api.Core.Services +{ + public class GenerateUpdateService + { + private static GenerateUpdateService _INSTANCE; + public static GenerateUpdateService INSTANCE + { + get + { + if (_INSTANCE == null) _INSTANCE = new GenerateUpdateService(); + return _INSTANCE; + } + } + + private int LastTaskID = 0; + public Dictionary Tasks = new Dictionary(); + + public UpdateGenerationStatus GetTask(int id) + { + UpdateGenerationStatus result; + lock (Tasks) + { + if (!Tasks.TryGetValue(id, out result)) return null; + } + return result; + } + + public UpdateGenerationStatus CreateTask(UpdateCreateModel request) + { + UpdateGenerationStatus task; + lock (Tasks) + { + task = new UpdateGenerationStatus(++LastTaskID, request); + Tasks[LastTaskID] = task; + } + Task.Run(() => BuildUpdate(task)); + return task; + } + + private void Exec(string cmd) + { + var escapedArgs = cmd.Replace("\"", "\\\""); + + var process = new Process + { + StartInfo = new ProcessStartInfo + { + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + FileName = "/bin/sh", + Arguments = $"-c \"{escapedArgs}\"" + } + }; + + process.Start(); + process.WaitForExit(); + } + + private void ClearFolderPermissions(string folder) + { + if (Environment.OSVersion.Platform == PlatformID.Unix) + Exec($"chmod -R 777 {folder}"); + } + + private string GetZipFolder(string path) + { + var directories = Directory.GetDirectories(path); + if (directories.Length != 1) return path; + var files = Directory.GetFiles(path); + if (files.Length != 0) return path; + return directories[0]; + } + + public async Task BuildUpdate(UpdateGenerationStatus status) + { + var request = status.Request; + var api = Api.INSTANCE; + + try + { + status.UpdateStatus(UpdateGenerationStatusCode.PREPARING); + using (var da = api.DAFactory.Get()) + { + var baseUpdateKey = "updates/"; + var branch = da.Updates.GetBranch(status.Request.branchID); + + //reserve update id. may cause race condition, but only one person can update anyways. + if (request.minorVersion) ++branch.minor_version_number; + else + { + ++branch.last_version_number; + branch.minor_version_number = 0; + } + var updateID = branch.last_version_number; + var minorChar = (branch.minor_version_number == 0) ? "" : ((char)('a' + (branch.minor_version_number - 1))).ToString(); + var versionName = branch.version_format.Replace("#", updateID.ToString()).Replace("@", minorChar); + var versionText = versionName; + + var result = new DbUpdate() + { + addon_id = branch.addon_id, + branch_id = branch.branch_id, + date = DateTime.UtcNow, + version_name = versionName, + deploy_after = Epoch.ToDate(status.Request.scheduledEpoch) + }; + + versionName = versionName.Replace('/', '-'); + + var client = new WebClient(); + //fetch artifacts + //http://servo.freeso.org/guestAuth/repository/download/FreeSO_TsoClient/.lastSuccessful/client-<>.zip + //http://servo.freeso.org/guestAuth/repository/download/FreeSO_TsoClient/.lastSuccessful/server-<>.zip + + int updateWorkID = status.TaskID; + + var updateDir = "updateTemp/" + updateWorkID + "/"; + try + { + Directory.Delete(updateDir, true); + } + catch (Exception) { } + Directory.CreateDirectory(updateDir); + Directory.CreateDirectory(updateDir + "client/"); + Directory.CreateDirectory(updateDir + "server/"); + + string clientArti = null; + string serverArti = null; + if (branch.base_build_url != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.DOWNLOADING_CLIENT); + await client.DownloadFileTaskAsync(new Uri(branch.base_build_url), updateDir + "client.zip"); + clientArti = updateDir + "client.zip"; + } + if (branch.base_server_build_url != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.DOWNLOADING_SERVER); + await client.DownloadFileTaskAsync(new Uri(branch.base_server_build_url), updateDir + "server.zip"); + serverArti = updateDir + "server.zip"; + } + + string clientAddon = null; + string serverAddon = null; + + if (branch.addon_id != null) + { + var addon = da.Updates.GetAddon(branch.addon_id.Value); + if (addon.addon_zip_url != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.DOWNLOADING_CLIENT_ADDON); + await client.DownloadFileTaskAsync(new Uri(addon.addon_zip_url), updateDir + "clientAddon.zip"); + clientAddon = updateDir + "clientAddon.zip"; + } + if (addon.server_zip_url != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.DOWNLOADING_SERVER_ADDON); + await client.DownloadFileTaskAsync(new Uri(addon.addon_zip_url), updateDir + "serverAddon.zip"); + serverAddon = updateDir + "serverAddon.zip"; + } + else + { + serverAddon = clientAddon; + } + } + + //last client update. + var previousUpdate = (branch.current_dist_id == null) ? null : da.Updates.GetUpdate(branch.current_dist_id.Value); + + //all files downloaded. build the folders. + //extract the artifact and then our artifact over it. + if (clientArti != null) + { + var clientPath = updateDir + "client/"; + status.UpdateStatus(UpdateGenerationStatusCode.EXTRACTING_CLIENT); + var clientZip = ZipFile.Open(clientArti, ZipArchiveMode.Read); + clientZip.ExtractToDirectory(clientPath, true); + clientZip.Dispose(); + File.Delete(clientArti); + clientPath = GetZipFolder(clientPath); + + if (clientAddon != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.EXTRACTING_CLIENT_ADDON); + var addonZip = ZipFile.Open(clientAddon, ZipArchiveMode.Read); + addonZip.ExtractToDirectory(clientPath, true); + addonZip.Dispose(); + if (clientAddon != serverAddon) File.Delete(clientAddon); + } + //emit version number + await System.IO.File.WriteAllTextAsync(Path.Combine(clientPath, "version.txt"), versionText); + if (request.catalog != null) + { + await System.IO.File.WriteAllTextAsync(Path.Combine(clientPath, "Content/Objects/catalog_downloads.xml"), request.catalog); + } + + string diffZip = null; + FSOUpdateManifest manifest = null; + + status.UpdateStatus(UpdateGenerationStatusCode.BUILDING_DIFF); + if (previousUpdate != null || request.disableIncremental) + { + result.last_update_id = previousUpdate.update_id; + //calculate difference, generate an incremental update manifest + zip + var prevFile = updateDir + "prev.zip"; + await client.DownloadFileTaskAsync(new Uri(previousUpdate.full_zip), updateDir + "prev.zip"); + var prevZip = ZipFile.Open(prevFile, ZipArchiveMode.Read); + prevZip.ExtractToDirectory(updateDir + "prev/", true); + prevZip.Dispose(); + File.Delete(updateDir + "prev.zip"); + + var diffs = DiffGenerator.GetDiffs(Path.GetFullPath(updateDir + "prev/"), Path.GetFullPath(clientPath)); + + status.UpdateStatus(UpdateGenerationStatusCode.BUILDING_INCREMENTAL_UPDATE); + var toZip = diffs.Where(x => x.DiffType == FileDiffType.Add || x.DiffType == FileDiffType.Modify); + if (request.contentOnly) toZip = toZip.Where(x => x.Path.Replace('\\', '/').TrimStart('/').StartsWith("Content")); + if (!request.includeMonogameDelta) toZip = toZip.Where(x => !x.Path.Replace('\\', '/').TrimStart('/').StartsWith("Monogame")); + //build diff folder + Directory.CreateDirectory(updateDir + "diff/"); + foreach (var diff in toZip) + { + Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(updateDir + "diff/", diff.Path))); + System.IO.File.Copy(Path.Combine(clientPath, diff.Path), Path.Combine(updateDir + "diff/", diff.Path)); + } + diffZip = updateDir + "diffResult.zip"; + ClearFolderPermissions(updateDir + "diff/"); + ZipFile.CreateFromDirectory(updateDir + "diff/", diffZip, CompressionLevel.Optimal, false); + Directory.Delete(updateDir + "diff/", true); + manifest = new FSOUpdateManifest() { Diffs = diffs }; + + Directory.Delete(updateDir + "prev/", true); + } + else + { + if (request.contentOnly) throw new Exception("Invalid request - you cannot make a content only update with no delta."); + //full update only. generate simple manifest that contains all files (added) + manifest = new FSOUpdateManifest() { Diffs = new List() }; + } + + //pack full client + if (!request.contentOnly) + { + status.UpdateStatus(UpdateGenerationStatusCode.BUILDING_CLIENT); + var finalClientZip = updateDir + "clientResult.zip"; + ClearFolderPermissions(clientPath); + ZipFile.CreateFromDirectory(clientPath, finalClientZip, CompressionLevel.Optimal, false); + Directory.Delete(updateDir + "client/", true); + + status.UpdateStatus(UpdateGenerationStatusCode.PUBLISHING_CLIENT); + result.full_zip = await Api.INSTANCE.UpdateUploaderClient.UploadFile($"{baseUpdateKey}client-{versionName}.zip", finalClientZip, versionName); + } + status.UpdateStatus(UpdateGenerationStatusCode.PUBLISHING_CLIENT); + if (diffZip != null) + { + result.incremental_zip = await Api.INSTANCE.UpdateUploaderClient.UploadFile($"{baseUpdateKey}incremental-{versionName}.zip", diffZip, versionName); + } + await System.IO.File.WriteAllTextAsync(updateDir + "manifest.json", Newtonsoft.Json.JsonConvert.SerializeObject(manifest)); + result.manifest_url = await Api.INSTANCE.UpdateUploaderClient.UploadFile($"{baseUpdateKey}{versionName}.json", updateDir + "manifest.json", versionName); + } + + if (serverArti != null && !request.contentOnly) + { + var serverPath = updateDir + "server/"; + status.UpdateStatus(UpdateGenerationStatusCode.EXTRACTING_SERVER); + var serverZip = ZipFile.Open(serverArti, ZipArchiveMode.Read); + serverZip.ExtractToDirectory(serverPath, true); + serverZip.Dispose(); + File.Delete(serverArti); + serverPath = GetZipFolder(serverPath); + + if (serverAddon != null) + { + status.UpdateStatus(UpdateGenerationStatusCode.EXTRACTING_SERVER_ADDON); + var addonZip = ZipFile.Open(serverAddon, ZipArchiveMode.Read); + addonZip.ExtractToDirectory(serverPath, true); + addonZip.Dispose(); + File.Delete(serverAddon); + } + //emit version number + await System.IO.File.WriteAllTextAsync(Path.Combine(serverPath, "version.txt"), versionText); + if (request.catalog != null) + { + await System.IO.File.WriteAllTextAsync(Path.Combine(serverPath, "Content/Objects/catalog_downloads.xml"), request.catalog); + } + + status.UpdateStatus(UpdateGenerationStatusCode.BUILDING_SERVER); + var finalServerZip = updateDir + "serverResult.zip"; + ClearFolderPermissions(serverPath); + ZipFile.CreateFromDirectory(serverPath, finalServerZip, CompressionLevel.Optimal, false); + Directory.Delete(updateDir + "server/", true); + + status.UpdateStatus(UpdateGenerationStatusCode.PUBLISHING_SERVER); + result.server_zip = await Api.INSTANCE.UpdateUploader.UploadFile($"{baseUpdateKey}server-{versionName}.zip", finalServerZip, versionName); + } else + { + result.server_zip = result.incremental_zip; //same as client, as server uses same content. + } + + status.UpdateStatus(UpdateGenerationStatusCode.SCHEDULING_UPDATE); + var finalID = da.Updates.AddUpdate(result); + da.Updates.UpdateBranchLatest(branch.branch_id, branch.last_version_number, branch.minor_version_number); + status.SetResult(result); + } + } catch (Exception e) + { + status.SetFailure("Update could not be completed." + e.ToString()); + } + } + } +} diff --git a/server/FSO.Server.Api.Core/Services/GithubUpdateUploader.cs b/server/FSO.Server.Api.Core/Services/GithubUpdateUploader.cs new file mode 100755 index 0000000..4303d81 --- /dev/null +++ b/server/FSO.Server.Api.Core/Services/GithubUpdateUploader.cs @@ -0,0 +1,61 @@ +using FSO.Server.Common.Config; +using Octokit; +using Octokit.Internal; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace FSO.Server.Api.Core.Services +{ + public class GithubUpdateUploader : IUpdateUploader + { + private GithubConfig Config; + + private static string Description = "This is an automated client release produced by the master FreeSO server. " + + "These releases match up with a branch on GitHub, but with some addon content such as a custom catalog and splash. " + + "It can be downloaded and installed directly, but it is better to do so through the game's launcher/updater. \n\n" + + "The incremental update is applied by simply extracting the zip over the previous version of the game " + + "(though the updater still affords extra validation here)"; + + public GithubUpdateUploader(GithubConfig config) + { + Config = config; + } + + public async Task UploadFile(string destPath, string fileName, string groupName) + { + destPath = Path.GetFileName(destPath); + var credentials = new InMemoryCredentialStore(new Credentials(Config.AccessToken)); + + var client = new GitHubClient(new ProductHeaderValue(Config.AppName), credentials); + + Release release; + try + { + release = await client.Repository.Release.Get(Config.User, Config.Repository, groupName); + } + catch (Exception) + { + release = null; + } + if (release == null) { + var newRel = new NewRelease(groupName); + newRel.Body = Description; + release = await client.Repository.Release.Create(Config.User, Config.Repository, newRel); + } + + using (var file = File.Open(fileName, System.IO.FileMode.Open, FileAccess.Read, FileShare.Read)) { + try + { + var asset = await client.Repository.Release.UploadAsset(release, new ReleaseAssetUpload(destPath, "application/zip", file, null)); + return asset.BrowserDownloadUrl; + } catch (Exception e) + { + //last time i tried, it mysteriously failed here but the file was uploaded :thinking: + Console.WriteLine($"!! Upload request for {destPath} failed, check it actually succeeded !! \n" + e.ToString()); + return $"https://github.com/{Config.User}/{Config.Repository}/releases/download/{groupName}/{destPath}"; + } + } + } + } +} diff --git a/server/FSO.Server.Api.Core/Services/IUpdateUploader.cs b/server/FSO.Server.Api.Core/Services/IUpdateUploader.cs new file mode 100755 index 0000000..20554ba --- /dev/null +++ b/server/FSO.Server.Api.Core/Services/IUpdateUploader.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; + +namespace FSO.Server.Api.Core.Services +{ + public interface IUpdateUploader + { + Task UploadFile(string destPath, string fileName, string groupName); + } +} diff --git a/server/FSO.Server.Api.Core/Startup.cs b/server/FSO.Server.Api.Core/Startup.cs new file mode 100755 index 0000000..ccc01fa --- /dev/null +++ b/server/FSO.Server.Api.Core/Startup.cs @@ -0,0 +1,63 @@ +using FSO.Server.Common; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace FSO.Server.Api.Core +{ + public class Startup : IAPILifetime + { + public IApplicationLifetime AppLifetime; + + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + + public IConfiguration Configuration { get; } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddCors(options => + { + options.AddDefaultPolicy( + builder => + { + + builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("content-disposition"); + }); + + options.AddPolicy("AdminAppPolicy", + builder => + { + builder.WithOrigins("https://freeso.org", "http://localhost:8080").AllowAnyMethod().AllowAnyHeader().AllowCredentials().WithExposedHeaders("content-disposition"); + }); + }).AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseHsts(); + } + app.UseCors(); + //app.UseHttpsRedirection(); + app.UseMvc(); + AppLifetime = appLifetime; + } + + public void Stop() + { + AppLifetime.StopApplication(); + } + } +} diff --git a/server/FSO.Server.Api.Core/Utils/ApiMail.cs b/server/FSO.Server.Api.Core/Utils/ApiMail.cs new file mode 100755 index 0000000..d7c2166 --- /dev/null +++ b/server/FSO.Server.Api.Core/Utils/ApiMail.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Net.Mail; + +namespace FSO.Server.Api.Core.Utils +{ + /// + /// Used to mail our users. + /// Could be more useful in the future when out of Beta. + /// + public class ApiMail + { + string subject; + string template; + Dictionary strings; + + public ApiMail(string template) + { + this.template = template; + this.strings = new Dictionary(); + } + + public void AddString(string key, string value) + { + strings.Add(key, value); + } + + private string ComposeBody(Dictionary strings) + { + string baseTemplate = File.ReadAllText("./MailTemplates/MailBase.html"); + string content = File.ReadAllText("./MailTemplates/" + template + ".html"); + + foreach (KeyValuePair entry in strings) + { + content = content.Replace("%" + entry.Key + "%", entry.Value); + } + + strings = new Dictionary(); + return baseTemplate.Replace("%content%", content); + } + + public bool Send(string to, string subject) + { + Api api = Api.INSTANCE; + + if(api.Config.SmtpEnabled) + { + try + { + MailMessage message = new MailMessage(); + message.From = new MailAddress(api.Config.SmtpUser, "FreeSO Staff"); + message.To.Add(to); + message.Subject = subject; + message.IsBodyHtml = true; + message.Body = ComposeBody(strings); + + SmtpClient client = new SmtpClient(); + client.UseDefaultCredentials = true; + + client.Host = api.Config.SmtpHost; + client.Port = api.Config.SmtpPort; + client.EnableSsl = true; + client.Credentials = new System.Net.NetworkCredential(api.Config.SmtpUser, api.Config.SmtpPassword); + + // Send async + client.SendMailAsync(message); + + return true; + } catch(Exception e) { + return false; + } + } + return false; + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Utils/ApiResponse.cs b/server/FSO.Server.Api.Core/Utils/ApiResponse.cs new file mode 100755 index 0000000..51e2374 --- /dev/null +++ b/server/FSO.Server.Api.Core/Utils/ApiResponse.cs @@ -0,0 +1,78 @@ +using FSO.Common.Utils; +using FSO.Server.Database.DA.Utils; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; +using System.Net; +using System.Xml; + +namespace FSO.Server.Api.Core.Utils +{ + public class ApiResponse + { + public static IActionResult Plain(HttpStatusCode code, string text) + { + return new ContentResult + { + StatusCode = (int)code, + Content = text, + ContentType = "text/plain" + }; + } + + public static IActionResult Json(HttpStatusCode code, object obj) + { + return new ContentResult + { + StatusCode = (int)code, + Content = Newtonsoft.Json.JsonConvert.SerializeObject(obj), + ContentType = "application/json" + }; + } + + public static IActionResult PagedList(HttpRequest request, HttpStatusCode code, PagedList list) + { + request.HttpContext.Response.Headers.Add("X-Total-Count", list.Total.ToString()); + request.HttpContext.Response.Headers.Add("X-Offset", list.Offset.ToString()); + + return new ContentResult + { + StatusCode = (int)code, + Content = Newtonsoft.Json.JsonConvert.SerializeObject(list), + ContentType = "application/json" + }; + } + + public static IActionResult Xml(HttpStatusCode code, IXMLEntity xml) + { + var doc = new XmlDocument(); + var firstChild = xml.Serialize(doc); + doc.AppendChild(firstChild); + + return new ContentResult + { + StatusCode = (int)code, + Content = doc.OuterXml, + ContentType = "text/xml" + }; + } + + public static Func XmlFuture(HttpStatusCode code, IXMLEntity xml) + { + var doc = new XmlDocument(); + var firstChild = xml.Serialize(doc); + doc.AppendChild(firstChild); + var serialized = doc.OuterXml; + + return () => + { + return new ContentResult + { + StatusCode = (int)code, + Content = serialized, + ContentType = "text/xml" + }; + }; + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/Utils/ApiUtils.cs b/server/FSO.Server.Api.Core/Utils/ApiUtils.cs new file mode 100755 index 0000000..4ab24c3 --- /dev/null +++ b/server/FSO.Server.Api.Core/Utils/ApiUtils.cs @@ -0,0 +1,35 @@ +using Microsoft.AspNetCore.Http; +using System.Linq; + +namespace FSO.Server.Api.Core.Utils +{ + public class ApiUtils + { + private const string HttpContext = "MS_HttpContext"; + private const string RemoteEndpointMessage = + "System.ServiceModel.Channels.RemoteEndpointMessageProperty"; + private const string OwinContext = "MS_OwinContext"; + + public static string GetIP(HttpRequest request) + { + var api = FSO.Server.Api.Core.Api.INSTANCE; + if (!api.Config.UseProxy) + { + return request.HttpContext.Connection.RemoteIpAddress.ToString(); + } + else + { + var ip = "127.0.0.1"; + var xff = request.Headers["X-Forwarded-For"]; + if (xff.Count != 0) + { + ip = xff.First(); + ip = ip.Substring(ip.IndexOf(",") + 1); + var last = ip.LastIndexOf(":"); + if (last != -1 && last < ip.Length - 5) ip = ip.Substring(0, last); + } + return ip; + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/appsettings.Development.json b/server/FSO.Server.Api.Core/appsettings.Development.json new file mode 100755 index 0000000..e203e94 --- /dev/null +++ b/server/FSO.Server.Api.Core/appsettings.Development.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Debug", + "System": "Information", + "Microsoft": "Information" + } + } +} diff --git a/server/FSO.Server.Api.Core/appsettings.json b/server/FSO.Server.Api.Core/appsettings.json new file mode 100755 index 0000000..def9159 --- /dev/null +++ b/server/FSO.Server.Api.Core/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/.NETCoreApp,Version=v2.2.AssemblyAttributes.cs b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/.NETCoreApp,Version=v2.2.AssemblyAttributes.cs new file mode 100644 index 0000000..5f4abba --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/.NETCoreApp,Version=v2.2.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v2.2", FrameworkDisplayName = ".NET Core 2.2")] diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfo.cs b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfo.cs new file mode 100644 index 0000000..2988283 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfo.cs @@ -0,0 +1,22 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("FSO.Server.Api.Core")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+f12ba1502b1a207b2b7e131c8ed38d8d4ef33d1e")] +[assembly: System.Reflection.AssemblyProductAttribute("FSO.Server.Api.Core")] +[assembly: System.Reflection.AssemblyTitleAttribute("FSO.Server.Api.Core")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfoInputs.cache b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfoInputs.cache new file mode 100644 index 0000000..ab49367 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +56295aa1e4d64bef744bb30e9641d816d4a2f240e548daea26ca3acc11acdbfc diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.GeneratedMSBuildEditorConfig.editorconfig b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 0000000..96e9427 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,5 @@ +is_global = true +build_property.RootNamespace = FSO.Server.Api.Core +build_property.ProjectDir = /Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cache b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cache new file mode 100644 index 0000000..0bcbefa --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cache @@ -0,0 +1 @@ +96ad7024ec164a21bac08e2efe1079153c67c90031478db2e40a71ebb48e40d6 diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cs b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cs new file mode 100644 index 0000000..e4b50b8 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.RazorAssemblyInfo.cs @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute("FSO.Server.Api.Core.Views")] +[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute("2.1")] +[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute("MVC-2.1")] +[assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute("MVC-2.1", "Microsoft.AspNetCore.Mvc.Razor.Extensions")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.assets.cache b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.assets.cache new file mode 100644 index 0000000..b5d3d60 Binary files /dev/null and b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.assets.cache differ diff --git a/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.csproj.AssemblyReference.cache b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.csproj.AssemblyReference.cache new file mode 100644 index 0000000..e252db7 Binary files /dev/null and b/server/FSO.Server.Api.Core/obj/Debug/netcoreapp2.2/FSO.Server.Api.Core.csproj.AssemblyReference.cache differ diff --git a/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.dgspec.json b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.dgspec.json new file mode 100644 index 0000000..8f11d2d --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.dgspec.json @@ -0,0 +1,267 @@ +{ + "format": 1, + "restore": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj": {} + }, + "projects": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj", + "projectName": "FSO.Server.Api.Core", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "outputPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "netcoreapp2.2" + ], + "sources": { + "/Volumes/TheD/.dotnet/library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netcoreapp2.2": { + "targetAlias": "netcoreapp2.2", + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + } + }, + "frameworks": { + "netcoreapp2.2": { + "targetAlias": "netcoreapp2.2", + "dependencies": { + "AWSSDK.Core": { + "target": "Package", + "version": "[3.3.103.48, )" + }, + "AWSSDK.S3": { + "target": "Package", + "version": "[3.3.104.36, )" + }, + "Microsoft.AspNetCore.All": { + "target": "Package", + "version": "[2.2.7, )" + }, + "Microsoft.AspNetCore.App": { + "suppressParent": "All", + "target": "Package", + "version": "[2.2.8, )", + "autoReferenced": true + }, + "Microsoft.AspNetCore.Cors": { + "target": "Package", + "version": "[2.2.0, )" + }, + "Microsoft.NETCore.App": { + "suppressParent": "All", + "target": "Package", + "version": "[2.2.8, )", + "autoReferenced": true + }, + "Octokit": { + "target": "Package", + "version": "[0.36.0, )" + }, + "System.Security.Cryptography.Algorithms": { + "target": "Package", + "version": "[4.3.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "/Volumes/TheD/.dotnet/sdk/8.0.204/RuntimeIdentifierGraph.json" + } + } + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj", + "projectName": "FSO.Server.Common", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "projectStyle": "PackagesConfig", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net45": { + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "packagesConfigPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/packages.config" + }, + "frameworks": { + "net45": {} + } + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj": { + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj", + "projectName": "FSO.Server.Database", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "projectStyle": "PackagesConfig", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net45": { + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "packagesConfigPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/packages.config" + }, + "frameworks": { + "net45": {} + } + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj": { + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj", + "projectName": "FSO.Server.Domain", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "projectStyle": "PackagesConfig", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net45": { + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "packagesConfigPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/packages.config" + }, + "frameworks": { + "net45": {} + } + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj": { + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj", + "projectName": "FSO.Server.Protocol", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "projectStyle": "PackagesConfig", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net45": { + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "packagesConfigPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/packages.config" + }, + "frameworks": { + "net45": {} + } + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj", + "projectName": "FSO.Common", + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "projectStyle": "PackagesConfig", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "sources": { + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "net45": { + "projectReferences": {} + } + }, + "packagesConfigPath": "/Volumes/TheD/Projects/ztso/server/tso.common/packages.config" + }, + "frameworks": { + "net45": {} + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.props b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.props new file mode 100644 index 0000000..640b626 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.props @@ -0,0 +1,32 @@ + + + + True + NuGet + $(MSBuildThisFileDirectory)project.assets.json + /Volumes/TheD/.nuget + /Volumes/TheD/.nuget + PackageReference + 6.9.1 + + + + + + + + + + + + + + + + /Volumes/TheD/.nuget/microsoft.entityframeworkcore.tools/2.2.6 + /Volumes/TheD/.nuget/microsoft.codeanalysis.analyzers/1.1.0 + /Volumes/TheD/.nuget/microsoft.aspnetcore.razor.design/2.2.0 + /Volumes/TheD/.nuget/awssdk.core/3.3.103.48 + /Volumes/TheD/.nuget/awssdk.s3/3.3.104.36 + + \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.targets b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.targets new file mode 100644 index 0000000..de77cea --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/FSO.Server.Api.Core.csproj.nuget.g.targets @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/obj/project.assets.json b/server/FSO.Server.Api.Core/obj/project.assets.json new file mode 100644 index 0000000..abf8b5b --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/project.assets.json @@ -0,0 +1,16011 @@ +{ + "version": 3, + "targets": { + ".NETCoreApp,Version=v2.2": { + "AWSSDK.Core/3.3.103.48": { + "type": "package", + "compile": { + "lib/netstandard2.0/AWSSDK.Core.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/AWSSDK.Core.dll": { + "related": ".pdb;.xml" + } + } + }, + "AWSSDK.S3/3.3.104.36": { + "type": "package", + "dependencies": { + "AWSSDK.Core": "[3.3.103.48, 3.4.0)" + }, + "compile": { + "lib/netstandard2.0/AWSSDK.S3.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/AWSSDK.S3.dll": { + "related": ".pdb;.xml" + } + } + }, + "Libuv/1.10.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1" + }, + "runtimeTargets": { + "runtimes/linux-arm/native/libuv.so": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/libuv.so": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-armel/native/libuv.so": { + "assetType": "native", + "rid": "linux-armel" + }, + "runtimes/linux-x64/native/libuv.so": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/osx/native/libuv.dylib": { + "assetType": "native", + "rid": "osx" + }, + "runtimes/win-arm/native/libuv.dll": { + "assetType": "native", + "rid": "win-arm" + }, + "runtimes/win-x64/native/libuv.dll": { + "assetType": "native", + "rid": "win-x64" + }, + "runtimes/win-x86/native/libuv.dll": { + "assetType": "native", + "rid": "win-x86" + } + } + }, + "MessagePack/1.7.3.7": { + "type": "package", + "dependencies": { + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0", + "System.ValueTuple": "4.3.0" + }, + "compile": { + "lib/netstandard2.0/MessagePack.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/MessagePack.dll": { + "related": ".xml" + } + } + }, + "Microsoft.ApplicationInsights/2.4.0": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Diagnostics.DiagnosticSource": "4.4.0", + "System.Diagnostics.StackTrace": "4.3.0" + }, + "compile": { + "lib/netstandard1.3/Microsoft.ApplicationInsights.dll": { + "related": ".XML" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.ApplicationInsights.dll": { + "related": ".XML" + } + } + }, + "Microsoft.ApplicationInsights.AspNetCore/2.1.1": { + "type": "package", + "dependencies": { + "Microsoft.ApplicationInsights": "2.4.0", + "Microsoft.ApplicationInsights.DependencyCollector": "2.4.1", + "Microsoft.AspNetCore.Hosting": "1.0.0", + "Microsoft.Extensions.Configuration": "1.0.0", + "Microsoft.Extensions.Configuration.Json": "1.0.0", + "Microsoft.Extensions.DiagnosticAdapter": "1.0.0", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0", + "NETStandard.Library": "1.6.1", + "System.Net.NameResolution": "4.3.0", + "System.Text.Encodings.Web": "4.3.1" + }, + "compile": { + "lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.dll": { + "related": ".xml" + } + } + }, + "Microsoft.ApplicationInsights.DependencyCollector/2.4.1": { + "type": "package", + "dependencies": { + "Microsoft.ApplicationInsights": "[2.4.0]", + "Microsoft.Extensions.PlatformAbstractions": "1.1.0", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.DiagnosticSource": "4.4.0", + "System.Diagnostics.StackTrace": "4.3.0" + }, + "compile": { + "lib/netstandard1.6/Microsoft.AI.DependencyCollector.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.6/Microsoft.AI.DependencyCollector.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNet.WebApi.Client/5.2.6": { + "type": "package", + "dependencies": { + "Newtonsoft.Json": "10.0.1", + "Newtonsoft.Json.Bson": "1.0.1" + }, + "compile": { + "lib/netstandard2.0/System.Net.Http.Formatting.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Net.Http.Formatting.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Diagnostics": "2.2.0", + "Microsoft.AspNetCore.HostFiltering": "2.2.0", + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.AspNetCore.Routing": "2.2.0", + "Microsoft.AspNetCore.Server.IIS": "2.2.0", + "Microsoft.AspNetCore.Server.IISIntegration": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Https": "2.2.0", + "Microsoft.Extensions.Configuration.CommandLine": "2.2.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "2.2.0", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0", + "Microsoft.Extensions.Configuration.Json": "2.2.0", + "Microsoft.Extensions.Configuration.UserSecrets": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Logging.Configuration": "2.2.0", + "Microsoft.Extensions.Logging.Console": "2.2.0", + "Microsoft.Extensions.Logging.Debug": "2.2.0", + "Microsoft.Extensions.Logging.EventSource": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.All/2.2.7": { + "type": "package", + "dependencies": { + "Microsoft.AspNet.WebApi.Client": "5.2.6", + "Microsoft.AspNetCore": "2.2.0", + "Microsoft.AspNetCore.Antiforgery": "2.2.0", + "Microsoft.AspNetCore.ApplicationInsights.HostingStartup": "2.2.0", + "Microsoft.AspNetCore.Authentication": "2.2.0", + "Microsoft.AspNetCore.Authentication.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Authentication.Cookies": "2.2.0", + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.Authentication.Facebook": "2.2.0", + "Microsoft.AspNetCore.Authentication.Google": "2.2.2", + "Microsoft.AspNetCore.Authentication.JwtBearer": "2.2.0", + "Microsoft.AspNetCore.Authentication.MicrosoftAccount": "2.2.0", + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "2.2.0", + "Microsoft.AspNetCore.Authentication.Twitter": "2.2.0", + "Microsoft.AspNetCore.Authentication.WsFederation": "2.2.0", + "Microsoft.AspNetCore.Authorization": "2.2.0", + "Microsoft.AspNetCore.Authorization.Policy": "2.2.0", + "Microsoft.AspNetCore.AzureAppServices.HostingStartup": "2.2.5", + "Microsoft.AspNetCore.AzureAppServicesIntegration": "2.2.5", + "Microsoft.AspNetCore.Connections.Abstractions": "2.2.0", + "Microsoft.AspNetCore.CookiePolicy": "2.2.0", + "Microsoft.AspNetCore.Cors": "2.2.0", + "Microsoft.AspNetCore.Cryptography.Internal": "2.2.0", + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "2.2.0", + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.2.0", + "Microsoft.AspNetCore.DataProtection.AzureKeyVault": "2.2.0", + "Microsoft.AspNetCore.DataProtection.AzureStorage": "2.2.7", + "Microsoft.AspNetCore.DataProtection.Extensions": "2.2.0", + "Microsoft.AspNetCore.Diagnostics": "2.2.0", + "Microsoft.AspNetCore.Diagnostics.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "2.2.1", + "Microsoft.AspNetCore.Diagnostics.HealthChecks": "2.2.0", + "Microsoft.AspNetCore.HostFiltering": "2.2.0", + "Microsoft.AspNetCore.Hosting": "2.2.7", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.2", + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Connections": "1.1.0", + "Microsoft.AspNetCore.Http.Connections.Common": "1.1.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.Http.Features": "2.2.0", + "Microsoft.AspNetCore.HttpOverrides": "2.2.0", + "Microsoft.AspNetCore.HttpsPolicy": "2.2.0", + "Microsoft.AspNetCore.Identity": "2.2.0", + "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "2.2.0", + "Microsoft.AspNetCore.Identity.UI": "2.2.5", + "Microsoft.AspNetCore.JsonPatch": "2.2.0", + "Microsoft.AspNetCore.Localization": "2.2.0", + "Microsoft.AspNetCore.Localization.Routing": "2.2.0", + "Microsoft.AspNetCore.MiddlewareAnalysis": "2.2.0", + "Microsoft.AspNetCore.Mvc": "2.2.0", + "Microsoft.AspNetCore.Mvc.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Mvc.Analyzers": "2.2.0", + "Microsoft.AspNetCore.Mvc.ApiExplorer": "2.2.0", + "Microsoft.AspNetCore.Mvc.Core": "2.2.5", + "Microsoft.AspNetCore.Mvc.Cors": "2.2.0", + "Microsoft.AspNetCore.Mvc.DataAnnotations": "2.2.0", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "2.2.0", + "Microsoft.AspNetCore.Mvc.Formatters.Xml": "2.2.0", + "Microsoft.AspNetCore.Mvc.Localization": "2.2.0", + "Microsoft.AspNetCore.Mvc.Razor": "2.2.0", + "Microsoft.AspNetCore.Mvc.Razor.Extensions": "2.2.0", + "Microsoft.AspNetCore.Mvc.Razor.ViewCompilation": "2.2.0", + "Microsoft.AspNetCore.Mvc.RazorPages": "2.2.5", + "Microsoft.AspNetCore.Mvc.TagHelpers": "2.2.0", + "Microsoft.AspNetCore.Mvc.ViewFeatures": "2.2.0", + "Microsoft.AspNetCore.NodeServices": "2.2.0", + "Microsoft.AspNetCore.Owin": "2.2.0", + "Microsoft.AspNetCore.Razor": "2.2.0", + "Microsoft.AspNetCore.Razor.Design": "2.2.0", + "Microsoft.AspNetCore.Razor.Language": "2.2.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.AspNetCore.ResponseCaching": "2.2.0", + "Microsoft.AspNetCore.ResponseCaching.Abstractions": "2.2.0", + "Microsoft.AspNetCore.ResponseCompression": "2.2.0", + "Microsoft.AspNetCore.Rewrite": "2.2.0", + "Microsoft.AspNetCore.Routing": "2.2.2", + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Server.HttpSys": "2.2.6", + "Microsoft.AspNetCore.Server.IIS": "2.2.6", + "Microsoft.AspNetCore.Server.IISIntegration": "2.2.1", + "Microsoft.AspNetCore.Server.Kestrel": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Core": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Https": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets": "2.2.1", + "Microsoft.AspNetCore.Session": "2.2.0", + "Microsoft.AspNetCore.SignalR": "1.1.0", + "Microsoft.AspNetCore.SignalR.Common": "1.1.0", + "Microsoft.AspNetCore.SignalR.Core": "1.1.0", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "1.1.0", + "Microsoft.AspNetCore.SignalR.Redis": "1.1.5", + "Microsoft.AspNetCore.SpaServices": "2.2.7", + "Microsoft.AspNetCore.SpaServices.Extensions": "2.2.0", + "Microsoft.AspNetCore.StaticFiles": "2.2.0", + "Microsoft.AspNetCore.WebSockets": "2.2.1", + "Microsoft.AspNetCore.WebUtilities": "2.2.0", + "Microsoft.CodeAnalysis.Razor": "2.2.0", + "Microsoft.Data.Sqlite": "2.2.6", + "Microsoft.Data.Sqlite.Core": "2.2.6", + "Microsoft.EntityFrameworkCore": "2.2.6", + "Microsoft.EntityFrameworkCore.Abstractions": "2.2.6", + "Microsoft.EntityFrameworkCore.Analyzers": "2.2.6", + "Microsoft.EntityFrameworkCore.Design": "2.2.6", + "Microsoft.EntityFrameworkCore.InMemory": "2.2.6", + "Microsoft.EntityFrameworkCore.Relational": "2.2.6", + "Microsoft.EntityFrameworkCore.SqlServer": "2.2.6", + "Microsoft.EntityFrameworkCore.Sqlite": "2.2.6", + "Microsoft.EntityFrameworkCore.Sqlite.Core": "2.2.6", + "Microsoft.EntityFrameworkCore.Tools": "2.2.6", + "Microsoft.Extensions.Caching.Abstractions": "2.2.0", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.Caching.Redis": "2.2.0", + "Microsoft.Extensions.Caching.SqlServer": "2.2.0", + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.Configuration.AzureKeyVault": "2.2.0", + "Microsoft.Extensions.Configuration.Binder": "2.2.4", + "Microsoft.Extensions.Configuration.CommandLine": "2.2.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "2.2.4", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0", + "Microsoft.Extensions.Configuration.Ini": "2.2.0", + "Microsoft.Extensions.Configuration.Json": "2.2.0", + "Microsoft.Extensions.Configuration.KeyPerFile": "2.2.4", + "Microsoft.Extensions.Configuration.UserSecrets": "2.2.0", + "Microsoft.Extensions.Configuration.Xml": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.DiagnosticAdapter": "2.2.0", + "Microsoft.Extensions.Diagnostics.HealthChecks": "2.2.5", + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "2.2.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.FileProviders.Composite": "2.2.0", + "Microsoft.Extensions.FileProviders.Embedded": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0", + "Microsoft.Extensions.FileSystemGlobbing": "2.2.0", + "Microsoft.Extensions.Hosting": "2.2.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Http": "2.2.0", + "Microsoft.Extensions.Identity.Core": "2.2.0", + "Microsoft.Extensions.Identity.Stores": "2.2.0", + "Microsoft.Extensions.Localization": "2.2.0", + "Microsoft.Extensions.Localization.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.AzureAppServices": "2.2.5", + "Microsoft.Extensions.Logging.Configuration": "2.2.0", + "Microsoft.Extensions.Logging.Console": "2.2.0", + "Microsoft.Extensions.Logging.Debug": "2.2.0", + "Microsoft.Extensions.Logging.EventSource": "2.2.0", + "Microsoft.Extensions.Logging.TraceSource": "2.2.0", + "Microsoft.Extensions.ObjectPool": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.2.0", + "Microsoft.Extensions.Options.DataAnnotations": "2.2.0", + "Microsoft.Extensions.Primitives": "2.2.0", + "Microsoft.Extensions.WebEncoders": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0", + "Microsoft.VisualStudio.Web.BrowserLink": "2.2.0", + "System.IO.Pipelines": "4.5.3" + }, + "compile": { + "lib/netcoreapp2.2/_._": {} + }, + "runtime": { + "lib/netcoreapp2.2/_._": {} + }, + "build": { + "build/netcoreapp2.2/Microsoft.AspNetCore.All.props": {}, + "build/netcoreapp2.2/Microsoft.AspNetCore.All.targets": {} + } + }, + "Microsoft.AspNetCore.Antiforgery/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.WebUtilities": "2.2.0", + "Microsoft.Extensions.ObjectPool": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Antiforgery.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Antiforgery.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.App/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.AspNet.WebApi.Client": "[5.2.6, 5.3.0)", + "Microsoft.AspNetCore": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Antiforgery": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Cookies": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Core": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Facebook": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Google": "[2.2.2, 2.3.0)", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.MicrosoftAccount": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.OAuth": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.Twitter": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authentication.WsFederation": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authorization": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Authorization.Policy": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Connections.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.CookiePolicy": "[2.2.8, 2.3.0)", + "Microsoft.AspNetCore.Cors": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Cryptography.Internal": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.DataProtection": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.DataProtection.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.DataProtection.Extensions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Diagnostics": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Diagnostics.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "[2.2.1, 2.3.0)", + "Microsoft.AspNetCore.Diagnostics.HealthChecks": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.HostFiltering": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Hosting": "[2.2.7, 2.3.0)", + "Microsoft.AspNetCore.Hosting.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Html.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Http": "[2.2.2, 2.3.0)", + "Microsoft.AspNetCore.Http.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Http.Connections": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.Http.Connections.Common": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.Http.Extensions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Http.Features": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.HttpOverrides": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.HttpsPolicy": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Identity": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Identity.UI": "[2.2.5, 2.3.0)", + "Microsoft.AspNetCore.JsonPatch": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Localization": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Localization.Routing": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.MiddlewareAnalysis": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Analyzers": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.ApiExplorer": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Core": "[2.2.5, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Cors": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.DataAnnotations": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Formatters.Xml": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Localization": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Razor": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Razor.Extensions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.Razor.ViewCompilation": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.RazorPages": "[2.2.5, 2.3.0)", + "Microsoft.AspNetCore.Mvc.TagHelpers": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Mvc.ViewFeatures": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.NodeServices": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Owin": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Razor": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Razor.Design": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Razor.Language": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Razor.Runtime": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.ResponseCaching": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.ResponseCaching.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.ResponseCompression": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Rewrite": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Routing": "[2.2.2, 2.3.0)", + "Microsoft.AspNetCore.Routing.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Server.HttpSys": "[2.2.6, 2.3.0)", + "Microsoft.AspNetCore.Server.IIS": "[2.2.6, 2.3.0)", + "Microsoft.AspNetCore.Server.IISIntegration": "[2.2.1, 2.3.0)", + "Microsoft.AspNetCore.Server.Kestrel": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Server.Kestrel.Core": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Server.Kestrel.Https": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets": "[2.2.1, 2.3.0)", + "Microsoft.AspNetCore.Session": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.SignalR": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.SignalR.Common": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.SignalR.Core": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "[1.1.0, 1.2.0)", + "Microsoft.AspNetCore.SpaServices": "[2.2.7, 2.3.0)", + "Microsoft.AspNetCore.SpaServices.Extensions": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.StaticFiles": "[2.2.0, 2.3.0)", + "Microsoft.AspNetCore.WebSockets": "[2.2.1, 2.3.0)", + "Microsoft.AspNetCore.WebUtilities": "[2.2.0, 2.3.0)", + "Microsoft.CodeAnalysis.Razor": "[2.2.0, 2.3.0)", + "Microsoft.EntityFrameworkCore": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.Abstractions": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.Analyzers": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.Design": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.InMemory": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.Relational": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.SqlServer": "[2.2.6, 2.3.0)", + "Microsoft.EntityFrameworkCore.Tools": "[2.2.6, 2.3.0)", + "Microsoft.Extensions.Caching.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Caching.Memory": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Caching.SqlServer": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.Binder": "[2.2.4, 2.3.0)", + "Microsoft.Extensions.Configuration.CommandLine": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[2.2.4, 2.3.0)", + "Microsoft.Extensions.Configuration.FileExtensions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.Ini": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.Json": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.KeyPerFile": "[2.2.4, 2.3.0)", + "Microsoft.Extensions.Configuration.UserSecrets": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Configuration.Xml": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.DependencyInjection": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.DependencyInjection.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.DiagnosticAdapter": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Diagnostics.HealthChecks": "[2.2.5, 2.3.0)", + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.FileProviders.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.FileProviders.Composite": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.FileProviders.Embedded": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.FileProviders.Physical": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.FileSystemGlobbing": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Hosting": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Hosting.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Http": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Identity.Core": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Identity.Stores": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Localization": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Localization.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.Abstractions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.Configuration": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.Console": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.Debug": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.EventSource": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Logging.TraceSource": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.ObjectPool": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Options": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Options.ConfigurationExtensions": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Options.DataAnnotations": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.Primitives": "[2.2.0, 2.3.0)", + "Microsoft.Extensions.WebEncoders": "[2.2.0, 2.3.0)", + "Microsoft.Net.Http.Headers": "[2.2.8, 2.3.0)", + "System.IO.Pipelines": "4.5.3" + }, + "compile": { + "lib/netcoreapp2.2/_._": {} + }, + "runtime": { + "lib/netcoreapp2.2/_._": {} + }, + "build": { + "build/netcoreapp2.2/Microsoft.AspNetCore.App.props": {}, + "build/netcoreapp2.2/Microsoft.AspNetCore.App.targets": {} + } + }, + "Microsoft.AspNetCore.ApplicationInsights.HostingStartup/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.ApplicationInsights.AspNetCore": "2.1.1", + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.Extensions.Configuration.Json": "2.2.0", + "Microsoft.Extensions.DiagnosticAdapter": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Logging.Configuration": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Extensions.WebEncoders": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Cookies/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Cookies.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Cookies.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Core/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Facebook/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Facebook.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Facebook.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Google/2.2.2": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Google.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Google.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.2.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.JwtBearer.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.JwtBearer.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.MicrosoftAccount/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.OAuth/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.2.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OAuth.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OAuth.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OpenIdConnect.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OpenIdConnect.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.Twitter/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.OAuth": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Twitter.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Twitter.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authentication.WsFederation/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication": "2.2.0", + "Microsoft.IdentityModel.Protocols.WsFederation": "5.3.0", + "System.IdentityModel.Tokens.Jwt": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.WsFederation.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.WsFederation.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authorization/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Authorization.Policy/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Authorization": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.Policy.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.Policy.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.AzureAppServices.HostingStartup/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.AzureAppServicesIntegration": "2.2.5", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "2.2.4" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.AzureAppServicesIntegration/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.Extensions.Logging.AzureAppServices": "2.2.5" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.AzureAppServicesIntegration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.AzureAppServicesIntegration.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Connections.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.2.0", + "System.IO.Pipelines": "4.5.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Connections.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Connections.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.CookiePolicy/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.CookiePolicy.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.CookiePolicy.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Cors/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Cors.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Cors.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Cryptography.Internal/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.Internal.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.Internal.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.DataProtection/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.2.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.DataProtection.AzureKeyVault/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.Azure.KeyVault": "2.3.2", + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.19.8" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.DataProtection.AzureStorage/2.2.7": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.Data.OData": "5.8.4", + "WindowsAzure.Storage": "8.1.4" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureStorage.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureStorage.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.DataProtection.Extensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Extensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Extensions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Diagnostics/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Diagnostics.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.WebUtilities": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Diagnostics.DiagnosticSource": "4.5.0", + "System.Reflection.Metadata": "1.6.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Diagnostics.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/2.2.1": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.EntityFrameworkCore.Relational": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Diagnostics.HealthChecks/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.Extensions.Diagnostics.HealthChecks": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.HealthChecks.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.HealthChecks.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.HostFiltering/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.HostFiltering.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.HostFiltering.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Hosting/2.2.7": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "2.2.4", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.Reflection.Metadata": "1.6.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Hosting.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.2.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Html.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "System.Text.Encodings.Web": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Html.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Html.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http/2.2.2": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.AspNetCore.WebUtilities": "2.2.0", + "Microsoft.Extensions.ObjectPool": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http.Connections/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authorization.Policy": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Connections.Common": "1.1.0", + "Microsoft.AspNetCore.Routing": "2.2.0", + "Microsoft.AspNetCore.WebSockets": "2.2.0", + "Newtonsoft.Json": "11.0.2", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.Http.Connections.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.Http.Connections.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http.Connections.Common/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "2.2.0", + "Newtonsoft.Json": "11.0.2", + "System.Buffers": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.Common.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.Common.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http.Extensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0", + "System.Buffers": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Extensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Extensions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Http.Features/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Features.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Features.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.HttpOverrides/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.HttpOverrides.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.HttpOverrides.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.HttpsPolicy/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Configuration.Binder": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.HttpsPolicy.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.HttpsPolicy.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Identity/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Cookies": "2.2.0", + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Identity.Core": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Identity.EntityFrameworkCore/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Identity": "2.2.0", + "Microsoft.EntityFrameworkCore.Relational": "2.2.0", + "Microsoft.Extensions.Identity.Stores": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Identity.UI/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Identity": "2.2.0", + "Microsoft.AspNetCore.Mvc": "2.2.0", + "Microsoft.AspNetCore.StaticFiles": "2.2.0", + "Microsoft.Extensions.FileProviders.Embedded": "2.2.0", + "Microsoft.Extensions.Identity.Stores": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V3.dll": {}, + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll": {}, + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V3.dll": {}, + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll": {}, + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.JsonPatch/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.JsonPatch.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.JsonPatch.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Localization/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Localization.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Localization.Routing/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Localization": "2.2.0", + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.Routing.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.Routing.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.MiddlewareAnalysis/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "System.Diagnostics.DiagnosticSource": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.MiddlewareAnalysis.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.MiddlewareAnalysis.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Analyzers": "2.2.0", + "Microsoft.AspNetCore.Mvc.ApiExplorer": "2.2.0", + "Microsoft.AspNetCore.Mvc.Cors": "2.2.0", + "Microsoft.AspNetCore.Mvc.DataAnnotations": "2.2.0", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "2.2.0", + "Microsoft.AspNetCore.Mvc.Localization": "2.2.0", + "Microsoft.AspNetCore.Mvc.Razor.Extensions": "2.2.0", + "Microsoft.AspNetCore.Mvc.RazorPages": "2.2.0", + "Microsoft.AspNetCore.Mvc.TagHelpers": "2.2.0", + "Microsoft.AspNetCore.Mvc.ViewFeatures": "2.2.0", + "Microsoft.AspNetCore.Razor.Design": "2.2.0", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Analyzers/2.2.0": { + "type": "package" + }, + "Microsoft.AspNetCore.Mvc.ApiExplorer/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ApiExplorer.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ApiExplorer.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Core/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.Authorization.Policy": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.Mvc.Abstractions": "2.2.0", + "Microsoft.AspNetCore.ResponseCaching.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Routing": "2.2.0", + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.DependencyModel": "2.1.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "System.Diagnostics.DiagnosticSource": "4.5.0", + "System.Threading.Tasks.Extensions": "4.5.1" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Cors/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Cors": "2.2.0", + "Microsoft.AspNetCore.Mvc.Core": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Cors.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Cors.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.DataAnnotations/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "2.2.0", + "Microsoft.Extensions.Localization": "2.2.0", + "System.ComponentModel.Annotations": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.DataAnnotations.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.DataAnnotations.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Formatters.Json/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.JsonPatch": "2.2.0", + "Microsoft.AspNetCore.Mvc.Core": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Json.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Formatters.Xml/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Core": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Xml.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Xml.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Localization/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Localization": "2.2.0", + "Microsoft.AspNetCore.Mvc.Razor": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.Localization": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Localization.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Localization.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Razor/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Razor.Extensions": "2.2.0", + "Microsoft.AspNetCore.Mvc.ViewFeatures": "2.2.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "2.8.0", + "Microsoft.CodeAnalysis.Razor": "2.2.0", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.FileProviders.Composite": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.Razor.Extensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "2.2.0", + "Microsoft.CodeAnalysis.Razor": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.dll": { + "related": ".xml" + } + }, + "build": { + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.props": {}, + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.targets": {} + } + }, + "Microsoft.AspNetCore.Mvc.Razor.ViewCompilation/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.AspNetCore.Mvc.RazorPages": "2.2.0" + }, + "build": { + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets": {} + } + }, + "Microsoft.AspNetCore.Mvc.RazorPages/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Razor": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.RazorPages.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.RazorPages.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.TagHelpers/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.Razor": "2.2.0", + "Microsoft.AspNetCore.Razor.Runtime": "2.2.0", + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.FileSystemGlobbing": "2.2.0", + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.TagHelpers.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.TagHelpers.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Mvc.ViewFeatures/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Antiforgery": "2.2.0", + "Microsoft.AspNetCore.Diagnostics.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Mvc.Core": "2.2.0", + "Microsoft.AspNetCore.Mvc.DataAnnotations": "2.2.0", + "Microsoft.AspNetCore.Mvc.Formatters.Json": "2.2.0", + "Microsoft.Extensions.WebEncoders": "2.2.0", + "Newtonsoft.Json.Bson": "1.0.1" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ViewFeatures.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ViewFeatures.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.NodeServices/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Console": "2.2.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.NodeServices.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.NodeServices.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Owin/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Owin.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Owin.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Razor/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Razor.Design/2.2.0": { + "type": "package", + "build": { + "build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.props": {} + }, + "buildMultiTargeting": { + "buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.props": {} + } + }, + "Microsoft.AspNetCore.Razor.Language/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Language.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Language.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Razor.Runtime/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Html.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Razor": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Runtime.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Runtime.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.ResponseCaching/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.ResponseCaching.Abstractions": "2.2.0", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.ResponseCaching.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.ResponseCompression/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.ResponseCompression.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.ResponseCompression.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Rewrite/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Rewrite.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Rewrite.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Routing/2.2.2": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.Routing.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.ObjectPool": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.Routing.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.Routing.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Routing.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.HttpSys/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.HttpSys.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.HttpSys.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.IIS/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.Connections.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "System.IO.Pipelines": "4.5.3", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IIS.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IIS.dll": { + "related": ".xml" + } + }, + "build": { + "build/netstandard2.0/Microsoft.AspNetCore.Server.IIS.targets": {} + }, + "runtimeTargets": { + "runtimes/win-x64/nativeassets/netcoreapp2.2/aspnetcorev2_inprocess.dll": { + "assetType": "native", + "rid": "win-x64" + }, + "runtimes/win-x86/nativeassets/netcoreapp2.2/aspnetcorev2_inprocess.dll": { + "assetType": "native", + "rid": "win-x86" + } + } + }, + "Microsoft.AspNetCore.Server.IISIntegration/2.2.1": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authentication.Core": "2.2.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.AspNetCore.HttpOverrides": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Buffers": "4.5.0", + "System.IO.Pipelines": "4.5.2", + "System.Memory": "4.5.1", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.1", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.dll": { + "related": ".xml" + } + }, + "build": { + "build/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.targets": {} + } + }, + "Microsoft.AspNetCore.Server.Kestrel/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Core": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Https": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.Kestrel.Core/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions": "2.2.0", + "Microsoft.AspNetCore.WebUtilities": "2.2.0", + "Microsoft.Extensions.Configuration.Binder": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Microsoft.Net.Http.Headers": "2.2.0", + "System.Memory": "4.5.1", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.1", + "System.Security.Cryptography.Cng": "4.5.0", + "System.Threading.Tasks.Extensions": "4.5.1" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.Kestrel.Https/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Core": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Https.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Https.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/2.2.0": { + "type": "package", + "dependencies": { + "Libuv": "1.10.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/2.2.1": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.Session/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.DataProtection": "2.2.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.Extensions.Caching.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.Session.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.Session.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SignalR/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Connections": "1.1.0", + "Microsoft.AspNetCore.SignalR.Core": "1.1.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SignalR.Common/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Connections.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "Newtonsoft.Json": "11.0.2", + "System.Buffers": "4.5.0" + }, + "compile": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.SignalR.Common.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.2/Microsoft.AspNetCore.SignalR.Common.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SignalR.Core/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Authorization": "2.2.0", + "Microsoft.AspNetCore.SignalR.Common": "1.1.0", + "Microsoft.AspNetCore.SignalR.Protocols.Json": "1.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "System.Reflection.Emit": "4.3.0", + "System.Threading.Channels": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json/1.1.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.SignalR.Common": "1.1.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Protocols.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Protocols.Json.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SignalR.Redis/1.1.5": { + "type": "package", + "dependencies": { + "MessagePack": "1.7.3.7", + "Microsoft.AspNetCore.SignalR.Core": "1.1.0", + "Microsoft.Extensions.Options": "2.2.0", + "StackExchange.Redis.StrongName": "1.2.6" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Redis.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Redis.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.SpaServices/2.2.7": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Mvc.TagHelpers": "2.2.0", + "Microsoft.AspNetCore.Mvc.ViewFeatures": "2.2.0", + "Microsoft.AspNetCore.NodeServices": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.dll": {} + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.dll": {} + } + }, + "Microsoft.AspNetCore.SpaServices.Extensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.SpaServices": "2.2.0", + "Microsoft.AspNetCore.StaticFiles": "2.2.0", + "Microsoft.AspNetCore.WebSockets": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.Extensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.Extensions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.StaticFiles/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.WebEncoders": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.StaticFiles.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.StaticFiles.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.WebSockets/2.2.1": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Net.WebSockets.WebSocketProtocol": "4.5.3" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.WebSockets.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.WebSockets.dll": { + "related": ".xml" + } + } + }, + "Microsoft.AspNetCore.WebUtilities/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Net.Http.Headers": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.AspNetCore.WebUtilities.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.AspNetCore.WebUtilities.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Azure.KeyVault/2.3.2": { + "type": "package", + "dependencies": { + "Microsoft.Azure.KeyVault.WebKey": "2.0.7", + "Microsoft.Rest.ClientRuntime": "[2.3.8, 3.0.0)", + "Microsoft.Rest.ClientRuntime.Azure": "[3.3.7, 4.0.0)", + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "9.0.1", + "System.Net.Http": "4.3.0" + }, + "compile": { + "lib/netstandard1.4/Microsoft.Azure.KeyVault.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/netstandard1.4/Microsoft.Azure.KeyVault.dll": { + "related": ".runtimeconfig.json;.xml" + } + } + }, + "Microsoft.Azure.KeyVault.WebKey/2.0.7": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.2", + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "9.0.1", + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Linq": "4.1.0", + "System.Runtime": "4.1.0", + "System.Security.Cryptography.Algorithms": "4.2.0" + }, + "compile": { + "lib/netstandard1.4/Microsoft.Azure.KeyVault.WebKey.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/netstandard1.4/Microsoft.Azure.KeyVault.WebKey.dll": { + "related": ".runtimeconfig.json;.xml" + } + } + }, + "Microsoft.Azure.Services.AppAuthentication/1.0.1": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + }, + "compile": { + "lib/netstandard1.4/Microsoft.Azure.Services.AppAuthentication.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/netstandard1.4/Microsoft.Azure.Services.AppAuthentication.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "build": { + "build/_._": {} + } + }, + "Microsoft.CodeAnalysis.Analyzers/1.1.0": { + "type": "package" + }, + "Microsoft.CodeAnalysis.Common/2.8.0": { + "type": "package", + "dependencies": { + "Microsoft.CodeAnalysis.Analyzers": "1.1.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Collections.Immutable": "1.3.1", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.FileVersionInfo": "4.3.0", + "System.Diagnostics.StackTrace": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Dynamic.Runtime": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Metadata": "1.4.2", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.CodePages": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Parallel": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.ValueTuple": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0", + "System.Xml.XPath.XDocument": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + }, + "compile": { + "lib/netstandard1.3/Microsoft.CodeAnalysis.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.CodeAnalysis.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.CodeAnalysis.CSharp/2.8.0": { + "type": "package", + "dependencies": { + "Microsoft.CodeAnalysis.Common": "[2.8.0]" + }, + "compile": { + "lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.CodeAnalysis.Razor/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Razor.Language": "2.2.0", + "Microsoft.CodeAnalysis.CSharp": "2.8.0", + "Microsoft.CodeAnalysis.Common": "2.8.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.CodeAnalysis.Razor.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.CodeAnalysis.Razor.dll": { + "related": ".xml" + } + } + }, + "Microsoft.CSharp/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + } + }, + "Microsoft.Data.Edm/5.8.4": { + "type": "package", + "compile": { + "lib/netstandard1.1/Microsoft.Data.Edm.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.1/Microsoft.Data.Edm.dll": { + "related": ".xml" + } + }, + "resource": { + "lib/netstandard1.1/de/Microsoft.Data.Edm.resources.dll": { + "locale": "de" + }, + "lib/netstandard1.1/es/Microsoft.Data.Edm.resources.dll": { + "locale": "es" + }, + "lib/netstandard1.1/fr/Microsoft.Data.Edm.resources.dll": { + "locale": "fr" + }, + "lib/netstandard1.1/it/Microsoft.Data.Edm.resources.dll": { + "locale": "it" + }, + "lib/netstandard1.1/ja/Microsoft.Data.Edm.resources.dll": { + "locale": "ja" + }, + "lib/netstandard1.1/ko/Microsoft.Data.Edm.resources.dll": { + "locale": "ko" + }, + "lib/netstandard1.1/ru/Microsoft.Data.Edm.resources.dll": { + "locale": "ru" + }, + "lib/netstandard1.1/zh-Hans/Microsoft.Data.Edm.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netstandard1.1/zh-Hant/Microsoft.Data.Edm.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.Data.OData/5.8.4": { + "type": "package", + "dependencies": { + "Microsoft.Data.Edm": "[5.8.4]", + "System.Spatial": "[5.8.4]" + }, + "compile": { + "lib/netstandard1.1/Microsoft.Data.OData.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.1/Microsoft.Data.OData.dll": { + "related": ".xml" + } + }, + "resource": { + "lib/netstandard1.1/de/Microsoft.Data.OData.resources.dll": { + "locale": "de" + }, + "lib/netstandard1.1/es/Microsoft.Data.OData.resources.dll": { + "locale": "es" + }, + "lib/netstandard1.1/fr/Microsoft.Data.OData.resources.dll": { + "locale": "fr" + }, + "lib/netstandard1.1/it/Microsoft.Data.OData.resources.dll": { + "locale": "it" + }, + "lib/netstandard1.1/ja/Microsoft.Data.OData.resources.dll": { + "locale": "ja" + }, + "lib/netstandard1.1/ko/Microsoft.Data.OData.resources.dll": { + "locale": "ko" + }, + "lib/netstandard1.1/ru/Microsoft.Data.OData.resources.dll": { + "locale": "ru" + }, + "lib/netstandard1.1/zh-Hans/Microsoft.Data.OData.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netstandard1.1/zh-Hant/Microsoft.Data.OData.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "Microsoft.Data.Sqlite/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "2.2.6", + "SQLitePCLRaw.bundle_green": "1.1.12" + }, + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + } + }, + "Microsoft.Data.Sqlite.Core/2.2.6": { + "type": "package", + "dependencies": { + "SQLitePCLRaw.core": "1.1.12" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Data.Sqlite.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Data.Sqlite.dll": { + "related": ".xml" + } + } + }, + "Microsoft.DotNet.PlatformAbstractions/2.1.0": { + "type": "package", + "dependencies": { + "System.AppContext": "4.1.0", + "System.Collections": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.0.0" + }, + "compile": { + "lib/netstandard1.3/Microsoft.DotNet.PlatformAbstractions.dll": {} + }, + "runtime": { + "lib/netstandard1.3/Microsoft.DotNet.PlatformAbstractions.dll": {} + } + }, + "Microsoft.EntityFrameworkCore/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "2.2.6", + "Microsoft.EntityFrameworkCore.Analyzers": "2.2.6", + "Microsoft.Extensions.Caching.Memory": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Remotion.Linq": "2.2.0", + "System.Collections.Immutable": "1.5.0", + "System.ComponentModel.Annotations": "4.5.0", + "System.Diagnostics.DiagnosticSource": "4.5.0", + "System.Interactive.Async": "3.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Abstractions/2.2.6": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Analyzers/2.2.6": { + "type": "package" + }, + "Microsoft.EntityFrameworkCore.Design/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.EntityFrameworkCore.Relational": "2.2.6" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Design.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Design.dll": { + "related": ".xml" + } + }, + "build": { + "build/netcoreapp2.0/Microsoft.EntityFrameworkCore.Design.props": {} + } + }, + "Microsoft.EntityFrameworkCore.InMemory/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore": "2.2.6" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.InMemory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.InMemory.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Relational/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore": "2.2.6" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Relational.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Relational.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Sqlite/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "2.2.6", + "SQLitePCLRaw.bundle_green": "1.1.12" + }, + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "2.2.6", + "Microsoft.EntityFrameworkCore.Relational": "2.2.6", + "Microsoft.Extensions.DependencyModel": "2.1.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Sqlite.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Sqlite.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.SqlServer/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "2.2.6", + "System.Data.SqlClient": "4.6.1" + }, + "compile": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.SqlServer.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.SqlServer.dll": { + "related": ".xml" + } + } + }, + "Microsoft.EntityFrameworkCore.Tools/2.2.6": { + "type": "package", + "dependencies": { + "Microsoft.EntityFrameworkCore.Design": "2.2.6" + }, + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + } + }, + "Microsoft.Extensions.Caching.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Caching.Memory/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Caching.Redis/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "StackExchange.Redis.StrongName": "1.2.6" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Redis.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.Redis.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Caching.SqlServer/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Data.SqlClient": "4.6.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.SqlServer.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Caching.SqlServer.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.AzureKeyVault/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Azure.KeyVault": "2.3.2", + "Microsoft.Azure.Services.AppAuthentication": "1.0.1", + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.AzureKeyVault.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.AzureKeyVault.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.Binder/2.2.4": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.CommandLine/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.CommandLine.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.CommandLine.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables/2.2.4": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.FileExtensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.FileExtensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.FileExtensions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.Ini/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Ini.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Ini.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.Json/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Json.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.KeyPerFile/2.2.4": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.KeyPerFile.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.KeyPerFile.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Configuration.UserSecrets/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Json": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.dll": { + "related": ".xml" + } + }, + "build": { + "build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props": {}, + "build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets": {} + } + }, + "Microsoft.Extensions.Configuration.Xml/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.Configuration.FileExtensions": "2.2.0", + "System.Security.Cryptography.Xml": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Xml.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Xml.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.DependencyInjection/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0" + }, + "compile": { + "lib/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.DependencyModel/2.1.0": { + "type": "package", + "dependencies": { + "Microsoft.DotNet.PlatformAbstractions": "2.1.0", + "Newtonsoft.Json": "9.0.1", + "System.Diagnostics.Debug": "4.0.11", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq": "4.1.0" + }, + "compile": { + "lib/netstandard1.6/Microsoft.Extensions.DependencyModel.dll": {} + }, + "runtime": { + "lib/netstandard1.6/Microsoft.Extensions.DependencyModel.dll": {} + } + }, + "Microsoft.Extensions.DiagnosticAdapter/2.2.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.DiagnosticSource": "4.5.0" + }, + "compile": { + "lib/netcoreapp2.0/Microsoft.Extensions.DiagnosticAdapter.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.0/Microsoft.Extensions.DiagnosticAdapter.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "2.2.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.FileProviders.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.FileProviders.Composite/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Composite.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Composite.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.FileProviders.Embedded/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.dll": { + "related": ".xml" + } + }, + "build": { + "build/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.props": {}, + "build/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.targets": {} + }, + "buildMultiTargeting": { + "buildMultiTargeting/Microsoft.Extensions.FileProviders.Embedded.props": {}, + "buildMultiTargeting/Microsoft.Extensions.FileProviders.Embedded.targets": {} + } + }, + "Microsoft.Extensions.FileProviders.Physical/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.FileSystemGlobbing": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Physical.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Physical.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.FileSystemGlobbing/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.FileSystemGlobbing.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.FileSystemGlobbing.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Hosting/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.2.0", + "Microsoft.Extensions.DependencyInjection": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Hosting.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Hosting.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Hosting.Abstractions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.FileProviders.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Hosting.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Hosting.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Http/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Http.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Http.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Identity.Core/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.ComponentModel.Annotations": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Identity.Core.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Identity.Core.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Identity.Stores/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Identity.Core": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "System.ComponentModel.Annotations": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Identity.Stores.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Identity.Stores.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Localization/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Localization.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Localization.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Localization.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Localization.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Localization.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Localization.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Binder": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.Abstractions/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.AzureAppServices/2.2.5": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.EnvironmentVariables": "2.2.0", + "Microsoft.Extensions.Configuration.Json": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Logging.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging.Configuration": "2.2.0", + "System.ValueTuple": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.AzureAppServices.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.AzureAppServices.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.Configuration/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Configuration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Configuration.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.Console/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.Logging": "2.2.0", + "Microsoft.Extensions.Logging.Configuration": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Console.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Console.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.Debug/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Debug.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.Debug.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.EventSource/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging": "2.2.0", + "Newtonsoft.Json": "11.0.2" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.EventSource.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.EventSource.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Logging.TraceSource/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Logging": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.TraceSource.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Logging.TraceSource.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.ObjectPool/2.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.ObjectPool.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.ObjectPool.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Options/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Primitives": "2.2.0", + "System.ComponentModel.Annotations": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Options.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.2.0", + "Microsoft.Extensions.Configuration.Binder": "2.2.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Options.DataAnnotations/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.ComponentModel.Annotations": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Options.DataAnnotations.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Options.DataAnnotations.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.PlatformAbstractions/1.1.0": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Reflection.TypeExtensions": "4.3.0" + }, + "compile": { + "lib/netstandard1.3/Microsoft.Extensions.PlatformAbstractions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.Extensions.PlatformAbstractions.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.Primitives/2.2.0": { + "type": "package", + "dependencies": { + "System.Memory": "4.5.1", + "System.Runtime.CompilerServices.Unsafe": "4.5.1" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Extensions.WebEncoders/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.2.0", + "Microsoft.Extensions.Options": "2.2.0", + "System.Text.Encodings.Web": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Extensions.WebEncoders.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Extensions.WebEncoders.dll": { + "related": ".xml" + } + } + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory/3.19.8": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0" + }, + "compile": { + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll": { + "related": ".xml" + }, + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.dll": { + "related": ".Platform.xml;.xml" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll": { + "related": ".xml" + }, + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.dll": { + "related": ".Platform.xml;.xml" + } + } + }, + "Microsoft.IdentityModel.JsonWebTokens/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.3.0", + "Newtonsoft.Json": "10.0.1" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Logging/5.3.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Protocols/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Logging": "5.3.0", + "Microsoft.IdentityModel.Tokens": "5.3.0", + "System.Collections.Specialized": "4.3.0", + "System.Diagnostics.Contracts": "4.3.0", + "System.Net.Http": "4.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "5.3.0", + "Newtonsoft.Json": "10.0.1", + "System.Dynamic.Runtime": "4.3.0", + "System.IdentityModel.Tokens.Jwt": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Protocols.WsFederation/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "5.3.0", + "Microsoft.IdentityModel.Tokens.Saml": "5.3.0", + "Microsoft.IdentityModel.Xml": "5.3.0", + "System.Xml.XmlDocument": "4.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.WsFederation.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.WsFederation.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Tokens/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Logging": "5.3.0", + "Newtonsoft.Json": "10.0.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Serialization.Xml": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Tokens.Saml/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.3.0", + "Microsoft.IdentityModel.Xml": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.Saml.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.Saml.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.IdentityModel.Xml/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "5.3.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.IdentityModel.Xml.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.IdentityModel.Xml.dll": { + "related": ".pdb;.xml" + } + } + }, + "Microsoft.Net.Http.Headers/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.2.0", + "System.Buffers": "4.5.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.Net.Http.Headers.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Net.Http.Headers.dll": { + "related": ".xml" + } + } + }, + "Microsoft.NETCore.App/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.DotNetHostPolicy": "2.2.8", + "Microsoft.NETCore.Platforms": "2.2.4", + "Microsoft.NETCore.Targets": "2.0.0", + "NETStandard.Library": "2.0.3" + }, + "compile": { + "ref/netcoreapp2.2/Microsoft.CSharp.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/Microsoft.VisualBasic.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.AppContext.dll": {}, + "ref/netcoreapp2.2/System.Buffers.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Collections.Concurrent.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Collections.Immutable.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Collections.NonGeneric.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Collections.Specialized.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Collections.dll": { + "related": ".Concurrent.xml;.Immutable.xml;.NonGeneric.xml;.Specialized.xml;.xml" + }, + "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll": {}, + "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.ComponentModel.dll": { + "related": ".Annotations.xml;.EventBasedAsync.xml;.Primitives.xml;.TypeConverter.xml;.xml" + }, + "ref/netcoreapp2.2/System.Configuration.dll": {}, + "ref/netcoreapp2.2/System.Console.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Core.dll": {}, + "ref/netcoreapp2.2/System.Data.Common.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Data.dll": { + "related": ".Common.xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.Debug.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.Process.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.Tools.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Drawing.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Drawing.dll": { + "related": ".Primitives.xml" + }, + "ref/netcoreapp2.2/System.Dynamic.Runtime.dll": {}, + "ref/netcoreapp2.2/System.Globalization.Calendars.dll": {}, + "ref/netcoreapp2.2/System.Globalization.Extensions.dll": {}, + "ref/netcoreapp2.2/System.Globalization.dll": {}, + "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll": {}, + "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll": {}, + "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.Compression.dll": { + "related": ".xml;.ZipFile.xml" + }, + "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll": {}, + "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.FileSystem.dll": { + "related": ".DriveInfo.xml;.Watcher.xml;.xml" + }, + "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.Pipes.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll": {}, + "ref/netcoreapp2.2/System.IO.dll": { + "related": ".Compression.xml;.Compression.ZipFile.xml;.FileSystem.DriveInfo.xml;.FileSystem.Watcher.xml;.FileSystem.xml;.IsolatedStorage.xml;.MemoryMappedFiles.xml;.Pipes.xml" + }, + "ref/netcoreapp2.2/System.Linq.Expressions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Linq.Parallel.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Linq.Queryable.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Linq.dll": { + "related": ".Expressions.xml;.Parallel.xml;.Queryable.xml;.xml" + }, + "ref/netcoreapp2.2/System.Memory.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Http.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.HttpListener.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Mail.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.NameResolution.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.NetworkInformation.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Ping.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Requests.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Security.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.ServicePoint.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.Sockets.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.WebClient.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.WebProxy.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Net.WebSockets.dll": { + "related": ".Client.xml;.xml" + }, + "ref/netcoreapp2.2/System.Net.dll": { + "related": ".Http.xml;.HttpListener.xml;.Mail.xml;.NameResolution.xml;.NetworkInformation.xml;.Ping.xml;.Primitives.xml;.Requests.xml;.Security.xml;.ServicePoint.xml;.Sockets.xml;.WebClient.xml;.WebHeaderCollection.xml;.WebProxy.xml;.WebSockets.Client.xml;.WebSockets.xml" + }, + "ref/netcoreapp2.2/System.Numerics.Vectors.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Numerics.dll": { + "related": ".Vectors.xml" + }, + "ref/netcoreapp2.2/System.ObjectModel.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.Emit.dll": { + "related": ".ILGeneration.xml;.Lightweight.xml;.xml" + }, + "ref/netcoreapp2.2/System.Reflection.Extensions.dll": {}, + "ref/netcoreapp2.2/System.Reflection.Metadata.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Reflection.dll": { + "related": ".DispatchProxy.xml;.Emit.ILGeneration.xml;.Emit.Lightweight.xml;.Emit.xml;.Metadata.xml;.Primitives.xml;.TypeExtensions.xml" + }, + "ref/netcoreapp2.2/System.Resources.Reader.dll": {}, + "ref/netcoreapp2.2/System.Resources.ResourceManager.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Resources.Writer.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Extensions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Handles.dll": {}, + "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.InteropServices.dll": { + "related": ".RuntimeInformation.xml;.WindowsRuntime.xml;.xml" + }, + "ref/netcoreapp2.2/System.Runtime.Loader.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Numerics.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Runtime.Serialization.dll": { + "related": ".Formatters.xml;.Json.xml;.Primitives.xml;.Xml.xml" + }, + "ref/netcoreapp2.2/System.Runtime.dll": { + "related": ".CompilerServices.VisualC.xml;.Extensions.xml;.InteropServices.RuntimeInformation.xml;.InteropServices.WindowsRuntime.xml;.InteropServices.xml;.Loader.xml;.Numerics.xml;.Serialization.Formatters.xml;.Serialization.Json.xml;.Serialization.Primitives.xml;.Serialization.Xml.xml;.xml" + }, + "ref/netcoreapp2.2/System.Security.Claims.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.Principal.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Security.SecureString.dll": {}, + "ref/netcoreapp2.2/System.Security.dll": { + "related": ".Claims.xml;.Cryptography.Algorithms.xml;.Cryptography.Csp.xml;.Cryptography.Encoding.xml;.Cryptography.Primitives.xml;.Cryptography.X509Certificates.xml;.Principal.xml" + }, + "ref/netcoreapp2.2/System.ServiceModel.Web.dll": {}, + "ref/netcoreapp2.2/System.ServiceProcess.dll": {}, + "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Text.Encoding.dll": { + "related": ".Extensions.xml" + }, + "ref/netcoreapp2.2/System.Text.RegularExpressions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Overlapped.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Tasks.dll": { + "related": ".Dataflow.xml;.Extensions.xml;.Parallel.xml;.xml" + }, + "ref/netcoreapp2.2/System.Threading.Thread.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.ThreadPool.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.Timer.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Threading.dll": { + "related": ".Overlapped.xml;.Tasks.Dataflow.xml;.Tasks.Extensions.xml;.Tasks.Parallel.xml;.Tasks.xml;.Thread.xml;.ThreadPool.xml;.Timer.xml;.xml" + }, + "ref/netcoreapp2.2/System.Transactions.Local.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Transactions.dll": { + "related": ".Local.xml" + }, + "ref/netcoreapp2.2/System.ValueTuple.dll": {}, + "ref/netcoreapp2.2/System.Web.HttpUtility.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Web.dll": { + "related": ".HttpUtility.xml" + }, + "ref/netcoreapp2.2/System.Windows.dll": {}, + "ref/netcoreapp2.2/System.Xml.Linq.dll": {}, + "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Xml.Serialization.dll": {}, + "ref/netcoreapp2.2/System.Xml.XDocument.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Xml.XPath.dll": { + "related": ".XDocument.xml;.xml" + }, + "ref/netcoreapp2.2/System.Xml.XmlDocument.dll": {}, + "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll": { + "related": ".xml" + }, + "ref/netcoreapp2.2/System.Xml.dll": { + "related": ".ReaderWriter.xml;.XDocument.xml;.XmlSerializer.xml;.XPath.XDocument.xml;.XPath.xml" + }, + "ref/netcoreapp2.2/System.dll": { + "related": ".Buffers.xml;.Collections.Concurrent.xml;.Collections.Immutable.xml;.Collections.NonGeneric.xml;.Collections.Specialized.xml;.Collections.xml;.ComponentModel.Annotations.xml;.ComponentModel.EventBasedAsync.xml;.ComponentModel.Primitives.xml;.ComponentModel.TypeConverter.xml;.ComponentModel.xml;.Console.xml;.Data.Common.xml;.Diagnostics.Contracts.xml;.Diagnostics.Debug.xml;.Diagnostics.DiagnosticSource.xml;.Diagnostics.FileVersionInfo.xml;.Diagnostics.Process.xml;.Diagnostics.StackTrace.xml;.Diagnostics.TextWriterTraceListener.xml;.Diagnostics.Tools.xml;.Diagnostics.TraceSource.xml;.Diagnostics.Tracing.xml;.Drawing.Primitives.xml;.IO.Compression.xml;.IO.Compression.ZipFile.xml;.IO.FileSystem.DriveInfo.xml;.IO.FileSystem.Watcher.xml;.IO.FileSystem.xml;.IO.IsolatedStorage.xml;.IO.MemoryMappedFiles.xml;.IO.Pipes.xml;.Linq.Expressions.xml;.Linq.Parallel.xml;.Linq.Queryable.xml;.Linq.xml;.Memory.xml;.Net.Http.xml;.Net.HttpListener.xml;.Net.Mail.xml;.Net.NameResolution.xml;.Net.NetworkInformation.xml;.Net.Ping.xml;.Net.Primitives.xml;.Net.Requests.xml;.Net.Security.xml;.Net.ServicePoint.xml;.Net.Sockets.xml;.Net.WebClient.xml;.Net.WebHeaderCollection.xml;.Net.WebProxy.xml;.Net.WebSockets.Client.xml;.Net.WebSockets.xml;.Numerics.Vectors.xml;.ObjectModel.xml;.Reflection.DispatchProxy.xml;.Reflection.Emit.ILGeneration.xml;.Reflection.Emit.Lightweight.xml;.Reflection.Emit.xml;.Reflection.Metadata.xml;.Reflection.Primitives.xml;.Reflection.TypeExtensions.xml;.Resources.ResourceManager.xml;.Resources.Writer.xml;.Runtime.CompilerServices.VisualC.xml;.Runtime.Extensions.xml;.Runtime.InteropServices.RuntimeInformation.xml;.Runtime.InteropServices.WindowsRuntime.xml;.Runtime.InteropServices.xml;.Runtime.Loader.xml;.Runtime.Numerics.xml;.Runtime.Serialization.Formatters.xml;.Runtime.Serialization.Json.xml;.Runtime.Serialization.Primitives.xml;.Runtime.Serialization.Xml.xml;.Runtime.xml;.Security.Claims.xml;.Security.Cryptography.Algorithms.xml;.Security.Cryptography.Csp.xml;.Security.Cryptography.Encoding.xml;.Security.Cryptography.Primitives.xml;.Security.Cryptography.X509Certificates.xml;.Security.Principal.xml;.Text.Encoding.Extensions.xml;.Text.RegularExpressions.xml;.Threading.Overlapped.xml;.Threading.Tasks.Dataflow.xml;.Threading.Tasks.Extensions.xml;.Threading.Tasks.Parallel.xml;.Threading.Tasks.xml;.Threading.Thread.xml;.Threading.ThreadPool.xml;.Threading.Timer.xml;.Threading.xml;.Transactions.Local.xml;.Web.HttpUtility.xml;.Xml.ReaderWriter.xml;.Xml.XDocument.xml;.Xml.XmlSerializer.xml;.Xml.XPath.XDocument.xml;.Xml.XPath.xml" + }, + "ref/netcoreapp2.2/WindowsBase.dll": {}, + "ref/netcoreapp2.2/mscorlib.dll": {}, + "ref/netcoreapp2.2/netstandard.dll": {} + }, + "build": { + "build/netcoreapp2.2/Microsoft.NETCore.App.props": {}, + "build/netcoreapp2.2/Microsoft.NETCore.App.targets": {} + } + }, + "Microsoft.NETCore.DotNetAppHost/2.2.8": { + "type": "package" + }, + "Microsoft.NETCore.DotNetHostPolicy/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.DotNetHostResolver": "2.2.8" + } + }, + "Microsoft.NETCore.DotNetHostResolver/2.2.8": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.DotNetAppHost": "2.2.8" + } + }, + "Microsoft.NETCore.Platforms/2.2.4": { + "type": "package", + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "Microsoft.NETCore.Targets/2.0.0": { + "type": "package", + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "Microsoft.Rest.ClientRuntime/2.3.8": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "9.0.1" + }, + "compile": { + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.dll": { + "related": ".runtimeconfig.json;.xml" + } + } + }, + "Microsoft.Rest.ClientRuntime.Azure/3.3.7": { + "type": "package", + "dependencies": { + "Microsoft.Rest.ClientRuntime": "[2.3.8, 3.0.0)", + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "9.0.1" + }, + "compile": { + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.Azure.dll": { + "related": ".runtimeconfig.json;.xml" + } + }, + "runtime": { + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.Azure.dll": { + "related": ".runtimeconfig.json;.xml" + } + } + }, + "Microsoft.VisualStudio.Web.BrowserLink/2.2.0": { + "type": "package", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.2.0", + "Microsoft.AspNetCore.Http.Extensions": "2.2.0", + "Microsoft.Extensions.FileProviders.Physical": "2.2.0" + }, + "compile": { + "lib/netstandard2.0/Microsoft.VisualStudio.Web.BrowserLink.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.VisualStudio.Web.BrowserLink.dll": { + "related": ".xml" + } + } + }, + "Microsoft.Win32.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + } + }, + "Microsoft.Win32.Registry/4.5.0": { + "type": "package", + "dependencies": { + "System.Security.AccessControl": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "ref/netstandard2.0/Microsoft.Win32.Registry.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Microsoft.Win32.Registry.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard2.0/Microsoft.Win32.Registry.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard2.0/Microsoft.Win32.Registry.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "NETStandard.Library/2.0.3": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + }, + "build": { + "build/netstandard2.0/NETStandard.Library.targets": {} + } + }, + "Newtonsoft.Json/11.0.2": { + "type": "package", + "compile": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Newtonsoft.Json.dll": { + "related": ".xml" + } + } + }, + "Newtonsoft.Json.Bson/1.0.1": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.1", + "Newtonsoft.Json": "10.0.1" + }, + "compile": { + "lib/netstandard1.3/Newtonsoft.Json.Bson.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/Newtonsoft.Json.Bson.dll": { + "related": ".xml" + } + } + }, + "Octokit/0.36.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/Octokit.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/Octokit.dll": { + "related": ".xml" + } + } + }, + "Remotion.Linq/2.2.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Linq.Queryable": "4.0.1", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + }, + "compile": { + "lib/netstandard1.0/Remotion.Linq.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.0/Remotion.Linq.dll": { + "related": ".xml" + } + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/debian.8-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "debian.8-x64" + } + } + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/fedora.23-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "fedora.23-x64" + } + } + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/fedora.24-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "fedora.24-x64" + } + } + }, + "runtime.native.System/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.native.System.Data.SqlClient.sni/4.5.0": { + "type": "package", + "dependencies": { + "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni": "4.4.0", + "runtime.win-x64.runtime.native.System.Data.SqlClient.sni": "4.4.0", + "runtime.win-x86.runtime.native.System.Data.SqlClient.sni": "4.4.0" + } + }, + "runtime.native.System.IO.Compression/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.native.System.Net.Http/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.native.System.Net.Security/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.1": { + "type": "package", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.1" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + }, + "compile": { + "lib/netstandard1.0/_._": {} + }, + "runtime": { + "lib/netstandard1.0/_._": {} + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/opensuse.13.2-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "opensuse.13.2-x64" + } + } + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/opensuse.42.1-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "opensuse.42.1-x64" + } + } + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.1": { + "type": "package", + "runtimeTargets": { + "runtimes/osx.10.10-x64/native/System.Security.Cryptography.Native.Apple.dylib": { + "assetType": "native", + "rid": "osx.10.10-x64" + } + } + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/osx.10.10-x64/native/System.Security.Cryptography.Native.OpenSsl.dylib": { + "assetType": "native", + "rid": "osx.10.10-x64" + } + } + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/rhel.7-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "rhel.7-x64" + } + } + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/ubuntu.14.04-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "ubuntu.14.04-x64" + } + } + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/ubuntu.16.04-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "ubuntu.16.04-x64" + } + } + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "type": "package", + "runtimeTargets": { + "runtimes/ubuntu.16.10-x64/native/System.Security.Cryptography.Native.OpenSsl.so": { + "assetType": "native", + "rid": "ubuntu.16.10-x64" + } + } + }, + "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "type": "package", + "runtimeTargets": { + "runtimes/win-arm64/native/sni.dll": { + "assetType": "native", + "rid": "win-arm64" + } + } + }, + "runtime.win-x64.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "type": "package", + "runtimeTargets": { + "runtimes/win-x64/native/sni.dll": { + "assetType": "native", + "rid": "win-x64" + } + } + }, + "runtime.win-x86.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "type": "package", + "runtimeTargets": { + "runtimes/win-x86/native/sni.dll": { + "assetType": "native", + "rid": "win-x86" + } + } + }, + "SQLitePCLRaw.bundle_green/1.1.12": { + "type": "package", + "dependencies": { + "SQLitePCLRaw.core": "1.1.12", + "SQLitePCLRaw.lib.e_sqlite3.linux": "1.1.12", + "SQLitePCLRaw.lib.e_sqlite3.osx": "1.1.12", + "SQLitePCLRaw.lib.e_sqlite3.v110_xp": "1.1.12", + "SQLitePCLRaw.provider.e_sqlite3.netstandard11": "1.1.12" + }, + "compile": { + "lib/netcoreapp/SQLitePCLRaw.batteries_green.dll": {}, + "lib/netcoreapp/SQLitePCLRaw.batteries_v2.dll": {} + }, + "runtime": { + "lib/netcoreapp/SQLitePCLRaw.batteries_green.dll": {}, + "lib/netcoreapp/SQLitePCLRaw.batteries_v2.dll": {} + } + }, + "SQLitePCLRaw.core/1.1.12": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.0" + }, + "compile": { + "lib/netstandard1.1/SQLitePCLRaw.core.dll": {} + }, + "runtime": { + "lib/netstandard1.1/SQLitePCLRaw.core.dll": {} + } + }, + "SQLitePCLRaw.lib.e_sqlite3.linux/1.1.12": { + "type": "package", + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + }, + "runtimeTargets": { + "runtimes/alpine-x64/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "alpine-x64" + }, + "runtimes/linux-arm/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-arm" + }, + "runtimes/linux-arm64/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-arm64" + }, + "runtimes/linux-armel/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-armel" + }, + "runtimes/linux-musl-x64/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-musl-x64" + }, + "runtimes/linux-x64/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-x64" + }, + "runtimes/linux-x86/native/libe_sqlite3.so": { + "assetType": "native", + "rid": "linux-x86" + } + } + }, + "SQLitePCLRaw.lib.e_sqlite3.osx/1.1.12": { + "type": "package", + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + }, + "runtimeTargets": { + "runtimes/osx-x64/native/libe_sqlite3.dylib": { + "assetType": "native", + "rid": "osx-x64" + } + } + }, + "SQLitePCLRaw.lib.e_sqlite3.v110_xp/1.1.12": { + "type": "package", + "compile": { + "lib/netstandard2.0/_._": {} + }, + "runtime": { + "lib/netstandard2.0/_._": {} + }, + "runtimeTargets": { + "runtimes/win-x64/native/e_sqlite3.dll": { + "assetType": "native", + "rid": "win-x64" + }, + "runtimes/win-x86/native/e_sqlite3.dll": { + "assetType": "native", + "rid": "win-x86" + }, + "runtimes/win8-arm/native/e_sqlite3.dll": { + "assetType": "native", + "rid": "win8-arm" + } + } + }, + "SQLitePCLRaw.provider.e_sqlite3.netstandard11/1.1.12": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.0", + "SQLitePCLRaw.core": "1.1.12" + }, + "compile": { + "lib/netstandard1.1/SQLitePCLRaw.provider.e_sqlite3.dll": {} + }, + "runtime": { + "lib/netstandard1.1/SQLitePCLRaw.provider.e_sqlite3.dll": {} + } + }, + "StackExchange.Redis.StrongName/1.2.6": { + "type": "package", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Collections.NonGeneric": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Linq": "4.3.0", + "System.Net.NameResolution": "4.3.0", + "System.Net.Security": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "System.Threading.Timer": "4.3.0" + }, + "compile": { + "lib/netstandard1.5/StackExchange.Redis.StrongName.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.5/StackExchange.Redis.StrongName.dll": { + "related": ".xml" + } + } + }, + "System.AppContext/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.6/System.AppContext.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.6/System.AppContext.dll": {} + } + }, + "System.Buffers/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + } + }, + "System.Collections/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Collections.dll": { + "related": ".xml" + } + } + }, + "System.Collections.Concurrent/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Collections.Concurrent.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Collections.Concurrent.dll": {} + } + }, + "System.Collections.Immutable/1.5.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/System.Collections.Immutable.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Collections.Immutable.dll": { + "related": ".xml" + } + } + }, + "System.Collections.NonGeneric/4.3.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Collections.NonGeneric.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Collections.NonGeneric.dll": {} + } + }, + "System.Collections.Specialized/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections.NonGeneric": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Collections.Specialized.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Collections.Specialized.dll": {} + } + }, + "System.ComponentModel.Annotations/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + } + }, + "System.Console/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Console.dll": { + "related": ".xml" + } + } + }, + "System.Data.SqlClient/4.6.1": { + "type": "package", + "dependencies": { + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Principal.Windows": "4.5.0", + "System.Text.Encoding.CodePages": "4.5.0", + "runtime.native.System.Data.SqlClient.sni": "4.5.0" + }, + "compile": { + "ref/netcoreapp2.1/System.Data.SqlClient.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/System.Data.SqlClient.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Diagnostics.Contracts/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Diagnostics.Contracts.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.0/System.Diagnostics.Contracts.dll": {} + } + }, + "System.Diagnostics.Debug/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Diagnostics.Debug.dll": { + "related": ".xml" + } + } + }, + "System.Diagnostics.DiagnosticSource/4.5.1": { + "type": "package", + "compile": { + "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.dll": { + "related": ".xml" + } + } + }, + "System.Diagnostics.FileVersionInfo/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Reflection.Metadata": "1.4.1", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.Diagnostics.FileVersionInfo.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Diagnostics.FileVersionInfo.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Diagnostics.Process/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + }, + "compile": { + "ref/netstandard1.4/System.Diagnostics.Process.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/linux/lib/netstandard1.4/System.Diagnostics.Process.dll": { + "assetType": "runtime", + "rid": "linux" + }, + "runtimes/osx/lib/netstandard1.4/System.Diagnostics.Process.dll": { + "assetType": "runtime", + "rid": "osx" + }, + "runtimes/win/lib/netstandard1.4/System.Diagnostics.Process.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Diagnostics.StackTrace/4.3.0": { + "type": "package", + "dependencies": { + "System.IO.FileSystem": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Metadata": "1.4.1", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Diagnostics.StackTrace.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Diagnostics.StackTrace.dll": {} + } + }, + "System.Diagnostics.Tools/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Diagnostics.Tools.dll": { + "related": ".xml" + } + } + }, + "System.Diagnostics.Tracing/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.5/System.Diagnostics.Tracing.dll": { + "related": ".xml" + } + } + }, + "System.Dynamic.Runtime/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Dynamic.Runtime.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Dynamic.Runtime.dll": {} + } + }, + "System.Globalization/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Globalization.dll": { + "related": ".xml" + } + } + }, + "System.Globalization.Calendars/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + } + }, + "System.Globalization.Extensions/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.Globalization.Extensions.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.IdentityModel.Tokens.Jwt/5.3.0": { + "type": "package", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "5.3.0", + "Microsoft.IdentityModel.Tokens": "5.3.0", + "Newtonsoft.Json": "10.0.1" + }, + "compile": { + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.dll": { + "related": ".pdb;.xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.dll": { + "related": ".pdb;.xml" + } + } + }, + "System.Interactive.Async/3.2.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/System.Interactive.Async.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Interactive.Async.dll": { + "related": ".xml" + } + } + }, + "System.IO/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.5/System.IO.dll": { + "related": ".xml" + } + } + }, + "System.IO.Compression/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.IO.Compression.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.IO.Compression.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.IO.Compression.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.IO.FileSystem/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.IO.FileSystem.dll": { + "related": ".xml" + } + } + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.IO.FileSystem.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.IO.FileSystem.Primitives.dll": {} + } + }, + "System.IO.Pipelines/4.5.3": { + "type": "package", + "compile": { + "lib/netcoreapp2.1/System.IO.Pipelines.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/System.IO.Pipelines.dll": { + "related": ".xml" + } + } + }, + "System.Linq/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + }, + "compile": { + "ref/netstandard1.6/System.Linq.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.6/System.Linq.dll": {} + } + }, + "System.Linq.Expressions/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.6/System.Linq.Expressions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.6/System.Linq.Expressions.dll": {} + } + }, + "System.Linq.Queryable/4.0.1": { + "type": "package", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + }, + "compile": { + "ref/netstandard1.0/System.Linq.Queryable.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Linq.Queryable.dll": {} + } + }, + "System.Memory/4.5.1": { + "type": "package", + "compile": { + "ref/netcoreapp2.1/_._": {} + }, + "runtime": { + "lib/netcoreapp2.1/_._": {} + } + }, + "System.Net.Http/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Net.Http.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Net.Http.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Net.NameResolution/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Principal.Windows": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Net.NameResolution.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.Net.NameResolution.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Net.NameResolution.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Net.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Net.Primitives.dll": { + "related": ".xml" + } + } + }, + "System.Net.Security/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Net.Security.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.6/System.Net.Security.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Net.Security.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Net.Sockets/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Net.Sockets.dll": { + "related": ".xml" + } + } + }, + "System.Net.WebSockets.WebSocketProtocol/4.5.3": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Net.WebSockets.WebSocketProtocol.dll": {} + }, + "runtime": { + "lib/netcoreapp2.1/System.Net.WebSockets.WebSocketProtocol.dll": {} + } + }, + "System.Numerics.Vectors/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + } + }, + "System.ObjectModel/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.ObjectModel.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.ObjectModel.dll": {} + } + }, + "System.Private.DataContractSerialization/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0", + "System.Xml.XmlDocument": "4.3.0", + "System.Xml.XmlSerializer": "4.3.0" + }, + "compile": { + "ref/netstandard/_._": {} + }, + "runtime": { + "lib/netstandard1.3/System.Private.DataContractSerialization.dll": {} + } + }, + "System.Reflection/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.5/System.Reflection.dll": { + "related": ".xml" + } + } + }, + "System.Reflection.Emit/4.3.0": { + "type": "package", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.1/System.Reflection.Emit.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Reflection.Emit.dll": {} + } + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "type": "package", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Reflection.Emit.ILGeneration.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Reflection.Emit.ILGeneration.dll": {} + } + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "type": "package", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Reflection.Emit.Lightweight.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Reflection.Emit.Lightweight.dll": {} + } + }, + "System.Reflection.Extensions/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Reflection.Extensions.dll": { + "related": ".xml" + } + } + }, + "System.Reflection.Metadata/1.6.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/System.Reflection.Metadata.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Reflection.Metadata.dll": { + "related": ".xml" + } + } + }, + "System.Reflection.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Reflection.Primitives.dll": { + "related": ".xml" + } + } + }, + "System.Reflection.TypeExtensions/4.3.0": { + "type": "package", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.5/System.Reflection.TypeExtensions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.5/System.Reflection.TypeExtensions.dll": {} + } + }, + "System.Resources.ResourceManager/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Resources.ResourceManager.dll": { + "related": ".xml" + } + } + }, + "System.Runtime/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + }, + "compile": { + "ref/netstandard1.5/System.Runtime.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.CompilerServices.Unsafe/4.5.1": { + "type": "package", + "compile": { + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.Extensions/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.5/System.Runtime.Extensions.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.Handles/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Runtime.Handles.dll": { + "related": ".xml" + } + } + }, + "System.Runtime.InteropServices/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + }, + "compile": { + "ref/netcoreapp1.1/System.Runtime.InteropServices.dll": {} + } + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "type": "package", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + }, + "compile": { + "ref/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": {} + }, + "runtime": { + "lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Runtime.Numerics/4.3.0": { + "type": "package", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + }, + "compile": { + "ref/netstandard1.1/System.Runtime.Numerics.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Runtime.Numerics.dll": {} + } + }, + "System.Runtime.Serialization.Json/4.3.0": { + "type": "package", + "dependencies": { + "System.IO": "4.3.0", + "System.Private.DataContractSerialization": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Runtime.Serialization.Json.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Runtime.Serialization.Json.dll": {} + } + }, + "System.Runtime.Serialization.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Runtime.Serialization.Primitives.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Runtime.Serialization.Primitives.dll": {} + } + }, + "System.Runtime.Serialization.Xml/4.3.0": { + "type": "package", + "dependencies": { + "System.IO": "4.3.0", + "System.Private.DataContractSerialization": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Serialization.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Runtime.Serialization.Xml.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Runtime.Serialization.Xml.dll": {} + } + }, + "System.Security.AccessControl/4.5.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "2.0.0", + "System.Security.Principal.Windows": "4.5.0" + }, + "compile": { + "ref/netstandard2.0/System.Security.AccessControl.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.AccessControl.dll": {} + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp2.0/System.Security.AccessControl.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Claims/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Security.Claims.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Security.Claims.dll": {} + } + }, + "System.Security.Cryptography.Algorithms/4.3.1": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.1", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + }, + "compile": { + "ref/netstandard1.6/System.Security.Cryptography.Algorithms.dll": {} + }, + "runtimeTargets": { + "runtimes/osx/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll": { + "assetType": "runtime", + "rid": "osx" + }, + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.Cng/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.1/System.Security.Cryptography.Cng.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/System.Security.Cryptography.Cng.dll": {} + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp2.1/System.Security.Cryptography.Cng.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.Csp/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Csp.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Csp.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Security.Cryptography.Encoding.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + }, + "compile": { + "ref/netstandard1.6/_._": {} + }, + "runtime": { + "lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll": { + "assetType": "runtime", + "rid": "unix" + } + } + }, + "System.Security.Cryptography.Pkcs/4.5.0": { + "type": "package", + "dependencies": { + "System.Security.Cryptography.Cng": "4.5.0" + }, + "compile": { + "ref/netcoreapp2.1/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/System.Security.Cryptography.Pkcs.dll": {} + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp2.1/System.Security.Cryptography.Pkcs.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Security.Cryptography.Primitives.dll": {} + }, + "runtime": { + "lib/netstandard1.3/System.Security.Cryptography.Primitives.dll": {} + } + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + }, + "compile": { + "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.dll": { + "related": ".xml" + } + }, + "runtimeTargets": { + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Security.Cryptography.Xml/4.5.0": { + "type": "package", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + }, + "compile": { + "ref/netstandard2.0/System.Security.Cryptography.Xml.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.Cryptography.Xml.dll": {} + } + }, + "System.Security.Permissions/4.5.0": { + "type": "package", + "dependencies": { + "System.Security.AccessControl": "4.5.0" + }, + "compile": { + "ref/netstandard2.0/System.Security.Permissions.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.Permissions.dll": {} + } + }, + "System.Security.Principal/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.0/System.Security.Principal.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.0/System.Security.Principal.dll": {} + } + }, + "System.Security.Principal.Windows/4.5.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "2.0.0" + }, + "compile": { + "ref/netstandard2.0/System.Security.Principal.Windows.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Security.Principal.Windows.dll": {} + }, + "runtimeTargets": { + "runtimes/unix/lib/netcoreapp2.0/System.Security.Principal.Windows.dll": { + "assetType": "runtime", + "rid": "unix" + }, + "runtimes/win/lib/netcoreapp2.0/System.Security.Principal.Windows.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Spatial/5.8.4": { + "type": "package", + "compile": { + "lib/netstandard1.1/System.Spatial.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.1/System.Spatial.dll": { + "related": ".xml" + } + }, + "resource": { + "lib/netstandard1.1/de/System.Spatial.resources.dll": { + "locale": "de" + }, + "lib/netstandard1.1/es/System.Spatial.resources.dll": { + "locale": "es" + }, + "lib/netstandard1.1/fr/System.Spatial.resources.dll": { + "locale": "fr" + }, + "lib/netstandard1.1/it/System.Spatial.resources.dll": { + "locale": "it" + }, + "lib/netstandard1.1/ja/System.Spatial.resources.dll": { + "locale": "ja" + }, + "lib/netstandard1.1/ko/System.Spatial.resources.dll": { + "locale": "ko" + }, + "lib/netstandard1.1/ru/System.Spatial.resources.dll": { + "locale": "ru" + }, + "lib/netstandard1.1/zh-Hans/System.Spatial.resources.dll": { + "locale": "zh-Hans" + }, + "lib/netstandard1.1/zh-Hant/System.Spatial.resources.dll": { + "locale": "zh-Hant" + } + } + }, + "System.Text.Encoding/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Text.Encoding.dll": { + "related": ".xml" + } + } + }, + "System.Text.Encoding.CodePages/4.5.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "2.0.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.0" + }, + "compile": { + "ref/netstandard2.0/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Text.Encoding.CodePages.dll": {} + }, + "runtimeTargets": { + "runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll": { + "assetType": "runtime", + "rid": "win" + } + } + }, + "System.Text.Encoding.Extensions/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Text.Encoding.Extensions.dll": { + "related": ".xml" + } + } + }, + "System.Text.Encodings.Web/4.5.0": { + "type": "package", + "compile": { + "lib/netstandard2.0/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard2.0/System.Text.Encodings.Web.dll": { + "related": ".xml" + } + } + }, + "System.Text.RegularExpressions/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netcoreapp1.1/System.Text.RegularExpressions.dll": {} + }, + "runtime": { + "lib/netstandard1.6/System.Text.RegularExpressions.dll": {} + } + }, + "System.Threading/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Threading.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Threading.dll": {} + } + }, + "System.Threading.Channels/4.5.0": { + "type": "package", + "compile": { + "lib/netcoreapp2.1/System.Threading.Channels.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netcoreapp2.1/System.Threading.Channels.dll": { + "related": ".xml" + } + } + }, + "System.Threading.Tasks/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Threading.Tasks.dll": { + "related": ".xml" + } + } + }, + "System.Threading.Tasks.Extensions/4.5.1": { + "type": "package", + "compile": { + "ref/netcoreapp2.1/_._": {} + }, + "runtime": { + "lib/netcoreapp2.1/_._": {} + } + }, + "System.Threading.Tasks.Parallel/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + }, + "compile": { + "ref/netstandard1.1/System.Threading.Tasks.Parallel.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Threading.Tasks.Parallel.dll": {} + } + }, + "System.Threading.Thread/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Threading.Thread.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Threading.Thread.dll": {} + } + }, + "System.Threading.ThreadPool/4.3.0": { + "type": "package", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Threading.ThreadPool.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Threading.ThreadPool.dll": {} + } + }, + "System.Threading.Timer/4.3.0": { + "type": "package", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + }, + "compile": { + "ref/netstandard1.2/System.Threading.Timer.dll": { + "related": ".xml" + } + } + }, + "System.ValueTuple/4.5.0": { + "type": "package", + "compile": { + "ref/netcoreapp2.0/_._": {} + }, + "runtime": { + "lib/netcoreapp2.0/_._": {} + } + }, + "System.Xml.ReaderWriter/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Xml.ReaderWriter.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.ReaderWriter.dll": {} + } + }, + "System.Xml.XDocument/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Xml.XDocument.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.XDocument.dll": {} + } + }, + "System.Xml.XmlDocument/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/System.Xml.XmlDocument.dll": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.XmlDocument.dll": {} + } + }, + "System.Xml.XmlSerializer/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.XmlSerializer.dll": {} + } + }, + "System.Xml.XPath/4.3.0": { + "type": "package", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.XPath.dll": {} + } + }, + "System.Xml.XPath.XDocument/4.3.0": { + "type": "package", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0", + "System.Xml.XPath": "4.3.0" + }, + "compile": { + "ref/netstandard1.3/_._": { + "related": ".xml" + } + }, + "runtime": { + "lib/netstandard1.3/System.Xml.XPath.XDocument.dll": {} + } + }, + "WindowsAzure.Storage/8.1.4": { + "type": "package", + "dependencies": { + "Microsoft.Data.OData": "5.8.2", + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Spatial": "5.8.2" + }, + "compile": { + "lib/netstandard1.3/Microsoft.WindowsAzure.Storage.dll": { + "related": ".pdb" + } + }, + "runtime": { + "lib/netstandard1.3/Microsoft.WindowsAzure.Storage.dll": { + "related": ".pdb" + } + } + }, + "FSO.Common/1.0.0": { + "type": "project", + "compile": { + "bin/placeholder/FSO.Common.dll": {} + }, + "runtime": { + "bin/placeholder/FSO.Common.dll": {} + } + }, + "FSO.Server.Common/1.0.0": { + "type": "project", + "dependencies": { + "FSO.Common": "1.0.0" + }, + "compile": { + "bin/placeholder/FSO.Server.Common.dll": {} + }, + "runtime": { + "bin/placeholder/FSO.Server.Common.dll": {} + } + }, + "FSO.Server.Database/1.0.0": { + "type": "project", + "dependencies": { + "FSO.Common": "1.0.0", + "FSO.Server.Common": "1.0.0" + }, + "compile": { + "bin/placeholder/FSO.Server.Database.dll": {} + }, + "runtime": { + "bin/placeholder/FSO.Server.Database.dll": {} + } + }, + "FSO.Server.Domain/1.0.0": { + "type": "project", + "dependencies": { + "FSO.Common": "1.0.0", + "FSO.Server.Common": "1.0.0", + "FSO.Server.Database": "1.0.0", + "FSO.Server.Protocol": "1.0.0" + }, + "compile": { + "bin/placeholder/FSO.Server.Domain.dll": {} + }, + "runtime": { + "bin/placeholder/FSO.Server.Domain.dll": {} + } + }, + "FSO.Server.Protocol/1.0.0": { + "type": "project", + "dependencies": { + "FSO.Common": "1.0.0", + "FSO.Server.Common": "1.0.0" + }, + "compile": { + "bin/placeholder/FSO.Server.Protocol.dll": {} + }, + "runtime": { + "bin/placeholder/FSO.Server.Protocol.dll": {} + } + } + } + }, + "libraries": { + "AWSSDK.Core/3.3.103.48": { + "sha512": "ltX0YbyTvGsR+69YLNnxO9l3isOh/ceoq7EwJsRqTB0a64qQh2kUtZV+enFxTsixDTlXfXBOzHVPjwLZ8wE4Dg==", + "type": "package", + "path": "awssdk.core/3.3.103.48", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "awssdk.core.3.3.103.48.nupkg.sha512", + "awssdk.core.nuspec", + "lib/MonoAndroid10/AWSSDK.Core.XML", + "lib/MonoAndroid10/AWSSDK.Core.dll", + "lib/MonoAndroid10/AWSSDK.Core.pdb", + "lib/MonoTouch10/AWSSDK.Core.XML", + "lib/MonoTouch10/AWSSDK.Core.dll", + "lib/Xamarin.Mac20/AWSSDK.Core.XML", + "lib/Xamarin.Mac20/AWSSDK.Core.dll", + "lib/Xamarin.iOS10/AWSSDK.Core.XML", + "lib/Xamarin.iOS10/AWSSDK.Core.dll", + "lib/net35/AWSSDK.Core.dll", + "lib/net35/AWSSDK.Core.pdb", + "lib/net35/AWSSDK.Core.xml", + "lib/net45/AWSSDK.Core.dll", + "lib/net45/AWSSDK.Core.pdb", + "lib/net45/AWSSDK.Core.xml", + "lib/netstandard1.3/AWSSDK.Core.dll", + "lib/netstandard1.3/AWSSDK.Core.pdb", + "lib/netstandard1.3/AWSSDK.Core.xml", + "lib/netstandard2.0/AWSSDK.Core.dll", + "lib/netstandard2.0/AWSSDK.Core.pdb", + "lib/netstandard2.0/AWSSDK.Core.xml", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.Core.XML", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.Core.dll", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.Core.pdb", + "lib/uap/AWSSDK.Core.XML", + "lib/uap/AWSSDK.Core.dll", + "lib/uap/AWSSDK.Core.pdb", + "lib/win8/AWSSDK.Core.XML", + "lib/win8/AWSSDK.Core.dll", + "lib/win8/AWSSDK.Core.pdb", + "lib/wp8/AWSSDK.Core.XML", + "lib/wp8/AWSSDK.Core.dll", + "lib/wp8/AWSSDK.Core.pdb", + "lib/wpa81/AWSSDK.Core.XML", + "lib/wpa81/AWSSDK.Core.dll", + "lib/wpa81/AWSSDK.Core.pdb", + "tools/account-management.ps1" + ] + }, + "AWSSDK.S3/3.3.104.36": { + "sha512": "IJcpjWWqX9HFJfKdzcduurCiPfidJQ33xLnd/efcWSNtS95S8JugDy1KNpirJueDpLNZdXR9u69q6Ru+upsZ6A==", + "type": "package", + "path": "awssdk.s3/3.3.104.36", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "analyzers/dotnet/cs/AWSSDK.S3.CodeAnalysis.dll", + "awssdk.s3.3.3.104.36.nupkg.sha512", + "awssdk.s3.nuspec", + "lib/MonoAndroid10/AWSSDK.S3.XML", + "lib/MonoAndroid10/AWSSDK.S3.dll", + "lib/MonoTouch10/AWSSDK.S3.XML", + "lib/MonoTouch10/AWSSDK.S3.dll", + "lib/MonoTouch10/AWSSDK.S3.pdb", + "lib/Xamarin.iOS10/AWSSDK.S3.XML", + "lib/Xamarin.iOS10/AWSSDK.S3.dll", + "lib/net35/AWSSDK.S3.dll", + "lib/net35/AWSSDK.S3.pdb", + "lib/net35/AWSSDK.S3.xml", + "lib/net45/AWSSDK.S3.dll", + "lib/net45/AWSSDK.S3.pdb", + "lib/net45/AWSSDK.S3.xml", + "lib/netstandard1.3/AWSSDK.S3.dll", + "lib/netstandard1.3/AWSSDK.S3.pdb", + "lib/netstandard1.3/AWSSDK.S3.xml", + "lib/netstandard2.0/AWSSDK.S3.dll", + "lib/netstandard2.0/AWSSDK.S3.pdb", + "lib/netstandard2.0/AWSSDK.S3.xml", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.S3.XML", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.S3.dll", + "lib/portable-net45+win8+wpa81+wp8/AWSSDK.S3.pdb", + "lib/uap/AWSSDK.S3.XML", + "lib/uap/AWSSDK.S3.dll", + "lib/uap/AWSSDK.S3.pdb", + "tools/install.ps1", + "tools/uninstall.ps1" + ] + }, + "Libuv/1.10.0": { + "sha512": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==", + "type": "package", + "path": "libuv/1.10.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "License.txt", + "libuv.1.10.0.nupkg.sha512", + "libuv.nuspec", + "runtimes/linux-arm/native/libuv.so", + "runtimes/linux-arm64/native/libuv.so", + "runtimes/linux-armel/native/libuv.so", + "runtimes/linux-x64/native/libuv.so", + "runtimes/osx/native/libuv.dylib", + "runtimes/win-arm/native/libuv.dll", + "runtimes/win-x64/native/libuv.dll", + "runtimes/win-x86/native/libuv.dll" + ] + }, + "MessagePack/1.7.3.7": { + "sha512": "gyJ8m987yI1O7h4P2DS7YjOfOWqJ+WcvX/jST+vYxCt004FYRm6cHfCK20fa1ehpQhOwRIezVennku+pFWwtiw==", + "type": "package", + "path": "messagepack/1.7.3.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/MessagePack.dll", + "lib/net45/MessagePack.xml", + "lib/net47/MessagePack.dll", + "lib/net47/MessagePack.xml", + "lib/netstandard1.6/MessagePack.dll", + "lib/netstandard1.6/MessagePack.xml", + "lib/netstandard2.0/MessagePack.dll", + "lib/netstandard2.0/MessagePack.xml", + "messagepack.1.7.3.7.nupkg.sha512", + "messagepack.nuspec" + ] + }, + "Microsoft.ApplicationInsights/2.4.0": { + "sha512": "4dX/zu3Psz9oM3ErU64xfOHuSxOwMxN6q5RabSkeYbX42Yn6dR/kDToqjs+txCRjrfHUxyYjfeJHu+MbCfvAsg==", + "type": "package", + "path": "microsoft.applicationinsights/2.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net40/Microsoft.ApplicationInsights.XML", + "lib/net40/Microsoft.ApplicationInsights.dll", + "lib/net45/Microsoft.ApplicationInsights.XML", + "lib/net45/Microsoft.ApplicationInsights.dll", + "lib/net46/Microsoft.ApplicationInsights.XML", + "lib/net46/Microsoft.ApplicationInsights.dll", + "lib/netstandard1.3/Microsoft.ApplicationInsights.XML", + "lib/netstandard1.3/Microsoft.ApplicationInsights.dll", + "lib/portable-win81+wpa81/Microsoft.ApplicationInsights.dll", + "lib/uap10.0/Microsoft.ApplicationInsights.dll", + "lib/wp8/Microsoft.ApplicationInsights.dll", + "microsoft.applicationinsights.2.4.0.nupkg.sha512", + "microsoft.applicationinsights.nuspec" + ] + }, + "Microsoft.ApplicationInsights.AspNetCore/2.1.1": { + "sha512": "kiGmzl9Cav34dF7AHVMoJxdJJQEeLB8KZGNwX1LjImG9iem5hGk4DkHpW7/m9Nh3DrL8IKSL3mqQo+IPqWfMRQ==", + "type": "package", + "path": "microsoft.applicationinsights.aspnetcore/2.1.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net451/Microsoft.ApplicationInsights.AspNetCore.dll", + "lib/net451/Microsoft.ApplicationInsights.AspNetCore.xml", + "lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.dll", + "lib/netstandard1.6/Microsoft.ApplicationInsights.AspNetCore.xml", + "microsoft.applicationinsights.aspnetcore.2.1.1.nupkg.sha512", + "microsoft.applicationinsights.aspnetcore.nuspec" + ] + }, + "Microsoft.ApplicationInsights.DependencyCollector/2.4.1": { + "sha512": "RWxdX90MY6tNF8S5lwRvJcHiBMIWwVLCxd4TGIEl3X0yAKaolY2vs4zTCvyCIVkEAMs1aInTgWkYwOjzYvAHWw==", + "type": "package", + "path": "microsoft.applicationinsights.dependencycollector/2.4.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "content/ApplicationInsights.config.install.xdt", + "content/ApplicationInsights.config.transform", + "content/ApplicationInsights.config.uninstall.xdt", + "lib/net40/Microsoft.AI.DependencyCollector.XML", + "lib/net40/Microsoft.AI.DependencyCollector.dll", + "lib/net45/Microsoft.AI.DependencyCollector.XML", + "lib/net45/Microsoft.AI.DependencyCollector.dll", + "lib/netstandard1.6/Microsoft.AI.DependencyCollector.dll", + "lib/netstandard1.6/Microsoft.AI.DependencyCollector.xml", + "microsoft.applicationinsights.dependencycollector.2.4.1.nupkg.sha512", + "microsoft.applicationinsights.dependencycollector.nuspec" + ] + }, + "Microsoft.AspNet.WebApi.Client/5.2.6": { + "sha512": "owAlEIUZXWSnkK8Z1c+zR47A0X6ykF4XjbPok4lQKNuciUfHLGPd6QnI+rt/8KlQ17PmF+I4S3f+m+Qe4IvViw==", + "type": "package", + "path": "microsoft.aspnet.webapi.client/5.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/System.Net.Http.Formatting.dll", + "lib/net45/System.Net.Http.Formatting.xml", + "lib/netstandard2.0/System.Net.Http.Formatting.dll", + "lib/netstandard2.0/System.Net.Http.Formatting.xml", + "lib/portable-wp8+netcore45+net45+wp81+wpa81/System.Net.Http.Formatting.dll", + "lib/portable-wp8+netcore45+net45+wp81+wpa81/System.Net.Http.Formatting.xml", + "microsoft.aspnet.webapi.client.5.2.6.nupkg.sha512", + "microsoft.aspnet.webapi.client.nuspec" + ] + }, + "Microsoft.AspNetCore/2.2.0": { + "sha512": "Bs75iht4lXS8uVWy/Cbsr9i0m2jRtnrfPEWU+6t0dQTZcJEfF9b7G2F7XvstLFWkAKSgYRzFkAwi/KypY0Qtew==", + "type": "package", + "path": "microsoft.aspnetcore/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.xml", + "microsoft.aspnetcore.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.nuspec" + ] + }, + "Microsoft.AspNetCore.All/2.2.7": { + "sha512": "2fFYF3ifJOnB5bk7ZCXCE7IRI04f15fYbiIvbIyEVIG6H/TgQBtzggCCjx655bU7CBJNrZKVXD3RYh2ovzt4Cw==", + "type": "package", + "path": "microsoft.aspnetcore.all/2.2.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netcoreapp2.2/Microsoft.AspNetCore.All.props", + "build/netcoreapp2.2/Microsoft.AspNetCore.All.targets", + "lib/netcoreapp2.2/_._", + "microsoft.aspnetcore.all.2.2.7.nupkg.sha512", + "microsoft.aspnetcore.all.nuspec" + ] + }, + "Microsoft.AspNetCore.Antiforgery/2.2.0": { + "sha512": "fVQsSXNZz38Ysx8iKwwqfOLHhLrAeKEMBS5Ia3Lh7BJjOC2vPV28/yk08AovOMsB3SNQPGnE7bv+lsIBTmAkvw==", + "type": "package", + "path": "microsoft.aspnetcore.antiforgery/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Antiforgery.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Antiforgery.xml", + "microsoft.aspnetcore.antiforgery.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.antiforgery.nuspec" + ] + }, + "Microsoft.AspNetCore.App/2.2.8": { + "sha512": "C8bHuH9mFLRO9GaAkrmWPrBzdOjzFbXHijzy66/Uff84j2wr/PVVol97mQlQaDB74W13oL8xE7mY6LJcm6zcrg==", + "type": "package", + "path": "microsoft.aspnetcore.app/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netcoreapp2.2/Microsoft.AspNetCore.App.props", + "build/netcoreapp2.2/Microsoft.AspNetCore.App.targets", + "lib/netcoreapp2.2/_._", + "microsoft.aspnetcore.app.2.2.8.nupkg.sha512", + "microsoft.aspnetcore.app.nuspec" + ] + }, + "Microsoft.AspNetCore.ApplicationInsights.HostingStartup/2.2.0": { + "sha512": "Flh4ch1+uQdU5s0rjCYe07Q8ZPyB88QU2ctPL0eqqafxnXcEDPi6deftmGrMJ5MCiiM7JVYf8OyxV3DDworHwA==", + "type": "package", + "path": "microsoft.aspnetcore.applicationinsights.hostingstartup/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net461/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll", + "lib/net461/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.xml", + "lib/netcoreapp2.0/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll", + "lib/netcoreapp2.0/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.xml", + "lib/netcoreapp2.1/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.ApplicationInsights.HostingStartup.xml", + "microsoft.aspnetcore.applicationinsights.hostingstartup.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.applicationinsights.hostingstartup.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication/2.2.0": { + "sha512": "b0R9X7L6zMqNsssKDvhYHuNi5x0s4DyHTeXybIAyGaitKiW1Q5aAGKdV2codHPiePv9yHfC9hAMyScXQ/xXhPw==", + "type": "package", + "path": "microsoft.aspnetcore.authentication/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.xml", + "microsoft.aspnetcore.authentication.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Abstractions/2.2.0": { + "sha512": "VloMLDJMf3n/9ic5lCBOa42IBYJgyB1JhzLsL68Zqg+2bEPWfGBj/xCJy/LrKTArN0coOcZp3wyVTZlx0y9pHQ==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Abstractions.xml", + "microsoft.aspnetcore.authentication.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Cookies/2.2.0": { + "sha512": "Iar9VFlBHkZGdSG9ZUTmn6Q8Qg+6CtW5G/TyJI2F8B432TOH+nZlkU7O0W0byow6xsxqOYeTviSHz4cCJ3amfQ==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.cookies/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Cookies.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Cookies.xml", + "microsoft.aspnetcore.authentication.cookies.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.cookies.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Core/2.2.0": { + "sha512": "XlVJzJ5wPOYW+Y0J6Q/LVTEyfS4ssLXmt60T0SPP+D8abVhBTl+cgw2gDHlyKYIkcJg7btMVh383NDkMVqD/fg==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.core/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Core.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Core.xml", + "microsoft.aspnetcore.authentication.core.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.core.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Facebook/2.2.0": { + "sha512": "SOc/wjoBntSWVZ6uG0R/TqQ0xmxu2H1PhkuYxINYpkUB7s3cQQuRDyZtJIdQonzpWVwBRj0ImwktiMaBF/7ihQ==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.facebook/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Facebook.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Facebook.xml", + "microsoft.aspnetcore.authentication.facebook.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.facebook.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Google/2.2.2": { + "sha512": "oiCm+HAkkP9vBEBmqIuq+mz+ZxMRrnXviHepSChCFvpJvjYm5vWjpqD+L8JMQaGUTs3k4hycjgWbmhd/3bJx/A==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.google/2.2.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Google.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Google.xml", + "microsoft.aspnetcore.authentication.google.2.2.2.nupkg.sha512", + "microsoft.aspnetcore.authentication.google.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.JwtBearer/2.2.0": { + "sha512": "FnyoLdiIo8KDobVcDuUYYFSbQYp1OR8vSMIOcW6M5+dtF9TC6XvCCS8Ook+DSbqUj6HPxwOIKa5BeIZm1/EpMw==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.jwtbearer/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.JwtBearer.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.JwtBearer.xml", + "microsoft.aspnetcore.authentication.jwtbearer.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.jwtbearer.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.MicrosoftAccount/2.2.0": { + "sha512": "troBjvJAMK7P2Vb5sDOzCztq9vR8BJtajDznam2XuQai7kLh5z7cmkB+2zMin+K/HzNjqItJSuSyuaK2PoZ8nA==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.microsoftaccount/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.MicrosoftAccount.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.MicrosoftAccount.xml", + "microsoft.aspnetcore.authentication.microsoftaccount.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.microsoftaccount.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.OAuth/2.2.0": { + "sha512": "i33SSdJd0g3ENRnHczgzrOlru3ciPsyYHMgAh90sbURS8wuBx0Y4xXfRQcYfu1W0/uiHQO832KNb/ICINWqLzA==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.oauth/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OAuth.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OAuth.xml", + "microsoft.aspnetcore.authentication.oauth.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.oauth.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect/2.2.0": { + "sha512": "y4iu3vMFnkMTaqT9mCJhD3XUMfavNP0CoOeNOHd7ArqZfgzs3GqAPcBc8Ld6mK2u5OOva8C6bhnQfRu9z0qJKQ==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.openidconnect/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OpenIdConnect.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.OpenIdConnect.xml", + "microsoft.aspnetcore.authentication.openidconnect.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.openidconnect.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.Twitter/2.2.0": { + "sha512": "wKfJeBL+13duv0o4q9zp4pW7UopBHaLafnq2GiIJTcu1x3RR/1N4sRIIppLSIJdulgM1XfNOivlIE2FEfZpmog==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.twitter/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Twitter.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.Twitter.xml", + "microsoft.aspnetcore.authentication.twitter.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.twitter.nuspec" + ] + }, + "Microsoft.AspNetCore.Authentication.WsFederation/2.2.0": { + "sha512": "TIBkO7Tx8uWXNL5Z7/6+iKdhTS+D9dpJMNcmiVxrAJUqxL4EWGHNqJyUp5yqI76GmbrT4GD23T3cUsSuCi7E0A==", + "type": "package", + "path": "microsoft.aspnetcore.authentication.wsfederation/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.WsFederation.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authentication.WsFederation.xml", + "microsoft.aspnetcore.authentication.wsfederation.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authentication.wsfederation.nuspec" + ] + }, + "Microsoft.AspNetCore.Authorization/2.2.0": { + "sha512": "/L0W8H3jMYWyaeA9gBJqS/tSWBegP9aaTM0mjRhxTttBY9z4RVDRYJ2CwPAmAXIuPr3r1sOw+CS8jFVRGHRezQ==", + "type": "package", + "path": "microsoft.aspnetcore.authorization/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.xml", + "microsoft.aspnetcore.authorization.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authorization.nuspec" + ] + }, + "Microsoft.AspNetCore.Authorization.Policy/2.2.0": { + "sha512": "aJCo6niDRKuNg2uS2WMEmhJTooQUGARhV2ENQ2tO5443zVHUo19MSgrgGo9FIrfD+4yKPF8Q+FF33WkWfPbyKw==", + "type": "package", + "path": "microsoft.aspnetcore.authorization.policy/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.Policy.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Authorization.Policy.xml", + "microsoft.aspnetcore.authorization.policy.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.authorization.policy.nuspec" + ] + }, + "Microsoft.AspNetCore.AzureAppServices.HostingStartup/2.2.5": { + "sha512": "tCSKgBt6OQ6JKUhB8xSc8+q404vQc9Vclvp1me8t2QEEPPLkjkUQrI11dE5v/8ODUlxhKtKYTrO2+sFL68FOhA==", + "type": "package", + "path": "microsoft.aspnetcore.azureappservices.hostingstartup/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net461/Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll", + "lib/net461/Microsoft.AspNetCore.AzureAppServices.HostingStartup.xml", + "lib/netcoreapp2.0/Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll", + "lib/netcoreapp2.0/Microsoft.AspNetCore.AzureAppServices.HostingStartup.xml", + "lib/netcoreapp2.1/Microsoft.AspNetCore.AzureAppServices.HostingStartup.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.AzureAppServices.HostingStartup.xml", + "microsoft.aspnetcore.azureappservices.hostingstartup.2.2.5.nupkg.sha512", + "microsoft.aspnetcore.azureappservices.hostingstartup.nuspec" + ] + }, + "Microsoft.AspNetCore.AzureAppServicesIntegration/2.2.5": { + "sha512": "WngdrV/8vlU7KBWBL3vfcRze7GdfjpdR2YDiqOhY2xtYPn8nl34PasLQ+h6c7jHPao+kiBqjVFL0FJo/X46wiA==", + "type": "package", + "path": "microsoft.aspnetcore.azureappservicesintegration/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.AzureAppServicesIntegration.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.AzureAppServicesIntegration.xml", + "microsoft.aspnetcore.azureappservicesintegration.2.2.5.nupkg.sha512", + "microsoft.aspnetcore.azureappservicesintegration.nuspec" + ] + }, + "Microsoft.AspNetCore.Connections.Abstractions/2.2.0": { + "sha512": "Aqr/16Cu5XmGv7mLKJvXRxhhd05UJ7cTTSaUV4MZ3ynAzfgWjsAdpIU8FWuxwAjmVdmI8oOWuVDrbs+sRkhKnA==", + "type": "package", + "path": "microsoft.aspnetcore.connections.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Connections.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Connections.Abstractions.xml", + "microsoft.aspnetcore.connections.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.connections.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.CookiePolicy/2.2.8": { + "sha512": "71BSJnZquxKXyqvC8CRPVZz+WqIxpzwNZWPMAxDdINWAMAXjXFi53bIiVW2+uiSypyIavECkt1ty/V12Yc1vnw==", + "type": "package", + "path": "microsoft.aspnetcore.cookiepolicy/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.CookiePolicy.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.CookiePolicy.xml", + "microsoft.aspnetcore.cookiepolicy.2.2.8.nupkg.sha512", + "microsoft.aspnetcore.cookiepolicy.nuspec" + ] + }, + "Microsoft.AspNetCore.Cors/2.2.0": { + "sha512": "LFlTM3ThS3ZCILuKnjy8HyK9/IlDh3opogdbCVx6tMGyDzTQBgMPXLjGDLtMk5QmLDCcP3l1TO3z/+1viA8GUg==", + "type": "package", + "path": "microsoft.aspnetcore.cors/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Cors.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Cors.xml", + "microsoft.aspnetcore.cors.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.cors.nuspec" + ] + }, + "Microsoft.AspNetCore.Cryptography.Internal/2.2.0": { + "sha512": "GXmMD8/vuTLPLvKzKEPz/4vapC5e0cwx1tUVd83ePRyWF9CCrn/pg4/1I+tGkQqFLPvi3nlI2QtPtC6MQN8Nww==", + "type": "package", + "path": "microsoft.aspnetcore.cryptography.internal/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.Internal.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.Internal.xml", + "microsoft.aspnetcore.cryptography.internal.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.cryptography.internal.nuspec" + ] + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation/2.2.0": { + "sha512": "NCY0PH3nrFYbhqiq72rwWsUXlV4OAE0MOukvGvIBOTnEPMC1yVL42k1DXLnaIu+c0yfMAxIIG9Iuaykp9BQQQw==", + "type": "package", + "path": "microsoft.aspnetcore.cryptography.keyderivation/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll", + "lib/netcoreapp2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Cryptography.KeyDerivation.xml", + "microsoft.aspnetcore.cryptography.keyderivation.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.cryptography.keyderivation.nuspec" + ] + }, + "Microsoft.AspNetCore.DataProtection/2.2.0": { + "sha512": "G6dvu5Nd2vjpYbzazZ//qBFbSEf2wmBUbyAR7E4AwO3gWjhoJD5YxpThcGJb7oE3VUcW65SVMXT+cPCiiBg8Sg==", + "type": "package", + "path": "microsoft.aspnetcore.dataprotection/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.xml", + "microsoft.aspnetcore.dataprotection.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.dataprotection.nuspec" + ] + }, + "Microsoft.AspNetCore.DataProtection.Abstractions/2.2.0": { + "sha512": "seANFXmp8mb5Y12m1ShiElJ3ZdOT3mBN3wA1GPhHJIvZ/BxOCPyqEOR+810OWsxEZwA5r5fDRNpG/CqiJmQnJg==", + "type": "package", + "path": "microsoft.aspnetcore.dataprotection.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Abstractions.xml", + "microsoft.aspnetcore.dataprotection.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.dataprotection.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.DataProtection.AzureKeyVault/2.2.0": { + "sha512": "oaJcyTD8fBCrmDHVLxVI2gXfFmRSiyy/H6GAdcFCPLnI8ie+L9ZH5Aq+8tb3NWuE3R/J7aJHGThiDWx1BBDfoA==", + "type": "package", + "path": "microsoft.aspnetcore.dataprotection.azurekeyvault/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureKeyVault.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureKeyVault.xml", + "microsoft.aspnetcore.dataprotection.azurekeyvault.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.dataprotection.azurekeyvault.nuspec" + ] + }, + "Microsoft.AspNetCore.DataProtection.AzureStorage/2.2.7": { + "sha512": "MBwvXb+I/VSOm0lCcvGOxIqVqoB+jDkR2LdGcPInxN5pSu56vIeWUI8RVr8RZzfa7UokclJsBkfO64qEeeAjYQ==", + "type": "package", + "path": "microsoft.aspnetcore.dataprotection.azurestorage/2.2.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureStorage.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.AzureStorage.xml", + "microsoft.aspnetcore.dataprotection.azurestorage.2.2.7.nupkg.sha512", + "microsoft.aspnetcore.dataprotection.azurestorage.nuspec" + ] + }, + "Microsoft.AspNetCore.DataProtection.Extensions/2.2.0": { + "sha512": "Goo1xU9WJnEJ0dKDgYFF+hFQqRMLKjf9zc8Bu3PaBdGncR7QwDMeFIkO7FEM6izaC38QjYrs1Q5AsmljkPyOrw==", + "type": "package", + "path": "microsoft.aspnetcore.dataprotection.extensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Extensions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.DataProtection.Extensions.xml", + "microsoft.aspnetcore.dataprotection.extensions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.dataprotection.extensions.nuspec" + ] + }, + "Microsoft.AspNetCore.Diagnostics/2.2.0": { + "sha512": "RobNuZecn/eefWVApOE+OWAZXCdgfzm8pB7tBvJkahsjWfn1a+bLM9I2cuKlp/9aFBok1O/oDXlgYSvaQYu/yg==", + "type": "package", + "path": "microsoft.aspnetcore.diagnostics/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.xml", + "microsoft.aspnetcore.diagnostics.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.diagnostics.nuspec" + ] + }, + "Microsoft.AspNetCore.Diagnostics.Abstractions/2.2.0": { + "sha512": "pva9ggfUDtnJIKzv0+wxwTX7LduDx6xLSpMqWwdOJkW52L0t31PI78+v+WqqMpUtMzcKug24jGs3nTFpAmA/2g==", + "type": "package", + "path": "microsoft.aspnetcore.diagnostics.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.Abstractions.xml", + "microsoft.aspnetcore.diagnostics.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.diagnostics.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore/2.2.1": { + "sha512": "bHR6mCzZifAeRogJBght6gwFYbGOVUTM+mcyMbM2U9/lilQ6B8VEZaCQRKrUv45nMrYRMJMKi71MRAWrwnQ2OA==", + "type": "package", + "path": "microsoft.aspnetcore.diagnostics.entityframeworkcore/2.2.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.xml", + "microsoft.aspnetcore.diagnostics.entityframeworkcore.2.2.1.nupkg.sha512", + "microsoft.aspnetcore.diagnostics.entityframeworkcore.nuspec" + ] + }, + "Microsoft.AspNetCore.Diagnostics.HealthChecks/2.2.0": { + "sha512": "RNmdLy9yncTprony49cuwhyTKoROpVflGM+pKlHA1671F00QUsjoY1Oi6xoa9XsUrfRDRYlxbt2CHYCMLzMh7Q==", + "type": "package", + "path": "microsoft.aspnetcore.diagnostics.healthchecks/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.HealthChecks.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Diagnostics.HealthChecks.xml", + "microsoft.aspnetcore.diagnostics.healthchecks.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.diagnostics.healthchecks.nuspec" + ] + }, + "Microsoft.AspNetCore.HostFiltering/2.2.0": { + "sha512": "JSX6ZlVWDkokZ+xCKDhUVQNqbmFn1lHQNzJc8K4Y/uTUocZS83+b/8Q7y/yx3oJ362etGMVy0keAvmCdqbP8nA==", + "type": "package", + "path": "microsoft.aspnetcore.hostfiltering/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.HostFiltering.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.HostFiltering.xml", + "microsoft.aspnetcore.hostfiltering.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.hostfiltering.nuspec" + ] + }, + "Microsoft.AspNetCore.Hosting/2.2.7": { + "sha512": "O0ZBE53Fa9bVGXykDzvgMFW0Pe1QyPPFg1pazN8l3RUFSWBsDJ9/iD1LHXgADA8+ZD3R/1zkvraPa9SZdievxQ==", + "type": "package", + "path": "microsoft.aspnetcore.hosting/2.2.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.xml", + "microsoft.aspnetcore.hosting.2.2.7.nupkg.sha512", + "microsoft.aspnetcore.hosting.nuspec" + ] + }, + "Microsoft.AspNetCore.Hosting.Abstractions/2.2.0": { + "sha512": "ubycklv+ZY7Kutdwuy1W4upWcZ6VFR8WUXU7l7B2+mvbDBBPAcfpi+E+Y5GFe+Q157YfA3C49D2GCjAZc7Mobw==", + "type": "package", + "path": "microsoft.aspnetcore.hosting.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Abstractions.xml", + "microsoft.aspnetcore.hosting.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.hosting.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions/2.2.0": { + "sha512": "1PMijw8RMtuQF60SsD/JlKtVfvh4NORAhF4wjysdABhlhTrYmtgssqyncR0Stq5vqtjplZcj6kbT4LRTglt9IQ==", + "type": "package", + "path": "microsoft.aspnetcore.hosting.server.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Hosting.Server.Abstractions.xml", + "microsoft.aspnetcore.hosting.server.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.hosting.server.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Html.Abstractions/2.2.0": { + "sha512": "Y4rs5aMEXY8G7wJo5S3EEt6ltqyOTr/qOeZzfn+hw/fuQj5GppGckMY5psGLETo1U9hcT5MmAhaT5xtusM1b5g==", + "type": "package", + "path": "microsoft.aspnetcore.html.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Html.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Html.Abstractions.xml", + "microsoft.aspnetcore.html.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.html.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Http/2.2.2": { + "sha512": "BAibpoItxI5puk7YJbIGj95arZueM8B8M5xT1fXBn3hb3L2G3ucrZcYXv1gXdaroLbntUs8qeV8iuBrpjQsrKw==", + "type": "package", + "path": "microsoft.aspnetcore.http/2.2.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.xml", + "microsoft.aspnetcore.http.2.2.2.nupkg.sha512", + "microsoft.aspnetcore.http.nuspec" + ] + }, + "Microsoft.AspNetCore.Http.Abstractions/2.2.0": { + "sha512": "Nxs7Z1q3f1STfLYKJSVXCs1iBl+Ya6E8o4Oy1bCxJ/rNI44E/0f6tbsrVqAWfB7jlnJfyaAtIalBVxPKUPQb4Q==", + "type": "package", + "path": "microsoft.aspnetcore.http.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Abstractions.xml", + "microsoft.aspnetcore.http.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.http.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Http.Connections/1.1.0": { + "sha512": "ZcwAM9rE5yjGC+vtiNAK0INybpKIqnvB+/rntZn2/CPtyiBAtovVrEp4UZOoC31zH5t0P78ix9gLNJzII/ODsA==", + "type": "package", + "path": "microsoft.aspnetcore.http.connections/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.2/Microsoft.AspNetCore.Http.Connections.dll", + "lib/netcoreapp2.2/Microsoft.AspNetCore.Http.Connections.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.xml", + "microsoft.aspnetcore.http.connections.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.http.connections.nuspec" + ] + }, + "Microsoft.AspNetCore.Http.Connections.Common/1.1.0": { + "sha512": "mYk5QUUjyXQmlyDHWDjkLYDArt97plwe6KsDsNVhDEQ+HgZMKGjISyM6YSA7BERQNR25kXBTbIYfSy1vePGQgg==", + "type": "package", + "path": "microsoft.aspnetcore.http.connections.common/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.Common.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Connections.Common.xml", + "microsoft.aspnetcore.http.connections.common.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.http.connections.common.nuspec" + ] + }, + "Microsoft.AspNetCore.Http.Extensions/2.2.0": { + "sha512": "2DgZ9rWrJtuR7RYiew01nGRzuQBDaGHGmK56Rk54vsLLsCdzuFUPqbDTJCS1qJQWTbmbIQ9wGIOjpxA1t0l7/w==", + "type": "package", + "path": "microsoft.aspnetcore.http.extensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Extensions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Extensions.xml", + "microsoft.aspnetcore.http.extensions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.http.extensions.nuspec" + ] + }, + "Microsoft.AspNetCore.Http.Features/2.2.0": { + "sha512": "ziFz5zH8f33En4dX81LW84I6XrYXKf9jg6aM39cM+LffN9KJahViKZ61dGMSO2gd3e+qe5yBRwsesvyqlZaSMg==", + "type": "package", + "path": "microsoft.aspnetcore.http.features/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Features.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Http.Features.xml", + "microsoft.aspnetcore.http.features.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.http.features.nuspec" + ] + }, + "Microsoft.AspNetCore.HttpOverrides/2.2.0": { + "sha512": "pOlLQyNKQduGbtbgB55RyTHFeshSfKi3DmofrVjk+UBQjyp+Tm0RNNJFQf+sv34hlFsel+VnD79QyO9Zk/c3oA==", + "type": "package", + "path": "microsoft.aspnetcore.httpoverrides/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.HttpOverrides.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.HttpOverrides.xml", + "microsoft.aspnetcore.httpoverrides.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.httpoverrides.nuspec" + ] + }, + "Microsoft.AspNetCore.HttpsPolicy/2.2.0": { + "sha512": "0EmmwzAkWEPCC8rpg9nGfcOiitIOYkZ13f+b5ED7AAZvz/ZwkdWbeMarGf77lSyA+Mb9O/iAt4LWup0RRMVOJw==", + "type": "package", + "path": "microsoft.aspnetcore.httpspolicy/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.HttpsPolicy.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.HttpsPolicy.xml", + "microsoft.aspnetcore.httpspolicy.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.httpspolicy.nuspec" + ] + }, + "Microsoft.AspNetCore.Identity/2.2.0": { + "sha512": "F16BKeS96wKhyIyhaFR7m8kRIwIvPUW9Dx7IlGWmu2IIwnUDCdo+2z7IrWKA8r77pZQ1UE9kYcBPg5456YdAIA==", + "type": "package", + "path": "microsoft.aspnetcore.identity/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.xml", + "microsoft.aspnetcore.identity.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.identity.nuspec" + ] + }, + "Microsoft.AspNetCore.Identity.EntityFrameworkCore/2.2.0": { + "sha512": "PGJ8f8sE9vbnyPJpSCMYAjh1itkM8uL9QnkO5lQSSJGeyG4b1+zNoLS+leJgjGnlkTzgWPffc4OuqH7wsYahWw==", + "type": "package", + "path": "microsoft.aspnetcore.identity.entityframeworkcore/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.EntityFrameworkCore.xml", + "microsoft.aspnetcore.identity.entityframeworkcore.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.identity.entityframeworkcore.nuspec" + ] + }, + "Microsoft.AspNetCore.Identity.UI/2.2.5": { + "sha512": "iYtjnE1GlKTUnUMNvRPsUZs6bQQLB+Nd+6FNbbpzhBItGFDgyTGqZ/RkIAUd1yxDO0O9JzBqxMS1uNNDn/ZQog==", + "type": "package", + "path": "microsoft.aspnetcore.identity.ui/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "THIRD-PARTY-NOTICES.txt", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V3.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.Views.V4.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Identity.UI.xml", + "microsoft.aspnetcore.identity.ui.2.2.5.nupkg.sha512", + "microsoft.aspnetcore.identity.ui.nuspec" + ] + }, + "Microsoft.AspNetCore.JsonPatch/2.2.0": { + "sha512": "o9BB9hftnCsyJalz9IT0DUFxz8Xvgh3TOfGWolpuf19duxB4FySq7c25XDYBmBMS+sun5/PsEUAi58ra4iJAoA==", + "type": "package", + "path": "microsoft.aspnetcore.jsonpatch/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.JsonPatch.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.JsonPatch.xml", + "microsoft.aspnetcore.jsonpatch.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.jsonpatch.nuspec" + ] + }, + "Microsoft.AspNetCore.Localization/2.2.0": { + "sha512": "+PGX1mEfq19EVvskBBb9XBQrXZpZrh6hYhX0x3FkPTEqr+rDM2ZmsEwAAMRmzcidmlDM1/7cyDSU/WhkecU8tA==", + "type": "package", + "path": "microsoft.aspnetcore.localization/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.xml", + "microsoft.aspnetcore.localization.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.localization.nuspec" + ] + }, + "Microsoft.AspNetCore.Localization.Routing/2.2.0": { + "sha512": "kjheDUpXWaGOH8bUQafFAkUvw74xoe0Y2hojgeYaAg5LKvaFUwupkz8wgyhfSbLdejxEQJ6PsA7Zq/AcdPoIUQ==", + "type": "package", + "path": "microsoft.aspnetcore.localization.routing/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.Routing.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Localization.Routing.xml", + "microsoft.aspnetcore.localization.routing.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.localization.routing.nuspec" + ] + }, + "Microsoft.AspNetCore.MiddlewareAnalysis/2.2.0": { + "sha512": "GISp0KoVyJ4llqkmUOWFbOb7g/rOABlsf0Nt8a4eanY71XfUCM0dqBaMct3IUE3KWUvjhKPACQimxgMjPcF7pA==", + "type": "package", + "path": "microsoft.aspnetcore.middlewareanalysis/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.MiddlewareAnalysis.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.MiddlewareAnalysis.xml", + "microsoft.aspnetcore.middlewareanalysis.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.middlewareanalysis.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc/2.2.0": { + "sha512": "noun9xcrEvOs/ubczt2OluY9/bOOM2erv1D/gyyYtfS2sfyx2uGknUIAWoqmqc401TvQDysyx8S4M9j5zPIVBw==", + "type": "package", + "path": "microsoft.aspnetcore.mvc/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.xml", + "microsoft.aspnetcore.mvc.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Abstractions/2.2.0": { + "sha512": "ET6uZpfVbGR1NjCuLaLy197cQ3qZUjzl7EG5SL4GfJH/c9KRE89MMBrQegqWsh0w1iRUB/zQaK0anAjxa/pz4g==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Abstractions.xml", + "microsoft.aspnetcore.mvc.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Analyzers/2.2.0": { + "sha512": "Wxxt1rFVHITp4MDaGQP/wyl+ROVVVeQCTWI6C8hxI8X66C4u6gcxvelqgnmsn+dISMCdE/7FQOwgiMx1HxuZqA==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.analyzers/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "analyzers/dotnet/cs/Microsoft.AspNetCore.Mvc.Analyzers.dll", + "microsoft.aspnetcore.mvc.analyzers.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.analyzers.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.ApiExplorer/2.2.0": { + "sha512": "iSREQct43Xg2t3KiQ2648e064al/HSLPXpI5yO9VPeTGDspWKHW23XFHRKPN1YjIQHHfBj8ytXbiF0XcSxp5pg==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.apiexplorer/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ApiExplorer.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ApiExplorer.xml", + "microsoft.aspnetcore.mvc.apiexplorer.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.apiexplorer.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Core/2.2.5": { + "sha512": "/8sr8ixIUD57UFwUntha9bOwex7/AkZfdk1f9oNJG1Ek7p/uuKVa7fuHmYZpQOf35Oxrt+2Ku4WPwMSbNxOuWg==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.core/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Core.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Core.xml", + "microsoft.aspnetcore.mvc.core.2.2.5.nupkg.sha512", + "microsoft.aspnetcore.mvc.core.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Cors/2.2.0": { + "sha512": "oINjMqhU7yzT2T9AMuvktlWlMd40i0do8E1aYslJS+c5fof+EMhjnwTh6cHN1dfrgjkoXJ/gutxn5Qaqf/81Kg==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.cors/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Cors.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Cors.xml", + "microsoft.aspnetcore.mvc.cors.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.cors.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.DataAnnotations/2.2.0": { + "sha512": "WOw4SA3oT47aiU7ZjN/88j+b79YU6VftmHmxK29Km3PTI7WZdmw675QTcgWfsjEX4joCB82v7TvarO3D0oqOyw==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.dataannotations/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.DataAnnotations.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.DataAnnotations.xml", + "microsoft.aspnetcore.mvc.dataannotations.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.dataannotations.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Formatters.Json/2.2.0": { + "sha512": "ScWwXrkAvw6PekWUFkIr5qa9NKn4uZGRvxtt3DvtUrBYW5Iu2y4SS/vx79JN0XDHNYgAJ81nVs+4M7UE1Y/O+g==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.formatters.json/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Json.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Json.xml", + "microsoft.aspnetcore.mvc.formatters.json.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.formatters.json.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Formatters.Xml/2.2.0": { + "sha512": "4pUhKtqhaNqSeMRRyEw1kGjg/pNLczzd4VAsanMGI539sCdkl1JBaoFojZb1helVdUvX9a1Jo+lYXq0lnwB/GQ==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.formatters.xml/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Xml.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Formatters.Xml.xml", + "microsoft.aspnetcore.mvc.formatters.xml.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.formatters.xml.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Localization/2.2.0": { + "sha512": "H1L4pP124mrN6duwOtNVIJUqy4CczC2/ah4MXarRt9ZRpJd2zNp1j3tJCgyEQpqai6zNVP6Vp2ZRMQcNDcNAKA==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.localization/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Localization.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Localization.xml", + "microsoft.aspnetcore.mvc.localization.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.localization.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Razor/2.2.0": { + "sha512": "TXvEOjp3r6qDEjmDtv3pXjQr/Zia9PpoGkl1MyTEqKqrUehBTpAdCjA8APXFwun19lH20OuyU+e4zDYv9g134w==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.razor/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.xml", + "microsoft.aspnetcore.mvc.razor.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.razor.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Razor.Extensions/2.2.0": { + "sha512": "Sei/0moqBDQKaAYT9PtOeRtvYgHQQLyw/jm3exHw2w9VdzejiMEqCQrN2d63Dk4y7IY0Irr/P9JUFkoVURRcNw==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.razor.extensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.props", + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.targets", + "lib/net46/Microsoft.AspNetCore.Mvc.Razor.Extensions.dll", + "lib/net46/Microsoft.AspNetCore.Mvc.Razor.Extensions.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.Extensions.xml", + "microsoft.aspnetcore.mvc.razor.extensions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.razor.extensions.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.Razor.ViewCompilation/2.2.0": { + "sha512": "dys8ggIDth3g5GBpCfeayU9sNg6Z9IbKFKOuaXbVaAiZQUd+Egk9op4NLHpqfR9Ey2HGw+u87LYC55bhEeOpag==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.razor.viewcompilation/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.Tasks.dll", + "build/netstandard2.0/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.targets", + "build/netstandard2.0/net461/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation-x86.exe", + "build/netstandard2.0/net461/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.exe", + "build/netstandard2.0/netcoreapp2.0/Microsoft.AspNetCore.Mvc.Razor.ViewCompilation.dll", + "microsoft.aspnetcore.mvc.razor.viewcompilation.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.razor.viewcompilation.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.RazorPages/2.2.5": { + "sha512": "l0Lcx0lfCF7SJQiv+5Aib9/pdkP4sXwMsal+pdAUekHu4MJrZB80r+LGvHyaJF8Z7ROMnjQ0oDVCccdneqXX8Q==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.razorpages/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.RazorPages.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.RazorPages.xml", + "microsoft.aspnetcore.mvc.razorpages.2.2.5.nupkg.sha512", + "microsoft.aspnetcore.mvc.razorpages.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.TagHelpers/2.2.0": { + "sha512": "hsrm/dLx7ztfWV+WEE7O8YqEePW7TmUwFwR7JsOUSTKaV9uSeghdmoOsYuk0HeoTiMhRxH8InQVE9/BgBj+jog==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.taghelpers/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.TagHelpers.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.TagHelpers.xml", + "microsoft.aspnetcore.mvc.taghelpers.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.taghelpers.nuspec" + ] + }, + "Microsoft.AspNetCore.Mvc.ViewFeatures/2.2.0": { + "sha512": "dt7MGkzCFVTAD5oesI8UeVVeiSgaZ0tPdFstQjG6YLJSCiq1koOUSHMpf0PASGdOW/H9hxXkolIBhT5dWqJi7g==", + "type": "package", + "path": "microsoft.aspnetcore.mvc.viewfeatures/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ViewFeatures.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Mvc.ViewFeatures.xml", + "microsoft.aspnetcore.mvc.viewfeatures.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.mvc.viewfeatures.nuspec" + ] + }, + "Microsoft.AspNetCore.NodeServices/2.2.0": { + "sha512": "ML+s+nv/ri3MxM4vXjTK3S4K925TGklSKH74VOkCqWQF9ki5yuYcyxaWTUsCyAXliw+N8HMNmW++uU81JngDDg==", + "type": "package", + "path": "microsoft.aspnetcore.nodeservices/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.NodeServices.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.NodeServices.xml", + "microsoft.aspnetcore.nodeservices.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.nodeservices.nuspec" + ] + }, + "Microsoft.AspNetCore.Owin/2.2.0": { + "sha512": "h9QIdnrH7fOTQgUwjz/v0fDk8j8JNtUB233gYFtngt7jLoVc7vfMEGs9rnOWh8ubz+JdrMt7UBrva07af4Smxw==", + "type": "package", + "path": "microsoft.aspnetcore.owin/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Owin.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Owin.xml", + "microsoft.aspnetcore.owin.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.owin.nuspec" + ] + }, + "Microsoft.AspNetCore.Razor/2.2.0": { + "sha512": "V54PIyDCFl8COnTp9gezNHpUNHk7F9UnerGeZy3UfbnwYvfzbo+ipqQmSgeoESH8e0JvKhRTyQyZquW2EPtCmg==", + "type": "package", + "path": "microsoft.aspnetcore.razor/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.xml", + "microsoft.aspnetcore.razor.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.razor.nuspec" + ] + }, + "Microsoft.AspNetCore.Razor.Design/2.2.0": { + "sha512": "VLWK+ZtMMNukY6XjxYHc7mz33vkquoEzQJHm/LCF5REVxIaexLr+UTImljRRJBdUDJluDAQwU+59IX0rFDfURA==", + "type": "package", + "path": "microsoft.aspnetcore.razor.design/2.2.0", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.CodeGeneration.targets", + "build/netstandard2.0/Microsoft.AspNetCore.Razor.Design.props", + "buildMultiTargeting/Microsoft.AspNetCore.Razor.Design.props", + "microsoft.aspnetcore.razor.design.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.razor.design.nuspec", + "tools/Microsoft.AspNetCore.Razor.Language.dll", + "tools/Microsoft.CodeAnalysis.CSharp.dll", + "tools/Microsoft.CodeAnalysis.Razor.dll", + "tools/Microsoft.CodeAnalysis.dll", + "tools/Newtonsoft.Json.dll", + "tools/runtimes/unix/lib/netstandard1.3/System.Text.Encoding.CodePages.dll", + "tools/runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll", + "tools/rzc.deps.json", + "tools/rzc.dll", + "tools/rzc.runtimeconfig.json" + ] + }, + "Microsoft.AspNetCore.Razor.Language/2.2.0": { + "sha512": "IeyzVFXZdpUAnWKWoNYE0SsP1Eu7JLjZaC94jaI1VfGtK57QykROz/iGMc8D0VcqC8i02qYTPQN/wPKm6PfidA==", + "type": "package", + "path": "microsoft.aspnetcore.razor.language/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net46/Microsoft.AspNetCore.Razor.Language.dll", + "lib/net46/Microsoft.AspNetCore.Razor.Language.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Language.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Language.xml", + "microsoft.aspnetcore.razor.language.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.razor.language.nuspec" + ] + }, + "Microsoft.AspNetCore.Razor.Runtime/2.2.0": { + "sha512": "7YqK+H61lN6yj9RiQUko7oaOhKtRR9Q/kBcoWNRemhJdTIWOh1OmdvJKzZrMWOlff3BAjejkPQm+0V0qXk+B1w==", + "type": "package", + "path": "microsoft.aspnetcore.razor.runtime/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Runtime.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Razor.Runtime.xml", + "microsoft.aspnetcore.razor.runtime.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.razor.runtime.nuspec" + ] + }, + "Microsoft.AspNetCore.ResponseCaching/2.2.0": { + "sha512": "MEBP1UwGD7X1vhO43LN5KhZDt4HMTX7u1YA0nq7HR6IDRhWczHczJPDu3GbL01IMdb03hyT/glJIv8PI5zKtnA==", + "type": "package", + "path": "microsoft.aspnetcore.responsecaching/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.xml", + "microsoft.aspnetcore.responsecaching.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.responsecaching.nuspec" + ] + }, + "Microsoft.AspNetCore.ResponseCaching.Abstractions/2.2.0": { + "sha512": "CIHWEKrHzZfFp7t57UXsueiSA/raku56TgRYauV/W1+KAQq6vevz60zjEKaazt3BI76zwMz3B4jGWnCwd8kwQw==", + "type": "package", + "path": "microsoft.aspnetcore.responsecaching.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCaching.Abstractions.xml", + "microsoft.aspnetcore.responsecaching.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.responsecaching.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.ResponseCompression/2.2.0": { + "sha512": "RvSstOhebIMDdRLd4iWjA6z2o2kGGwEYGPajvTXwndOA3TZpWH3FOIV4L7mehN/HoKrbTbX5vZ54ZFDwWoAFKA==", + "type": "package", + "path": "microsoft.aspnetcore.responsecompression/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net461/Microsoft.AspNetCore.ResponseCompression.dll", + "lib/net461/Microsoft.AspNetCore.ResponseCompression.xml", + "lib/netcoreapp2.1/Microsoft.AspNetCore.ResponseCompression.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.ResponseCompression.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCompression.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.ResponseCompression.xml", + "microsoft.aspnetcore.responsecompression.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.responsecompression.nuspec" + ] + }, + "Microsoft.AspNetCore.Rewrite/2.2.0": { + "sha512": "jztwQxyn4CcWZj/1mQtFiZ5+pIWYltHIXk5ykyrXMjO6qaKVvc+mlffSUCQ0AOl3vH7vxsZnda8poHwVaT0QIA==", + "type": "package", + "path": "microsoft.aspnetcore.rewrite/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Rewrite.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Rewrite.xml", + "microsoft.aspnetcore.rewrite.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.rewrite.nuspec" + ] + }, + "Microsoft.AspNetCore.Routing/2.2.2": { + "sha512": "HcmJmmGYewdNZ6Vcrr5RkQbc/YWU4F79P3uPPBi6fCFOgUewXNM1P4kbPuoem7tN4f7x8mq7gTsm5QGohQ5g/w==", + "type": "package", + "path": "microsoft.aspnetcore.routing/2.2.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.2/Microsoft.AspNetCore.Routing.dll", + "lib/netcoreapp2.2/Microsoft.AspNetCore.Routing.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.xml", + "microsoft.aspnetcore.routing.2.2.2.nupkg.sha512", + "microsoft.aspnetcore.routing.nuspec" + ] + }, + "Microsoft.AspNetCore.Routing.Abstractions/2.2.0": { + "sha512": "lRRaPN7jDlUCVCp9i0W+PB0trFaKB0bgMJD7hEJS9Uo4R9MXaMC8X2tJhPLmeVE3SGDdYI4QNKdVmhNvMJGgPQ==", + "type": "package", + "path": "microsoft.aspnetcore.routing.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Routing.Abstractions.xml", + "microsoft.aspnetcore.routing.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.routing.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.HttpSys/2.2.6": { + "sha512": "aT/Q1JS9aq5qmYFgEMqksbyP0Q53Qd1M3wOCMa5CMCgzQ4xih/ODiZ/Wq+4uY4TtDW/r1/4JweGbmqwjj41aiw==", + "type": "package", + "path": "microsoft.aspnetcore.server.httpsys/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.HttpSys.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.HttpSys.xml", + "microsoft.aspnetcore.server.httpsys.2.2.6.nupkg.sha512", + "microsoft.aspnetcore.server.httpsys.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.IIS/2.2.6": { + "sha512": "gyODQZv0fifUKPDQ3aDyauiABfRq7AI1eUbg0ZNuostsw2fH9nCd0vpW6BR8wnW/udFlvfvK1cI28SzROqMf+w==", + "type": "package", + "path": "microsoft.aspnetcore.server.iis/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.AspNetCore.Server.IIS.targets", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IIS.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IIS.xml", + "microsoft.aspnetcore.server.iis.2.2.6.nupkg.sha512", + "microsoft.aspnetcore.server.iis.nuspec", + "runtimes/win-x64/nativeassets/netcoreapp2.2/aspnetcorev2_inprocess.dll", + "runtimes/win-x86/nativeassets/netcoreapp2.2/aspnetcorev2_inprocess.dll" + ] + }, + "Microsoft.AspNetCore.Server.IISIntegration/2.2.1": { + "sha512": "Yzjx64GXNm6uteHQr1jCTJP+VB/6FndMyALud2CQpGmBWqXfklqctmncvLPtvljn5Y9stZNeECDUNrReFC8VRA==", + "type": "package", + "path": "microsoft.aspnetcore.server.iisintegration/2.2.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.targets", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.IISIntegration.xml", + "microsoft.aspnetcore.server.iisintegration.2.2.1.nupkg.sha512", + "microsoft.aspnetcore.server.iisintegration.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel/2.2.0": { + "sha512": "D0vGB8Tp0UNMiAhT+pwAVeqDDx2OFrfpu/plwm0WhA+1DZvTLc99eDwGISL6LAY8x7a12lhl9w7/m+VdoyDu8Q==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.xml", + "microsoft.aspnetcore.server.kestrel.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel.Core/2.2.0": { + "sha512": "F6/Vesd3ODq/ISbHfcvfRf7IzRtTvrNX8VA36Knm5e7bteJhoRA2GKQUVQ+neoO1njLvaQKnjcA3rdCZ6AF6cg==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel.core/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Core.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Core.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Core.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Core.xml", + "microsoft.aspnetcore.server.kestrel.core.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.core.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel.Https/2.2.0": { + "sha512": "nEH5mU6idUYS3/+9BKw2stMOM25ZdGwIH4P4kyj6PVkMPgQUTkBQ7l/ScPkepdhejcOlPa+g3+M4dYsSYPUJ8g==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel.https/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Https.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Https.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Https.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Https.xml", + "microsoft.aspnetcore.server.kestrel.https.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.https.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions/2.2.0": { + "sha512": "j1ai2CG8BGp4mYf2TWSFjjy1pRgW9XbqhdR4EOVvrlFVbcpEPfXNIPEdjkcgK+txWCupGzkFnFF8oZsASMtmyw==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel.transport.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.xml", + "microsoft.aspnetcore.server.kestrel.transport.abstractions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.transport.abstractions.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv/2.2.0": { + "sha512": "ityQuQVasDvrLk6O6dGM0DnlmBXsetgqBSLBq3wVJ/3p4jOYI2yPITynkZYIuOy1VUIsAXv7QyNQmfF8iC663w==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel.transport.libuv/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.xml", + "microsoft.aspnetcore.server.kestrel.transport.libuv.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.transport.libuv.nuspec" + ] + }, + "Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets/2.2.1": { + "sha512": "tzRdyQ0qrMJ5YS0qsXfmhVd/kr25IzLpayoIAvU1yi27wqsqxXVPADDEv0S9PaS7xn6bpMFit8kZw92IICDSWg==", + "type": "package", + "path": "microsoft.aspnetcore.server.kestrel.transport.sockets/2.2.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll", + "lib/netcoreapp2.1/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.xml", + "microsoft.aspnetcore.server.kestrel.transport.sockets.2.2.1.nupkg.sha512", + "microsoft.aspnetcore.server.kestrel.transport.sockets.nuspec" + ] + }, + "Microsoft.AspNetCore.Session/2.2.0": { + "sha512": "lOjJVh293AKaOEPi1MIC1/G9gOVZMrve2a05o56oslK6bo0PMgMB17rmPomvqrJAjMdlWZ/MGdN2y78Z9wzWTw==", + "type": "package", + "path": "microsoft.aspnetcore.session/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.Session.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.Session.xml", + "microsoft.aspnetcore.session.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.session.nuspec" + ] + }, + "Microsoft.AspNetCore.SignalR/1.1.0": { + "sha512": "V5X5XkeAHaFyyBOGPrddVeqTNo6zRPJNS5PRhlzEyBXiNG9AtqUbMyWFdZahQyMiIWJau550z59A4kdC9g5I9A==", + "type": "package", + "path": "microsoft.aspnetcore.signalr/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.xml", + "microsoft.aspnetcore.signalr.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.signalr.nuspec" + ] + }, + "Microsoft.AspNetCore.SignalR.Common/1.1.0": { + "sha512": "TyLgQ4y4RVUIxiYFnHT181/rJ33/tL/NcBWC9BwLpulDt5/yGCG4EvsToZ49EBQ7256zj+R6OGw6JF+jj6MdPQ==", + "type": "package", + "path": "microsoft.aspnetcore.signalr.common/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netcoreapp2.2/Microsoft.AspNetCore.SignalR.Common.dll", + "lib/netcoreapp2.2/Microsoft.AspNetCore.SignalR.Common.xml", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Common.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Common.xml", + "microsoft.aspnetcore.signalr.common.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.signalr.common.nuspec" + ] + }, + "Microsoft.AspNetCore.SignalR.Core/1.1.0": { + "sha512": "mk69z50oFk2e89d3F/AfKeAvP3kvGG7MHG4ErydZiUd3ncSRq0kl0czq/COn/QVKYua9yGr2LIDwuR1C6/pu8Q==", + "type": "package", + "path": "microsoft.aspnetcore.signalr.core/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Core.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Core.xml", + "microsoft.aspnetcore.signalr.core.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.signalr.core.nuspec" + ] + }, + "Microsoft.AspNetCore.SignalR.Protocols.Json/1.1.0": { + "sha512": "BOsjatDJnvnnXCMajOlC0ISmiFnJi/EyJzMo0i//5fZJVCLrQ4fyV/HzrhhAhSJuwJOQDdDozKQ9MB9jHq84pg==", + "type": "package", + "path": "microsoft.aspnetcore.signalr.protocols.json/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Protocols.Json.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Protocols.Json.xml", + "microsoft.aspnetcore.signalr.protocols.json.1.1.0.nupkg.sha512", + "microsoft.aspnetcore.signalr.protocols.json.nuspec" + ] + }, + "Microsoft.AspNetCore.SignalR.Redis/1.1.5": { + "sha512": "qVKEVLZiWUUSaQdNWIg/Um9SGTGjXI6qeeFGozoqjwWI9XLORokp+AzfXA9OKx27wQBjknC7vdYF6Fr4uOjN2g==", + "type": "package", + "path": "microsoft.aspnetcore.signalr.redis/1.1.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Redis.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SignalR.Redis.xml", + "microsoft.aspnetcore.signalr.redis.1.1.5.nupkg.sha512", + "microsoft.aspnetcore.signalr.redis.nuspec" + ] + }, + "Microsoft.AspNetCore.SpaServices/2.2.7": { + "sha512": "OsxPRaZ6UoBjXl+SdAFsJEmqymTILM2Pz9kgh55/di6x5ypvHionXdAdwBgIsJ+K908OYykq6RfgjtkNLSKQ/A==", + "type": "package", + "path": "microsoft.aspnetcore.spaservices/2.2.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.dll", + "microsoft.aspnetcore.spaservices.2.2.7.nupkg.sha512", + "microsoft.aspnetcore.spaservices.nuspec" + ] + }, + "Microsoft.AspNetCore.SpaServices.Extensions/2.2.0": { + "sha512": "RvzzubzGPD+dGCfKVVtAvyIsnWpAWOA/x1n6fGLwICPER7Ze6budQGFPdZ7yuXTwtTMRvHa4O4AaGLG1XmoXGw==", + "type": "package", + "path": "microsoft.aspnetcore.spaservices.extensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.Extensions.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.SpaServices.Extensions.xml", + "microsoft.aspnetcore.spaservices.extensions.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.spaservices.extensions.nuspec" + ] + }, + "Microsoft.AspNetCore.StaticFiles/2.2.0": { + "sha512": "byZDrjir6Co5EoWbraQyG0qbPCUG6XgGYQstipMF9lucOAjq/mqnIyt8B8iMWnin/ghZoOln9Y01af4rUAwOhA==", + "type": "package", + "path": "microsoft.aspnetcore.staticfiles/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.StaticFiles.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.StaticFiles.xml", + "microsoft.aspnetcore.staticfiles.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.staticfiles.nuspec" + ] + }, + "Microsoft.AspNetCore.WebSockets/2.2.1": { + "sha512": "Ilk4fQ0xdVpJk1a+72thHv2LglUZPWL+vECOG3mw+gOesNx0/p56HNJXZw8k1pj8ff1cVHn8KtfvyRZxdplNQA==", + "type": "package", + "path": "microsoft.aspnetcore.websockets/2.2.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.WebSockets.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.WebSockets.xml", + "microsoft.aspnetcore.websockets.2.2.1.nupkg.sha512", + "microsoft.aspnetcore.websockets.nuspec" + ] + }, + "Microsoft.AspNetCore.WebUtilities/2.2.0": { + "sha512": "9ErxAAKaDzxXASB/b5uLEkLgUWv1QbeVxyJYEHQwMaxXOeFFVkQxiq8RyfVcifLU7NR0QY0p3acqx4ZpYfhHDg==", + "type": "package", + "path": "microsoft.aspnetcore.webutilities/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.AspNetCore.WebUtilities.dll", + "lib/netstandard2.0/Microsoft.AspNetCore.WebUtilities.xml", + "microsoft.aspnetcore.webutilities.2.2.0.nupkg.sha512", + "microsoft.aspnetcore.webutilities.nuspec" + ] + }, + "Microsoft.Azure.KeyVault/2.3.2": { + "sha512": "A82ESUdfLz2wMhYuPxrwf/fA7JVt3IARgeMCG3TsaLtxUxa9RBKX3f0zdnKmvBvJ/u1/5g03OLR26GPekqY5HQ==", + "type": "package", + "path": "microsoft.azure.keyvault/2.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net452/Microsoft.Azure.KeyVault.dll", + "lib/net452/Microsoft.Azure.KeyVault.runtimeconfig.json", + "lib/net452/Microsoft.Azure.KeyVault.xml", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.dll", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.runtimeconfig.json", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.xml", + "microsoft.azure.keyvault.2.3.2.nupkg.sha512", + "microsoft.azure.keyvault.nuspec" + ] + }, + "Microsoft.Azure.KeyVault.WebKey/2.0.7": { + "sha512": "MVSYao62R9rwl9KF+IsJm+XBLupJj1ma2lfwNeFlSWziXGAopnYK+YkDWqABOqNIV9kpza/MvNBxITzhlJIyIw==", + "type": "package", + "path": "microsoft.azure.keyvault.webkey/2.0.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net452/Microsoft.Azure.KeyVault.WebKey.dll", + "lib/net452/Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json", + "lib/net452/Microsoft.Azure.KeyVault.WebKey.xml", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.WebKey.dll", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.WebKey.runtimeconfig.json", + "lib/netstandard1.4/Microsoft.Azure.KeyVault.WebKey.xml", + "microsoft.azure.keyvault.webkey.2.0.7.nupkg.sha512", + "microsoft.azure.keyvault.webkey.nuspec" + ] + }, + "Microsoft.Azure.Services.AppAuthentication/1.0.1": { + "sha512": "oSVQ+YLgn0PfDLBRwOtHrkw06Pc6HvqIVrtFFWMg/1eafY+Hbrm1CSXnzXKXJwqUUv0ynvuwqzjN+IFR3g588w==", + "type": "package", + "path": "microsoft.azure.services.appauthentication/1.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/Microsoft.Azure.Services.AppAuthentication.targets", + "lib/net452/Microsoft.Azure.Services.AppAuthentication.dll", + "lib/net452/Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json", + "lib/net452/Microsoft.Azure.Services.AppAuthentication.xml", + "lib/netstandard1.4/Microsoft.Azure.Services.AppAuthentication.dll", + "lib/netstandard1.4/Microsoft.Azure.Services.AppAuthentication.runtimeconfig.json", + "lib/netstandard1.4/Microsoft.Azure.Services.AppAuthentication.xml", + "microsoft.azure.services.appauthentication.1.0.1.nupkg.sha512", + "microsoft.azure.services.appauthentication.nuspec" + ] + }, + "Microsoft.CodeAnalysis.Analyzers/1.1.0": { + "sha512": "HS3iRWZKcUw/8eZ/08GXKY2Bn7xNzQPzf8gRPHGSowX7u7XXu9i9YEaBeBNKUXWfI7qjvT2zXtLUvbN0hds8vg==", + "type": "package", + "path": "microsoft.codeanalysis.analyzers/1.1.0", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.rtf", + "analyzers/dotnet/cs/Microsoft.CodeAnalysis.Analyzers.dll", + "analyzers/dotnet/cs/Microsoft.CodeAnalysis.CSharp.Analyzers.dll", + "analyzers/dotnet/vb/Microsoft.CodeAnalysis.Analyzers.dll", + "analyzers/dotnet/vb/Microsoft.CodeAnalysis.VisualBasic.Analyzers.dll", + "microsoft.codeanalysis.analyzers.1.1.0.nupkg.sha512", + "microsoft.codeanalysis.analyzers.nuspec", + "tools/install.ps1", + "tools/uninstall.ps1" + ] + }, + "Microsoft.CodeAnalysis.Common/2.8.0": { + "sha512": "06AzG7oOLKTCN1EnoVYL1bQz+Zwa10LMpUn7Kc+PdpN8CQXRqXTyhfxuKIz6t0qWfoatBNXdHD0OLcEYp5pOvQ==", + "type": "package", + "path": "microsoft.codeanalysis.common/2.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard1.3/Microsoft.CodeAnalysis.dll", + "lib/netstandard1.3/Microsoft.CodeAnalysis.pdb", + "lib/netstandard1.3/Microsoft.CodeAnalysis.xml", + "microsoft.codeanalysis.common.2.8.0.nupkg.sha512", + "microsoft.codeanalysis.common.nuspec" + ] + }, + "Microsoft.CodeAnalysis.CSharp/2.8.0": { + "sha512": "RizcFXuHgGmeuZhxxE1qQdhFA9lGOHlk0MJlCUt6LOnYsevo72gNikPcbANFHY02YK8L/buNrihchY0TroGvXQ==", + "type": "package", + "path": "microsoft.codeanalysis.csharp/2.8.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.dll", + "lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.pdb", + "lib/netstandard1.3/Microsoft.CodeAnalysis.CSharp.xml", + "microsoft.codeanalysis.csharp.2.8.0.nupkg.sha512", + "microsoft.codeanalysis.csharp.nuspec" + ] + }, + "Microsoft.CodeAnalysis.Razor/2.2.0": { + "sha512": "2qL0Qyu5qHzg6/JzF80mLgsqn9NP/Q0mQwjH+Z+DiqcuODJx8segjN4un2Tnz6bEAWv8FCRFNXR/s5wzlxqA8A==", + "type": "package", + "path": "microsoft.codeanalysis.razor/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net46/Microsoft.CodeAnalysis.Razor.dll", + "lib/net46/Microsoft.CodeAnalysis.Razor.xml", + "lib/netstandard2.0/Microsoft.CodeAnalysis.Razor.dll", + "lib/netstandard2.0/Microsoft.CodeAnalysis.Razor.xml", + "microsoft.codeanalysis.razor.2.2.0.nupkg.sha512", + "microsoft.codeanalysis.razor.nuspec" + ] + }, + "Microsoft.CSharp/4.5.0": { + "sha512": "kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ==", + "type": "package", + "path": "microsoft.csharp/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/Microsoft.CSharp.dll", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.3/Microsoft.CSharp.dll", + "lib/netstandard2.0/Microsoft.CSharp.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/uap10.0.16299/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "microsoft.csharp.4.5.0.nupkg.sha512", + "microsoft.csharp.nuspec", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/Microsoft.CSharp.dll", + "ref/netcore50/Microsoft.CSharp.xml", + "ref/netcore50/de/Microsoft.CSharp.xml", + "ref/netcore50/es/Microsoft.CSharp.xml", + "ref/netcore50/fr/Microsoft.CSharp.xml", + "ref/netcore50/it/Microsoft.CSharp.xml", + "ref/netcore50/ja/Microsoft.CSharp.xml", + "ref/netcore50/ko/Microsoft.CSharp.xml", + "ref/netcore50/ru/Microsoft.CSharp.xml", + "ref/netcore50/zh-hans/Microsoft.CSharp.xml", + "ref/netcore50/zh-hant/Microsoft.CSharp.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.0/Microsoft.CSharp.dll", + "ref/netstandard1.0/Microsoft.CSharp.xml", + "ref/netstandard1.0/de/Microsoft.CSharp.xml", + "ref/netstandard1.0/es/Microsoft.CSharp.xml", + "ref/netstandard1.0/fr/Microsoft.CSharp.xml", + "ref/netstandard1.0/it/Microsoft.CSharp.xml", + "ref/netstandard1.0/ja/Microsoft.CSharp.xml", + "ref/netstandard1.0/ko/Microsoft.CSharp.xml", + "ref/netstandard1.0/ru/Microsoft.CSharp.xml", + "ref/netstandard1.0/zh-hans/Microsoft.CSharp.xml", + "ref/netstandard1.0/zh-hant/Microsoft.CSharp.xml", + "ref/netstandard2.0/Microsoft.CSharp.dll", + "ref/netstandard2.0/Microsoft.CSharp.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/uap10.0.16299/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "Microsoft.Data.Edm/5.8.4": { + "sha512": "pTN7J6ep8upUZFWGPnFL47j+kRN3ihKra+mDdqDmC2HN0AIuVAE6Dd/0IAqAUpKJc6uo5p5wNlCVn2eweAYhQQ==", + "type": "package", + "path": "microsoft.data.edm/5.8.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net40/Microsoft.Data.Edm.dll", + "lib/net40/Microsoft.Data.Edm.xml", + "lib/net40/de/Microsoft.Data.Edm.resources.dll", + "lib/net40/es/Microsoft.Data.Edm.resources.dll", + "lib/net40/fr/Microsoft.Data.Edm.resources.dll", + "lib/net40/it/Microsoft.Data.Edm.resources.dll", + "lib/net40/ja/Microsoft.Data.Edm.resources.dll", + "lib/net40/ko/Microsoft.Data.Edm.resources.dll", + "lib/net40/ru/Microsoft.Data.Edm.resources.dll", + "lib/net40/zh-Hans/Microsoft.Data.Edm.resources.dll", + "lib/net40/zh-Hant/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/Microsoft.Data.Edm.dll", + "lib/netstandard1.1/Microsoft.Data.Edm.xml", + "lib/netstandard1.1/de/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/es/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/fr/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/it/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/ja/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/ko/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/ru/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/zh-Hans/Microsoft.Data.Edm.resources.dll", + "lib/netstandard1.1/zh-Hant/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/Microsoft.Data.Edm.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/Microsoft.Data.Edm.xml", + "lib/portable-net40+sl5+wp8+win8+wpa/de/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/es/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/fr/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/it/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ja/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ko/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ru/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hans/Microsoft.Data.Edm.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hant/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/Microsoft.Data.Edm.dll", + "lib/portable-net45+wp8+win8+wpa/Microsoft.Data.Edm.xml", + "lib/portable-net45+wp8+win8+wpa/de/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/es/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/fr/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/it/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ja/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ko/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ru/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hans/Microsoft.Data.Edm.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hant/Microsoft.Data.Edm.resources.dll", + "lib/sl4/Microsoft.Data.Edm.dll", + "lib/sl4/Microsoft.Data.Edm.xml", + "lib/sl4/de/Microsoft.Data.Edm.resources.dll", + "lib/sl4/es/Microsoft.Data.Edm.resources.dll", + "lib/sl4/fr/Microsoft.Data.Edm.resources.dll", + "lib/sl4/it/Microsoft.Data.Edm.resources.dll", + "lib/sl4/ja/Microsoft.Data.Edm.resources.dll", + "lib/sl4/ko/Microsoft.Data.Edm.resources.dll", + "lib/sl4/ru/Microsoft.Data.Edm.resources.dll", + "lib/sl4/zh-Hans/Microsoft.Data.Edm.resources.dll", + "lib/sl4/zh-Hant/Microsoft.Data.Edm.resources.dll", + "microsoft.data.edm.5.8.4.nupkg.sha512", + "microsoft.data.edm.nuspec" + ] + }, + "Microsoft.Data.OData/5.8.4": { + "sha512": "dK+jMmswaFFWLcgpz9jE8Kwi+LSUkfGVp+MY2egIB7K6ZPWPxiDSTo2I48bpRiMm18nF02/XJL5NwIWH10/l/Q==", + "type": "package", + "path": "microsoft.data.odata/5.8.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net40/Microsoft.Data.OData.dll", + "lib/net40/Microsoft.Data.OData.xml", + "lib/net40/de/Microsoft.Data.OData.resources.dll", + "lib/net40/es/Microsoft.Data.OData.resources.dll", + "lib/net40/fr/Microsoft.Data.OData.resources.dll", + "lib/net40/it/Microsoft.Data.OData.resources.dll", + "lib/net40/ja/Microsoft.Data.OData.resources.dll", + "lib/net40/ko/Microsoft.Data.OData.resources.dll", + "lib/net40/ru/Microsoft.Data.OData.resources.dll", + "lib/net40/zh-Hans/Microsoft.Data.OData.resources.dll", + "lib/net40/zh-Hant/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/Microsoft.Data.OData.dll", + "lib/netstandard1.1/Microsoft.Data.OData.xml", + "lib/netstandard1.1/de/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/es/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/fr/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/it/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/ja/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/ko/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/ru/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/zh-Hans/Microsoft.Data.OData.resources.dll", + "lib/netstandard1.1/zh-Hant/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/Microsoft.Data.OData.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/Microsoft.Data.OData.xml", + "lib/portable-net40+sl5+wp8+win8+wpa/de/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/es/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/fr/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/it/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ja/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ko/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ru/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hans/Microsoft.Data.OData.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hant/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/Microsoft.Data.OData.dll", + "lib/portable-net45+wp8+win8+wpa/Microsoft.Data.OData.xml", + "lib/portable-net45+wp8+win8+wpa/de/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/es/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/fr/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/it/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ja/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ko/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ru/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hans/Microsoft.Data.OData.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hant/Microsoft.Data.OData.resources.dll", + "lib/sl4/Microsoft.Data.OData.dll", + "lib/sl4/Microsoft.Data.OData.xml", + "lib/sl4/de/Microsoft.Data.OData.resources.dll", + "lib/sl4/es/Microsoft.Data.OData.resources.dll", + "lib/sl4/fr/Microsoft.Data.OData.resources.dll", + "lib/sl4/it/Microsoft.Data.OData.resources.dll", + "lib/sl4/ja/Microsoft.Data.OData.resources.dll", + "lib/sl4/ko/Microsoft.Data.OData.resources.dll", + "lib/sl4/ru/Microsoft.Data.OData.resources.dll", + "lib/sl4/zh-Hans/Microsoft.Data.OData.resources.dll", + "lib/sl4/zh-Hant/Microsoft.Data.OData.resources.dll", + "microsoft.data.odata.5.8.4.nupkg.sha512", + "microsoft.data.odata.nuspec" + ] + }, + "Microsoft.Data.Sqlite/2.2.6": { + "sha512": "hjfzgqml2DMKWY+aIuN90piObxWJo4g63kzf0Iy+4op1EKqJNXP5s0/HCLujJkTkJSZD6pvOZXOxdL6h7D/Hbg==", + "type": "package", + "path": "microsoft.data.sqlite/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/_._", + "microsoft.data.sqlite.2.2.6.nupkg.sha512", + "microsoft.data.sqlite.nuspec" + ] + }, + "Microsoft.Data.Sqlite.Core/2.2.6": { + "sha512": "JuHLktt4mb5jSTKr+lq4OeuG8tUcCdk/9Gg9kX955+BNcIpSrDqLTcktBOyOIWWUrqBp1zjEbd+/u/9rF57H1w==", + "type": "package", + "path": "microsoft.data.sqlite.core/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Data.Sqlite.dll", + "lib/netstandard2.0/Microsoft.Data.Sqlite.xml", + "microsoft.data.sqlite.core.2.2.6.nupkg.sha512", + "microsoft.data.sqlite.core.nuspec" + ] + }, + "Microsoft.DotNet.PlatformAbstractions/2.1.0": { + "sha512": "9KPDwvb/hLEVXYruVHVZ8BkebC8j17DmPb56LnqRF74HqSPLjCkrlFUjOtFpQPA2DeADBRTI/e69aCfRBfrhxw==", + "type": "package", + "path": "microsoft.dotnet.platformabstractions/2.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net45/Microsoft.DotNet.PlatformAbstractions.dll", + "lib/netstandard1.3/Microsoft.DotNet.PlatformAbstractions.dll", + "microsoft.dotnet.platformabstractions.2.1.0.nupkg.sha512", + "microsoft.dotnet.platformabstractions.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore/2.2.6": { + "sha512": "vmrMrjiCO7FkuFJwt/MHl6pk6cSXPtB1miPMtn0KTO7WqwaQ2WQ4gWpC/m753PzVriH2X2kIadWrd9SJb7KVww==", + "type": "package", + "path": "microsoft.entityframeworkcore/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.xml", + "microsoft.entityframeworkcore.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Abstractions/2.2.6": { + "sha512": "4CrelpMMLszWqi0gFEYPhbsinXCQ2Vw6rA190IIwKY7THge/ckOwj6QIQKOu3Lmxj4khpzs+b6QADbpRRnOIaQ==", + "type": "package", + "path": "microsoft.entityframeworkcore.abstractions/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Abstractions.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Abstractions.xml", + "microsoft.entityframeworkcore.abstractions.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.abstractions.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Analyzers/2.2.6": { + "sha512": "BpNllkfZABCvMAaIL/pSLxTYYZQqiVesSG6xQpvelrlEfC0s9PS217Sq5Apn/zYW8ALtGoVEY12TblHrZ4SRRA==", + "type": "package", + "path": "microsoft.entityframeworkcore.analyzers/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "analyzers/dotnet/cs/Microsoft.EntityFrameworkCore.Analyzers.dll", + "microsoft.entityframeworkcore.analyzers.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.analyzers.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Design/2.2.6": { + "sha512": "ouDKXTXY+ItF+PAK/jkp+Cp6Ve8Pd9sblyqOErjaiK7CzeN28peFsv3NfDeoqTAXXCCKEyuv/iXYtLs4r3wI0w==", + "type": "package", + "path": "microsoft.entityframeworkcore.design/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/net461/Microsoft.EntityFrameworkCore.Design.props", + "build/netcoreapp2.0/Microsoft.EntityFrameworkCore.Design.props", + "lib/net461/Microsoft.EntityFrameworkCore.Design.dll", + "lib/net461/Microsoft.EntityFrameworkCore.Design.xml", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Design.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Design.xml", + "microsoft.entityframeworkcore.design.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.design.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.InMemory/2.2.6": { + "sha512": "PREu4MsAGz3NEheW4TX4e8Bl4l34OrA4R4KFyWb3r475QRS1/ul4vK1mUzWF/fEwJgx7n1h1tvNZW7I04sl5fw==", + "type": "package", + "path": "microsoft.entityframeworkcore.inmemory/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.InMemory.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.InMemory.xml", + "microsoft.entityframeworkcore.inmemory.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.inmemory.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Relational/2.2.6": { + "sha512": "AlB4Gg1nplg6fwieCLixphmYkhwM1SSHecE43oDizAjFUSs7vlL5mlwf620X4SB037pVg+naxhBEtF53TGa6yQ==", + "type": "package", + "path": "microsoft.entityframeworkcore.relational/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Relational.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Relational.xml", + "microsoft.entityframeworkcore.relational.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.relational.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Sqlite/2.2.6": { + "sha512": "U4ifHn7YJsj31waXLbXwR/HMdQnp/v+bBGw5VfSRqVtO10npQa3LBOXWZTaocXgJBoIX0ADI2ZkfjX+hb0CnJA==", + "type": "package", + "path": "microsoft.entityframeworkcore.sqlite/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/_._", + "microsoft.entityframeworkcore.sqlite.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.sqlite.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core/2.2.6": { + "sha512": "FRwNvIjcoDaMGExrrGb02ULgY0dhkk70OuY7Bc61wK4rOVHweLiCAaJJ3y3s9w604lM1lBcTWmEilFincRJRhw==", + "type": "package", + "path": "microsoft.entityframeworkcore.sqlite.core/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Sqlite.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.Sqlite.xml", + "microsoft.entityframeworkcore.sqlite.core.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.sqlite.core.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.SqlServer/2.2.6": { + "sha512": "rNnCA7ntlpITeYl1p3lAeS0kyHhETlanTghfpoDgyGIoxyUm2VsI2eyzL6EMYrqWnhAOwx3HzP0/50XRM/0CHw==", + "type": "package", + "path": "microsoft.entityframeworkcore.sqlserver/2.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.SqlServer.dll", + "lib/netstandard2.0/Microsoft.EntityFrameworkCore.SqlServer.xml", + "microsoft.entityframeworkcore.sqlserver.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.sqlserver.nuspec" + ] + }, + "Microsoft.EntityFrameworkCore.Tools/2.2.6": { + "sha512": "L6vi+eT++Q+2jSIWtOB1LD4yB4dR1nQrWg/Wx1kArPo0rD8D9R4uD6LU5OFz3U/ibjADxLgmQmYDqjusrOI7SA==", + "type": "package", + "path": "microsoft.entityframeworkcore.tools/2.2.6", + "hasTools": true, + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/_._", + "microsoft.entityframeworkcore.tools.2.2.6.nupkg.sha512", + "microsoft.entityframeworkcore.tools.nuspec", + "tools/EntityFrameworkCore.PowerShell2.psd1", + "tools/EntityFrameworkCore.PowerShell2.psm1", + "tools/EntityFrameworkCore.psd1", + "tools/EntityFrameworkCore.psm1", + "tools/about_EntityFrameworkCore.help.txt", + "tools/init.ps1", + "tools/install.ps1", + "tools/net461/any/ef.exe", + "tools/net461/win-x86/ef.exe", + "tools/netcoreapp2.0/any/ef.dll", + "tools/netcoreapp2.0/any/ef.runtimeconfig.json" + ] + }, + "Microsoft.Extensions.Caching.Abstractions/2.2.0": { + "sha512": "spsJkYo8gGJapaxTSQFN/wqA+ghpJMLwB4ZyTB+fSdpd7AmMFP/YSpIcGmczcw4KggpxLGhLk7lCkSIlgvHaqQ==", + "type": "package", + "path": "microsoft.extensions.caching.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Abstractions.xml", + "microsoft.extensions.caching.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.caching.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.Caching.Memory/2.2.0": { + "sha512": "yFs44RzB2Pzfoj4uk+mEz3MTTQKyeWb8gDhv5GyVPfHnLv0eQhGwzbw/5WpxAcVyOgG/H3/0ULY6g0/7/B+r7w==", + "type": "package", + "path": "microsoft.extensions.caching.memory/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Memory.xml", + "microsoft.extensions.caching.memory.2.2.0.nupkg.sha512", + "microsoft.extensions.caching.memory.nuspec" + ] + }, + "Microsoft.Extensions.Caching.Redis/2.2.0": { + "sha512": "cb21miiGDVjlNl8TRBKIi7OEFdlKuV8d4ZoYqFOhKdZhzo7Sv+b8Puy3NLW3y/g+UDclt7FTh+Za7ykurtaVMQ==", + "type": "package", + "path": "microsoft.extensions.caching.redis/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Redis.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.Redis.xml", + "microsoft.extensions.caching.redis.2.2.0.nupkg.sha512", + "microsoft.extensions.caching.redis.nuspec" + ] + }, + "Microsoft.Extensions.Caching.SqlServer/2.2.0": { + "sha512": "hDAunudTCNyVb22W+ctToi9T3mcrix2L+GfnuhbIcbzgXVyUGMULUJmb2D5ElIJKkcGxkC/lM1aBMgHsSFFZcA==", + "type": "package", + "path": "microsoft.extensions.caching.sqlserver/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Caching.SqlServer.dll", + "lib/netstandard2.0/Microsoft.Extensions.Caching.SqlServer.xml", + "microsoft.extensions.caching.sqlserver.2.2.0.nupkg.sha512", + "microsoft.extensions.caching.sqlserver.nuspec" + ] + }, + "Microsoft.Extensions.Configuration/2.2.0": { + "sha512": "nOP8R1mVb/6mZtm2qgAJXn/LFm/2kMjHDAg/QJLFG6CuWYJtaD3p1BwQhufBVvRzL9ceJ/xF0SQ0qsI2GkDQAA==", + "type": "package", + "path": "microsoft.extensions.configuration/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.xml", + "microsoft.extensions.configuration.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.Abstractions/2.2.0": { + "sha512": "65MrmXCziWaQFrI0UHkQbesrX5wTwf9XPjY5yFm/VkgJKFJ5gqvXRoXjIZcf2wLi5ZlwGz/oMYfyURVCWbM5iw==", + "type": "package", + "path": "microsoft.extensions.configuration.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Abstractions.xml", + "microsoft.extensions.configuration.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.AzureKeyVault/2.2.0": { + "sha512": "aTt0fNYOVehKBrflWUBDZFTV51K986Y4LOIIEjyhk3LJ+VEwajJijKLNy5fsfddWUUDRxkNRr5gIFeUAV8OaaQ==", + "type": "package", + "path": "microsoft.extensions.configuration.azurekeyvault/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.AzureKeyVault.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.AzureKeyVault.xml", + "microsoft.extensions.configuration.azurekeyvault.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.azurekeyvault.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.Binder/2.2.4": { + "sha512": "TNTCeQwiVsBc9p4C+xPG+CmdaLVAwp+o9pHqYxtlTcXIA8ma7hCqTrXIjn7tPUEGufNEQ48sH1mfjO08jLjMdQ==", + "type": "package", + "path": "microsoft.extensions.configuration.binder/2.2.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Binder.xml", + "microsoft.extensions.configuration.binder.2.2.4.nupkg.sha512", + "microsoft.extensions.configuration.binder.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.CommandLine/2.2.0": { + "sha512": "4kJIGOSRqD1Ccqerst4t/zsNs51plR7BIxbdKO1J/9rL+2DuNT+ieAuEv+HROelqTam3yOpKFR7TtHBt3oLpOA==", + "type": "package", + "path": "microsoft.extensions.configuration.commandline/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.CommandLine.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.CommandLine.xml", + "microsoft.extensions.configuration.commandline.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.commandline.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables/2.2.4": { + "sha512": "Os7uRhp9xwawY5w2tgXw/86YrmAJZl6aHiQVdS9boWybTWPkJOvXXrQ3AGwuldN1W/r+cfnwRe2ePGeFO4zlzg==", + "type": "package", + "path": "microsoft.extensions.configuration.environmentvariables/2.2.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.EnvironmentVariables.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.EnvironmentVariables.xml", + "microsoft.extensions.configuration.environmentvariables.2.2.4.nupkg.sha512", + "microsoft.extensions.configuration.environmentvariables.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.FileExtensions/2.2.0": { + "sha512": "H1qCpWBC8Ed4tguTR/qYkbb3F6DI5Su3t8xyFo3/5MzAd8PwPpHzgX8X04KbBxKmk173Pb64x7xMHarczVFQUA==", + "type": "package", + "path": "microsoft.extensions.configuration.fileextensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.FileExtensions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.FileExtensions.xml", + "microsoft.extensions.configuration.fileextensions.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.fileextensions.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.Ini/2.2.0": { + "sha512": "uEDasBxY7m0GJseqHD8QhfiznxDMhxN9YE3j01Es6eks42rRm3yL8ZMbRxuEjyKqGZqjjt+Vr297/nKcg0eOow==", + "type": "package", + "path": "microsoft.extensions.configuration.ini/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Ini.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Ini.xml", + "microsoft.extensions.configuration.ini.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.ini.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.Json/2.2.0": { + "sha512": "jUDdmLyFmLf9V3mqnMzSAzAv4QigJ67tZh5Q7HBXeBnESL2UyeesNG6jSBti+b63JpxZf+EDyn+anx3gyrNxug==", + "type": "package", + "path": "microsoft.extensions.configuration.json/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Json.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Json.xml", + "microsoft.extensions.configuration.json.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.json.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.KeyPerFile/2.2.4": { + "sha512": "Giap+i/Z/VH+RzYSsFmuESSxzO3z6QYE2tk9Mjwxtw+VgaZcfNZgToHmoEKducKOOIvt5V7hPbfm0H5yKV2ztQ==", + "type": "package", + "path": "microsoft.extensions.configuration.keyperfile/2.2.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.KeyPerFile.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.KeyPerFile.xml", + "microsoft.extensions.configuration.keyperfile.2.2.4.nupkg.sha512", + "microsoft.extensions.configuration.keyperfile.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.UserSecrets/2.2.0": { + "sha512": "2/N2xo6/sNbVshnKktmq5lwaQbsAR2SrzCVrJEeMP8OKZVI7SzT8P6/WXZF8/YC7dTYsMe3nrHzgl1cF9i5ZKQ==", + "type": "package", + "path": "microsoft.extensions.configuration.usersecrets/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.props", + "build/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.targets", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.UserSecrets.xml", + "microsoft.extensions.configuration.usersecrets.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.usersecrets.nuspec" + ] + }, + "Microsoft.Extensions.Configuration.Xml/2.2.0": { + "sha512": "toCFesKf2KZgRtb6T7tulnJv3IBVL+Gqd4KE3ebQZ20wA2Z5Rp6A44MsRGZ1ollmihzkxxBDavVfgufFeji3Sw==", + "type": "package", + "path": "microsoft.extensions.configuration.xml/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Xml.dll", + "lib/netstandard2.0/Microsoft.Extensions.Configuration.Xml.xml", + "microsoft.extensions.configuration.xml.2.2.0.nupkg.sha512", + "microsoft.extensions.configuration.xml.nuspec" + ] + }, + "Microsoft.Extensions.DependencyInjection/2.2.0": { + "sha512": "MZtBIwfDFork5vfjpJdG5g8wuJFt7d/y3LOSVVtDK/76wlbtz6cjltfKHqLx2TKVqTj5/c41t77m1+h20zqtPA==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net461/Microsoft.Extensions.DependencyInjection.dll", + "lib/net461/Microsoft.Extensions.DependencyInjection.xml", + "lib/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.dll", + "lib/netcoreapp2.0/Microsoft.Extensions.DependencyInjection.xml", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.xml", + "microsoft.extensions.dependencyinjection.2.2.0.nupkg.sha512", + "microsoft.extensions.dependencyinjection.nuspec" + ] + }, + "Microsoft.Extensions.DependencyInjection.Abstractions/2.2.0": { + "sha512": "f9hstgjVmr6rmrfGSpfsVOl2irKAgr1QjrSi3FgnS7kulxband50f2brRLwySAQTADPZeTdow0mpSMcoAdadCw==", + "type": "package", + "path": "microsoft.extensions.dependencyinjection.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.DependencyInjection.Abstractions.xml", + "microsoft.extensions.dependencyinjection.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.dependencyinjection.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.DependencyModel/2.1.0": { + "sha512": "nS2XKqi+1A1umnYNLX2Fbm/XnzCxs5i+zXVJ3VC6r9t2z0NZr9FLnJN4VQpKigdcWH/iFTbMuX6M6WQJcTjVIg==", + "type": "package", + "path": "microsoft.extensions.dependencymodel/2.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net451/Microsoft.Extensions.DependencyModel.dll", + "lib/netstandard1.3/Microsoft.Extensions.DependencyModel.dll", + "lib/netstandard1.6/Microsoft.Extensions.DependencyModel.dll", + "microsoft.extensions.dependencymodel.2.1.0.nupkg.sha512", + "microsoft.extensions.dependencymodel.nuspec" + ] + }, + "Microsoft.Extensions.DiagnosticAdapter/2.2.0": { + "sha512": "Av0QGyboU9hYcprPduZg8Ny4mtp1Z0xOfZGCiBhYMh6a0loNomZ74U1P9EJUBksT2ZJd0+hh/pOQIVdAJ8+AbA==", + "type": "package", + "path": "microsoft.extensions.diagnosticadapter/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net461/Microsoft.Extensions.DiagnosticAdapter.dll", + "lib/net461/Microsoft.Extensions.DiagnosticAdapter.xml", + "lib/netcoreapp2.0/Microsoft.Extensions.DiagnosticAdapter.dll", + "lib/netcoreapp2.0/Microsoft.Extensions.DiagnosticAdapter.xml", + "lib/netstandard2.0/Microsoft.Extensions.DiagnosticAdapter.dll", + "lib/netstandard2.0/Microsoft.Extensions.DiagnosticAdapter.xml", + "microsoft.extensions.diagnosticadapter.2.2.0.nupkg.sha512", + "microsoft.extensions.diagnosticadapter.nuspec" + ] + }, + "Microsoft.Extensions.Diagnostics.HealthChecks/2.2.5": { + "sha512": "/Il+nqw4dgR0b01qJnE9e99bnF8JpZQye1dTlTn9OSKFkdPXJsNZj9uzaJJIhd+Bc17saIqRW8gUUSLqlayqKg==", + "type": "package", + "path": "microsoft.extensions.diagnostics.healthchecks/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.dll", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.xml", + "microsoft.extensions.diagnostics.healthchecks.2.2.5.nupkg.sha512", + "microsoft.extensions.diagnostics.healthchecks.nuspec" + ] + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions/2.2.0": { + "sha512": "cO6f4csTakJXuLWnU/p5mfQInyNq5sSi4mS2YtQZcGoHynU6P/TD6gjqt1TRnVfwuZLw3tmmw2ipFrHbBUqWew==", + "type": "package", + "path": "microsoft.extensions.diagnostics.healthchecks.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.xml", + "microsoft.extensions.diagnostics.healthchecks.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.diagnostics.healthchecks.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.FileProviders.Abstractions/2.2.0": { + "sha512": "EcnaSsPTqx2MGnHrmWOD0ugbuuqVT8iICqSqPzi45V5/MA1LjUNb0kwgcxBGqizV1R+WeBK7/Gw25Jzkyk9bIw==", + "type": "package", + "path": "microsoft.extensions.fileproviders.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Abstractions.xml", + "microsoft.extensions.fileproviders.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.fileproviders.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.FileProviders.Composite/2.2.0": { + "sha512": "Az/RxWB+UlyVN/TvQFaGXx8XAXVZN5WQnnuJOsjwBzghSJc1i8zqNjIypPHOedcuIXs2XSWgOSL6YQ3BlCnoJA==", + "type": "package", + "path": "microsoft.extensions.fileproviders.composite/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Composite.dll", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Composite.xml", + "microsoft.extensions.fileproviders.composite.2.2.0.nupkg.sha512", + "microsoft.extensions.fileproviders.composite.nuspec" + ] + }, + "Microsoft.Extensions.FileProviders.Embedded/2.2.0": { + "sha512": "6e22jnVntG9JLLowjY40UBPLXkKTRlDpFHmo2evN8lwZIpO89ZRGz6JRdqhnVYCaavq5KeFU2W5VKPA5y5farA==", + "type": "package", + "path": "microsoft.extensions.fileproviders.embedded/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.props", + "build/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.targets", + "buildMultiTargeting/Microsoft.Extensions.FileProviders.Embedded.props", + "buildMultiTargeting/Microsoft.Extensions.FileProviders.Embedded.targets", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.dll", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Embedded.xml", + "microsoft.extensions.fileproviders.embedded.2.2.0.nupkg.sha512", + "microsoft.extensions.fileproviders.embedded.nuspec", + "tasks/net461/Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll", + "tasks/netstandard1.5/Microsoft.Extensions.FileProviders.Embedded.Manifest.Task.dll" + ] + }, + "Microsoft.Extensions.FileProviders.Physical/2.2.0": { + "sha512": "tbDHZnBJkjYd9NjlRZ9ondDiv1Te3KYCTW2RWpR1B0e1Z8+EnFRo7qNnHkkSCixLdlPZzhjlX24d/PixQ7w2dA==", + "type": "package", + "path": "microsoft.extensions.fileproviders.physical/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Physical.dll", + "lib/netstandard2.0/Microsoft.Extensions.FileProviders.Physical.xml", + "microsoft.extensions.fileproviders.physical.2.2.0.nupkg.sha512", + "microsoft.extensions.fileproviders.physical.nuspec" + ] + }, + "Microsoft.Extensions.FileSystemGlobbing/2.2.0": { + "sha512": "ZSsHZp3PyW6vk37tDEdypjgGlNtpJ0EixBMOfUod2Thx7GtwfFSAQXUQx8a8BN8vfWKGGMbp7jPWdoHx/At4wQ==", + "type": "package", + "path": "microsoft.extensions.filesystemglobbing/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.FileSystemGlobbing.dll", + "lib/netstandard2.0/Microsoft.Extensions.FileSystemGlobbing.xml", + "microsoft.extensions.filesystemglobbing.2.2.0.nupkg.sha512", + "microsoft.extensions.filesystemglobbing.nuspec" + ] + }, + "Microsoft.Extensions.Hosting/2.2.0": { + "sha512": "PxZPd5QbWr8+3JN2segEaD7IAYI+mR8ZmMqgo6GOk+E+UKnRcbC3RSQgJrZYuWVQwJCvdxesO5e64LSHC1zC8g==", + "type": "package", + "path": "microsoft.extensions.hosting/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Hosting.dll", + "lib/netstandard2.0/Microsoft.Extensions.Hosting.xml", + "microsoft.extensions.hosting.2.2.0.nupkg.sha512", + "microsoft.extensions.hosting.nuspec" + ] + }, + "Microsoft.Extensions.Hosting.Abstractions/2.2.0": { + "sha512": "+k4AEn68HOJat5gj1TWa6X28WlirNQO9sPIIeQbia+91n03esEtMSSoekSTpMjUzjqtJWQN3McVx0GvSPFHF/Q==", + "type": "package", + "path": "microsoft.extensions.hosting.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Hosting.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Hosting.Abstractions.xml", + "microsoft.extensions.hosting.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.hosting.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.Http/2.2.0": { + "sha512": "hZ8mz6FgxSeFtkHzw+Ad0QOt2yjjpq4WaG9itnkyChtXYTrDlbkw3af2WJ9wdEAAyYqOlQaVDB6MJSEo8dd/vw==", + "type": "package", + "path": "microsoft.extensions.http/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Http.dll", + "lib/netstandard2.0/Microsoft.Extensions.Http.xml", + "microsoft.extensions.http.2.2.0.nupkg.sha512", + "microsoft.extensions.http.nuspec" + ] + }, + "Microsoft.Extensions.Identity.Core/2.2.0": { + "sha512": "/C+Valwg8IeUwDIunusittHivA9iyf82Jr1yeUFWO2zH2mDMMeYgjRyDLZqfL/7Vq94PEQsgv1XAaDfAX8msMw==", + "type": "package", + "path": "microsoft.extensions.identity.core/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Identity.Core.dll", + "lib/netstandard2.0/Microsoft.Extensions.Identity.Core.xml", + "microsoft.extensions.identity.core.2.2.0.nupkg.sha512", + "microsoft.extensions.identity.core.nuspec" + ] + }, + "Microsoft.Extensions.Identity.Stores/2.2.0": { + "sha512": "WY6os4m5LcG7XXHQK1vQggjdNFs7h6CsidVLOzPjG7Cb1zwRYKzfRT/pSUD40JNGvVp4oNENjLPvu/30ufIGNw==", + "type": "package", + "path": "microsoft.extensions.identity.stores/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Identity.Stores.dll", + "lib/netstandard2.0/Microsoft.Extensions.Identity.Stores.xml", + "microsoft.extensions.identity.stores.2.2.0.nupkg.sha512", + "microsoft.extensions.identity.stores.nuspec" + ] + }, + "Microsoft.Extensions.Localization/2.2.0": { + "sha512": "3nBQLeBrcd4Rgd9vQi4gF5NgAWxnQrHekjjwlgww4wyLNfJDizjiex2resOLoAuAgy3y2IIAWjOpbr0UKR2ykw==", + "type": "package", + "path": "microsoft.extensions.localization/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Localization.dll", + "lib/netstandard2.0/Microsoft.Extensions.Localization.xml", + "microsoft.extensions.localization.2.2.0.nupkg.sha512", + "microsoft.extensions.localization.nuspec" + ] + }, + "Microsoft.Extensions.Localization.Abstractions/2.2.0": { + "sha512": "FQzXG/lYR9UOM2zHpqsjTRpp3EghIYo3FCsQpfmtbp+glPaU0WXZfNmMjyqBRmMj1Sq93fPnC+G9zzYRauuRQA==", + "type": "package", + "path": "microsoft.extensions.localization.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Localization.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Localization.Abstractions.xml", + "microsoft.extensions.localization.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.localization.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.Logging/2.2.0": { + "sha512": "Nxqhadc9FCmFHzU+fz3oc8sFlE6IadViYg8dfUdGzJZ2JUxnCsRghBhhOWdM4B2zSZqEc+0BjliBh/oNdRZuig==", + "type": "package", + "path": "microsoft.extensions.logging/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.xml", + "microsoft.extensions.logging.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.nuspec" + ] + }, + "Microsoft.Extensions.Logging.Abstractions/2.2.0": { + "sha512": "B2WqEox8o+4KUOpL7rZPyh6qYjik8tHi2tN8Z9jZkHzED8ElYgZa/h6K+xliB435SqUcWT290Fr2aa8BtZjn8A==", + "type": "package", + "path": "microsoft.extensions.logging.abstractions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Abstractions.xml", + "microsoft.extensions.logging.abstractions.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.abstractions.nuspec" + ] + }, + "Microsoft.Extensions.Logging.AzureAppServices/2.2.5": { + "sha512": "ig+AMvywAaBZnD2WeHnmw5DojcbB8m1oC6T0kCDGcHe8e1wdaylxjYqOq0t2Q4Hq4/Ie8G8Bneej13Ol/fKdKg==", + "type": "package", + "path": "microsoft.extensions.logging.azureappservices/2.2.5", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.AzureAppServices.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.AzureAppServices.xml", + "microsoft.extensions.logging.azureappservices.2.2.5.nupkg.sha512", + "microsoft.extensions.logging.azureappservices.nuspec" + ] + }, + "Microsoft.Extensions.Logging.Configuration/2.2.0": { + "sha512": "ukU1mQGX9+xBsEzpNd13yl4deFVYI+fxxnmKpOhvNZsF+/trCrAUQh+9QM5pPGHbfYkz3lLQ4BXfKCP0502dLw==", + "type": "package", + "path": "microsoft.extensions.logging.configuration/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Configuration.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Configuration.xml", + "microsoft.extensions.logging.configuration.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.configuration.nuspec" + ] + }, + "Microsoft.Extensions.Logging.Console/2.2.0": { + "sha512": "1eGgcOJ++PMxW6sn++j6U7wsWvhEBm/5ScqBUUBGLRE8M7AHahi9tsxivDMqEXVM3F0/pshHl3kEpMXtw4BeFg==", + "type": "package", + "path": "microsoft.extensions.logging.console/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Console.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Console.xml", + "microsoft.extensions.logging.console.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.console.nuspec" + ] + }, + "Microsoft.Extensions.Logging.Debug/2.2.0": { + "sha512": "JjqWtshxUujSnxslFccCRAaH8uFOciqXkYdRw+h5MwpC4sUc+ju9yZzvVi6PA5vW09ckv26EkasEvXrofGiaJg==", + "type": "package", + "path": "microsoft.extensions.logging.debug/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Debug.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.Debug.xml", + "microsoft.extensions.logging.debug.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.debug.nuspec" + ] + }, + "Microsoft.Extensions.Logging.EventSource/2.2.0": { + "sha512": "oOa5H+vdNgpsxE6vgtX4U/godKtX2edVi+QjlWb2PBQfavGIQ3WxtjxN+B0DQAjwBNdV4mW8cgOiDEZ8KdR7Ig==", + "type": "package", + "path": "microsoft.extensions.logging.eventsource/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.EventSource.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.EventSource.xml", + "microsoft.extensions.logging.eventsource.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.eventsource.nuspec" + ] + }, + "Microsoft.Extensions.Logging.TraceSource/2.2.0": { + "sha512": "2laIg/Mf1OhhduUKVN3//j+sYceyUocgGC/ySx6cnZFeNf2mezs32TmRZyzfkQAZQ6azlo/0wTxi8BgIVUyRYA==", + "type": "package", + "path": "microsoft.extensions.logging.tracesource/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Logging.TraceSource.dll", + "lib/netstandard2.0/Microsoft.Extensions.Logging.TraceSource.xml", + "microsoft.extensions.logging.tracesource.2.2.0.nupkg.sha512", + "microsoft.extensions.logging.tracesource.nuspec" + ] + }, + "Microsoft.Extensions.ObjectPool/2.2.0": { + "sha512": "gA8H7uQOnM5gb+L0uTNjViHYr+hRDqCdfugheGo/MxQnuHzmhhzCBTIPm19qL1z1Xe0NEMabfcOBGv9QghlZ8g==", + "type": "package", + "path": "microsoft.extensions.objectpool/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.ObjectPool.dll", + "lib/netstandard2.0/Microsoft.Extensions.ObjectPool.xml", + "microsoft.extensions.objectpool.2.2.0.nupkg.sha512", + "microsoft.extensions.objectpool.nuspec" + ] + }, + "Microsoft.Extensions.Options/2.2.0": { + "sha512": "UpZLNLBpIZ0GTebShui7xXYh6DmBHjWM8NxGxZbdQh/bPZ5e6YswqI+bru6BnEL5eWiOdodsXtEz3FROcgi/qg==", + "type": "package", + "path": "microsoft.extensions.options/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Options.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.xml", + "microsoft.extensions.options.2.2.0.nupkg.sha512", + "microsoft.extensions.options.nuspec" + ] + }, + "Microsoft.Extensions.Options.ConfigurationExtensions/2.2.0": { + "sha512": "d4WS6yVXaw43ffiUnHj8oG1t2B6RbDDiQcgdA+Eq//NlPa3Wd+GTJFKj4OM4eDF3GjVumGr/CEVRS/jcYoF5LA==", + "type": "package", + "path": "microsoft.extensions.options.configurationextensions/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.ConfigurationExtensions.xml", + "microsoft.extensions.options.configurationextensions.2.2.0.nupkg.sha512", + "microsoft.extensions.options.configurationextensions.nuspec" + ] + }, + "Microsoft.Extensions.Options.DataAnnotations/2.2.0": { + "sha512": "Xk7okx/u+ZQb8xvz71FwVmfZjwDh2DWrovhtQXprWE16KqaP8bs6A8wb0h9nTSFh9rcFDVeo42d47iduu01XvQ==", + "type": "package", + "path": "microsoft.extensions.options.dataannotations/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Options.DataAnnotations.dll", + "lib/netstandard2.0/Microsoft.Extensions.Options.DataAnnotations.xml", + "microsoft.extensions.options.dataannotations.2.2.0.nupkg.sha512", + "microsoft.extensions.options.dataannotations.nuspec" + ] + }, + "Microsoft.Extensions.PlatformAbstractions/1.1.0": { + "sha512": "H6ZsQzxYw/6k2DfEQRXdC+vQ6obd6Uba3uGJrnJ2vG4PRXjQZ7seB13JdCfE72abp8E6Fk3gGgDzfJiLZi5ZpQ==", + "type": "package", + "path": "microsoft.extensions.platformabstractions/1.1.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net451/Microsoft.Extensions.PlatformAbstractions.dll", + "lib/net451/Microsoft.Extensions.PlatformAbstractions.xml", + "lib/netstandard1.3/Microsoft.Extensions.PlatformAbstractions.dll", + "lib/netstandard1.3/Microsoft.Extensions.PlatformAbstractions.xml", + "microsoft.extensions.platformabstractions.1.1.0.nupkg.sha512", + "microsoft.extensions.platformabstractions.nuspec" + ] + }, + "Microsoft.Extensions.Primitives/2.2.0": { + "sha512": "azyQtqbm4fSaDzZHD/J+V6oWMFaf2tWP4WEGIYePLCMw3+b2RQdj9ybgbQyjCshcitQKQ4lEDOZjmSlTTrHxUg==", + "type": "package", + "path": "microsoft.extensions.primitives/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.dll", + "lib/netstandard2.0/Microsoft.Extensions.Primitives.xml", + "microsoft.extensions.primitives.2.2.0.nupkg.sha512", + "microsoft.extensions.primitives.nuspec" + ] + }, + "Microsoft.Extensions.WebEncoders/2.2.0": { + "sha512": "V8XcqYcpcdBAxUhLeyYcuKmxu4CtNQA9IphTnARpQGhkop4A93v2XgM3AtaVVJo3H2cDWxWM6aeO8HxkifREqw==", + "type": "package", + "path": "microsoft.extensions.webencoders/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Extensions.WebEncoders.dll", + "lib/netstandard2.0/Microsoft.Extensions.WebEncoders.xml", + "microsoft.extensions.webencoders.2.2.0.nupkg.sha512", + "microsoft.extensions.webencoders.nuspec" + ] + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory/3.19.8": { + "sha512": "PRTE+0vg/e+wNFDBEPdZlDVVwopyOZtGnbg0B4ANxR0eeZKoEwfumBoAIO6iC91jRLMTpCfYXTArmn8BpyLIIg==", + "type": "package", + "path": "microsoft.identitymodel.clients.activedirectory/3.19.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/MonoAndroid7/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/MonoAndroid7/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/MonoAndroid7/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/MonoAndroid7/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/Xamarin.iOS10/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/Xamarin.iOS10/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/Xamarin.iOS10/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/Xamarin.iOS10/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/net45/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/net45/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/net45/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/net45/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/netcore45/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/netcore45/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/netcore45/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/netcore45/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/netstandard1.1/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/netstandard1.1/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/netstandard1.1/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/netstandard1.1/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/netstandard1.3/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "lib/portable-net45+win/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll", + "lib/portable-net45+win/Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.xml", + "lib/portable-net45+win/Microsoft.IdentityModel.Clients.ActiveDirectory.dll", + "lib/portable-net45+win/Microsoft.IdentityModel.Clients.ActiveDirectory.xml", + "microsoft.identitymodel.clients.activedirectory.3.19.8.nupkg.sha512", + "microsoft.identitymodel.clients.activedirectory.nuspec" + ] + }, + "Microsoft.IdentityModel.JsonWebTokens/5.3.0": { + "sha512": "5LW5VYvGZLvrbEGxyaE6dSQhT1B5frnpwX/c4/PWrNXeuJ6GkYmiOPf2u5Iwk1qQXPTvDedwEfnBg+i/0cFAyA==", + "type": "package", + "path": "microsoft.identitymodel.jsonwebtokens/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net45/Microsoft.IdentityModel.JsonWebTokens.pdb", + "lib/net45/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net451/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net451/Microsoft.IdentityModel.JsonWebTokens.pdb", + "lib/net451/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/net461/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/net461/Microsoft.IdentityModel.JsonWebTokens.pdb", + "lib/net461/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.JsonWebTokens.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.JsonWebTokens.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.JsonWebTokens.xml", + "microsoft.identitymodel.jsonwebtokens.5.3.0.nupkg.sha512", + "microsoft.identitymodel.jsonwebtokens.nuspec" + ] + }, + "Microsoft.IdentityModel.Logging/5.3.0": { + "sha512": "o+bBauEMOi6ZI0MlJEC69Sw9UPwKLFmN+lD942g9UCx5pfiLFvJBKp8OPmxtGFL02ZxzXCIUyhyKn85izBDsnQ==", + "type": "package", + "path": "microsoft.identitymodel.logging/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Logging.dll", + "lib/net45/Microsoft.IdentityModel.Logging.pdb", + "lib/net45/Microsoft.IdentityModel.Logging.xml", + "lib/net451/Microsoft.IdentityModel.Logging.dll", + "lib/net451/Microsoft.IdentityModel.Logging.pdb", + "lib/net451/Microsoft.IdentityModel.Logging.xml", + "lib/net461/Microsoft.IdentityModel.Logging.dll", + "lib/net461/Microsoft.IdentityModel.Logging.pdb", + "lib/net461/Microsoft.IdentityModel.Logging.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Logging.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Logging.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Logging.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Logging.xml", + "microsoft.identitymodel.logging.5.3.0.nupkg.sha512", + "microsoft.identitymodel.logging.nuspec" + ] + }, + "Microsoft.IdentityModel.Protocols/5.3.0": { + "sha512": "o2Fx9cYQHKtOyVrCXB41kEmny1Zvm+fqXNTD5heB9yPY0C+qYm7fo1yCvtHaH2JPEersGW0iS2dE0s65kWkVEw==", + "type": "package", + "path": "microsoft.identitymodel.protocols/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Protocols.dll", + "lib/net45/Microsoft.IdentityModel.Protocols.pdb", + "lib/net45/Microsoft.IdentityModel.Protocols.xml", + "lib/net451/Microsoft.IdentityModel.Protocols.dll", + "lib/net451/Microsoft.IdentityModel.Protocols.pdb", + "lib/net451/Microsoft.IdentityModel.Protocols.xml", + "lib/net461/Microsoft.IdentityModel.Protocols.dll", + "lib/net461/Microsoft.IdentityModel.Protocols.pdb", + "lib/net461/Microsoft.IdentityModel.Protocols.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.xml", + "microsoft.identitymodel.protocols.5.3.0.nupkg.sha512", + "microsoft.identitymodel.protocols.nuspec" + ] + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect/5.3.0": { + "sha512": "NihXp2JT3fRbTq6AOQhEQT8TuJzhUNg9TOeK+TxlkkvanllWFF0gfXH5hTRn9Qn68HJQXtp/mtLbCWzi+4bCSg==", + "type": "package", + "path": "microsoft.identitymodel.protocols.openidconnect/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll", + "lib/net45/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb", + "lib/net45/Microsoft.IdentityModel.Protocols.OpenIdConnect.xml", + "lib/net451/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll", + "lib/net451/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb", + "lib/net451/Microsoft.IdentityModel.Protocols.OpenIdConnect.xml", + "lib/net461/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll", + "lib/net461/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb", + "lib/net461/Microsoft.IdentityModel.Protocols.OpenIdConnect.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.OpenIdConnect.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.xml", + "microsoft.identitymodel.protocols.openidconnect.5.3.0.nupkg.sha512", + "microsoft.identitymodel.protocols.openidconnect.nuspec" + ] + }, + "Microsoft.IdentityModel.Protocols.WsFederation/5.3.0": { + "sha512": "6nGUoC+foCQ2UTsRD/Z6TLgsghuX10tunLXxuLE+LljW9H1oANqAQWrP8DNP++nfXke+qu1zVi6yBl6MMK/Dfg==", + "type": "package", + "path": "microsoft.identitymodel.protocols.wsfederation/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Protocols.WsFederation.dll", + "lib/net45/Microsoft.IdentityModel.Protocols.WsFederation.pdb", + "lib/net45/Microsoft.IdentityModel.Protocols.WsFederation.xml", + "lib/net451/Microsoft.IdentityModel.Protocols.WsFederation.dll", + "lib/net451/Microsoft.IdentityModel.Protocols.WsFederation.pdb", + "lib/net451/Microsoft.IdentityModel.Protocols.WsFederation.xml", + "lib/net461/Microsoft.IdentityModel.Protocols.WsFederation.dll", + "lib/net461/Microsoft.IdentityModel.Protocols.WsFederation.pdb", + "lib/net461/Microsoft.IdentityModel.Protocols.WsFederation.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.WsFederation.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.WsFederation.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Protocols.WsFederation.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.WsFederation.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.WsFederation.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Protocols.WsFederation.xml", + "microsoft.identitymodel.protocols.wsfederation.5.3.0.nupkg.sha512", + "microsoft.identitymodel.protocols.wsfederation.nuspec" + ] + }, + "Microsoft.IdentityModel.Tokens/5.3.0": { + "sha512": "/piauST4FL0qzVI6oqLWxqhFReg12KwVGy0jRlnVOpGMeOVSKdtNVtHsN/hARc25hOOPEp9WKMce5ILzyMx/tQ==", + "type": "package", + "path": "microsoft.identitymodel.tokens/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Tokens.dll", + "lib/net45/Microsoft.IdentityModel.Tokens.pdb", + "lib/net45/Microsoft.IdentityModel.Tokens.xml", + "lib/net451/Microsoft.IdentityModel.Tokens.dll", + "lib/net451/Microsoft.IdentityModel.Tokens.pdb", + "lib/net451/Microsoft.IdentityModel.Tokens.xml", + "lib/net461/Microsoft.IdentityModel.Tokens.dll", + "lib/net461/Microsoft.IdentityModel.Tokens.pdb", + "lib/net461/Microsoft.IdentityModel.Tokens.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.xml", + "microsoft.identitymodel.tokens.5.3.0.nupkg.sha512", + "microsoft.identitymodel.tokens.nuspec" + ] + }, + "Microsoft.IdentityModel.Tokens.Saml/5.3.0": { + "sha512": "XS6zgN7jKG7QDqG3fV9BRADs8HmRJ6vJDKVBPFFly9MCkS6KMFps4hBdBJ5ycPrXtPBfnISCLiGLHP54blCvWw==", + "type": "package", + "path": "microsoft.identitymodel.tokens.saml/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Tokens.Saml.dll", + "lib/net45/Microsoft.IdentityModel.Tokens.Saml.pdb", + "lib/net45/Microsoft.IdentityModel.Tokens.Saml.xml", + "lib/net451/Microsoft.IdentityModel.Tokens.Saml.dll", + "lib/net451/Microsoft.IdentityModel.Tokens.Saml.pdb", + "lib/net451/Microsoft.IdentityModel.Tokens.Saml.xml", + "lib/net461/Microsoft.IdentityModel.Tokens.Saml.dll", + "lib/net461/Microsoft.IdentityModel.Tokens.Saml.pdb", + "lib/net461/Microsoft.IdentityModel.Tokens.Saml.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.Saml.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.Saml.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Tokens.Saml.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.Saml.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.Saml.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Tokens.Saml.xml", + "microsoft.identitymodel.tokens.saml.5.3.0.nupkg.sha512", + "microsoft.identitymodel.tokens.saml.nuspec" + ] + }, + "Microsoft.IdentityModel.Xml/5.3.0": { + "sha512": "i4uFRjipeRXGhyfHmJaZ3PkOQIWhwxBJABNDWNaxcwUvramMCWYRLE1P3g4sLjiw8zXehH6eZwxww8F+dB7/+g==", + "type": "package", + "path": "microsoft.identitymodel.xml/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.IdentityModel.Xml.dll", + "lib/net45/Microsoft.IdentityModel.Xml.pdb", + "lib/net45/Microsoft.IdentityModel.Xml.xml", + "lib/net451/Microsoft.IdentityModel.Xml.dll", + "lib/net451/Microsoft.IdentityModel.Xml.pdb", + "lib/net451/Microsoft.IdentityModel.Xml.xml", + "lib/net461/Microsoft.IdentityModel.Xml.dll", + "lib/net461/Microsoft.IdentityModel.Xml.pdb", + "lib/net461/Microsoft.IdentityModel.Xml.xml", + "lib/netstandard1.4/Microsoft.IdentityModel.Xml.dll", + "lib/netstandard1.4/Microsoft.IdentityModel.Xml.pdb", + "lib/netstandard1.4/Microsoft.IdentityModel.Xml.xml", + "lib/netstandard2.0/Microsoft.IdentityModel.Xml.dll", + "lib/netstandard2.0/Microsoft.IdentityModel.Xml.pdb", + "lib/netstandard2.0/Microsoft.IdentityModel.Xml.xml", + "microsoft.identitymodel.xml.5.3.0.nupkg.sha512", + "microsoft.identitymodel.xml.nuspec" + ] + }, + "Microsoft.Net.Http.Headers/2.2.8": { + "sha512": "wHdwMv0QDDG2NWDSwax9cjkeQceGC1Qq53a31+31XpvTXVljKXRjWISlMoS/wZYKiqdqzuEvKFKwGHl+mt2jCA==", + "type": "package", + "path": "microsoft.net.http.headers/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.Net.Http.Headers.dll", + "lib/netstandard2.0/Microsoft.Net.Http.Headers.xml", + "microsoft.net.http.headers.2.2.8.nupkg.sha512", + "microsoft.net.http.headers.nuspec" + ] + }, + "Microsoft.NETCore.App/2.2.8": { + "sha512": "GOxlvyc8hFrnhDjYlm25JJ7PwoyeoOpZzcg6ZgF8n8l6VxezNupRkkTeA2ek1WsspN0CdAoA8e7iDVNU84/F+Q==", + "type": "package", + "path": "microsoft.netcore.app/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "Microsoft.NETCore.App.versions.txt", + "THIRD-PARTY-NOTICES.TXT", + "build/netcoreapp2.2/Microsoft.NETCore.App.PlatformManifest.txt", + "build/netcoreapp2.2/Microsoft.NETCore.App.props", + "build/netcoreapp2.2/Microsoft.NETCore.App.targets", + "microsoft.netcore.app.2.2.8.nupkg.sha512", + "microsoft.netcore.app.nuspec", + "ref/netcoreapp2.2/Microsoft.CSharp.dll", + "ref/netcoreapp2.2/Microsoft.CSharp.xml", + "ref/netcoreapp2.2/Microsoft.VisualBasic.dll", + "ref/netcoreapp2.2/Microsoft.VisualBasic.xml", + "ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll", + "ref/netcoreapp2.2/Microsoft.Win32.Primitives.xml", + "ref/netcoreapp2.2/System.AppContext.dll", + "ref/netcoreapp2.2/System.Buffers.dll", + "ref/netcoreapp2.2/System.Buffers.xml", + "ref/netcoreapp2.2/System.Collections.Concurrent.dll", + "ref/netcoreapp2.2/System.Collections.Concurrent.xml", + "ref/netcoreapp2.2/System.Collections.Immutable.dll", + "ref/netcoreapp2.2/System.Collections.Immutable.xml", + "ref/netcoreapp2.2/System.Collections.NonGeneric.dll", + "ref/netcoreapp2.2/System.Collections.NonGeneric.xml", + "ref/netcoreapp2.2/System.Collections.Specialized.dll", + "ref/netcoreapp2.2/System.Collections.Specialized.xml", + "ref/netcoreapp2.2/System.Collections.dll", + "ref/netcoreapp2.2/System.Collections.xml", + "ref/netcoreapp2.2/System.ComponentModel.Annotations.dll", + "ref/netcoreapp2.2/System.ComponentModel.Annotations.xml", + "ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll", + "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll", + "ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.xml", + "ref/netcoreapp2.2/System.ComponentModel.Primitives.dll", + "ref/netcoreapp2.2/System.ComponentModel.Primitives.xml", + "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll", + "ref/netcoreapp2.2/System.ComponentModel.TypeConverter.xml", + "ref/netcoreapp2.2/System.ComponentModel.dll", + "ref/netcoreapp2.2/System.ComponentModel.xml", + "ref/netcoreapp2.2/System.Configuration.dll", + "ref/netcoreapp2.2/System.Console.dll", + "ref/netcoreapp2.2/System.Console.xml", + "ref/netcoreapp2.2/System.Core.dll", + "ref/netcoreapp2.2/System.Data.Common.dll", + "ref/netcoreapp2.2/System.Data.Common.xml", + "ref/netcoreapp2.2/System.Data.dll", + "ref/netcoreapp2.2/System.Diagnostics.Contracts.dll", + "ref/netcoreapp2.2/System.Diagnostics.Contracts.xml", + "ref/netcoreapp2.2/System.Diagnostics.Debug.dll", + "ref/netcoreapp2.2/System.Diagnostics.Debug.xml", + "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll", + "ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.xml", + "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll", + "ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.xml", + "ref/netcoreapp2.2/System.Diagnostics.Process.dll", + "ref/netcoreapp2.2/System.Diagnostics.Process.xml", + "ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll", + "ref/netcoreapp2.2/System.Diagnostics.StackTrace.xml", + "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll", + "ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.xml", + "ref/netcoreapp2.2/System.Diagnostics.Tools.dll", + "ref/netcoreapp2.2/System.Diagnostics.Tools.xml", + "ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll", + "ref/netcoreapp2.2/System.Diagnostics.TraceSource.xml", + "ref/netcoreapp2.2/System.Diagnostics.Tracing.dll", + "ref/netcoreapp2.2/System.Diagnostics.Tracing.xml", + "ref/netcoreapp2.2/System.Drawing.Primitives.dll", + "ref/netcoreapp2.2/System.Drawing.Primitives.xml", + "ref/netcoreapp2.2/System.Drawing.dll", + "ref/netcoreapp2.2/System.Dynamic.Runtime.dll", + "ref/netcoreapp2.2/System.Globalization.Calendars.dll", + "ref/netcoreapp2.2/System.Globalization.Extensions.dll", + "ref/netcoreapp2.2/System.Globalization.dll", + "ref/netcoreapp2.2/System.IO.Compression.Brotli.dll", + "ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll", + "ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll", + "ref/netcoreapp2.2/System.IO.Compression.ZipFile.xml", + "ref/netcoreapp2.2/System.IO.Compression.dll", + "ref/netcoreapp2.2/System.IO.Compression.xml", + "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll", + "ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.xml", + "ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll", + "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll", + "ref/netcoreapp2.2/System.IO.FileSystem.Watcher.xml", + "ref/netcoreapp2.2/System.IO.FileSystem.dll", + "ref/netcoreapp2.2/System.IO.FileSystem.xml", + "ref/netcoreapp2.2/System.IO.IsolatedStorage.dll", + "ref/netcoreapp2.2/System.IO.IsolatedStorage.xml", + "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll", + "ref/netcoreapp2.2/System.IO.MemoryMappedFiles.xml", + "ref/netcoreapp2.2/System.IO.Pipes.dll", + "ref/netcoreapp2.2/System.IO.Pipes.xml", + "ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll", + "ref/netcoreapp2.2/System.IO.dll", + "ref/netcoreapp2.2/System.Linq.Expressions.dll", + "ref/netcoreapp2.2/System.Linq.Expressions.xml", + "ref/netcoreapp2.2/System.Linq.Parallel.dll", + "ref/netcoreapp2.2/System.Linq.Parallel.xml", + "ref/netcoreapp2.2/System.Linq.Queryable.dll", + "ref/netcoreapp2.2/System.Linq.Queryable.xml", + "ref/netcoreapp2.2/System.Linq.dll", + "ref/netcoreapp2.2/System.Linq.xml", + "ref/netcoreapp2.2/System.Memory.dll", + "ref/netcoreapp2.2/System.Memory.xml", + "ref/netcoreapp2.2/System.Net.Http.dll", + "ref/netcoreapp2.2/System.Net.Http.xml", + "ref/netcoreapp2.2/System.Net.HttpListener.dll", + "ref/netcoreapp2.2/System.Net.HttpListener.xml", + "ref/netcoreapp2.2/System.Net.Mail.dll", + "ref/netcoreapp2.2/System.Net.Mail.xml", + "ref/netcoreapp2.2/System.Net.NameResolution.dll", + "ref/netcoreapp2.2/System.Net.NameResolution.xml", + "ref/netcoreapp2.2/System.Net.NetworkInformation.dll", + "ref/netcoreapp2.2/System.Net.NetworkInformation.xml", + "ref/netcoreapp2.2/System.Net.Ping.dll", + "ref/netcoreapp2.2/System.Net.Ping.xml", + "ref/netcoreapp2.2/System.Net.Primitives.dll", + "ref/netcoreapp2.2/System.Net.Primitives.xml", + "ref/netcoreapp2.2/System.Net.Requests.dll", + "ref/netcoreapp2.2/System.Net.Requests.xml", + "ref/netcoreapp2.2/System.Net.Security.dll", + "ref/netcoreapp2.2/System.Net.Security.xml", + "ref/netcoreapp2.2/System.Net.ServicePoint.dll", + "ref/netcoreapp2.2/System.Net.ServicePoint.xml", + "ref/netcoreapp2.2/System.Net.Sockets.dll", + "ref/netcoreapp2.2/System.Net.Sockets.xml", + "ref/netcoreapp2.2/System.Net.WebClient.dll", + "ref/netcoreapp2.2/System.Net.WebClient.xml", + "ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll", + "ref/netcoreapp2.2/System.Net.WebHeaderCollection.xml", + "ref/netcoreapp2.2/System.Net.WebProxy.dll", + "ref/netcoreapp2.2/System.Net.WebProxy.xml", + "ref/netcoreapp2.2/System.Net.WebSockets.Client.dll", + "ref/netcoreapp2.2/System.Net.WebSockets.Client.xml", + "ref/netcoreapp2.2/System.Net.WebSockets.dll", + "ref/netcoreapp2.2/System.Net.WebSockets.xml", + "ref/netcoreapp2.2/System.Net.dll", + "ref/netcoreapp2.2/System.Numerics.Vectors.dll", + "ref/netcoreapp2.2/System.Numerics.Vectors.xml", + "ref/netcoreapp2.2/System.Numerics.dll", + "ref/netcoreapp2.2/System.ObjectModel.dll", + "ref/netcoreapp2.2/System.ObjectModel.xml", + "ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll", + "ref/netcoreapp2.2/System.Reflection.DispatchProxy.xml", + "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll", + "ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.xml", + "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll", + "ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.xml", + "ref/netcoreapp2.2/System.Reflection.Emit.dll", + "ref/netcoreapp2.2/System.Reflection.Emit.xml", + "ref/netcoreapp2.2/System.Reflection.Extensions.dll", + "ref/netcoreapp2.2/System.Reflection.Metadata.dll", + "ref/netcoreapp2.2/System.Reflection.Metadata.xml", + "ref/netcoreapp2.2/System.Reflection.Primitives.dll", + "ref/netcoreapp2.2/System.Reflection.Primitives.xml", + "ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll", + "ref/netcoreapp2.2/System.Reflection.TypeExtensions.xml", + "ref/netcoreapp2.2/System.Reflection.dll", + "ref/netcoreapp2.2/System.Resources.Reader.dll", + "ref/netcoreapp2.2/System.Resources.ResourceManager.dll", + "ref/netcoreapp2.2/System.Resources.ResourceManager.xml", + "ref/netcoreapp2.2/System.Resources.Writer.dll", + "ref/netcoreapp2.2/System.Resources.Writer.xml", + "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll", + "ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.xml", + "ref/netcoreapp2.2/System.Runtime.Extensions.dll", + "ref/netcoreapp2.2/System.Runtime.Extensions.xml", + "ref/netcoreapp2.2/System.Runtime.Handles.dll", + "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll", + "ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.xml", + "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll", + "ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.xml", + "ref/netcoreapp2.2/System.Runtime.InteropServices.dll", + "ref/netcoreapp2.2/System.Runtime.InteropServices.xml", + "ref/netcoreapp2.2/System.Runtime.Loader.dll", + "ref/netcoreapp2.2/System.Runtime.Loader.xml", + "ref/netcoreapp2.2/System.Runtime.Numerics.dll", + "ref/netcoreapp2.2/System.Runtime.Numerics.xml", + "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll", + "ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.xml", + "ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll", + "ref/netcoreapp2.2/System.Runtime.Serialization.Json.xml", + "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll", + "ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.xml", + "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll", + "ref/netcoreapp2.2/System.Runtime.Serialization.Xml.xml", + "ref/netcoreapp2.2/System.Runtime.Serialization.dll", + "ref/netcoreapp2.2/System.Runtime.dll", + "ref/netcoreapp2.2/System.Runtime.xml", + "ref/netcoreapp2.2/System.Security.Claims.dll", + "ref/netcoreapp2.2/System.Security.Claims.xml", + "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll", + "ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.xml", + "ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll", + "ref/netcoreapp2.2/System.Security.Cryptography.Csp.xml", + "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll", + "ref/netcoreapp2.2/System.Security.Cryptography.Encoding.xml", + "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll", + "ref/netcoreapp2.2/System.Security.Cryptography.Primitives.xml", + "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll", + "ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.xml", + "ref/netcoreapp2.2/System.Security.Principal.dll", + "ref/netcoreapp2.2/System.Security.Principal.xml", + "ref/netcoreapp2.2/System.Security.SecureString.dll", + "ref/netcoreapp2.2/System.Security.dll", + "ref/netcoreapp2.2/System.ServiceModel.Web.dll", + "ref/netcoreapp2.2/System.ServiceProcess.dll", + "ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll", + "ref/netcoreapp2.2/System.Text.Encoding.Extensions.xml", + "ref/netcoreapp2.2/System.Text.Encoding.dll", + "ref/netcoreapp2.2/System.Text.RegularExpressions.dll", + "ref/netcoreapp2.2/System.Text.RegularExpressions.xml", + "ref/netcoreapp2.2/System.Threading.Overlapped.dll", + "ref/netcoreapp2.2/System.Threading.Overlapped.xml", + "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll", + "ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.xml", + "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll", + "ref/netcoreapp2.2/System.Threading.Tasks.Extensions.xml", + "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll", + "ref/netcoreapp2.2/System.Threading.Tasks.Parallel.xml", + "ref/netcoreapp2.2/System.Threading.Tasks.dll", + "ref/netcoreapp2.2/System.Threading.Tasks.xml", + "ref/netcoreapp2.2/System.Threading.Thread.dll", + "ref/netcoreapp2.2/System.Threading.Thread.xml", + "ref/netcoreapp2.2/System.Threading.ThreadPool.dll", + "ref/netcoreapp2.2/System.Threading.ThreadPool.xml", + "ref/netcoreapp2.2/System.Threading.Timer.dll", + "ref/netcoreapp2.2/System.Threading.Timer.xml", + "ref/netcoreapp2.2/System.Threading.dll", + "ref/netcoreapp2.2/System.Threading.xml", + "ref/netcoreapp2.2/System.Transactions.Local.dll", + "ref/netcoreapp2.2/System.Transactions.Local.xml", + "ref/netcoreapp2.2/System.Transactions.dll", + "ref/netcoreapp2.2/System.ValueTuple.dll", + "ref/netcoreapp2.2/System.Web.HttpUtility.dll", + "ref/netcoreapp2.2/System.Web.HttpUtility.xml", + "ref/netcoreapp2.2/System.Web.dll", + "ref/netcoreapp2.2/System.Windows.dll", + "ref/netcoreapp2.2/System.Xml.Linq.dll", + "ref/netcoreapp2.2/System.Xml.ReaderWriter.dll", + "ref/netcoreapp2.2/System.Xml.ReaderWriter.xml", + "ref/netcoreapp2.2/System.Xml.Serialization.dll", + "ref/netcoreapp2.2/System.Xml.XDocument.dll", + "ref/netcoreapp2.2/System.Xml.XDocument.xml", + "ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll", + "ref/netcoreapp2.2/System.Xml.XPath.XDocument.xml", + "ref/netcoreapp2.2/System.Xml.XPath.dll", + "ref/netcoreapp2.2/System.Xml.XPath.xml", + "ref/netcoreapp2.2/System.Xml.XmlDocument.dll", + "ref/netcoreapp2.2/System.Xml.XmlSerializer.dll", + "ref/netcoreapp2.2/System.Xml.XmlSerializer.xml", + "ref/netcoreapp2.2/System.Xml.dll", + "ref/netcoreapp2.2/System.dll", + "ref/netcoreapp2.2/WindowsBase.dll", + "ref/netcoreapp2.2/mscorlib.dll", + "ref/netcoreapp2.2/netstandard.dll", + "runtime.json" + ] + }, + "Microsoft.NETCore.DotNetAppHost/2.2.8": { + "sha512": "Lh1F6z41levvtfC3KuuiQe9ppWKRP1oIB42vP1QNQE4uumo95h+LpjPDeysX1DlTjCzG0BVGSUEpCW5fHkni7w==", + "type": "package", + "path": "microsoft.netcore.dotnetapphost/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "microsoft.netcore.dotnetapphost.2.2.8.nupkg.sha512", + "microsoft.netcore.dotnetapphost.nuspec", + "runtime.json" + ] + }, + "Microsoft.NETCore.DotNetHostPolicy/2.2.8": { + "sha512": "rOHr0Dk87vaiq9d1hMpXETB4IKq1jIiPQlVKNUjRGilK/cjOcadhsk+1MsrJ/GnM3eovhy8zW2PGkN8pYEolnw==", + "type": "package", + "path": "microsoft.netcore.dotnethostpolicy/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "microsoft.netcore.dotnethostpolicy.2.2.8.nupkg.sha512", + "microsoft.netcore.dotnethostpolicy.nuspec", + "runtime.json" + ] + }, + "Microsoft.NETCore.DotNetHostResolver/2.2.8": { + "sha512": "culLr+x2GvUkXVGi4ULZ7jmWJEhuAMyS7iTWBlkWnqbKtYJ36ZlgHbw/6qTm82790gJemEFeo9RehDwfRXfJzA==", + "type": "package", + "path": "microsoft.netcore.dotnethostresolver/2.2.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "microsoft.netcore.dotnethostresolver.2.2.8.nupkg.sha512", + "microsoft.netcore.dotnethostresolver.nuspec", + "runtime.json" + ] + }, + "Microsoft.NETCore.Platforms/2.2.4": { + "sha512": "ZeCe9PRhMpKzVWrNgTvWpLjJigppErzN663lJOqAzcx0xjXpcAMpIImFI46IE1gze18VWw6bbfo7JDkcaRWuOg==", + "type": "package", + "path": "microsoft.netcore.platforms/2.2.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.0/_._", + "microsoft.netcore.platforms.2.2.4.nupkg.sha512", + "microsoft.netcore.platforms.nuspec", + "runtime.json", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "Microsoft.NETCore.Targets/2.0.0": { + "sha512": "odP/tJj1z6GylFpNo7pMtbd/xQgTC3Ex2If63dRTL38bBNMwsBnJ+RceUIyHdRBC0oik/3NehYT+oECwBhIM3Q==", + "type": "package", + "path": "microsoft.netcore.targets/2.0.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.0/_._", + "microsoft.netcore.targets.2.0.0.nupkg.sha512", + "microsoft.netcore.targets.nuspec", + "runtime.json", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "Microsoft.Rest.ClientRuntime/2.3.8": { + "sha512": "Hj96LBoCwKY2VQKfSCVGGPV1sSumVjuYnrlpBwL4JSTnSK4b6ZxjLtXj8LgmKav8xJ2gps+UN7eI3hHVFKvBFw==", + "type": "package", + "path": "microsoft.rest.clientruntime/2.3.8", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net452/Microsoft.Rest.ClientRuntime.dll", + "lib/net452/Microsoft.Rest.ClientRuntime.runtimeconfig.json", + "lib/net452/Microsoft.Rest.ClientRuntime.xml", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.dll", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.runtimeconfig.json", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.xml", + "microsoft.rest.clientruntime.2.3.8.nupkg.sha512", + "microsoft.rest.clientruntime.nuspec" + ] + }, + "Microsoft.Rest.ClientRuntime.Azure/3.3.7": { + "sha512": "6u8JIuvrztse4tPOcvNzAJuzGBP0uY+Ijggk8ZYhp0siGEZ1XfZylf1vpNGUicvwcrhhoIgDW73Z1L6QGssr2g==", + "type": "package", + "path": "microsoft.rest.clientruntime.azure/3.3.7", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net452/Microsoft.Rest.ClientRuntime.Azure.dll", + "lib/net452/Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json", + "lib/net452/Microsoft.Rest.ClientRuntime.Azure.xml", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.Azure.dll", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.Azure.runtimeconfig.json", + "lib/netstandard1.4/Microsoft.Rest.ClientRuntime.Azure.xml", + "microsoft.rest.clientruntime.azure.3.3.7.nupkg.sha512", + "microsoft.rest.clientruntime.azure.nuspec" + ] + }, + "Microsoft.VisualStudio.Web.BrowserLink/2.2.0": { + "sha512": "cmeqhbB+rdMia3bj6cJaKQw1GDOqHxzDWAjoJqCnz+JYi9a2xsBdzycYy9eMEssVwLmLAUw6sWLMPMfGXAQmWA==", + "type": "package", + "path": "microsoft.visualstudio.web.browserlink/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard2.0/Microsoft.VisualStudio.Web.BrowserLink.dll", + "lib/netstandard2.0/Microsoft.VisualStudio.Web.BrowserLink.xml", + "microsoft.visualstudio.web.browserlink.2.2.0.nupkg.sha512", + "microsoft.visualstudio.web.browserlink.nuspec" + ] + }, + "Microsoft.Win32.Primitives/4.3.0": { + "sha512": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "type": "package", + "path": "microsoft.win32.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/Microsoft.Win32.Primitives.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "microsoft.win32.primitives.4.3.0.nupkg.sha512", + "microsoft.win32.primitives.nuspec", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/Microsoft.Win32.Primitives.dll", + "ref/netstandard1.3/Microsoft.Win32.Primitives.dll", + "ref/netstandard1.3/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/de/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/es/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/fr/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/it/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/ja/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/ko/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/ru/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/zh-hans/Microsoft.Win32.Primitives.xml", + "ref/netstandard1.3/zh-hant/Microsoft.Win32.Primitives.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._" + ] + }, + "Microsoft.Win32.Registry/4.5.0": { + "sha512": "+FWlwd//+Tt56316p00hVePBCouXyEzT86Jb3+AuRotTND0IYn0OO3obs1gnQEs/txEnt+rF2JBGLItTG+Be6A==", + "type": "package", + "path": "microsoft.win32.registry/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/Microsoft.Win32.Registry.dll", + "lib/net461/Microsoft.Win32.Registry.dll", + "lib/netstandard1.3/Microsoft.Win32.Registry.dll", + "lib/netstandard2.0/Microsoft.Win32.Registry.dll", + "microsoft.win32.registry.4.5.0.nupkg.sha512", + "microsoft.win32.registry.nuspec", + "ref/net46/Microsoft.Win32.Registry.dll", + "ref/net461/Microsoft.Win32.Registry.dll", + "ref/net461/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/Microsoft.Win32.Registry.dll", + "ref/netstandard1.3/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/de/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/es/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/fr/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/it/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ja/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ko/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/ru/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/zh-hans/Microsoft.Win32.Registry.xml", + "ref/netstandard1.3/zh-hant/Microsoft.Win32.Registry.xml", + "ref/netstandard2.0/Microsoft.Win32.Registry.dll", + "ref/netstandard2.0/Microsoft.Win32.Registry.xml", + "runtimes/unix/lib/netstandard2.0/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/net46/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/net461/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/netstandard1.3/Microsoft.Win32.Registry.dll", + "runtimes/win/lib/netstandard2.0/Microsoft.Win32.Registry.dll", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "NETStandard.Library/2.0.3": { + "sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "type": "package", + "path": "netstandard.library/2.0.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "build/netstandard2.0/NETStandard.Library.targets", + "build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll", + "build/netstandard2.0/ref/System.AppContext.dll", + "build/netstandard2.0/ref/System.Collections.Concurrent.dll", + "build/netstandard2.0/ref/System.Collections.NonGeneric.dll", + "build/netstandard2.0/ref/System.Collections.Specialized.dll", + "build/netstandard2.0/ref/System.Collections.dll", + "build/netstandard2.0/ref/System.ComponentModel.Composition.dll", + "build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll", + "build/netstandard2.0/ref/System.ComponentModel.Primitives.dll", + "build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll", + "build/netstandard2.0/ref/System.ComponentModel.dll", + "build/netstandard2.0/ref/System.Console.dll", + "build/netstandard2.0/ref/System.Core.dll", + "build/netstandard2.0/ref/System.Data.Common.dll", + "build/netstandard2.0/ref/System.Data.dll", + "build/netstandard2.0/ref/System.Diagnostics.Contracts.dll", + "build/netstandard2.0/ref/System.Diagnostics.Debug.dll", + "build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll", + "build/netstandard2.0/ref/System.Diagnostics.Process.dll", + "build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll", + "build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tools.dll", + "build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll", + "build/netstandard2.0/ref/System.Diagnostics.Tracing.dll", + "build/netstandard2.0/ref/System.Drawing.Primitives.dll", + "build/netstandard2.0/ref/System.Drawing.dll", + "build/netstandard2.0/ref/System.Dynamic.Runtime.dll", + "build/netstandard2.0/ref/System.Globalization.Calendars.dll", + "build/netstandard2.0/ref/System.Globalization.Extensions.dll", + "build/netstandard2.0/ref/System.Globalization.dll", + "build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll", + "build/netstandard2.0/ref/System.IO.Compression.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll", + "build/netstandard2.0/ref/System.IO.FileSystem.dll", + "build/netstandard2.0/ref/System.IO.IsolatedStorage.dll", + "build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll", + "build/netstandard2.0/ref/System.IO.Pipes.dll", + "build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll", + "build/netstandard2.0/ref/System.IO.dll", + "build/netstandard2.0/ref/System.Linq.Expressions.dll", + "build/netstandard2.0/ref/System.Linq.Parallel.dll", + "build/netstandard2.0/ref/System.Linq.Queryable.dll", + "build/netstandard2.0/ref/System.Linq.dll", + "build/netstandard2.0/ref/System.Net.Http.dll", + "build/netstandard2.0/ref/System.Net.NameResolution.dll", + "build/netstandard2.0/ref/System.Net.NetworkInformation.dll", + "build/netstandard2.0/ref/System.Net.Ping.dll", + "build/netstandard2.0/ref/System.Net.Primitives.dll", + "build/netstandard2.0/ref/System.Net.Requests.dll", + "build/netstandard2.0/ref/System.Net.Security.dll", + "build/netstandard2.0/ref/System.Net.Sockets.dll", + "build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.Client.dll", + "build/netstandard2.0/ref/System.Net.WebSockets.dll", + "build/netstandard2.0/ref/System.Net.dll", + "build/netstandard2.0/ref/System.Numerics.dll", + "build/netstandard2.0/ref/System.ObjectModel.dll", + "build/netstandard2.0/ref/System.Reflection.Extensions.dll", + "build/netstandard2.0/ref/System.Reflection.Primitives.dll", + "build/netstandard2.0/ref/System.Reflection.dll", + "build/netstandard2.0/ref/System.Resources.Reader.dll", + "build/netstandard2.0/ref/System.Resources.ResourceManager.dll", + "build/netstandard2.0/ref/System.Resources.Writer.dll", + "build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll", + "build/netstandard2.0/ref/System.Runtime.Extensions.dll", + "build/netstandard2.0/ref/System.Runtime.Handles.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll", + "build/netstandard2.0/ref/System.Runtime.InteropServices.dll", + "build/netstandard2.0/ref/System.Runtime.Numerics.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll", + "build/netstandard2.0/ref/System.Runtime.Serialization.dll", + "build/netstandard2.0/ref/System.Runtime.dll", + "build/netstandard2.0/ref/System.Security.Claims.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll", + "build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll", + "build/netstandard2.0/ref/System.Security.Principal.dll", + "build/netstandard2.0/ref/System.Security.SecureString.dll", + "build/netstandard2.0/ref/System.ServiceModel.Web.dll", + "build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll", + "build/netstandard2.0/ref/System.Text.Encoding.dll", + "build/netstandard2.0/ref/System.Text.RegularExpressions.dll", + "build/netstandard2.0/ref/System.Threading.Overlapped.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll", + "build/netstandard2.0/ref/System.Threading.Tasks.dll", + "build/netstandard2.0/ref/System.Threading.Thread.dll", + "build/netstandard2.0/ref/System.Threading.ThreadPool.dll", + "build/netstandard2.0/ref/System.Threading.Timer.dll", + "build/netstandard2.0/ref/System.Threading.dll", + "build/netstandard2.0/ref/System.Transactions.dll", + "build/netstandard2.0/ref/System.ValueTuple.dll", + "build/netstandard2.0/ref/System.Web.dll", + "build/netstandard2.0/ref/System.Windows.dll", + "build/netstandard2.0/ref/System.Xml.Linq.dll", + "build/netstandard2.0/ref/System.Xml.ReaderWriter.dll", + "build/netstandard2.0/ref/System.Xml.Serialization.dll", + "build/netstandard2.0/ref/System.Xml.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll", + "build/netstandard2.0/ref/System.Xml.XPath.dll", + "build/netstandard2.0/ref/System.Xml.XmlDocument.dll", + "build/netstandard2.0/ref/System.Xml.XmlSerializer.dll", + "build/netstandard2.0/ref/System.Xml.dll", + "build/netstandard2.0/ref/System.dll", + "build/netstandard2.0/ref/mscorlib.dll", + "build/netstandard2.0/ref/netstandard.dll", + "build/netstandard2.0/ref/netstandard.xml", + "lib/netstandard1.0/_._", + "netstandard.library.2.0.3.nupkg.sha512", + "netstandard.library.nuspec" + ] + }, + "Newtonsoft.Json/11.0.2": { + "sha512": "IvJe1pj7JHEsP8B8J8DwlMEx8UInrs/x+9oVY+oCD13jpLu4JbJU2WCIsMRn5C4yW9+DgkaO8uiVE5VHKjpmdQ==", + "type": "package", + "path": "newtonsoft.json/11.0.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.md", + "lib/net20/Newtonsoft.Json.dll", + "lib/net20/Newtonsoft.Json.xml", + "lib/net35/Newtonsoft.Json.dll", + "lib/net35/Newtonsoft.Json.xml", + "lib/net40/Newtonsoft.Json.dll", + "lib/net40/Newtonsoft.Json.xml", + "lib/net45/Newtonsoft.Json.dll", + "lib/net45/Newtonsoft.Json.xml", + "lib/netstandard1.0/Newtonsoft.Json.dll", + "lib/netstandard1.0/Newtonsoft.Json.xml", + "lib/netstandard1.3/Newtonsoft.Json.dll", + "lib/netstandard1.3/Newtonsoft.Json.xml", + "lib/netstandard2.0/Newtonsoft.Json.dll", + "lib/netstandard2.0/Newtonsoft.Json.xml", + "lib/portable-net40+sl5+win8+wp8+wpa81/Newtonsoft.Json.dll", + "lib/portable-net40+sl5+win8+wp8+wpa81/Newtonsoft.Json.xml", + "lib/portable-net45+win8+wp8+wpa81/Newtonsoft.Json.dll", + "lib/portable-net45+win8+wp8+wpa81/Newtonsoft.Json.xml", + "newtonsoft.json.11.0.2.nupkg.sha512", + "newtonsoft.json.nuspec" + ] + }, + "Newtonsoft.Json.Bson/1.0.1": { + "sha512": "5PYT/IqQ+UK31AmZiSS102R6EsTo+LGTSI8bp7WAUqDKaF4wHXD8U9u4WxTI1vc64tYi++8p3dk3WWNqPFgldw==", + "type": "package", + "path": "newtonsoft.json.bson/1.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Newtonsoft.Json.Bson.dll", + "lib/net45/Newtonsoft.Json.Bson.xml", + "lib/netstandard1.3/Newtonsoft.Json.Bson.dll", + "lib/netstandard1.3/Newtonsoft.Json.Bson.xml", + "newtonsoft.json.bson.1.0.1.nupkg.sha512", + "newtonsoft.json.bson.nuspec" + ] + }, + "Octokit/0.36.0": { + "sha512": "u9SwD0wne6NrxcwOxz2kzcni4r8X4E9y+Oul5CVbnDN3q0ZFYLu5FlI+JgkADmtTsYZMZ4huGfk51S+CXQSCFA==", + "type": "package", + "path": "octokit/0.36.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Octokit.dll", + "lib/net45/Octokit.xml", + "lib/net46/Octokit.dll", + "lib/net46/Octokit.xml", + "lib/netstandard1.1/Octokit.dll", + "lib/netstandard1.1/Octokit.xml", + "lib/netstandard2.0/Octokit.dll", + "lib/netstandard2.0/Octokit.xml", + "octokit.0.36.0.nupkg.sha512", + "octokit.nuspec" + ] + }, + "Remotion.Linq/2.2.0": { + "sha512": "fK/76UmpC0FXBlGDFVPLJHQlDLYnGC+XY3eoDgCgbtrhi0vzbXDQ3n/IYHhqSKqXQfGw/u04A1drWs7rFVkRjw==", + "type": "package", + "path": "remotion.linq/2.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net35/Remotion.Linq.XML", + "lib/net35/Remotion.Linq.dll", + "lib/net40/Remotion.Linq.XML", + "lib/net40/Remotion.Linq.dll", + "lib/net45/Remotion.Linq.XML", + "lib/net45/Remotion.Linq.dll", + "lib/netstandard1.0/Remotion.Linq.dll", + "lib/netstandard1.0/Remotion.Linq.xml", + "lib/portable-net45+win+wpa81+wp80/Remotion.Linq.dll", + "lib/portable-net45+win+wpa81+wp80/Remotion.Linq.xml", + "remotion.linq.2.2.0.nupkg.sha512", + "remotion.linq.nuspec" + ] + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==", + "type": "package", + "path": "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/debian.8-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==", + "type": "package", + "path": "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/fedora.23-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==", + "type": "package", + "path": "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/fedora.24-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.native.System/4.3.0": { + "sha512": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "type": "package", + "path": "runtime.native.system/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.4.3.0.nupkg.sha512", + "runtime.native.system.nuspec" + ] + }, + "runtime.native.System.Data.SqlClient.sni/4.5.0": { + "sha512": "AJfX7owAAkMjWQYhoml5IBfXh8UyYPjktn8pK0BFGAdKgBS7HqMz1fw5vdzfZUWfhtTPDGCjgNttt46ZyEmSjg==", + "type": "package", + "path": "runtime.native.system.data.sqlclient.sni/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "runtime.native.system.data.sqlclient.sni.4.5.0.nupkg.sha512", + "runtime.native.system.data.sqlclient.sni.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "runtime.native.System.IO.Compression/4.3.0": { + "sha512": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "type": "package", + "path": "runtime.native.system.io.compression/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.io.compression.4.3.0.nupkg.sha512", + "runtime.native.system.io.compression.nuspec" + ] + }, + "runtime.native.System.Net.Http/4.3.0": { + "sha512": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "type": "package", + "path": "runtime.native.system.net.http/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.net.http.4.3.0.nupkg.sha512", + "runtime.native.system.net.http.nuspec" + ] + }, + "runtime.native.System.Net.Security/4.3.0": { + "sha512": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "type": "package", + "path": "runtime.native.system.net.security/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.net.security.4.3.0.nupkg.sha512", + "runtime.native.system.net.security.nuspec" + ] + }, + "runtime.native.System.Security.Cryptography.Apple/4.3.1": { + "sha512": "UPrVPlqPRSVZaB4ADmbsQ77KXn9ORiWXyA1RP2W2+byCh3bhgT1bQz0jbeOoog9/2oTQ5wWZSDSMeb74MjezcA==", + "type": "package", + "path": "runtime.native.system.security.cryptography.apple/4.3.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.security.cryptography.apple.4.3.1.nupkg.sha512", + "runtime.native.system.security.cryptography.apple.nuspec" + ] + }, + "runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "type": "package", + "path": "runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.0/_._", + "runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.native.system.security.cryptography.openssl.nuspec" + ] + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==", + "type": "package", + "path": "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/opensuse.13.2-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==", + "type": "package", + "path": "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/opensuse.42.1-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple/4.3.1": { + "sha512": "t15yGf5r6vMV1rB5O6TgfXKChtCaN3niwFw44M2ImX3eZ8yzueplqMqXPCbWzoBDHJVz9fE+9LFUGCsUmS2Jgg==", + "type": "package", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple/4.3.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.1.nupkg.sha512", + "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.nuspec", + "runtimes/osx.10.10-x64/native/System.Security.Cryptography.Native.Apple.dylib" + ] + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==", + "type": "package", + "path": "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/osx.10.10-x64/native/System.Security.Cryptography.Native.OpenSsl.dylib" + ] + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==", + "type": "package", + "path": "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/rhel.7-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==", + "type": "package", + "path": "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/ubuntu.14.04-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==", + "type": "package", + "path": "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/ubuntu.16.04-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl/4.3.2": { + "sha512": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==", + "type": "package", + "path": "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl/4.3.2", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.nuspec", + "runtimes/ubuntu.16.10-x64/native/System.Security.Cryptography.Native.OpenSsl.so" + ] + }, + "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "sha512": "LbrynESTp3bm5O/+jGL8v0Qg5SJlTV08lpIpFesXjF6uGNMWqFnUQbYBJwZTeua6E/Y7FIM1C54Ey1btLWupdg==", + "type": "package", + "path": "runtime.win-arm64.runtime.native.system.data.sqlclient.sni/4.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.win-arm64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "runtime.win-arm64.runtime.native.system.data.sqlclient.sni.nuspec", + "runtimes/win-arm64/native/sni.dll", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "runtime.win-x64.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "sha512": "38ugOfkYJqJoX9g6EYRlZB5U2ZJH51UP8ptxZgdpS07FgOEToV+lS11ouNK2PM12Pr6X/PpT5jK82G3DwH/SxQ==", + "type": "package", + "path": "runtime.win-x64.runtime.native.system.data.sqlclient.sni/4.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "runtime.win-x64.runtime.native.system.data.sqlclient.sni.nuspec", + "runtimes/win-x64/native/sni.dll", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "runtime.win-x86.runtime.native.System.Data.SqlClient.sni/4.4.0": { + "sha512": "YhEdSQUsTx+C8m8Bw7ar5/VesXvCFMItyZF7G1AUY+OM0VPZUOeAVpJ4Wl6fydBGUYZxojTDR3I6Bj/+BPkJNA==", + "type": "package", + "path": "runtime.win-x86.runtime.native.system.data.sqlclient.sni/4.4.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "runtime.win-x86.runtime.native.system.data.sqlclient.sni.nuspec", + "runtimes/win-x86/native/sni.dll", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "SQLitePCLRaw.bundle_green/1.1.12": { + "sha512": "U5lZv+E0JBCG5uQngaRgyIAlbzIwRczb0m46XJfLGXovtfVOaMNRY/oGyKAJjdexVrfqLRd+JyopGMySpAZRGQ==", + "type": "package", + "path": "sqlitepclraw.bundle_green/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/wp8/SQLitePCLRaw.bundle_green.targets", + "build/wp80/arm/SQLitePCLRaw.batteries_green.dll", + "build/wp80/arm/SQLitePCLRaw.batteries_v2.dll", + "build/wp80/x86/SQLitePCLRaw.batteries_green.dll", + "build/wp80/x86/SQLitePCLRaw.batteries_v2.dll", + "lib/MonoAndroid/SQLitePCLRaw.batteries_green.dll", + "lib/MonoAndroid/SQLitePCLRaw.batteries_v2.dll", + "lib/Xamarin.Mac20/SQLitePCLRaw.batteries_green.dll", + "lib/Xamarin.Mac20/SQLitePCLRaw.batteries_v2.dll", + "lib/Xamarin.iOS10/SQLitePCLRaw.batteries_green.dll", + "lib/Xamarin.iOS10/SQLitePCLRaw.batteries_v2.dll", + "lib/net35/SQLitePCLRaw.batteries_green.dll", + "lib/net35/SQLitePCLRaw.batteries_v2.dll", + "lib/net40/SQLitePCLRaw.batteries_green.dll", + "lib/net40/SQLitePCLRaw.batteries_v2.dll", + "lib/net45/SQLitePCLRaw.batteries_green.dll", + "lib/net45/SQLitePCLRaw.batteries_v2.dll", + "lib/netcoreapp/SQLitePCLRaw.batteries_green.dll", + "lib/netcoreapp/SQLitePCLRaw.batteries_v2.dll", + "lib/netstandard1.1/SQLitePCLRaw.batteries_green.dll", + "lib/netstandard1.1/SQLitePCLRaw.batteries_v2.dll", + "lib/portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_green.dll", + "lib/portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_v2.dll", + "lib/portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_green.dll", + "lib/portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_v2.dll", + "lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_green.dll", + "lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.batteries_v2.dll", + "lib/uap10.0/SQLitePCLRaw.batteries_green.dll", + "lib/uap10.0/SQLitePCLRaw.batteries_v2.dll", + "lib/win8/SQLitePCLRaw.batteries_green.dll", + "lib/win8/SQLitePCLRaw.batteries_v2.dll", + "lib/win81/SQLitePCLRaw.batteries_green.dll", + "lib/win81/SQLitePCLRaw.batteries_v2.dll", + "lib/wp8/_._", + "lib/wpa81/SQLitePCLRaw.batteries_green.dll", + "lib/wpa81/SQLitePCLRaw.batteries_v2.dll", + "sqlitepclraw.bundle_green.1.1.12.nupkg.sha512", + "sqlitepclraw.bundle_green.nuspec" + ] + }, + "SQLitePCLRaw.core/1.1.12": { + "sha512": "S4hr+tE275ran5jyKFW/FYPG6Bz6nsHUp9H8chqKxzk21PxJadLd9LnvLe6LMRP/IqY5+LOIIDQF3m/2iDlZ7Q==", + "type": "package", + "path": "sqlitepclraw.core/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/MonoAndroid/SQLitePCLRaw.core.dll", + "lib/Xamarin.Mac20/SQLitePCLRaw.core.dll", + "lib/Xamarin.iOS10/SQLitePCLRaw.core.dll", + "lib/net35/SQLitePCLRaw.core.dll", + "lib/net40/SQLitePCLRaw.core.dll", + "lib/net45/SQLitePCLRaw.core.dll", + "lib/netstandard1.0/SQLitePCLRaw.core.dll", + "lib/netstandard1.1/SQLitePCLRaw.core.dll", + "lib/portable-net40+sl5+netcore45+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.core.dll", + "lib/portable-net45+netcore45+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.core.dll", + "lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid10+MonoTouch10+Xamarin.iOS10/SQLitePCLRaw.core.dll", + "lib/uap10.0/SQLitePCLRaw.core.dll", + "lib/win8/SQLitePCLRaw.core.dll", + "lib/win81/SQLitePCLRaw.core.dll", + "lib/wpa81/SQLitePCLRaw.core.dll", + "sqlitepclraw.core.1.1.12.nupkg.sha512", + "sqlitepclraw.core.nuspec" + ] + }, + "SQLitePCLRaw.lib.e_sqlite3.linux/1.1.12": { + "sha512": "Tn/YE1VxWtHa4MQ9KC//ptIw6cLAUh+xXSdpX7MyGINmb4/igqyx0IOEq5WeH/+cuI/EnDtdWAOn98eMQnKsTQ==", + "type": "package", + "path": "sqlitepclraw.lib.e_sqlite3.linux/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/net35/SQLitePCLRaw.lib.e_sqlite3.linux.targets", + "lib/net35/_._", + "lib/netstandard1.0/_._", + "lib/netstandard2.0/_._", + "runtimes/alpine-x64/native/libe_sqlite3.so", + "runtimes/linux-arm/native/libe_sqlite3.so", + "runtimes/linux-arm64/native/libe_sqlite3.so", + "runtimes/linux-armel/native/libe_sqlite3.so", + "runtimes/linux-musl-x64/native/libe_sqlite3.so", + "runtimes/linux-x64/native/libe_sqlite3.so", + "runtimes/linux-x86/native/libe_sqlite3.so", + "sqlitepclraw.lib.e_sqlite3.linux.1.1.12.nupkg.sha512", + "sqlitepclraw.lib.e_sqlite3.linux.nuspec" + ] + }, + "SQLitePCLRaw.lib.e_sqlite3.osx/1.1.12": { + "sha512": "qfl1ljn6NOQDyM2i9JDZc6xekHoC+Fqe4GzuhWFCS6siI7lLInw09HHSZRqyimV36vjdQYnyBBFKSn53rSOYkA==", + "type": "package", + "path": "sqlitepclraw.lib.e_sqlite3.osx/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/Xamarin.Mac20/SQLitePCLRaw.lib.e_sqlite3.osx.targets", + "build/net35/SQLitePCLRaw.lib.e_sqlite3.osx.targets", + "lib/Xamarin.Mac20/_._", + "lib/net35/_._", + "lib/netstandard1.0/_._", + "lib/netstandard2.0/_._", + "runtimes/osx-x64/native/libe_sqlite3.dylib", + "sqlitepclraw.lib.e_sqlite3.osx.1.1.12.nupkg.sha512", + "sqlitepclraw.lib.e_sqlite3.osx.nuspec" + ] + }, + "SQLitePCLRaw.lib.e_sqlite3.v110_xp/1.1.12": { + "sha512": "YfmaVhcEyAGU6BZ7NQiYYfCHKsCYjldwsafiFKArzqeM8MHuhfqft1Fjdv7ncukXrvKsHXhCrzJzKEMwPXiSSg==", + "type": "package", + "path": "sqlitepclraw.lib.e_sqlite3.v110_xp/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "build/net35/SQLitePCLRaw.lib.e_sqlite3.v110_xp.targets", + "lib/net35/_._", + "lib/netstandard1.0/_._", + "lib/netstandard2.0/_._", + "runtimes/win-x64/native/e_sqlite3.dll", + "runtimes/win-x86/native/e_sqlite3.dll", + "runtimes/win8-arm/native/e_sqlite3.dll", + "sqlitepclraw.lib.e_sqlite3.v110_xp.1.1.12.nupkg.sha512", + "sqlitepclraw.lib.e_sqlite3.v110_xp.nuspec" + ] + }, + "SQLitePCLRaw.provider.e_sqlite3.netstandard11/1.1.12": { + "sha512": "qjz6Ad1Q5hiI8imCiG5Mpa/w8E8+rAk3SRJdX54uEOo5nPywiN1H0jmMZO+ID0nPibQA3yjlAHt5/GcLW9Iftg==", + "type": "package", + "path": "sqlitepclraw.provider.e_sqlite3.netstandard11/1.1.12", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/netstandard1.1/SQLitePCLRaw.provider.e_sqlite3.dll", + "sqlitepclraw.provider.e_sqlite3.netstandard11.1.1.12.nupkg.sha512", + "sqlitepclraw.provider.e_sqlite3.netstandard11.nuspec" + ] + }, + "StackExchange.Redis.StrongName/1.2.6": { + "sha512": "UFmT1/JYu1PLiRwkyvEPVHk/tVTJa8Ka2rb9yzidzDoQARvhBVRpaWUeaP81373v54jupDBvAoGHGl0EY/HphQ==", + "type": "package", + "path": "stackexchange.redis.strongname/1.2.6", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/StackExchange.Redis.StrongName.dll", + "lib/net45/StackExchange.Redis.StrongName.xml", + "lib/net46/StackExchange.Redis.StrongName.dll", + "lib/net46/StackExchange.Redis.StrongName.xml", + "lib/netstandard1.5/StackExchange.Redis.StrongName.dll", + "lib/netstandard1.5/StackExchange.Redis.StrongName.xml", + "stackexchange.redis.strongname.1.2.6.nupkg.sha512", + "stackexchange.redis.strongname.nuspec" + ] + }, + "System.AppContext/4.3.0": { + "sha512": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "type": "package", + "path": "system.appcontext/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.AppContext.dll", + "lib/net463/System.AppContext.dll", + "lib/netcore50/System.AppContext.dll", + "lib/netstandard1.6/System.AppContext.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.AppContext.dll", + "ref/net463/System.AppContext.dll", + "ref/netstandard/_._", + "ref/netstandard1.3/System.AppContext.dll", + "ref/netstandard1.3/System.AppContext.xml", + "ref/netstandard1.3/de/System.AppContext.xml", + "ref/netstandard1.3/es/System.AppContext.xml", + "ref/netstandard1.3/fr/System.AppContext.xml", + "ref/netstandard1.3/it/System.AppContext.xml", + "ref/netstandard1.3/ja/System.AppContext.xml", + "ref/netstandard1.3/ko/System.AppContext.xml", + "ref/netstandard1.3/ru/System.AppContext.xml", + "ref/netstandard1.3/zh-hans/System.AppContext.xml", + "ref/netstandard1.3/zh-hant/System.AppContext.xml", + "ref/netstandard1.6/System.AppContext.dll", + "ref/netstandard1.6/System.AppContext.xml", + "ref/netstandard1.6/de/System.AppContext.xml", + "ref/netstandard1.6/es/System.AppContext.xml", + "ref/netstandard1.6/fr/System.AppContext.xml", + "ref/netstandard1.6/it/System.AppContext.xml", + "ref/netstandard1.6/ja/System.AppContext.xml", + "ref/netstandard1.6/ko/System.AppContext.xml", + "ref/netstandard1.6/ru/System.AppContext.xml", + "ref/netstandard1.6/zh-hans/System.AppContext.xml", + "ref/netstandard1.6/zh-hant/System.AppContext.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.AppContext.dll", + "system.appcontext.4.3.0.nupkg.sha512", + "system.appcontext.nuspec" + ] + }, + "System.Buffers/4.5.0": { + "sha512": "pL2ChpaRRWI/p4LXyy4RgeWlYF2sgfj/pnVMvBqwNFr5cXg7CXNnWZWxrOONLg8VGdFB8oB+EG2Qw4MLgTOe+A==", + "type": "package", + "path": "system.buffers/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.1/System.Buffers.dll", + "lib/netstandard1.1/System.Buffers.xml", + "lib/netstandard2.0/System.Buffers.dll", + "lib/netstandard2.0/System.Buffers.xml", + "lib/uap10.0.16299/_._", + "ref/net45/System.Buffers.dll", + "ref/net45/System.Buffers.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.1/System.Buffers.dll", + "ref/netstandard1.1/System.Buffers.xml", + "ref/netstandard2.0/System.Buffers.dll", + "ref/netstandard2.0/System.Buffers.xml", + "ref/uap10.0.16299/_._", + "system.buffers.4.5.0.nupkg.sha512", + "system.buffers.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Collections/4.3.0": { + "sha512": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "type": "package", + "path": "system.collections/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Collections.dll", + "ref/netcore50/System.Collections.xml", + "ref/netcore50/de/System.Collections.xml", + "ref/netcore50/es/System.Collections.xml", + "ref/netcore50/fr/System.Collections.xml", + "ref/netcore50/it/System.Collections.xml", + "ref/netcore50/ja/System.Collections.xml", + "ref/netcore50/ko/System.Collections.xml", + "ref/netcore50/ru/System.Collections.xml", + "ref/netcore50/zh-hans/System.Collections.xml", + "ref/netcore50/zh-hant/System.Collections.xml", + "ref/netstandard1.0/System.Collections.dll", + "ref/netstandard1.0/System.Collections.xml", + "ref/netstandard1.0/de/System.Collections.xml", + "ref/netstandard1.0/es/System.Collections.xml", + "ref/netstandard1.0/fr/System.Collections.xml", + "ref/netstandard1.0/it/System.Collections.xml", + "ref/netstandard1.0/ja/System.Collections.xml", + "ref/netstandard1.0/ko/System.Collections.xml", + "ref/netstandard1.0/ru/System.Collections.xml", + "ref/netstandard1.0/zh-hans/System.Collections.xml", + "ref/netstandard1.0/zh-hant/System.Collections.xml", + "ref/netstandard1.3/System.Collections.dll", + "ref/netstandard1.3/System.Collections.xml", + "ref/netstandard1.3/de/System.Collections.xml", + "ref/netstandard1.3/es/System.Collections.xml", + "ref/netstandard1.3/fr/System.Collections.xml", + "ref/netstandard1.3/it/System.Collections.xml", + "ref/netstandard1.3/ja/System.Collections.xml", + "ref/netstandard1.3/ko/System.Collections.xml", + "ref/netstandard1.3/ru/System.Collections.xml", + "ref/netstandard1.3/zh-hans/System.Collections.xml", + "ref/netstandard1.3/zh-hant/System.Collections.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.collections.4.3.0.nupkg.sha512", + "system.collections.nuspec" + ] + }, + "System.Collections.Concurrent/4.3.0": { + "sha512": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "type": "package", + "path": "system.collections.concurrent/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Collections.Concurrent.dll", + "lib/netstandard1.3/System.Collections.Concurrent.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Collections.Concurrent.dll", + "ref/netcore50/System.Collections.Concurrent.xml", + "ref/netcore50/de/System.Collections.Concurrent.xml", + "ref/netcore50/es/System.Collections.Concurrent.xml", + "ref/netcore50/fr/System.Collections.Concurrent.xml", + "ref/netcore50/it/System.Collections.Concurrent.xml", + "ref/netcore50/ja/System.Collections.Concurrent.xml", + "ref/netcore50/ko/System.Collections.Concurrent.xml", + "ref/netcore50/ru/System.Collections.Concurrent.xml", + "ref/netcore50/zh-hans/System.Collections.Concurrent.xml", + "ref/netcore50/zh-hant/System.Collections.Concurrent.xml", + "ref/netstandard1.1/System.Collections.Concurrent.dll", + "ref/netstandard1.1/System.Collections.Concurrent.xml", + "ref/netstandard1.1/de/System.Collections.Concurrent.xml", + "ref/netstandard1.1/es/System.Collections.Concurrent.xml", + "ref/netstandard1.1/fr/System.Collections.Concurrent.xml", + "ref/netstandard1.1/it/System.Collections.Concurrent.xml", + "ref/netstandard1.1/ja/System.Collections.Concurrent.xml", + "ref/netstandard1.1/ko/System.Collections.Concurrent.xml", + "ref/netstandard1.1/ru/System.Collections.Concurrent.xml", + "ref/netstandard1.1/zh-hans/System.Collections.Concurrent.xml", + "ref/netstandard1.1/zh-hant/System.Collections.Concurrent.xml", + "ref/netstandard1.3/System.Collections.Concurrent.dll", + "ref/netstandard1.3/System.Collections.Concurrent.xml", + "ref/netstandard1.3/de/System.Collections.Concurrent.xml", + "ref/netstandard1.3/es/System.Collections.Concurrent.xml", + "ref/netstandard1.3/fr/System.Collections.Concurrent.xml", + "ref/netstandard1.3/it/System.Collections.Concurrent.xml", + "ref/netstandard1.3/ja/System.Collections.Concurrent.xml", + "ref/netstandard1.3/ko/System.Collections.Concurrent.xml", + "ref/netstandard1.3/ru/System.Collections.Concurrent.xml", + "ref/netstandard1.3/zh-hans/System.Collections.Concurrent.xml", + "ref/netstandard1.3/zh-hant/System.Collections.Concurrent.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.collections.concurrent.4.3.0.nupkg.sha512", + "system.collections.concurrent.nuspec" + ] + }, + "System.Collections.Immutable/1.5.0": { + "sha512": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ==", + "type": "package", + "path": "system.collections.immutable/1.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.0/System.Collections.Immutable.dll", + "lib/netstandard1.0/System.Collections.Immutable.xml", + "lib/netstandard1.3/System.Collections.Immutable.dll", + "lib/netstandard1.3/System.Collections.Immutable.xml", + "lib/netstandard2.0/System.Collections.Immutable.dll", + "lib/netstandard2.0/System.Collections.Immutable.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Collections.Immutable.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Collections.Immutable.xml", + "system.collections.immutable.1.5.0.nupkg.sha512", + "system.collections.immutable.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Collections.NonGeneric/4.3.0": { + "sha512": "prtjIEMhGUnQq6RnPEYLpFt8AtLbp9yq2zxOSrY7KJJZrw25Fi97IzBqY7iqssbM61Ek5b8f3MG/sG1N2sN5KA==", + "type": "package", + "path": "system.collections.nongeneric/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Collections.NonGeneric.dll", + "lib/netstandard1.3/System.Collections.NonGeneric.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Collections.NonGeneric.dll", + "ref/netstandard1.3/System.Collections.NonGeneric.dll", + "ref/netstandard1.3/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/de/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/es/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/fr/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/it/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/ja/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/ko/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/ru/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/zh-hans/System.Collections.NonGeneric.xml", + "ref/netstandard1.3/zh-hant/System.Collections.NonGeneric.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.collections.nongeneric.4.3.0.nupkg.sha512", + "system.collections.nongeneric.nuspec" + ] + }, + "System.Collections.Specialized/4.3.0": { + "sha512": "Epx8PoVZR0iuOnJJDzp7pWvdfMMOAvpUo95pC4ScH2mJuXkKA2Y4aR3cG9qt2klHgSons1WFh4kcGW7cSXvrxg==", + "type": "package", + "path": "system.collections.specialized/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Collections.Specialized.dll", + "lib/netstandard1.3/System.Collections.Specialized.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Collections.Specialized.dll", + "ref/netstandard1.3/System.Collections.Specialized.dll", + "ref/netstandard1.3/System.Collections.Specialized.xml", + "ref/netstandard1.3/de/System.Collections.Specialized.xml", + "ref/netstandard1.3/es/System.Collections.Specialized.xml", + "ref/netstandard1.3/fr/System.Collections.Specialized.xml", + "ref/netstandard1.3/it/System.Collections.Specialized.xml", + "ref/netstandard1.3/ja/System.Collections.Specialized.xml", + "ref/netstandard1.3/ko/System.Collections.Specialized.xml", + "ref/netstandard1.3/ru/System.Collections.Specialized.xml", + "ref/netstandard1.3/zh-hans/System.Collections.Specialized.xml", + "ref/netstandard1.3/zh-hant/System.Collections.Specialized.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.collections.specialized.4.3.0.nupkg.sha512", + "system.collections.specialized.nuspec" + ] + }, + "System.ComponentModel.Annotations/4.5.0": { + "sha512": "UxYQ3FGUOtzJ7LfSdnYSFd7+oEv6M8NgUatatIN2HxNtDdlcvFAf+VIq4Of9cDMJEJC0aSRv/x898RYhB4Yppg==", + "type": "package", + "path": "system.componentmodel.annotations/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net461/System.ComponentModel.Annotations.dll", + "lib/netcore50/System.ComponentModel.Annotations.dll", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.4/System.ComponentModel.Annotations.dll", + "lib/netstandard2.0/System.ComponentModel.Annotations.dll", + "lib/portable-net45+win8/_._", + "lib/uap10.0.16299/_._", + "lib/win8/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net461/System.ComponentModel.Annotations.dll", + "ref/net461/System.ComponentModel.Annotations.xml", + "ref/netcore50/System.ComponentModel.Annotations.dll", + "ref/netcore50/System.ComponentModel.Annotations.xml", + "ref/netcore50/de/System.ComponentModel.Annotations.xml", + "ref/netcore50/es/System.ComponentModel.Annotations.xml", + "ref/netcore50/fr/System.ComponentModel.Annotations.xml", + "ref/netcore50/it/System.ComponentModel.Annotations.xml", + "ref/netcore50/ja/System.ComponentModel.Annotations.xml", + "ref/netcore50/ko/System.ComponentModel.Annotations.xml", + "ref/netcore50/ru/System.ComponentModel.Annotations.xml", + "ref/netcore50/zh-hans/System.ComponentModel.Annotations.xml", + "ref/netcore50/zh-hant/System.ComponentModel.Annotations.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.1/System.ComponentModel.Annotations.dll", + "ref/netstandard1.1/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/de/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/es/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/fr/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/it/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/ja/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/ko/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/ru/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/zh-hans/System.ComponentModel.Annotations.xml", + "ref/netstandard1.1/zh-hant/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/System.ComponentModel.Annotations.dll", + "ref/netstandard1.3/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/de/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/es/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/fr/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/it/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/ja/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/ko/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/ru/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/zh-hans/System.ComponentModel.Annotations.xml", + "ref/netstandard1.3/zh-hant/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/System.ComponentModel.Annotations.dll", + "ref/netstandard1.4/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/de/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/es/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/fr/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/it/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/ja/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/ko/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/ru/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/zh-hans/System.ComponentModel.Annotations.xml", + "ref/netstandard1.4/zh-hant/System.ComponentModel.Annotations.xml", + "ref/netstandard2.0/System.ComponentModel.Annotations.dll", + "ref/netstandard2.0/System.ComponentModel.Annotations.xml", + "ref/portable-net45+win8/_._", + "ref/uap10.0.16299/_._", + "ref/win8/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.componentmodel.annotations.4.5.0.nupkg.sha512", + "system.componentmodel.annotations.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Console/4.3.0": { + "sha512": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "type": "package", + "path": "system.console/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Console.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Console.dll", + "ref/netstandard1.3/System.Console.dll", + "ref/netstandard1.3/System.Console.xml", + "ref/netstandard1.3/de/System.Console.xml", + "ref/netstandard1.3/es/System.Console.xml", + "ref/netstandard1.3/fr/System.Console.xml", + "ref/netstandard1.3/it/System.Console.xml", + "ref/netstandard1.3/ja/System.Console.xml", + "ref/netstandard1.3/ko/System.Console.xml", + "ref/netstandard1.3/ru/System.Console.xml", + "ref/netstandard1.3/zh-hans/System.Console.xml", + "ref/netstandard1.3/zh-hant/System.Console.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.console.4.3.0.nupkg.sha512", + "system.console.nuspec" + ] + }, + "System.Data.SqlClient/4.6.1": { + "sha512": "7MTJhBFt4/tSJ2VRpG+TQNPcDdbCnWuoYzbe0kD5O3mQ7aZ2Q+Q3D9Y5Y3/aper5Gp3Lrs+8edk9clvxyPYXPw==", + "type": "package", + "path": "system.data.sqlclient/4.6.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net451/System.Data.SqlClient.dll", + "lib/net46/System.Data.SqlClient.dll", + "lib/net461/System.Data.SqlClient.dll", + "lib/netcoreapp2.1/System.Data.SqlClient.dll", + "lib/netstandard1.2/System.Data.SqlClient.dll", + "lib/netstandard1.3/System.Data.SqlClient.dll", + "lib/netstandard2.0/System.Data.SqlClient.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net451/System.Data.SqlClient.dll", + "ref/net46/System.Data.SqlClient.dll", + "ref/net461/System.Data.SqlClient.dll", + "ref/net461/System.Data.SqlClient.xml", + "ref/netcoreapp2.1/System.Data.SqlClient.dll", + "ref/netcoreapp2.1/System.Data.SqlClient.xml", + "ref/netstandard1.2/System.Data.SqlClient.dll", + "ref/netstandard1.2/System.Data.SqlClient.xml", + "ref/netstandard1.2/de/System.Data.SqlClient.xml", + "ref/netstandard1.2/es/System.Data.SqlClient.xml", + "ref/netstandard1.2/fr/System.Data.SqlClient.xml", + "ref/netstandard1.2/it/System.Data.SqlClient.xml", + "ref/netstandard1.2/ja/System.Data.SqlClient.xml", + "ref/netstandard1.2/ko/System.Data.SqlClient.xml", + "ref/netstandard1.2/ru/System.Data.SqlClient.xml", + "ref/netstandard1.2/zh-hans/System.Data.SqlClient.xml", + "ref/netstandard1.2/zh-hant/System.Data.SqlClient.xml", + "ref/netstandard1.3/System.Data.SqlClient.dll", + "ref/netstandard1.3/System.Data.SqlClient.xml", + "ref/netstandard1.3/de/System.Data.SqlClient.xml", + "ref/netstandard1.3/es/System.Data.SqlClient.xml", + "ref/netstandard1.3/fr/System.Data.SqlClient.xml", + "ref/netstandard1.3/it/System.Data.SqlClient.xml", + "ref/netstandard1.3/ja/System.Data.SqlClient.xml", + "ref/netstandard1.3/ko/System.Data.SqlClient.xml", + "ref/netstandard1.3/ru/System.Data.SqlClient.xml", + "ref/netstandard1.3/zh-hans/System.Data.SqlClient.xml", + "ref/netstandard1.3/zh-hant/System.Data.SqlClient.xml", + "ref/netstandard2.0/System.Data.SqlClient.dll", + "ref/netstandard2.0/System.Data.SqlClient.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netcoreapp2.1/System.Data.SqlClient.dll", + "runtimes/unix/lib/netstandard1.3/System.Data.SqlClient.dll", + "runtimes/unix/lib/netstandard2.0/System.Data.SqlClient.dll", + "runtimes/win/lib/net451/System.Data.SqlClient.dll", + "runtimes/win/lib/net46/System.Data.SqlClient.dll", + "runtimes/win/lib/net461/System.Data.SqlClient.dll", + "runtimes/win/lib/netcoreapp2.1/System.Data.SqlClient.dll", + "runtimes/win/lib/netstandard1.3/System.Data.SqlClient.dll", + "runtimes/win/lib/netstandard2.0/System.Data.SqlClient.dll", + "runtimes/win/lib/uap10.0.16299/System.Data.SqlClient.dll", + "system.data.sqlclient.4.6.1.nupkg.sha512", + "system.data.sqlclient.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Diagnostics.Contracts/4.3.0": { + "sha512": "eelRRbnm+OloiQvp9CXS0ixjNQldjjkHO4iIkR5XH2VIP8sUB/SIpa1TdUW6/+HDcQ+MlhP3pNa1u5SbzYuWGA==", + "type": "package", + "path": "system.diagnostics.contracts/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Diagnostics.Contracts.dll", + "lib/netstandard1.0/System.Diagnostics.Contracts.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Diagnostics.Contracts.dll", + "ref/netcore50/System.Diagnostics.Contracts.xml", + "ref/netcore50/de/System.Diagnostics.Contracts.xml", + "ref/netcore50/es/System.Diagnostics.Contracts.xml", + "ref/netcore50/fr/System.Diagnostics.Contracts.xml", + "ref/netcore50/it/System.Diagnostics.Contracts.xml", + "ref/netcore50/ja/System.Diagnostics.Contracts.xml", + "ref/netcore50/ko/System.Diagnostics.Contracts.xml", + "ref/netcore50/ru/System.Diagnostics.Contracts.xml", + "ref/netcore50/zh-hans/System.Diagnostics.Contracts.xml", + "ref/netcore50/zh-hant/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/System.Diagnostics.Contracts.dll", + "ref/netstandard1.0/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/de/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/es/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/fr/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/it/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/ja/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/ko/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/ru/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/zh-hans/System.Diagnostics.Contracts.xml", + "ref/netstandard1.0/zh-hant/System.Diagnostics.Contracts.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Diagnostics.Contracts.dll", + "system.diagnostics.contracts.4.3.0.nupkg.sha512", + "system.diagnostics.contracts.nuspec" + ] + }, + "System.Diagnostics.Debug/4.3.0": { + "sha512": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "type": "package", + "path": "system.diagnostics.debug/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Diagnostics.Debug.dll", + "ref/netcore50/System.Diagnostics.Debug.xml", + "ref/netcore50/de/System.Diagnostics.Debug.xml", + "ref/netcore50/es/System.Diagnostics.Debug.xml", + "ref/netcore50/fr/System.Diagnostics.Debug.xml", + "ref/netcore50/it/System.Diagnostics.Debug.xml", + "ref/netcore50/ja/System.Diagnostics.Debug.xml", + "ref/netcore50/ko/System.Diagnostics.Debug.xml", + "ref/netcore50/ru/System.Diagnostics.Debug.xml", + "ref/netcore50/zh-hans/System.Diagnostics.Debug.xml", + "ref/netcore50/zh-hant/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/System.Diagnostics.Debug.dll", + "ref/netstandard1.0/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/de/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/es/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/fr/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/it/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/ja/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/ko/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/ru/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/zh-hans/System.Diagnostics.Debug.xml", + "ref/netstandard1.0/zh-hant/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/System.Diagnostics.Debug.dll", + "ref/netstandard1.3/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/de/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/es/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/fr/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/it/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/ja/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/ko/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/ru/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/zh-hans/System.Diagnostics.Debug.xml", + "ref/netstandard1.3/zh-hant/System.Diagnostics.Debug.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.diagnostics.debug.4.3.0.nupkg.sha512", + "system.diagnostics.debug.nuspec" + ] + }, + "System.Diagnostics.DiagnosticSource/4.5.1": { + "sha512": "zCno/m44ymWhgLFh7tELDG9587q0l/EynPM0m4KgLaWQbz/TEKvNRX2YT5ip2qXW/uayifQ2ZqbnErsKJ4lYrQ==", + "type": "package", + "path": "system.diagnostics.diagnosticsource/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net45/System.Diagnostics.DiagnosticSource.dll", + "lib/net45/System.Diagnostics.DiagnosticSource.xml", + "lib/net46/System.Diagnostics.DiagnosticSource.dll", + "lib/net46/System.Diagnostics.DiagnosticSource.xml", + "lib/netstandard1.1/System.Diagnostics.DiagnosticSource.dll", + "lib/netstandard1.1/System.Diagnostics.DiagnosticSource.xml", + "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.dll", + "lib/netstandard1.3/System.Diagnostics.DiagnosticSource.xml", + "lib/portable-net45+win8+wpa81/System.Diagnostics.DiagnosticSource.dll", + "lib/portable-net45+win8+wpa81/System.Diagnostics.DiagnosticSource.xml", + "system.diagnostics.diagnosticsource.4.5.1.nupkg.sha512", + "system.diagnostics.diagnosticsource.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Diagnostics.FileVersionInfo/4.3.0": { + "sha512": "omCF64wzQ3Q2CeIqkD6lmmxeMZtGHUmzgFMPjfVaOsyqpR66p/JaZzManMw1s33osoAb5gqpncsjie67+yUPHQ==", + "type": "package", + "path": "system.diagnostics.fileversioninfo/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Diagnostics.FileVersionInfo.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Diagnostics.FileVersionInfo.dll", + "ref/netstandard1.3/System.Diagnostics.FileVersionInfo.dll", + "ref/netstandard1.3/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/de/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/es/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/fr/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/it/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/ja/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/ko/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/ru/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/zh-hans/System.Diagnostics.FileVersionInfo.xml", + "ref/netstandard1.3/zh-hant/System.Diagnostics.FileVersionInfo.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.Diagnostics.FileVersionInfo.dll", + "runtimes/win/lib/net46/System.Diagnostics.FileVersionInfo.dll", + "runtimes/win/lib/netcore50/System.Diagnostics.FileVersionInfo.dll", + "runtimes/win/lib/netstandard1.3/System.Diagnostics.FileVersionInfo.dll", + "system.diagnostics.fileversioninfo.4.3.0.nupkg.sha512", + "system.diagnostics.fileversioninfo.nuspec" + ] + }, + "System.Diagnostics.Process/4.3.0": { + "sha512": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "type": "package", + "path": "system.diagnostics.process/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Diagnostics.Process.dll", + "lib/net461/System.Diagnostics.Process.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Diagnostics.Process.dll", + "ref/net461/System.Diagnostics.Process.dll", + "ref/netstandard1.3/System.Diagnostics.Process.dll", + "ref/netstandard1.3/System.Diagnostics.Process.xml", + "ref/netstandard1.3/de/System.Diagnostics.Process.xml", + "ref/netstandard1.3/es/System.Diagnostics.Process.xml", + "ref/netstandard1.3/fr/System.Diagnostics.Process.xml", + "ref/netstandard1.3/it/System.Diagnostics.Process.xml", + "ref/netstandard1.3/ja/System.Diagnostics.Process.xml", + "ref/netstandard1.3/ko/System.Diagnostics.Process.xml", + "ref/netstandard1.3/ru/System.Diagnostics.Process.xml", + "ref/netstandard1.3/zh-hans/System.Diagnostics.Process.xml", + "ref/netstandard1.3/zh-hant/System.Diagnostics.Process.xml", + "ref/netstandard1.4/System.Diagnostics.Process.dll", + "ref/netstandard1.4/System.Diagnostics.Process.xml", + "ref/netstandard1.4/de/System.Diagnostics.Process.xml", + "ref/netstandard1.4/es/System.Diagnostics.Process.xml", + "ref/netstandard1.4/fr/System.Diagnostics.Process.xml", + "ref/netstandard1.4/it/System.Diagnostics.Process.xml", + "ref/netstandard1.4/ja/System.Diagnostics.Process.xml", + "ref/netstandard1.4/ko/System.Diagnostics.Process.xml", + "ref/netstandard1.4/ru/System.Diagnostics.Process.xml", + "ref/netstandard1.4/zh-hans/System.Diagnostics.Process.xml", + "ref/netstandard1.4/zh-hant/System.Diagnostics.Process.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/linux/lib/netstandard1.4/System.Diagnostics.Process.dll", + "runtimes/osx/lib/netstandard1.4/System.Diagnostics.Process.dll", + "runtimes/win/lib/net46/System.Diagnostics.Process.dll", + "runtimes/win/lib/net461/System.Diagnostics.Process.dll", + "runtimes/win/lib/netstandard1.4/System.Diagnostics.Process.dll", + "runtimes/win7/lib/netcore50/_._", + "system.diagnostics.process.4.3.0.nupkg.sha512", + "system.diagnostics.process.nuspec" + ] + }, + "System.Diagnostics.StackTrace/4.3.0": { + "sha512": "BiHg0vgtd35/DM9jvtaC1eKRpWZxr0gcQd643ABG7GnvSlf5pOkY2uyd42mMOJoOmKvnpNj0F4tuoS1pacTwYw==", + "type": "package", + "path": "system.diagnostics.stacktrace/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Diagnostics.StackTrace.dll", + "lib/netstandard1.3/System.Diagnostics.StackTrace.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Diagnostics.StackTrace.dll", + "ref/netstandard1.3/System.Diagnostics.StackTrace.dll", + "ref/netstandard1.3/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/de/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/es/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/fr/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/it/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/ja/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/ko/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/ru/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/zh-hans/System.Diagnostics.StackTrace.xml", + "ref/netstandard1.3/zh-hant/System.Diagnostics.StackTrace.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Diagnostics.StackTrace.dll", + "system.diagnostics.stacktrace.4.3.0.nupkg.sha512", + "system.diagnostics.stacktrace.nuspec" + ] + }, + "System.Diagnostics.Tools/4.3.0": { + "sha512": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "type": "package", + "path": "system.diagnostics.tools/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Diagnostics.Tools.dll", + "ref/netcore50/System.Diagnostics.Tools.xml", + "ref/netcore50/de/System.Diagnostics.Tools.xml", + "ref/netcore50/es/System.Diagnostics.Tools.xml", + "ref/netcore50/fr/System.Diagnostics.Tools.xml", + "ref/netcore50/it/System.Diagnostics.Tools.xml", + "ref/netcore50/ja/System.Diagnostics.Tools.xml", + "ref/netcore50/ko/System.Diagnostics.Tools.xml", + "ref/netcore50/ru/System.Diagnostics.Tools.xml", + "ref/netcore50/zh-hans/System.Diagnostics.Tools.xml", + "ref/netcore50/zh-hant/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/System.Diagnostics.Tools.dll", + "ref/netstandard1.0/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/de/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/es/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/fr/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/it/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/ja/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/ko/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/ru/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/zh-hans/System.Diagnostics.Tools.xml", + "ref/netstandard1.0/zh-hant/System.Diagnostics.Tools.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.diagnostics.tools.4.3.0.nupkg.sha512", + "system.diagnostics.tools.nuspec" + ] + }, + "System.Diagnostics.Tracing/4.3.0": { + "sha512": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "type": "package", + "path": "system.diagnostics.tracing/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.Diagnostics.Tracing.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.Diagnostics.Tracing.dll", + "ref/netcore50/System.Diagnostics.Tracing.dll", + "ref/netcore50/System.Diagnostics.Tracing.xml", + "ref/netcore50/de/System.Diagnostics.Tracing.xml", + "ref/netcore50/es/System.Diagnostics.Tracing.xml", + "ref/netcore50/fr/System.Diagnostics.Tracing.xml", + "ref/netcore50/it/System.Diagnostics.Tracing.xml", + "ref/netcore50/ja/System.Diagnostics.Tracing.xml", + "ref/netcore50/ko/System.Diagnostics.Tracing.xml", + "ref/netcore50/ru/System.Diagnostics.Tracing.xml", + "ref/netcore50/zh-hans/System.Diagnostics.Tracing.xml", + "ref/netcore50/zh-hant/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/System.Diagnostics.Tracing.dll", + "ref/netstandard1.1/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/de/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/es/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/fr/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/it/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/ja/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/ko/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/ru/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/zh-hans/System.Diagnostics.Tracing.xml", + "ref/netstandard1.1/zh-hant/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/System.Diagnostics.Tracing.dll", + "ref/netstandard1.2/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/de/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/es/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/fr/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/it/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/ja/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/ko/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/ru/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/zh-hans/System.Diagnostics.Tracing.xml", + "ref/netstandard1.2/zh-hant/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/System.Diagnostics.Tracing.dll", + "ref/netstandard1.3/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/de/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/es/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/fr/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/it/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/ja/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/ko/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/ru/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/zh-hans/System.Diagnostics.Tracing.xml", + "ref/netstandard1.3/zh-hant/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/System.Diagnostics.Tracing.dll", + "ref/netstandard1.5/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/de/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/es/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/fr/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/it/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/ja/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/ko/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/ru/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/zh-hans/System.Diagnostics.Tracing.xml", + "ref/netstandard1.5/zh-hant/System.Diagnostics.Tracing.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.diagnostics.tracing.4.3.0.nupkg.sha512", + "system.diagnostics.tracing.nuspec" + ] + }, + "System.Dynamic.Runtime/4.3.0": { + "sha512": "SNVi1E/vfWUAs/WYKhE9+qlS6KqK0YVhnlT0HQtr8pMIA8YX3lwy3uPMownDwdYISBdmAF/2holEIldVp85Wag==", + "type": "package", + "path": "system.dynamic.runtime/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Dynamic.Runtime.dll", + "lib/netstandard1.3/System.Dynamic.Runtime.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Dynamic.Runtime.dll", + "ref/netcore50/System.Dynamic.Runtime.xml", + "ref/netcore50/de/System.Dynamic.Runtime.xml", + "ref/netcore50/es/System.Dynamic.Runtime.xml", + "ref/netcore50/fr/System.Dynamic.Runtime.xml", + "ref/netcore50/it/System.Dynamic.Runtime.xml", + "ref/netcore50/ja/System.Dynamic.Runtime.xml", + "ref/netcore50/ko/System.Dynamic.Runtime.xml", + "ref/netcore50/ru/System.Dynamic.Runtime.xml", + "ref/netcore50/zh-hans/System.Dynamic.Runtime.xml", + "ref/netcore50/zh-hant/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/System.Dynamic.Runtime.dll", + "ref/netstandard1.0/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/de/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/es/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/fr/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/it/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/ja/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/ko/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/ru/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/zh-hans/System.Dynamic.Runtime.xml", + "ref/netstandard1.0/zh-hant/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/System.Dynamic.Runtime.dll", + "ref/netstandard1.3/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/de/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/es/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/fr/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/it/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/ja/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/ko/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/ru/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/zh-hans/System.Dynamic.Runtime.xml", + "ref/netstandard1.3/zh-hant/System.Dynamic.Runtime.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Dynamic.Runtime.dll", + "system.dynamic.runtime.4.3.0.nupkg.sha512", + "system.dynamic.runtime.nuspec" + ] + }, + "System.Globalization/4.3.0": { + "sha512": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "type": "package", + "path": "system.globalization/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Globalization.dll", + "ref/netcore50/System.Globalization.xml", + "ref/netcore50/de/System.Globalization.xml", + "ref/netcore50/es/System.Globalization.xml", + "ref/netcore50/fr/System.Globalization.xml", + "ref/netcore50/it/System.Globalization.xml", + "ref/netcore50/ja/System.Globalization.xml", + "ref/netcore50/ko/System.Globalization.xml", + "ref/netcore50/ru/System.Globalization.xml", + "ref/netcore50/zh-hans/System.Globalization.xml", + "ref/netcore50/zh-hant/System.Globalization.xml", + "ref/netstandard1.0/System.Globalization.dll", + "ref/netstandard1.0/System.Globalization.xml", + "ref/netstandard1.0/de/System.Globalization.xml", + "ref/netstandard1.0/es/System.Globalization.xml", + "ref/netstandard1.0/fr/System.Globalization.xml", + "ref/netstandard1.0/it/System.Globalization.xml", + "ref/netstandard1.0/ja/System.Globalization.xml", + "ref/netstandard1.0/ko/System.Globalization.xml", + "ref/netstandard1.0/ru/System.Globalization.xml", + "ref/netstandard1.0/zh-hans/System.Globalization.xml", + "ref/netstandard1.0/zh-hant/System.Globalization.xml", + "ref/netstandard1.3/System.Globalization.dll", + "ref/netstandard1.3/System.Globalization.xml", + "ref/netstandard1.3/de/System.Globalization.xml", + "ref/netstandard1.3/es/System.Globalization.xml", + "ref/netstandard1.3/fr/System.Globalization.xml", + "ref/netstandard1.3/it/System.Globalization.xml", + "ref/netstandard1.3/ja/System.Globalization.xml", + "ref/netstandard1.3/ko/System.Globalization.xml", + "ref/netstandard1.3/ru/System.Globalization.xml", + "ref/netstandard1.3/zh-hans/System.Globalization.xml", + "ref/netstandard1.3/zh-hant/System.Globalization.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.globalization.4.3.0.nupkg.sha512", + "system.globalization.nuspec" + ] + }, + "System.Globalization.Calendars/4.3.0": { + "sha512": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "type": "package", + "path": "system.globalization.calendars/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Globalization.Calendars.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Globalization.Calendars.dll", + "ref/netstandard1.3/System.Globalization.Calendars.dll", + "ref/netstandard1.3/System.Globalization.Calendars.xml", + "ref/netstandard1.3/de/System.Globalization.Calendars.xml", + "ref/netstandard1.3/es/System.Globalization.Calendars.xml", + "ref/netstandard1.3/fr/System.Globalization.Calendars.xml", + "ref/netstandard1.3/it/System.Globalization.Calendars.xml", + "ref/netstandard1.3/ja/System.Globalization.Calendars.xml", + "ref/netstandard1.3/ko/System.Globalization.Calendars.xml", + "ref/netstandard1.3/ru/System.Globalization.Calendars.xml", + "ref/netstandard1.3/zh-hans/System.Globalization.Calendars.xml", + "ref/netstandard1.3/zh-hant/System.Globalization.Calendars.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.globalization.calendars.4.3.0.nupkg.sha512", + "system.globalization.calendars.nuspec" + ] + }, + "System.Globalization.Extensions/4.3.0": { + "sha512": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "type": "package", + "path": "system.globalization.extensions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Globalization.Extensions.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Globalization.Extensions.dll", + "ref/netstandard1.3/System.Globalization.Extensions.dll", + "ref/netstandard1.3/System.Globalization.Extensions.xml", + "ref/netstandard1.3/de/System.Globalization.Extensions.xml", + "ref/netstandard1.3/es/System.Globalization.Extensions.xml", + "ref/netstandard1.3/fr/System.Globalization.Extensions.xml", + "ref/netstandard1.3/it/System.Globalization.Extensions.xml", + "ref/netstandard1.3/ja/System.Globalization.Extensions.xml", + "ref/netstandard1.3/ko/System.Globalization.Extensions.xml", + "ref/netstandard1.3/ru/System.Globalization.Extensions.xml", + "ref/netstandard1.3/zh-hans/System.Globalization.Extensions.xml", + "ref/netstandard1.3/zh-hant/System.Globalization.Extensions.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.Globalization.Extensions.dll", + "runtimes/win/lib/net46/System.Globalization.Extensions.dll", + "runtimes/win/lib/netstandard1.3/System.Globalization.Extensions.dll", + "system.globalization.extensions.4.3.0.nupkg.sha512", + "system.globalization.extensions.nuspec" + ] + }, + "System.IdentityModel.Tokens.Jwt/5.3.0": { + "sha512": "EdcMk+36u9gQtbwTiPQ7ckIfiADBwOmCZ6rGD2rfkaozIdW1t7vbXk/FPVAu2r9KgCQZ5245Z+P0YMM/0Q0G2g==", + "type": "package", + "path": "system.identitymodel.tokens.jwt/5.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/System.IdentityModel.Tokens.Jwt.dll", + "lib/net45/System.IdentityModel.Tokens.Jwt.pdb", + "lib/net45/System.IdentityModel.Tokens.Jwt.xml", + "lib/net451/System.IdentityModel.Tokens.Jwt.dll", + "lib/net451/System.IdentityModel.Tokens.Jwt.pdb", + "lib/net451/System.IdentityModel.Tokens.Jwt.xml", + "lib/net461/System.IdentityModel.Tokens.Jwt.dll", + "lib/net461/System.IdentityModel.Tokens.Jwt.pdb", + "lib/net461/System.IdentityModel.Tokens.Jwt.xml", + "lib/netstandard1.4/System.IdentityModel.Tokens.Jwt.dll", + "lib/netstandard1.4/System.IdentityModel.Tokens.Jwt.pdb", + "lib/netstandard1.4/System.IdentityModel.Tokens.Jwt.xml", + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.dll", + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.pdb", + "lib/netstandard2.0/System.IdentityModel.Tokens.Jwt.xml", + "system.identitymodel.tokens.jwt.5.3.0.nupkg.sha512", + "system.identitymodel.tokens.jwt.nuspec" + ] + }, + "System.Interactive.Async/3.2.0": { + "sha512": "C07p0dAA5lGqYUPiPCK3paR709gqS4aMDDsje0v0pvffwzLaxmsn5YQTfZbyNG5qrudPx+BCxTqISnncQ3wIoQ==", + "type": "package", + "path": "system.interactive.async/3.2.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/System.Interactive.Async.dll", + "lib/net45/System.Interactive.Async.xml", + "lib/net46/System.Interactive.Async.dll", + "lib/net46/System.Interactive.Async.xml", + "lib/netstandard1.0/System.Interactive.Async.dll", + "lib/netstandard1.0/System.Interactive.Async.xml", + "lib/netstandard1.3/System.Interactive.Async.dll", + "lib/netstandard1.3/System.Interactive.Async.xml", + "lib/netstandard2.0/System.Interactive.Async.dll", + "lib/netstandard2.0/System.Interactive.Async.xml", + "system.interactive.async.3.2.0.nupkg.sha512", + "system.interactive.async.nuspec" + ] + }, + "System.IO/4.3.0": { + "sha512": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "type": "package", + "path": "system.io/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.IO.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.IO.dll", + "ref/netcore50/System.IO.dll", + "ref/netcore50/System.IO.xml", + "ref/netcore50/de/System.IO.xml", + "ref/netcore50/es/System.IO.xml", + "ref/netcore50/fr/System.IO.xml", + "ref/netcore50/it/System.IO.xml", + "ref/netcore50/ja/System.IO.xml", + "ref/netcore50/ko/System.IO.xml", + "ref/netcore50/ru/System.IO.xml", + "ref/netcore50/zh-hans/System.IO.xml", + "ref/netcore50/zh-hant/System.IO.xml", + "ref/netstandard1.0/System.IO.dll", + "ref/netstandard1.0/System.IO.xml", + "ref/netstandard1.0/de/System.IO.xml", + "ref/netstandard1.0/es/System.IO.xml", + "ref/netstandard1.0/fr/System.IO.xml", + "ref/netstandard1.0/it/System.IO.xml", + "ref/netstandard1.0/ja/System.IO.xml", + "ref/netstandard1.0/ko/System.IO.xml", + "ref/netstandard1.0/ru/System.IO.xml", + "ref/netstandard1.0/zh-hans/System.IO.xml", + "ref/netstandard1.0/zh-hant/System.IO.xml", + "ref/netstandard1.3/System.IO.dll", + "ref/netstandard1.3/System.IO.xml", + "ref/netstandard1.3/de/System.IO.xml", + "ref/netstandard1.3/es/System.IO.xml", + "ref/netstandard1.3/fr/System.IO.xml", + "ref/netstandard1.3/it/System.IO.xml", + "ref/netstandard1.3/ja/System.IO.xml", + "ref/netstandard1.3/ko/System.IO.xml", + "ref/netstandard1.3/ru/System.IO.xml", + "ref/netstandard1.3/zh-hans/System.IO.xml", + "ref/netstandard1.3/zh-hant/System.IO.xml", + "ref/netstandard1.5/System.IO.dll", + "ref/netstandard1.5/System.IO.xml", + "ref/netstandard1.5/de/System.IO.xml", + "ref/netstandard1.5/es/System.IO.xml", + "ref/netstandard1.5/fr/System.IO.xml", + "ref/netstandard1.5/it/System.IO.xml", + "ref/netstandard1.5/ja/System.IO.xml", + "ref/netstandard1.5/ko/System.IO.xml", + "ref/netstandard1.5/ru/System.IO.xml", + "ref/netstandard1.5/zh-hans/System.IO.xml", + "ref/netstandard1.5/zh-hant/System.IO.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.io.4.3.0.nupkg.sha512", + "system.io.nuspec" + ] + }, + "System.IO.Compression/4.3.0": { + "sha512": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "type": "package", + "path": "system.io.compression/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net46/System.IO.Compression.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net46/System.IO.Compression.dll", + "ref/netcore50/System.IO.Compression.dll", + "ref/netcore50/System.IO.Compression.xml", + "ref/netcore50/de/System.IO.Compression.xml", + "ref/netcore50/es/System.IO.Compression.xml", + "ref/netcore50/fr/System.IO.Compression.xml", + "ref/netcore50/it/System.IO.Compression.xml", + "ref/netcore50/ja/System.IO.Compression.xml", + "ref/netcore50/ko/System.IO.Compression.xml", + "ref/netcore50/ru/System.IO.Compression.xml", + "ref/netcore50/zh-hans/System.IO.Compression.xml", + "ref/netcore50/zh-hant/System.IO.Compression.xml", + "ref/netstandard1.1/System.IO.Compression.dll", + "ref/netstandard1.1/System.IO.Compression.xml", + "ref/netstandard1.1/de/System.IO.Compression.xml", + "ref/netstandard1.1/es/System.IO.Compression.xml", + "ref/netstandard1.1/fr/System.IO.Compression.xml", + "ref/netstandard1.1/it/System.IO.Compression.xml", + "ref/netstandard1.1/ja/System.IO.Compression.xml", + "ref/netstandard1.1/ko/System.IO.Compression.xml", + "ref/netstandard1.1/ru/System.IO.Compression.xml", + "ref/netstandard1.1/zh-hans/System.IO.Compression.xml", + "ref/netstandard1.1/zh-hant/System.IO.Compression.xml", + "ref/netstandard1.3/System.IO.Compression.dll", + "ref/netstandard1.3/System.IO.Compression.xml", + "ref/netstandard1.3/de/System.IO.Compression.xml", + "ref/netstandard1.3/es/System.IO.Compression.xml", + "ref/netstandard1.3/fr/System.IO.Compression.xml", + "ref/netstandard1.3/it/System.IO.Compression.xml", + "ref/netstandard1.3/ja/System.IO.Compression.xml", + "ref/netstandard1.3/ko/System.IO.Compression.xml", + "ref/netstandard1.3/ru/System.IO.Compression.xml", + "ref/netstandard1.3/zh-hans/System.IO.Compression.xml", + "ref/netstandard1.3/zh-hant/System.IO.Compression.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.IO.Compression.dll", + "runtimes/win/lib/net46/System.IO.Compression.dll", + "runtimes/win/lib/netstandard1.3/System.IO.Compression.dll", + "system.io.compression.4.3.0.nupkg.sha512", + "system.io.compression.nuspec" + ] + }, + "System.IO.FileSystem/4.3.0": { + "sha512": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "type": "package", + "path": "system.io.filesystem/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.IO.FileSystem.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.IO.FileSystem.dll", + "ref/netstandard1.3/System.IO.FileSystem.dll", + "ref/netstandard1.3/System.IO.FileSystem.xml", + "ref/netstandard1.3/de/System.IO.FileSystem.xml", + "ref/netstandard1.3/es/System.IO.FileSystem.xml", + "ref/netstandard1.3/fr/System.IO.FileSystem.xml", + "ref/netstandard1.3/it/System.IO.FileSystem.xml", + "ref/netstandard1.3/ja/System.IO.FileSystem.xml", + "ref/netstandard1.3/ko/System.IO.FileSystem.xml", + "ref/netstandard1.3/ru/System.IO.FileSystem.xml", + "ref/netstandard1.3/zh-hans/System.IO.FileSystem.xml", + "ref/netstandard1.3/zh-hant/System.IO.FileSystem.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.io.filesystem.4.3.0.nupkg.sha512", + "system.io.filesystem.nuspec" + ] + }, + "System.IO.FileSystem.Primitives/4.3.0": { + "sha512": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "type": "package", + "path": "system.io.filesystem.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.IO.FileSystem.Primitives.dll", + "lib/netstandard1.3/System.IO.FileSystem.Primitives.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.IO.FileSystem.Primitives.dll", + "ref/netstandard1.3/System.IO.FileSystem.Primitives.dll", + "ref/netstandard1.3/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/de/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/es/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/fr/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/it/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/ja/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/ko/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/ru/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/zh-hans/System.IO.FileSystem.Primitives.xml", + "ref/netstandard1.3/zh-hant/System.IO.FileSystem.Primitives.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.io.filesystem.primitives.4.3.0.nupkg.sha512", + "system.io.filesystem.primitives.nuspec" + ] + }, + "System.IO.Pipelines/4.5.3": { + "sha512": "k6Ac5MuJ/GbFo7l/bB0Bxg0JxHReDi19eW1wuDGIy/iSIAJob0cNHChvILde/v4fdX1ZNmL2Nr7axKG21wbNLw==", + "type": "package", + "path": "system.io.pipelines/4.5.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.1/System.IO.Pipelines.dll", + "lib/netcoreapp2.1/System.IO.Pipelines.xml", + "lib/netstandard1.3/System.IO.Pipelines.dll", + "lib/netstandard1.3/System.IO.Pipelines.xml", + "lib/netstandard2.0/System.IO.Pipelines.dll", + "lib/netstandard2.0/System.IO.Pipelines.xml", + "system.io.pipelines.4.5.3.nupkg.sha512", + "system.io.pipelines.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Linq/4.3.0": { + "sha512": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "type": "package", + "path": "system.linq/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net463/System.Linq.dll", + "lib/netcore50/System.Linq.dll", + "lib/netstandard1.6/System.Linq.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net463/System.Linq.dll", + "ref/netcore50/System.Linq.dll", + "ref/netcore50/System.Linq.xml", + "ref/netcore50/de/System.Linq.xml", + "ref/netcore50/es/System.Linq.xml", + "ref/netcore50/fr/System.Linq.xml", + "ref/netcore50/it/System.Linq.xml", + "ref/netcore50/ja/System.Linq.xml", + "ref/netcore50/ko/System.Linq.xml", + "ref/netcore50/ru/System.Linq.xml", + "ref/netcore50/zh-hans/System.Linq.xml", + "ref/netcore50/zh-hant/System.Linq.xml", + "ref/netstandard1.0/System.Linq.dll", + "ref/netstandard1.0/System.Linq.xml", + "ref/netstandard1.0/de/System.Linq.xml", + "ref/netstandard1.0/es/System.Linq.xml", + "ref/netstandard1.0/fr/System.Linq.xml", + "ref/netstandard1.0/it/System.Linq.xml", + "ref/netstandard1.0/ja/System.Linq.xml", + "ref/netstandard1.0/ko/System.Linq.xml", + "ref/netstandard1.0/ru/System.Linq.xml", + "ref/netstandard1.0/zh-hans/System.Linq.xml", + "ref/netstandard1.0/zh-hant/System.Linq.xml", + "ref/netstandard1.6/System.Linq.dll", + "ref/netstandard1.6/System.Linq.xml", + "ref/netstandard1.6/de/System.Linq.xml", + "ref/netstandard1.6/es/System.Linq.xml", + "ref/netstandard1.6/fr/System.Linq.xml", + "ref/netstandard1.6/it/System.Linq.xml", + "ref/netstandard1.6/ja/System.Linq.xml", + "ref/netstandard1.6/ko/System.Linq.xml", + "ref/netstandard1.6/ru/System.Linq.xml", + "ref/netstandard1.6/zh-hans/System.Linq.xml", + "ref/netstandard1.6/zh-hant/System.Linq.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.linq.4.3.0.nupkg.sha512", + "system.linq.nuspec" + ] + }, + "System.Linq.Expressions/4.3.0": { + "sha512": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "type": "package", + "path": "system.linq.expressions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net463/System.Linq.Expressions.dll", + "lib/netcore50/System.Linq.Expressions.dll", + "lib/netstandard1.6/System.Linq.Expressions.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net463/System.Linq.Expressions.dll", + "ref/netcore50/System.Linq.Expressions.dll", + "ref/netcore50/System.Linq.Expressions.xml", + "ref/netcore50/de/System.Linq.Expressions.xml", + "ref/netcore50/es/System.Linq.Expressions.xml", + "ref/netcore50/fr/System.Linq.Expressions.xml", + "ref/netcore50/it/System.Linq.Expressions.xml", + "ref/netcore50/ja/System.Linq.Expressions.xml", + "ref/netcore50/ko/System.Linq.Expressions.xml", + "ref/netcore50/ru/System.Linq.Expressions.xml", + "ref/netcore50/zh-hans/System.Linq.Expressions.xml", + "ref/netcore50/zh-hant/System.Linq.Expressions.xml", + "ref/netstandard1.0/System.Linq.Expressions.dll", + "ref/netstandard1.0/System.Linq.Expressions.xml", + "ref/netstandard1.0/de/System.Linq.Expressions.xml", + "ref/netstandard1.0/es/System.Linq.Expressions.xml", + "ref/netstandard1.0/fr/System.Linq.Expressions.xml", + "ref/netstandard1.0/it/System.Linq.Expressions.xml", + "ref/netstandard1.0/ja/System.Linq.Expressions.xml", + "ref/netstandard1.0/ko/System.Linq.Expressions.xml", + "ref/netstandard1.0/ru/System.Linq.Expressions.xml", + "ref/netstandard1.0/zh-hans/System.Linq.Expressions.xml", + "ref/netstandard1.0/zh-hant/System.Linq.Expressions.xml", + "ref/netstandard1.3/System.Linq.Expressions.dll", + "ref/netstandard1.3/System.Linq.Expressions.xml", + "ref/netstandard1.3/de/System.Linq.Expressions.xml", + "ref/netstandard1.3/es/System.Linq.Expressions.xml", + "ref/netstandard1.3/fr/System.Linq.Expressions.xml", + "ref/netstandard1.3/it/System.Linq.Expressions.xml", + "ref/netstandard1.3/ja/System.Linq.Expressions.xml", + "ref/netstandard1.3/ko/System.Linq.Expressions.xml", + "ref/netstandard1.3/ru/System.Linq.Expressions.xml", + "ref/netstandard1.3/zh-hans/System.Linq.Expressions.xml", + "ref/netstandard1.3/zh-hant/System.Linq.Expressions.xml", + "ref/netstandard1.6/System.Linq.Expressions.dll", + "ref/netstandard1.6/System.Linq.Expressions.xml", + "ref/netstandard1.6/de/System.Linq.Expressions.xml", + "ref/netstandard1.6/es/System.Linq.Expressions.xml", + "ref/netstandard1.6/fr/System.Linq.Expressions.xml", + "ref/netstandard1.6/it/System.Linq.Expressions.xml", + "ref/netstandard1.6/ja/System.Linq.Expressions.xml", + "ref/netstandard1.6/ko/System.Linq.Expressions.xml", + "ref/netstandard1.6/ru/System.Linq.Expressions.xml", + "ref/netstandard1.6/zh-hans/System.Linq.Expressions.xml", + "ref/netstandard1.6/zh-hant/System.Linq.Expressions.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Linq.Expressions.dll", + "system.linq.expressions.4.3.0.nupkg.sha512", + "system.linq.expressions.nuspec" + ] + }, + "System.Linq.Queryable/4.0.1": { + "sha512": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "type": "package", + "path": "system.linq.queryable/4.0.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/monoandroid10/_._", + "lib/monotouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Linq.Queryable.dll", + "lib/netstandard1.3/System.Linq.Queryable.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/monoandroid10/_._", + "ref/monotouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Linq.Queryable.dll", + "ref/netcore50/System.Linq.Queryable.xml", + "ref/netcore50/de/System.Linq.Queryable.xml", + "ref/netcore50/es/System.Linq.Queryable.xml", + "ref/netcore50/fr/System.Linq.Queryable.xml", + "ref/netcore50/it/System.Linq.Queryable.xml", + "ref/netcore50/ja/System.Linq.Queryable.xml", + "ref/netcore50/ko/System.Linq.Queryable.xml", + "ref/netcore50/ru/System.Linq.Queryable.xml", + "ref/netcore50/zh-hans/System.Linq.Queryable.xml", + "ref/netcore50/zh-hant/System.Linq.Queryable.xml", + "ref/netstandard1.0/System.Linq.Queryable.dll", + "ref/netstandard1.0/System.Linq.Queryable.xml", + "ref/netstandard1.0/de/System.Linq.Queryable.xml", + "ref/netstandard1.0/es/System.Linq.Queryable.xml", + "ref/netstandard1.0/fr/System.Linq.Queryable.xml", + "ref/netstandard1.0/it/System.Linq.Queryable.xml", + "ref/netstandard1.0/ja/System.Linq.Queryable.xml", + "ref/netstandard1.0/ko/System.Linq.Queryable.xml", + "ref/netstandard1.0/ru/System.Linq.Queryable.xml", + "ref/netstandard1.0/zh-hans/System.Linq.Queryable.xml", + "ref/netstandard1.0/zh-hant/System.Linq.Queryable.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.linq.queryable.4.0.1.nupkg.sha512", + "system.linq.queryable.nuspec" + ] + }, + "System.Memory/4.5.1": { + "sha512": "sDJYJpGtTgx+23Ayu5euxG5mAXWdkDb4+b0rD0Cab0M1oQS9H0HXGPriKcqpXuiJDTV7fTp/d+fMDJmnr6sNvA==", + "type": "package", + "path": "system.memory/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.1/_._", + "lib/netstandard1.1/System.Memory.dll", + "lib/netstandard1.1/System.Memory.xml", + "lib/netstandard2.0/System.Memory.dll", + "lib/netstandard2.0/System.Memory.xml", + "ref/netcoreapp2.1/_._", + "ref/netstandard1.1/System.Memory.dll", + "ref/netstandard1.1/System.Memory.xml", + "ref/netstandard2.0/System.Memory.dll", + "ref/netstandard2.0/System.Memory.xml", + "system.memory.4.5.1.nupkg.sha512", + "system.memory.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Net.Http/4.3.0": { + "sha512": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "type": "package", + "path": "system.net.http/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/Xamarinmac20/_._", + "lib/monoandroid10/_._", + "lib/monotouch10/_._", + "lib/net45/_._", + "lib/net46/System.Net.Http.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/Xamarinmac20/_._", + "ref/monoandroid10/_._", + "ref/monotouch10/_._", + "ref/net45/_._", + "ref/net46/System.Net.Http.dll", + "ref/net46/System.Net.Http.xml", + "ref/net46/de/System.Net.Http.xml", + "ref/net46/es/System.Net.Http.xml", + "ref/net46/fr/System.Net.Http.xml", + "ref/net46/it/System.Net.Http.xml", + "ref/net46/ja/System.Net.Http.xml", + "ref/net46/ko/System.Net.Http.xml", + "ref/net46/ru/System.Net.Http.xml", + "ref/net46/zh-hans/System.Net.Http.xml", + "ref/net46/zh-hant/System.Net.Http.xml", + "ref/netcore50/System.Net.Http.dll", + "ref/netcore50/System.Net.Http.xml", + "ref/netcore50/de/System.Net.Http.xml", + "ref/netcore50/es/System.Net.Http.xml", + "ref/netcore50/fr/System.Net.Http.xml", + "ref/netcore50/it/System.Net.Http.xml", + "ref/netcore50/ja/System.Net.Http.xml", + "ref/netcore50/ko/System.Net.Http.xml", + "ref/netcore50/ru/System.Net.Http.xml", + "ref/netcore50/zh-hans/System.Net.Http.xml", + "ref/netcore50/zh-hant/System.Net.Http.xml", + "ref/netstandard1.1/System.Net.Http.dll", + "ref/netstandard1.1/System.Net.Http.xml", + "ref/netstandard1.1/de/System.Net.Http.xml", + "ref/netstandard1.1/es/System.Net.Http.xml", + "ref/netstandard1.1/fr/System.Net.Http.xml", + "ref/netstandard1.1/it/System.Net.Http.xml", + "ref/netstandard1.1/ja/System.Net.Http.xml", + "ref/netstandard1.1/ko/System.Net.Http.xml", + "ref/netstandard1.1/ru/System.Net.Http.xml", + "ref/netstandard1.1/zh-hans/System.Net.Http.xml", + "ref/netstandard1.1/zh-hant/System.Net.Http.xml", + "ref/netstandard1.3/System.Net.Http.dll", + "ref/netstandard1.3/System.Net.Http.xml", + "ref/netstandard1.3/de/System.Net.Http.xml", + "ref/netstandard1.3/es/System.Net.Http.xml", + "ref/netstandard1.3/fr/System.Net.Http.xml", + "ref/netstandard1.3/it/System.Net.Http.xml", + "ref/netstandard1.3/ja/System.Net.Http.xml", + "ref/netstandard1.3/ko/System.Net.Http.xml", + "ref/netstandard1.3/ru/System.Net.Http.xml", + "ref/netstandard1.3/zh-hans/System.Net.Http.xml", + "ref/netstandard1.3/zh-hant/System.Net.Http.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.6/System.Net.Http.dll", + "runtimes/win/lib/net46/System.Net.Http.dll", + "runtimes/win/lib/netcore50/System.Net.Http.dll", + "runtimes/win/lib/netstandard1.3/System.Net.Http.dll", + "system.net.http.4.3.0.nupkg.sha512", + "system.net.http.nuspec" + ] + }, + "System.Net.NameResolution/4.3.0": { + "sha512": "AFYl08R7MrsrEjqpQWTZWBadqXyTzNDaWpMqyxhb0d6sGhV6xMDKueuBXlLL30gz+DIRY6MpdgnHWlCh5wmq9w==", + "type": "package", + "path": "system.net.nameresolution/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Net.NameResolution.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Net.NameResolution.dll", + "ref/netstandard1.3/System.Net.NameResolution.dll", + "ref/netstandard1.3/System.Net.NameResolution.xml", + "ref/netstandard1.3/de/System.Net.NameResolution.xml", + "ref/netstandard1.3/es/System.Net.NameResolution.xml", + "ref/netstandard1.3/fr/System.Net.NameResolution.xml", + "ref/netstandard1.3/it/System.Net.NameResolution.xml", + "ref/netstandard1.3/ja/System.Net.NameResolution.xml", + "ref/netstandard1.3/ko/System.Net.NameResolution.xml", + "ref/netstandard1.3/ru/System.Net.NameResolution.xml", + "ref/netstandard1.3/zh-hans/System.Net.NameResolution.xml", + "ref/netstandard1.3/zh-hant/System.Net.NameResolution.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.Net.NameResolution.dll", + "runtimes/win/lib/net46/System.Net.NameResolution.dll", + "runtimes/win/lib/netcore50/System.Net.NameResolution.dll", + "runtimes/win/lib/netstandard1.3/System.Net.NameResolution.dll", + "system.net.nameresolution.4.3.0.nupkg.sha512", + "system.net.nameresolution.nuspec" + ] + }, + "System.Net.Primitives/4.3.0": { + "sha512": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "type": "package", + "path": "system.net.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Net.Primitives.dll", + "ref/netcore50/System.Net.Primitives.xml", + "ref/netcore50/de/System.Net.Primitives.xml", + "ref/netcore50/es/System.Net.Primitives.xml", + "ref/netcore50/fr/System.Net.Primitives.xml", + "ref/netcore50/it/System.Net.Primitives.xml", + "ref/netcore50/ja/System.Net.Primitives.xml", + "ref/netcore50/ko/System.Net.Primitives.xml", + "ref/netcore50/ru/System.Net.Primitives.xml", + "ref/netcore50/zh-hans/System.Net.Primitives.xml", + "ref/netcore50/zh-hant/System.Net.Primitives.xml", + "ref/netstandard1.0/System.Net.Primitives.dll", + "ref/netstandard1.0/System.Net.Primitives.xml", + "ref/netstandard1.0/de/System.Net.Primitives.xml", + "ref/netstandard1.0/es/System.Net.Primitives.xml", + "ref/netstandard1.0/fr/System.Net.Primitives.xml", + "ref/netstandard1.0/it/System.Net.Primitives.xml", + "ref/netstandard1.0/ja/System.Net.Primitives.xml", + "ref/netstandard1.0/ko/System.Net.Primitives.xml", + "ref/netstandard1.0/ru/System.Net.Primitives.xml", + "ref/netstandard1.0/zh-hans/System.Net.Primitives.xml", + "ref/netstandard1.0/zh-hant/System.Net.Primitives.xml", + "ref/netstandard1.1/System.Net.Primitives.dll", + "ref/netstandard1.1/System.Net.Primitives.xml", + "ref/netstandard1.1/de/System.Net.Primitives.xml", + "ref/netstandard1.1/es/System.Net.Primitives.xml", + "ref/netstandard1.1/fr/System.Net.Primitives.xml", + "ref/netstandard1.1/it/System.Net.Primitives.xml", + "ref/netstandard1.1/ja/System.Net.Primitives.xml", + "ref/netstandard1.1/ko/System.Net.Primitives.xml", + "ref/netstandard1.1/ru/System.Net.Primitives.xml", + "ref/netstandard1.1/zh-hans/System.Net.Primitives.xml", + "ref/netstandard1.1/zh-hant/System.Net.Primitives.xml", + "ref/netstandard1.3/System.Net.Primitives.dll", + "ref/netstandard1.3/System.Net.Primitives.xml", + "ref/netstandard1.3/de/System.Net.Primitives.xml", + "ref/netstandard1.3/es/System.Net.Primitives.xml", + "ref/netstandard1.3/fr/System.Net.Primitives.xml", + "ref/netstandard1.3/it/System.Net.Primitives.xml", + "ref/netstandard1.3/ja/System.Net.Primitives.xml", + "ref/netstandard1.3/ko/System.Net.Primitives.xml", + "ref/netstandard1.3/ru/System.Net.Primitives.xml", + "ref/netstandard1.3/zh-hans/System.Net.Primitives.xml", + "ref/netstandard1.3/zh-hant/System.Net.Primitives.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.net.primitives.4.3.0.nupkg.sha512", + "system.net.primitives.nuspec" + ] + }, + "System.Net.Security/4.3.0": { + "sha512": "IgJKNfALqw7JRWp5LMQ5SWHNKvXVz094U6wNE3c1i8bOkMQvgBL+MMQuNt3xl9Qg9iWpj3lFxPZEY6XHmROjMQ==", + "type": "package", + "path": "system.net.security/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Net.Security.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Net.Security.dll", + "ref/netstandard1.3/System.Net.Security.dll", + "ref/netstandard1.3/System.Net.Security.xml", + "ref/netstandard1.3/de/System.Net.Security.xml", + "ref/netstandard1.3/es/System.Net.Security.xml", + "ref/netstandard1.3/fr/System.Net.Security.xml", + "ref/netstandard1.3/it/System.Net.Security.xml", + "ref/netstandard1.3/ja/System.Net.Security.xml", + "ref/netstandard1.3/ko/System.Net.Security.xml", + "ref/netstandard1.3/ru/System.Net.Security.xml", + "ref/netstandard1.3/zh-hans/System.Net.Security.xml", + "ref/netstandard1.3/zh-hant/System.Net.Security.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.6/System.Net.Security.dll", + "runtimes/win/lib/net46/System.Net.Security.dll", + "runtimes/win/lib/netstandard1.3/System.Net.Security.dll", + "runtimes/win7/lib/netcore50/_._", + "system.net.security.4.3.0.nupkg.sha512", + "system.net.security.nuspec" + ] + }, + "System.Net.Sockets/4.3.0": { + "sha512": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "type": "package", + "path": "system.net.sockets/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Net.Sockets.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Net.Sockets.dll", + "ref/netstandard1.3/System.Net.Sockets.dll", + "ref/netstandard1.3/System.Net.Sockets.xml", + "ref/netstandard1.3/de/System.Net.Sockets.xml", + "ref/netstandard1.3/es/System.Net.Sockets.xml", + "ref/netstandard1.3/fr/System.Net.Sockets.xml", + "ref/netstandard1.3/it/System.Net.Sockets.xml", + "ref/netstandard1.3/ja/System.Net.Sockets.xml", + "ref/netstandard1.3/ko/System.Net.Sockets.xml", + "ref/netstandard1.3/ru/System.Net.Sockets.xml", + "ref/netstandard1.3/zh-hans/System.Net.Sockets.xml", + "ref/netstandard1.3/zh-hant/System.Net.Sockets.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.net.sockets.4.3.0.nupkg.sha512", + "system.net.sockets.nuspec" + ] + }, + "System.Net.WebSockets.WebSocketProtocol/4.5.3": { + "sha512": "O8RIMEVeOFzT8fscu6MDc4y+0LfnlXdqGovb0rJHBNVKhwn6BsNJmTY1oYUZPPsMfcc5OP20WpX4vj/aK8n98g==", + "type": "package", + "path": "system.net.websockets.websocketprotocol/4.5.3", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.1/System.Net.WebSockets.WebSocketProtocol.dll", + "lib/netstandard2.0/System.Net.WebSockets.WebSocketProtocol.dll", + "ref/netstandard2.0/System.Net.WebSockets.WebSocketProtocol.dll", + "system.net.websockets.websocketprotocol.4.5.3.nupkg.sha512", + "system.net.websockets.websocketprotocol.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Numerics.Vectors/4.5.0": { + "sha512": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==", + "type": "package", + "path": "system.numerics.vectors/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Numerics.Vectors.dll", + "lib/net46/System.Numerics.Vectors.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.0/System.Numerics.Vectors.dll", + "lib/netstandard1.0/System.Numerics.Vectors.xml", + "lib/netstandard2.0/System.Numerics.Vectors.dll", + "lib/netstandard2.0/System.Numerics.Vectors.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Numerics.Vectors.xml", + "lib/uap10.0.16299/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/System.Numerics.Vectors.dll", + "ref/net45/System.Numerics.Vectors.xml", + "ref/net46/System.Numerics.Vectors.dll", + "ref/net46/System.Numerics.Vectors.xml", + "ref/netcoreapp2.0/_._", + "ref/netstandard1.0/System.Numerics.Vectors.dll", + "ref/netstandard1.0/System.Numerics.Vectors.xml", + "ref/netstandard2.0/System.Numerics.Vectors.dll", + "ref/netstandard2.0/System.Numerics.Vectors.xml", + "ref/uap10.0.16299/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.numerics.vectors.4.5.0.nupkg.sha512", + "system.numerics.vectors.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.ObjectModel/4.3.0": { + "sha512": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "type": "package", + "path": "system.objectmodel/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.ObjectModel.dll", + "lib/netstandard1.3/System.ObjectModel.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.ObjectModel.dll", + "ref/netcore50/System.ObjectModel.xml", + "ref/netcore50/de/System.ObjectModel.xml", + "ref/netcore50/es/System.ObjectModel.xml", + "ref/netcore50/fr/System.ObjectModel.xml", + "ref/netcore50/it/System.ObjectModel.xml", + "ref/netcore50/ja/System.ObjectModel.xml", + "ref/netcore50/ko/System.ObjectModel.xml", + "ref/netcore50/ru/System.ObjectModel.xml", + "ref/netcore50/zh-hans/System.ObjectModel.xml", + "ref/netcore50/zh-hant/System.ObjectModel.xml", + "ref/netstandard1.0/System.ObjectModel.dll", + "ref/netstandard1.0/System.ObjectModel.xml", + "ref/netstandard1.0/de/System.ObjectModel.xml", + "ref/netstandard1.0/es/System.ObjectModel.xml", + "ref/netstandard1.0/fr/System.ObjectModel.xml", + "ref/netstandard1.0/it/System.ObjectModel.xml", + "ref/netstandard1.0/ja/System.ObjectModel.xml", + "ref/netstandard1.0/ko/System.ObjectModel.xml", + "ref/netstandard1.0/ru/System.ObjectModel.xml", + "ref/netstandard1.0/zh-hans/System.ObjectModel.xml", + "ref/netstandard1.0/zh-hant/System.ObjectModel.xml", + "ref/netstandard1.3/System.ObjectModel.dll", + "ref/netstandard1.3/System.ObjectModel.xml", + "ref/netstandard1.3/de/System.ObjectModel.xml", + "ref/netstandard1.3/es/System.ObjectModel.xml", + "ref/netstandard1.3/fr/System.ObjectModel.xml", + "ref/netstandard1.3/it/System.ObjectModel.xml", + "ref/netstandard1.3/ja/System.ObjectModel.xml", + "ref/netstandard1.3/ko/System.ObjectModel.xml", + "ref/netstandard1.3/ru/System.ObjectModel.xml", + "ref/netstandard1.3/zh-hans/System.ObjectModel.xml", + "ref/netstandard1.3/zh-hant/System.ObjectModel.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.objectmodel.4.3.0.nupkg.sha512", + "system.objectmodel.nuspec" + ] + }, + "System.Private.DataContractSerialization/4.3.0": { + "sha512": "yDaJ2x3mMmjdZEDB4IbezSnCsnjQ4BxinKhRAaP6kEgL6Bb6jANWphs5SzyD8imqeC/3FxgsuXT6ykkiH1uUmA==", + "type": "package", + "path": "system.private.datacontractserialization/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.3/System.Private.DataContractSerialization.dll", + "ref/netstandard/_._", + "runtimes/aot/lib/netcore50/System.Private.DataContractSerialization.dll", + "system.private.datacontractserialization.4.3.0.nupkg.sha512", + "system.private.datacontractserialization.nuspec" + ] + }, + "System.Reflection/4.3.0": { + "sha512": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "type": "package", + "path": "system.reflection/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.Reflection.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.Reflection.dll", + "ref/netcore50/System.Reflection.dll", + "ref/netcore50/System.Reflection.xml", + "ref/netcore50/de/System.Reflection.xml", + "ref/netcore50/es/System.Reflection.xml", + "ref/netcore50/fr/System.Reflection.xml", + "ref/netcore50/it/System.Reflection.xml", + "ref/netcore50/ja/System.Reflection.xml", + "ref/netcore50/ko/System.Reflection.xml", + "ref/netcore50/ru/System.Reflection.xml", + "ref/netcore50/zh-hans/System.Reflection.xml", + "ref/netcore50/zh-hant/System.Reflection.xml", + "ref/netstandard1.0/System.Reflection.dll", + "ref/netstandard1.0/System.Reflection.xml", + "ref/netstandard1.0/de/System.Reflection.xml", + "ref/netstandard1.0/es/System.Reflection.xml", + "ref/netstandard1.0/fr/System.Reflection.xml", + "ref/netstandard1.0/it/System.Reflection.xml", + "ref/netstandard1.0/ja/System.Reflection.xml", + "ref/netstandard1.0/ko/System.Reflection.xml", + "ref/netstandard1.0/ru/System.Reflection.xml", + "ref/netstandard1.0/zh-hans/System.Reflection.xml", + "ref/netstandard1.0/zh-hant/System.Reflection.xml", + "ref/netstandard1.3/System.Reflection.dll", + "ref/netstandard1.3/System.Reflection.xml", + "ref/netstandard1.3/de/System.Reflection.xml", + "ref/netstandard1.3/es/System.Reflection.xml", + "ref/netstandard1.3/fr/System.Reflection.xml", + "ref/netstandard1.3/it/System.Reflection.xml", + "ref/netstandard1.3/ja/System.Reflection.xml", + "ref/netstandard1.3/ko/System.Reflection.xml", + "ref/netstandard1.3/ru/System.Reflection.xml", + "ref/netstandard1.3/zh-hans/System.Reflection.xml", + "ref/netstandard1.3/zh-hant/System.Reflection.xml", + "ref/netstandard1.5/System.Reflection.dll", + "ref/netstandard1.5/System.Reflection.xml", + "ref/netstandard1.5/de/System.Reflection.xml", + "ref/netstandard1.5/es/System.Reflection.xml", + "ref/netstandard1.5/fr/System.Reflection.xml", + "ref/netstandard1.5/it/System.Reflection.xml", + "ref/netstandard1.5/ja/System.Reflection.xml", + "ref/netstandard1.5/ko/System.Reflection.xml", + "ref/netstandard1.5/ru/System.Reflection.xml", + "ref/netstandard1.5/zh-hans/System.Reflection.xml", + "ref/netstandard1.5/zh-hant/System.Reflection.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.reflection.4.3.0.nupkg.sha512", + "system.reflection.nuspec" + ] + }, + "System.Reflection.Emit/4.3.0": { + "sha512": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "type": "package", + "path": "system.reflection.emit/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/monotouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Reflection.Emit.dll", + "lib/netstandard1.3/System.Reflection.Emit.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/net45/_._", + "ref/netstandard1.1/System.Reflection.Emit.dll", + "ref/netstandard1.1/System.Reflection.Emit.xml", + "ref/netstandard1.1/de/System.Reflection.Emit.xml", + "ref/netstandard1.1/es/System.Reflection.Emit.xml", + "ref/netstandard1.1/fr/System.Reflection.Emit.xml", + "ref/netstandard1.1/it/System.Reflection.Emit.xml", + "ref/netstandard1.1/ja/System.Reflection.Emit.xml", + "ref/netstandard1.1/ko/System.Reflection.Emit.xml", + "ref/netstandard1.1/ru/System.Reflection.Emit.xml", + "ref/netstandard1.1/zh-hans/System.Reflection.Emit.xml", + "ref/netstandard1.1/zh-hant/System.Reflection.Emit.xml", + "ref/xamarinmac20/_._", + "system.reflection.emit.4.3.0.nupkg.sha512", + "system.reflection.emit.nuspec" + ] + }, + "System.Reflection.Emit.ILGeneration/4.3.0": { + "sha512": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "type": "package", + "path": "system.reflection.emit.ilgeneration/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Reflection.Emit.ILGeneration.dll", + "lib/netstandard1.3/System.Reflection.Emit.ILGeneration.dll", + "lib/portable-net45+wp8/_._", + "lib/wp80/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netstandard1.0/System.Reflection.Emit.ILGeneration.dll", + "ref/netstandard1.0/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/de/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/es/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/fr/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/it/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/ja/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/ko/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/ru/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/zh-hans/System.Reflection.Emit.ILGeneration.xml", + "ref/netstandard1.0/zh-hant/System.Reflection.Emit.ILGeneration.xml", + "ref/portable-net45+wp8/_._", + "ref/wp80/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/_._", + "system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512", + "system.reflection.emit.ilgeneration.nuspec" + ] + }, + "System.Reflection.Emit.Lightweight/4.3.0": { + "sha512": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "type": "package", + "path": "system.reflection.emit.lightweight/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Reflection.Emit.Lightweight.dll", + "lib/netstandard1.3/System.Reflection.Emit.Lightweight.dll", + "lib/portable-net45+wp8/_._", + "lib/wp80/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netstandard1.0/System.Reflection.Emit.Lightweight.dll", + "ref/netstandard1.0/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/de/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/es/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/fr/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/it/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/ja/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/ko/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/ru/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/zh-hans/System.Reflection.Emit.Lightweight.xml", + "ref/netstandard1.0/zh-hant/System.Reflection.Emit.Lightweight.xml", + "ref/portable-net45+wp8/_._", + "ref/wp80/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/_._", + "system.reflection.emit.lightweight.4.3.0.nupkg.sha512", + "system.reflection.emit.lightweight.nuspec" + ] + }, + "System.Reflection.Extensions/4.3.0": { + "sha512": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "type": "package", + "path": "system.reflection.extensions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Reflection.Extensions.dll", + "ref/netcore50/System.Reflection.Extensions.xml", + "ref/netcore50/de/System.Reflection.Extensions.xml", + "ref/netcore50/es/System.Reflection.Extensions.xml", + "ref/netcore50/fr/System.Reflection.Extensions.xml", + "ref/netcore50/it/System.Reflection.Extensions.xml", + "ref/netcore50/ja/System.Reflection.Extensions.xml", + "ref/netcore50/ko/System.Reflection.Extensions.xml", + "ref/netcore50/ru/System.Reflection.Extensions.xml", + "ref/netcore50/zh-hans/System.Reflection.Extensions.xml", + "ref/netcore50/zh-hant/System.Reflection.Extensions.xml", + "ref/netstandard1.0/System.Reflection.Extensions.dll", + "ref/netstandard1.0/System.Reflection.Extensions.xml", + "ref/netstandard1.0/de/System.Reflection.Extensions.xml", + "ref/netstandard1.0/es/System.Reflection.Extensions.xml", + "ref/netstandard1.0/fr/System.Reflection.Extensions.xml", + "ref/netstandard1.0/it/System.Reflection.Extensions.xml", + "ref/netstandard1.0/ja/System.Reflection.Extensions.xml", + "ref/netstandard1.0/ko/System.Reflection.Extensions.xml", + "ref/netstandard1.0/ru/System.Reflection.Extensions.xml", + "ref/netstandard1.0/zh-hans/System.Reflection.Extensions.xml", + "ref/netstandard1.0/zh-hant/System.Reflection.Extensions.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.reflection.extensions.4.3.0.nupkg.sha512", + "system.reflection.extensions.nuspec" + ] + }, + "System.Reflection.Metadata/1.6.0": { + "sha512": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==", + "type": "package", + "path": "system.reflection.metadata/1.6.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.1/System.Reflection.Metadata.dll", + "lib/netstandard1.1/System.Reflection.Metadata.xml", + "lib/netstandard2.0/System.Reflection.Metadata.dll", + "lib/netstandard2.0/System.Reflection.Metadata.xml", + "lib/portable-net45+win8/System.Reflection.Metadata.dll", + "lib/portable-net45+win8/System.Reflection.Metadata.xml", + "system.reflection.metadata.1.6.0.nupkg.sha512", + "system.reflection.metadata.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Reflection.Primitives/4.3.0": { + "sha512": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "type": "package", + "path": "system.reflection.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Reflection.Primitives.dll", + "ref/netcore50/System.Reflection.Primitives.xml", + "ref/netcore50/de/System.Reflection.Primitives.xml", + "ref/netcore50/es/System.Reflection.Primitives.xml", + "ref/netcore50/fr/System.Reflection.Primitives.xml", + "ref/netcore50/it/System.Reflection.Primitives.xml", + "ref/netcore50/ja/System.Reflection.Primitives.xml", + "ref/netcore50/ko/System.Reflection.Primitives.xml", + "ref/netcore50/ru/System.Reflection.Primitives.xml", + "ref/netcore50/zh-hans/System.Reflection.Primitives.xml", + "ref/netcore50/zh-hant/System.Reflection.Primitives.xml", + "ref/netstandard1.0/System.Reflection.Primitives.dll", + "ref/netstandard1.0/System.Reflection.Primitives.xml", + "ref/netstandard1.0/de/System.Reflection.Primitives.xml", + "ref/netstandard1.0/es/System.Reflection.Primitives.xml", + "ref/netstandard1.0/fr/System.Reflection.Primitives.xml", + "ref/netstandard1.0/it/System.Reflection.Primitives.xml", + "ref/netstandard1.0/ja/System.Reflection.Primitives.xml", + "ref/netstandard1.0/ko/System.Reflection.Primitives.xml", + "ref/netstandard1.0/ru/System.Reflection.Primitives.xml", + "ref/netstandard1.0/zh-hans/System.Reflection.Primitives.xml", + "ref/netstandard1.0/zh-hant/System.Reflection.Primitives.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.reflection.primitives.4.3.0.nupkg.sha512", + "system.reflection.primitives.nuspec" + ] + }, + "System.Reflection.TypeExtensions/4.3.0": { + "sha512": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "type": "package", + "path": "system.reflection.typeextensions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Reflection.TypeExtensions.dll", + "lib/net462/System.Reflection.TypeExtensions.dll", + "lib/netcore50/System.Reflection.TypeExtensions.dll", + "lib/netstandard1.5/System.Reflection.TypeExtensions.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Reflection.TypeExtensions.dll", + "ref/net462/System.Reflection.TypeExtensions.dll", + "ref/netstandard1.3/System.Reflection.TypeExtensions.dll", + "ref/netstandard1.3/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/de/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/es/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/fr/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/it/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/ja/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/ko/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/ru/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/zh-hans/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.3/zh-hant/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/System.Reflection.TypeExtensions.dll", + "ref/netstandard1.5/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/de/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/es/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/fr/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/it/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/ja/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/ko/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/ru/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/zh-hans/System.Reflection.TypeExtensions.xml", + "ref/netstandard1.5/zh-hant/System.Reflection.TypeExtensions.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Reflection.TypeExtensions.dll", + "system.reflection.typeextensions.4.3.0.nupkg.sha512", + "system.reflection.typeextensions.nuspec" + ] + }, + "System.Resources.ResourceManager/4.3.0": { + "sha512": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "type": "package", + "path": "system.resources.resourcemanager/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Resources.ResourceManager.dll", + "ref/netcore50/System.Resources.ResourceManager.xml", + "ref/netcore50/de/System.Resources.ResourceManager.xml", + "ref/netcore50/es/System.Resources.ResourceManager.xml", + "ref/netcore50/fr/System.Resources.ResourceManager.xml", + "ref/netcore50/it/System.Resources.ResourceManager.xml", + "ref/netcore50/ja/System.Resources.ResourceManager.xml", + "ref/netcore50/ko/System.Resources.ResourceManager.xml", + "ref/netcore50/ru/System.Resources.ResourceManager.xml", + "ref/netcore50/zh-hans/System.Resources.ResourceManager.xml", + "ref/netcore50/zh-hant/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/System.Resources.ResourceManager.dll", + "ref/netstandard1.0/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/de/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/es/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/fr/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/it/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/ja/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/ko/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/ru/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/zh-hans/System.Resources.ResourceManager.xml", + "ref/netstandard1.0/zh-hant/System.Resources.ResourceManager.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.resources.resourcemanager.4.3.0.nupkg.sha512", + "system.resources.resourcemanager.nuspec" + ] + }, + "System.Runtime/4.3.0": { + "sha512": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "type": "package", + "path": "system.runtime/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.Runtime.dll", + "lib/portable-net45+win8+wp80+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.Runtime.dll", + "ref/netcore50/System.Runtime.dll", + "ref/netcore50/System.Runtime.xml", + "ref/netcore50/de/System.Runtime.xml", + "ref/netcore50/es/System.Runtime.xml", + "ref/netcore50/fr/System.Runtime.xml", + "ref/netcore50/it/System.Runtime.xml", + "ref/netcore50/ja/System.Runtime.xml", + "ref/netcore50/ko/System.Runtime.xml", + "ref/netcore50/ru/System.Runtime.xml", + "ref/netcore50/zh-hans/System.Runtime.xml", + "ref/netcore50/zh-hant/System.Runtime.xml", + "ref/netstandard1.0/System.Runtime.dll", + "ref/netstandard1.0/System.Runtime.xml", + "ref/netstandard1.0/de/System.Runtime.xml", + "ref/netstandard1.0/es/System.Runtime.xml", + "ref/netstandard1.0/fr/System.Runtime.xml", + "ref/netstandard1.0/it/System.Runtime.xml", + "ref/netstandard1.0/ja/System.Runtime.xml", + "ref/netstandard1.0/ko/System.Runtime.xml", + "ref/netstandard1.0/ru/System.Runtime.xml", + "ref/netstandard1.0/zh-hans/System.Runtime.xml", + "ref/netstandard1.0/zh-hant/System.Runtime.xml", + "ref/netstandard1.2/System.Runtime.dll", + "ref/netstandard1.2/System.Runtime.xml", + "ref/netstandard1.2/de/System.Runtime.xml", + "ref/netstandard1.2/es/System.Runtime.xml", + "ref/netstandard1.2/fr/System.Runtime.xml", + "ref/netstandard1.2/it/System.Runtime.xml", + "ref/netstandard1.2/ja/System.Runtime.xml", + "ref/netstandard1.2/ko/System.Runtime.xml", + "ref/netstandard1.2/ru/System.Runtime.xml", + "ref/netstandard1.2/zh-hans/System.Runtime.xml", + "ref/netstandard1.2/zh-hant/System.Runtime.xml", + "ref/netstandard1.3/System.Runtime.dll", + "ref/netstandard1.3/System.Runtime.xml", + "ref/netstandard1.3/de/System.Runtime.xml", + "ref/netstandard1.3/es/System.Runtime.xml", + "ref/netstandard1.3/fr/System.Runtime.xml", + "ref/netstandard1.3/it/System.Runtime.xml", + "ref/netstandard1.3/ja/System.Runtime.xml", + "ref/netstandard1.3/ko/System.Runtime.xml", + "ref/netstandard1.3/ru/System.Runtime.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.xml", + "ref/netstandard1.5/System.Runtime.dll", + "ref/netstandard1.5/System.Runtime.xml", + "ref/netstandard1.5/de/System.Runtime.xml", + "ref/netstandard1.5/es/System.Runtime.xml", + "ref/netstandard1.5/fr/System.Runtime.xml", + "ref/netstandard1.5/it/System.Runtime.xml", + "ref/netstandard1.5/ja/System.Runtime.xml", + "ref/netstandard1.5/ko/System.Runtime.xml", + "ref/netstandard1.5/ru/System.Runtime.xml", + "ref/netstandard1.5/zh-hans/System.Runtime.xml", + "ref/netstandard1.5/zh-hant/System.Runtime.xml", + "ref/portable-net45+win8+wp80+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.4.3.0.nupkg.sha512", + "system.runtime.nuspec" + ] + }, + "System.Runtime.CompilerServices.Unsafe/4.5.1": { + "sha512": "Zh8t8oqolRaFa9vmOZfdQm/qKejdqz0J9kr7o2Fu0vPeoH3BL1EOXipKWwkWtLT1JPzjByrF19fGuFlNbmPpiw==", + "type": "package", + "path": "system.runtime.compilerservices.unsafe/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netcoreapp2.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "lib/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.dll", + "ref/netstandard1.0/System.Runtime.CompilerServices.Unsafe.xml", + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.dll", + "ref/netstandard2.0/System.Runtime.CompilerServices.Unsafe.xml", + "system.runtime.compilerservices.unsafe.4.5.1.nupkg.sha512", + "system.runtime.compilerservices.unsafe.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Runtime.Extensions/4.3.0": { + "sha512": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "type": "package", + "path": "system.runtime.extensions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.Runtime.Extensions.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.Runtime.Extensions.dll", + "ref/netcore50/System.Runtime.Extensions.dll", + "ref/netcore50/System.Runtime.Extensions.xml", + "ref/netcore50/de/System.Runtime.Extensions.xml", + "ref/netcore50/es/System.Runtime.Extensions.xml", + "ref/netcore50/fr/System.Runtime.Extensions.xml", + "ref/netcore50/it/System.Runtime.Extensions.xml", + "ref/netcore50/ja/System.Runtime.Extensions.xml", + "ref/netcore50/ko/System.Runtime.Extensions.xml", + "ref/netcore50/ru/System.Runtime.Extensions.xml", + "ref/netcore50/zh-hans/System.Runtime.Extensions.xml", + "ref/netcore50/zh-hant/System.Runtime.Extensions.xml", + "ref/netstandard1.0/System.Runtime.Extensions.dll", + "ref/netstandard1.0/System.Runtime.Extensions.xml", + "ref/netstandard1.0/de/System.Runtime.Extensions.xml", + "ref/netstandard1.0/es/System.Runtime.Extensions.xml", + "ref/netstandard1.0/fr/System.Runtime.Extensions.xml", + "ref/netstandard1.0/it/System.Runtime.Extensions.xml", + "ref/netstandard1.0/ja/System.Runtime.Extensions.xml", + "ref/netstandard1.0/ko/System.Runtime.Extensions.xml", + "ref/netstandard1.0/ru/System.Runtime.Extensions.xml", + "ref/netstandard1.0/zh-hans/System.Runtime.Extensions.xml", + "ref/netstandard1.0/zh-hant/System.Runtime.Extensions.xml", + "ref/netstandard1.3/System.Runtime.Extensions.dll", + "ref/netstandard1.3/System.Runtime.Extensions.xml", + "ref/netstandard1.3/de/System.Runtime.Extensions.xml", + "ref/netstandard1.3/es/System.Runtime.Extensions.xml", + "ref/netstandard1.3/fr/System.Runtime.Extensions.xml", + "ref/netstandard1.3/it/System.Runtime.Extensions.xml", + "ref/netstandard1.3/ja/System.Runtime.Extensions.xml", + "ref/netstandard1.3/ko/System.Runtime.Extensions.xml", + "ref/netstandard1.3/ru/System.Runtime.Extensions.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.Extensions.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.Extensions.xml", + "ref/netstandard1.5/System.Runtime.Extensions.dll", + "ref/netstandard1.5/System.Runtime.Extensions.xml", + "ref/netstandard1.5/de/System.Runtime.Extensions.xml", + "ref/netstandard1.5/es/System.Runtime.Extensions.xml", + "ref/netstandard1.5/fr/System.Runtime.Extensions.xml", + "ref/netstandard1.5/it/System.Runtime.Extensions.xml", + "ref/netstandard1.5/ja/System.Runtime.Extensions.xml", + "ref/netstandard1.5/ko/System.Runtime.Extensions.xml", + "ref/netstandard1.5/ru/System.Runtime.Extensions.xml", + "ref/netstandard1.5/zh-hans/System.Runtime.Extensions.xml", + "ref/netstandard1.5/zh-hant/System.Runtime.Extensions.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.extensions.4.3.0.nupkg.sha512", + "system.runtime.extensions.nuspec" + ] + }, + "System.Runtime.Handles/4.3.0": { + "sha512": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "type": "package", + "path": "system.runtime.handles/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/_._", + "ref/netstandard1.3/System.Runtime.Handles.dll", + "ref/netstandard1.3/System.Runtime.Handles.xml", + "ref/netstandard1.3/de/System.Runtime.Handles.xml", + "ref/netstandard1.3/es/System.Runtime.Handles.xml", + "ref/netstandard1.3/fr/System.Runtime.Handles.xml", + "ref/netstandard1.3/it/System.Runtime.Handles.xml", + "ref/netstandard1.3/ja/System.Runtime.Handles.xml", + "ref/netstandard1.3/ko/System.Runtime.Handles.xml", + "ref/netstandard1.3/ru/System.Runtime.Handles.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.Handles.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.Handles.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.handles.4.3.0.nupkg.sha512", + "system.runtime.handles.nuspec" + ] + }, + "System.Runtime.InteropServices/4.3.0": { + "sha512": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "type": "package", + "path": "system.runtime.interopservices/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net462/System.Runtime.InteropServices.dll", + "lib/net463/System.Runtime.InteropServices.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net462/System.Runtime.InteropServices.dll", + "ref/net463/System.Runtime.InteropServices.dll", + "ref/netcore50/System.Runtime.InteropServices.dll", + "ref/netcore50/System.Runtime.InteropServices.xml", + "ref/netcore50/de/System.Runtime.InteropServices.xml", + "ref/netcore50/es/System.Runtime.InteropServices.xml", + "ref/netcore50/fr/System.Runtime.InteropServices.xml", + "ref/netcore50/it/System.Runtime.InteropServices.xml", + "ref/netcore50/ja/System.Runtime.InteropServices.xml", + "ref/netcore50/ko/System.Runtime.InteropServices.xml", + "ref/netcore50/ru/System.Runtime.InteropServices.xml", + "ref/netcore50/zh-hans/System.Runtime.InteropServices.xml", + "ref/netcore50/zh-hant/System.Runtime.InteropServices.xml", + "ref/netcoreapp1.1/System.Runtime.InteropServices.dll", + "ref/netstandard1.1/System.Runtime.InteropServices.dll", + "ref/netstandard1.1/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/de/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/es/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/fr/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/it/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/ja/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/ko/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/ru/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/zh-hans/System.Runtime.InteropServices.xml", + "ref/netstandard1.1/zh-hant/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/System.Runtime.InteropServices.dll", + "ref/netstandard1.2/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/de/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/es/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/fr/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/it/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/ja/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/ko/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/ru/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/zh-hans/System.Runtime.InteropServices.xml", + "ref/netstandard1.2/zh-hant/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/System.Runtime.InteropServices.dll", + "ref/netstandard1.3/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/de/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/es/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/fr/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/it/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/ja/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/ko/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/ru/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.InteropServices.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/System.Runtime.InteropServices.dll", + "ref/netstandard1.5/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/de/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/es/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/fr/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/it/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/ja/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/ko/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/ru/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/zh-hans/System.Runtime.InteropServices.xml", + "ref/netstandard1.5/zh-hant/System.Runtime.InteropServices.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.interopservices.4.3.0.nupkg.sha512", + "system.runtime.interopservices.nuspec" + ] + }, + "System.Runtime.InteropServices.RuntimeInformation/4.3.0": { + "sha512": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "type": "package", + "path": "system.runtime.interopservices.runtimeinformation/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/System.Runtime.InteropServices.RuntimeInformation.dll", + "lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", + "lib/win8/System.Runtime.InteropServices.RuntimeInformation.dll", + "lib/wpa81/System.Runtime.InteropServices.RuntimeInformation.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Runtime.InteropServices.RuntimeInformation.dll", + "runtimes/unix/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", + "runtimes/win/lib/net45/System.Runtime.InteropServices.RuntimeInformation.dll", + "runtimes/win/lib/netcore50/System.Runtime.InteropServices.RuntimeInformation.dll", + "runtimes/win/lib/netstandard1.1/System.Runtime.InteropServices.RuntimeInformation.dll", + "system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512", + "system.runtime.interopservices.runtimeinformation.nuspec" + ] + }, + "System.Runtime.Numerics/4.3.0": { + "sha512": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "type": "package", + "path": "system.runtime.numerics/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Runtime.Numerics.dll", + "lib/netstandard1.3/System.Runtime.Numerics.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Runtime.Numerics.dll", + "ref/netcore50/System.Runtime.Numerics.xml", + "ref/netcore50/de/System.Runtime.Numerics.xml", + "ref/netcore50/es/System.Runtime.Numerics.xml", + "ref/netcore50/fr/System.Runtime.Numerics.xml", + "ref/netcore50/it/System.Runtime.Numerics.xml", + "ref/netcore50/ja/System.Runtime.Numerics.xml", + "ref/netcore50/ko/System.Runtime.Numerics.xml", + "ref/netcore50/ru/System.Runtime.Numerics.xml", + "ref/netcore50/zh-hans/System.Runtime.Numerics.xml", + "ref/netcore50/zh-hant/System.Runtime.Numerics.xml", + "ref/netstandard1.1/System.Runtime.Numerics.dll", + "ref/netstandard1.1/System.Runtime.Numerics.xml", + "ref/netstandard1.1/de/System.Runtime.Numerics.xml", + "ref/netstandard1.1/es/System.Runtime.Numerics.xml", + "ref/netstandard1.1/fr/System.Runtime.Numerics.xml", + "ref/netstandard1.1/it/System.Runtime.Numerics.xml", + "ref/netstandard1.1/ja/System.Runtime.Numerics.xml", + "ref/netstandard1.1/ko/System.Runtime.Numerics.xml", + "ref/netstandard1.1/ru/System.Runtime.Numerics.xml", + "ref/netstandard1.1/zh-hans/System.Runtime.Numerics.xml", + "ref/netstandard1.1/zh-hant/System.Runtime.Numerics.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.numerics.4.3.0.nupkg.sha512", + "system.runtime.numerics.nuspec" + ] + }, + "System.Runtime.Serialization.Json/4.3.0": { + "sha512": "CpVfOH0M/uZ5PH+M9+Gu56K0j9lJw3M+PKRegTkcrY/stOIvRUeonggxNrfBYLA5WOHL2j15KNJuTuld3x4o9w==", + "type": "package", + "path": "system.runtime.serialization.json/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Runtime.Serialization.Json.dll", + "lib/netstandard1.3/System.Runtime.Serialization.Json.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Runtime.Serialization.Json.dll", + "ref/netcore50/System.Runtime.Serialization.Json.xml", + "ref/netcore50/de/System.Runtime.Serialization.Json.xml", + "ref/netcore50/es/System.Runtime.Serialization.Json.xml", + "ref/netcore50/fr/System.Runtime.Serialization.Json.xml", + "ref/netcore50/it/System.Runtime.Serialization.Json.xml", + "ref/netcore50/ja/System.Runtime.Serialization.Json.xml", + "ref/netcore50/ko/System.Runtime.Serialization.Json.xml", + "ref/netcore50/ru/System.Runtime.Serialization.Json.xml", + "ref/netcore50/zh-hans/System.Runtime.Serialization.Json.xml", + "ref/netcore50/zh-hant/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/System.Runtime.Serialization.Json.dll", + "ref/netstandard1.0/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/de/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/es/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/fr/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/it/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/ja/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/ko/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/ru/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/zh-hans/System.Runtime.Serialization.Json.xml", + "ref/netstandard1.0/zh-hant/System.Runtime.Serialization.Json.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.serialization.json.4.3.0.nupkg.sha512", + "system.runtime.serialization.json.nuspec" + ] + }, + "System.Runtime.Serialization.Primitives/4.3.0": { + "sha512": "Wz+0KOukJGAlXjtKr+5Xpuxf8+c8739RI1C+A2BoQZT+wMCCoMDDdO8/4IRHfaVINqL78GO8dW8G2lW/e45Mcw==", + "type": "package", + "path": "system.runtime.serialization.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net46/System.Runtime.Serialization.Primitives.dll", + "lib/netcore50/System.Runtime.Serialization.Primitives.dll", + "lib/netstandard1.3/System.Runtime.Serialization.Primitives.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net46/System.Runtime.Serialization.Primitives.dll", + "ref/netcore50/System.Runtime.Serialization.Primitives.dll", + "ref/netcore50/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/de/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/es/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/fr/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/it/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/ja/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/ko/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/ru/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/zh-hans/System.Runtime.Serialization.Primitives.xml", + "ref/netcore50/zh-hant/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/System.Runtime.Serialization.Primitives.dll", + "ref/netstandard1.0/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/de/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/es/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/fr/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/it/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/ja/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/ko/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/ru/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/zh-hans/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.0/zh-hant/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/System.Runtime.Serialization.Primitives.dll", + "ref/netstandard1.3/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/de/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/es/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/fr/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/it/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/ja/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/ko/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/ru/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.Serialization.Primitives.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.Serialization.Primitives.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Runtime.Serialization.Primitives.dll", + "system.runtime.serialization.primitives.4.3.0.nupkg.sha512", + "system.runtime.serialization.primitives.nuspec" + ] + }, + "System.Runtime.Serialization.Xml/4.3.0": { + "sha512": "nUQx/5OVgrqEba3+j7OdiofvVq9koWZAC7Z3xGI8IIViZqApWnZ5+lLcwYgTlbkobrl/Rat+Jb8GeD4WQESD2A==", + "type": "package", + "path": "system.runtime.serialization.xml/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net46/System.Runtime.Serialization.Xml.dll", + "lib/netcore50/System.Runtime.Serialization.Xml.dll", + "lib/netstandard1.3/System.Runtime.Serialization.Xml.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net46/System.Runtime.Serialization.Xml.dll", + "ref/netcore50/System.Runtime.Serialization.Xml.dll", + "ref/netcore50/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/de/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/es/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/fr/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/it/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/ja/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/ko/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/ru/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/zh-hans/System.Runtime.Serialization.Xml.xml", + "ref/netcore50/zh-hant/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/System.Runtime.Serialization.Xml.dll", + "ref/netstandard1.0/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/de/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/es/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/fr/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/it/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/ja/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/ko/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/ru/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/zh-hans/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.0/zh-hant/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/System.Runtime.Serialization.Xml.dll", + "ref/netstandard1.3/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/de/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/es/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/fr/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/it/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/ja/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/ko/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/ru/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/zh-hans/System.Runtime.Serialization.Xml.xml", + "ref/netstandard1.3/zh-hant/System.Runtime.Serialization.Xml.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.runtime.serialization.xml.4.3.0.nupkg.sha512", + "system.runtime.serialization.xml.nuspec" + ] + }, + "System.Security.AccessControl/4.5.0": { + "sha512": "vW8Eoq0TMyz5vAG/6ce483x/CP83fgm4SJe5P8Tb1tZaobcvPrbMEL7rhH1DRdrYbbb6F0vq3OlzmK0Pkwks5A==", + "type": "package", + "path": "system.security.accesscontrol/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/System.Security.AccessControl.dll", + "lib/net461/System.Security.AccessControl.dll", + "lib/netstandard1.3/System.Security.AccessControl.dll", + "lib/netstandard2.0/System.Security.AccessControl.dll", + "lib/uap10.0.16299/_._", + "ref/net46/System.Security.AccessControl.dll", + "ref/net461/System.Security.AccessControl.dll", + "ref/net461/System.Security.AccessControl.xml", + "ref/netstandard1.3/System.Security.AccessControl.dll", + "ref/netstandard1.3/System.Security.AccessControl.xml", + "ref/netstandard1.3/de/System.Security.AccessControl.xml", + "ref/netstandard1.3/es/System.Security.AccessControl.xml", + "ref/netstandard1.3/fr/System.Security.AccessControl.xml", + "ref/netstandard1.3/it/System.Security.AccessControl.xml", + "ref/netstandard1.3/ja/System.Security.AccessControl.xml", + "ref/netstandard1.3/ko/System.Security.AccessControl.xml", + "ref/netstandard1.3/ru/System.Security.AccessControl.xml", + "ref/netstandard1.3/zh-hans/System.Security.AccessControl.xml", + "ref/netstandard1.3/zh-hant/System.Security.AccessControl.xml", + "ref/netstandard2.0/System.Security.AccessControl.dll", + "ref/netstandard2.0/System.Security.AccessControl.xml", + "ref/uap10.0.16299/_._", + "runtimes/win/lib/net46/System.Security.AccessControl.dll", + "runtimes/win/lib/net461/System.Security.AccessControl.dll", + "runtimes/win/lib/netcoreapp2.0/System.Security.AccessControl.dll", + "runtimes/win/lib/netstandard1.3/System.Security.AccessControl.dll", + "runtimes/win/lib/uap10.0.16299/_._", + "system.security.accesscontrol.4.5.0.nupkg.sha512", + "system.security.accesscontrol.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Claims/4.3.0": { + "sha512": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "type": "package", + "path": "system.security.claims/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Claims.dll", + "lib/netstandard1.3/System.Security.Claims.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Claims.dll", + "ref/netstandard1.3/System.Security.Claims.dll", + "ref/netstandard1.3/System.Security.Claims.xml", + "ref/netstandard1.3/de/System.Security.Claims.xml", + "ref/netstandard1.3/es/System.Security.Claims.xml", + "ref/netstandard1.3/fr/System.Security.Claims.xml", + "ref/netstandard1.3/it/System.Security.Claims.xml", + "ref/netstandard1.3/ja/System.Security.Claims.xml", + "ref/netstandard1.3/ko/System.Security.Claims.xml", + "ref/netstandard1.3/ru/System.Security.Claims.xml", + "ref/netstandard1.3/zh-hans/System.Security.Claims.xml", + "ref/netstandard1.3/zh-hant/System.Security.Claims.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.security.claims.4.3.0.nupkg.sha512", + "system.security.claims.nuspec" + ] + }, + "System.Security.Cryptography.Algorithms/4.3.1": { + "sha512": "DVUblnRfnarrI5olEC2B/OCsJQd0anjVaObQMndHSc43efbc88/RMOlDyg/EyY0ix5ecyZMXS8zMksb5ukebZA==", + "type": "package", + "path": "system.security.cryptography.algorithms/4.3.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.Algorithms.dll", + "lib/net461/System.Security.Cryptography.Algorithms.dll", + "lib/net463/System.Security.Cryptography.Algorithms.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.Algorithms.dll", + "ref/net461/System.Security.Cryptography.Algorithms.dll", + "ref/net463/System.Security.Cryptography.Algorithms.dll", + "ref/netstandard1.3/System.Security.Cryptography.Algorithms.dll", + "ref/netstandard1.4/System.Security.Cryptography.Algorithms.dll", + "ref/netstandard1.6/System.Security.Cryptography.Algorithms.dll", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/osx/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll", + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll", + "runtimes/win/lib/net46/System.Security.Cryptography.Algorithms.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.Algorithms.dll", + "runtimes/win/lib/net463/System.Security.Cryptography.Algorithms.dll", + "runtimes/win/lib/netcore50/System.Security.Cryptography.Algorithms.dll", + "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Algorithms.dll", + "system.security.cryptography.algorithms.4.3.1.nupkg.sha512", + "system.security.cryptography.algorithms.nuspec" + ] + }, + "System.Security.Cryptography.Cng/4.5.0": { + "sha512": "WG3r7EyjUe9CMPFSs6bty5doUqT+q9pbI80hlNzo2SkPkZ4VTuZkGWjpp77JB8+uaL4DFPRdBsAY+DX3dBK92A==", + "type": "package", + "path": "system.security.cryptography.cng/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.Cng.dll", + "lib/net461/System.Security.Cryptography.Cng.dll", + "lib/net462/System.Security.Cryptography.Cng.dll", + "lib/net47/System.Security.Cryptography.Cng.dll", + "lib/netcoreapp2.1/System.Security.Cryptography.Cng.dll", + "lib/netstandard1.3/System.Security.Cryptography.Cng.dll", + "lib/netstandard1.4/System.Security.Cryptography.Cng.dll", + "lib/netstandard1.6/System.Security.Cryptography.Cng.dll", + "lib/netstandard2.0/System.Security.Cryptography.Cng.dll", + "lib/uap10.0.16299/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.Cng.dll", + "ref/net461/System.Security.Cryptography.Cng.dll", + "ref/net461/System.Security.Cryptography.Cng.xml", + "ref/net462/System.Security.Cryptography.Cng.dll", + "ref/net462/System.Security.Cryptography.Cng.xml", + "ref/net47/System.Security.Cryptography.Cng.dll", + "ref/net47/System.Security.Cryptography.Cng.xml", + "ref/netcoreapp2.0/System.Security.Cryptography.Cng.dll", + "ref/netcoreapp2.0/System.Security.Cryptography.Cng.xml", + "ref/netcoreapp2.1/System.Security.Cryptography.Cng.dll", + "ref/netcoreapp2.1/System.Security.Cryptography.Cng.xml", + "ref/netstandard1.3/System.Security.Cryptography.Cng.dll", + "ref/netstandard1.4/System.Security.Cryptography.Cng.dll", + "ref/netstandard1.6/System.Security.Cryptography.Cng.dll", + "ref/netstandard2.0/System.Security.Cryptography.Cng.dll", + "ref/netstandard2.0/System.Security.Cryptography.Cng.xml", + "ref/uap10.0.16299/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/win/lib/net46/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/net462/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/net47/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/netcoreapp2.0/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/netcoreapp2.1/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/netstandard1.4/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.Cng.dll", + "runtimes/win/lib/uap10.0.16299/_._", + "system.security.cryptography.cng.4.5.0.nupkg.sha512", + "system.security.cryptography.cng.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Cryptography.Csp/4.3.0": { + "sha512": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "type": "package", + "path": "system.security.cryptography.csp/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.Csp.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.Csp.dll", + "ref/netstandard1.3/System.Security.Cryptography.Csp.dll", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Csp.dll", + "runtimes/win/lib/net46/System.Security.Cryptography.Csp.dll", + "runtimes/win/lib/netcore50/_._", + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Csp.dll", + "system.security.cryptography.csp.4.3.0.nupkg.sha512", + "system.security.cryptography.csp.nuspec" + ] + }, + "System.Security.Cryptography.Encoding/4.3.0": { + "sha512": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "type": "package", + "path": "system.security.cryptography.encoding/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.Encoding.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.Encoding.dll", + "ref/netstandard1.3/System.Security.Cryptography.Encoding.dll", + "ref/netstandard1.3/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/de/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/es/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/fr/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/it/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/ja/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/ko/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/ru/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/zh-hans/System.Security.Cryptography.Encoding.xml", + "ref/netstandard1.3/zh-hant/System.Security.Cryptography.Encoding.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll", + "runtimes/win/lib/net46/System.Security.Cryptography.Encoding.dll", + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Encoding.dll", + "system.security.cryptography.encoding.4.3.0.nupkg.sha512", + "system.security.cryptography.encoding.nuspec" + ] + }, + "System.Security.Cryptography.OpenSsl/4.3.0": { + "sha512": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "type": "package", + "path": "system.security.cryptography.openssl/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll", + "ref/netstandard1.6/System.Security.Cryptography.OpenSsl.dll", + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.OpenSsl.dll", + "system.security.cryptography.openssl.4.3.0.nupkg.sha512", + "system.security.cryptography.openssl.nuspec" + ] + }, + "System.Security.Cryptography.Pkcs/4.5.0": { + "sha512": "TGQX51gxpY3K3I6LJlE2LAftVlIMqJf0cBGhz68Y89jjk3LJCB6SrwiD+YN1fkqemBvWGs+GjyMJukl6d6goyQ==", + "type": "package", + "path": "system.security.cryptography.pkcs/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/System.Security.Cryptography.Pkcs.dll", + "lib/net461/System.Security.Cryptography.Pkcs.dll", + "lib/netcoreapp2.1/System.Security.Cryptography.Pkcs.dll", + "lib/netstandard1.3/System.Security.Cryptography.Pkcs.dll", + "lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll", + "ref/net46/System.Security.Cryptography.Pkcs.dll", + "ref/net461/System.Security.Cryptography.Pkcs.dll", + "ref/net461/System.Security.Cryptography.Pkcs.xml", + "ref/netcoreapp2.1/System.Security.Cryptography.Pkcs.dll", + "ref/netcoreapp2.1/System.Security.Cryptography.Pkcs.xml", + "ref/netstandard1.3/System.Security.Cryptography.Pkcs.dll", + "ref/netstandard2.0/System.Security.Cryptography.Pkcs.dll", + "ref/netstandard2.0/System.Security.Cryptography.Pkcs.xml", + "runtimes/win/lib/net46/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netcoreapp2.1/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netstandard1.3/System.Security.Cryptography.Pkcs.dll", + "runtimes/win/lib/netstandard2.0/System.Security.Cryptography.Pkcs.dll", + "system.security.cryptography.pkcs.4.5.0.nupkg.sha512", + "system.security.cryptography.pkcs.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Cryptography.Primitives/4.3.0": { + "sha512": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "type": "package", + "path": "system.security.cryptography.primitives/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.Primitives.dll", + "lib/netstandard1.3/System.Security.Cryptography.Primitives.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.Primitives.dll", + "ref/netstandard1.3/System.Security.Cryptography.Primitives.dll", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.security.cryptography.primitives.4.3.0.nupkg.sha512", + "system.security.cryptography.primitives.nuspec" + ] + }, + "System.Security.Cryptography.X509Certificates/4.3.0": { + "sha512": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "type": "package", + "path": "system.security.cryptography.x509certificates/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Security.Cryptography.X509Certificates.dll", + "lib/net461/System.Security.Cryptography.X509Certificates.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Security.Cryptography.X509Certificates.dll", + "ref/net461/System.Security.Cryptography.X509Certificates.dll", + "ref/netstandard1.3/System.Security.Cryptography.X509Certificates.dll", + "ref/netstandard1.3/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/de/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/es/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/fr/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/it/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/ja/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/ko/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/ru/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/zh-hans/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.3/zh-hant/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.dll", + "ref/netstandard1.4/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/de/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/es/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/fr/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/it/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/ja/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/ko/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/ru/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/zh-hans/System.Security.Cryptography.X509Certificates.xml", + "ref/netstandard1.4/zh-hant/System.Security.Cryptography.X509Certificates.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/unix/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll", + "runtimes/win/lib/net46/System.Security.Cryptography.X509Certificates.dll", + "runtimes/win/lib/net461/System.Security.Cryptography.X509Certificates.dll", + "runtimes/win/lib/netcore50/System.Security.Cryptography.X509Certificates.dll", + "runtimes/win/lib/netstandard1.6/System.Security.Cryptography.X509Certificates.dll", + "system.security.cryptography.x509certificates.4.3.0.nupkg.sha512", + "system.security.cryptography.x509certificates.nuspec" + ] + }, + "System.Security.Cryptography.Xml/4.5.0": { + "sha512": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "type": "package", + "path": "system.security.cryptography.xml/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Security.Cryptography.Xml.dll", + "lib/netstandard2.0/System.Security.Cryptography.Xml.dll", + "ref/net461/System.Security.Cryptography.Xml.dll", + "ref/net461/System.Security.Cryptography.Xml.xml", + "ref/netstandard2.0/System.Security.Cryptography.Xml.dll", + "ref/netstandard2.0/System.Security.Cryptography.Xml.xml", + "system.security.cryptography.xml.4.5.0.nupkg.sha512", + "system.security.cryptography.xml.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Permissions/4.5.0": { + "sha512": "9gdyuARhUR7H+p5CjyUB/zPk7/Xut3wUSP8NJQB6iZr8L3XUXTMdoLeVAg9N4rqF8oIpE7MpdqHdDHQ7XgJe0g==", + "type": "package", + "path": "system.security.permissions/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net461/System.Security.Permissions.dll", + "lib/netstandard2.0/System.Security.Permissions.dll", + "ref/net461/System.Security.Permissions.dll", + "ref/net461/System.Security.Permissions.xml", + "ref/netstandard2.0/System.Security.Permissions.dll", + "ref/netstandard2.0/System.Security.Permissions.xml", + "system.security.permissions.4.5.0.nupkg.sha512", + "system.security.permissions.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Security.Principal/4.3.0": { + "sha512": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "type": "package", + "path": "system.security.principal/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Security.Principal.dll", + "lib/netstandard1.0/System.Security.Principal.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Security.Principal.dll", + "ref/netcore50/System.Security.Principal.xml", + "ref/netcore50/de/System.Security.Principal.xml", + "ref/netcore50/es/System.Security.Principal.xml", + "ref/netcore50/fr/System.Security.Principal.xml", + "ref/netcore50/it/System.Security.Principal.xml", + "ref/netcore50/ja/System.Security.Principal.xml", + "ref/netcore50/ko/System.Security.Principal.xml", + "ref/netcore50/ru/System.Security.Principal.xml", + "ref/netcore50/zh-hans/System.Security.Principal.xml", + "ref/netcore50/zh-hant/System.Security.Principal.xml", + "ref/netstandard1.0/System.Security.Principal.dll", + "ref/netstandard1.0/System.Security.Principal.xml", + "ref/netstandard1.0/de/System.Security.Principal.xml", + "ref/netstandard1.0/es/System.Security.Principal.xml", + "ref/netstandard1.0/fr/System.Security.Principal.xml", + "ref/netstandard1.0/it/System.Security.Principal.xml", + "ref/netstandard1.0/ja/System.Security.Principal.xml", + "ref/netstandard1.0/ko/System.Security.Principal.xml", + "ref/netstandard1.0/ru/System.Security.Principal.xml", + "ref/netstandard1.0/zh-hans/System.Security.Principal.xml", + "ref/netstandard1.0/zh-hant/System.Security.Principal.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.security.principal.4.3.0.nupkg.sha512", + "system.security.principal.nuspec" + ] + }, + "System.Security.Principal.Windows/4.5.0": { + "sha512": "U77HfRXlZlOeIXd//Yoj6Jnk8AXlbeisf1oq1os+hxOGVnuG+lGSfGqTwTZBoORFF6j/0q7HXIl8cqwQ9aUGqQ==", + "type": "package", + "path": "system.security.principal.windows/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/net46/System.Security.Principal.Windows.dll", + "lib/net461/System.Security.Principal.Windows.dll", + "lib/netstandard1.3/System.Security.Principal.Windows.dll", + "lib/netstandard2.0/System.Security.Principal.Windows.dll", + "lib/uap10.0.16299/_._", + "ref/net46/System.Security.Principal.Windows.dll", + "ref/net461/System.Security.Principal.Windows.dll", + "ref/net461/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/System.Security.Principal.Windows.dll", + "ref/netstandard1.3/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/de/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/es/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/fr/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/it/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ja/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ko/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/ru/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/zh-hans/System.Security.Principal.Windows.xml", + "ref/netstandard1.3/zh-hant/System.Security.Principal.Windows.xml", + "ref/netstandard2.0/System.Security.Principal.Windows.dll", + "ref/netstandard2.0/System.Security.Principal.Windows.xml", + "ref/uap10.0.16299/_._", + "runtimes/unix/lib/netcoreapp2.0/System.Security.Principal.Windows.dll", + "runtimes/win/lib/net46/System.Security.Principal.Windows.dll", + "runtimes/win/lib/net461/System.Security.Principal.Windows.dll", + "runtimes/win/lib/netcoreapp2.0/System.Security.Principal.Windows.dll", + "runtimes/win/lib/netstandard1.3/System.Security.Principal.Windows.dll", + "runtimes/win/lib/uap10.0.16299/_._", + "system.security.principal.windows.4.5.0.nupkg.sha512", + "system.security.principal.windows.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Spatial/5.8.4": { + "sha512": "0xPUcjZX/SlFA34BeXGC3oPX0wX98ndJApYjdDnisWubuAprbqAX8mRPoM10vFfUE6VQyyBj7u2we7be52D+BQ==", + "type": "package", + "path": "system.spatial/5.8.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net40/System.Spatial.dll", + "lib/net40/System.Spatial.xml", + "lib/net40/de/System.Spatial.resources.dll", + "lib/net40/es/System.Spatial.resources.dll", + "lib/net40/fr/System.Spatial.resources.dll", + "lib/net40/it/System.Spatial.resources.dll", + "lib/net40/ja/System.Spatial.resources.dll", + "lib/net40/ko/System.Spatial.resources.dll", + "lib/net40/ru/System.Spatial.resources.dll", + "lib/net40/zh-Hans/System.Spatial.resources.dll", + "lib/net40/zh-Hant/System.Spatial.resources.dll", + "lib/netstandard1.1/System.Spatial.dll", + "lib/netstandard1.1/System.Spatial.xml", + "lib/netstandard1.1/de/System.Spatial.resources.dll", + "lib/netstandard1.1/es/System.Spatial.resources.dll", + "lib/netstandard1.1/fr/System.Spatial.resources.dll", + "lib/netstandard1.1/it/System.Spatial.resources.dll", + "lib/netstandard1.1/ja/System.Spatial.resources.dll", + "lib/netstandard1.1/ko/System.Spatial.resources.dll", + "lib/netstandard1.1/ru/System.Spatial.resources.dll", + "lib/netstandard1.1/zh-Hans/System.Spatial.resources.dll", + "lib/netstandard1.1/zh-Hant/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/System.Spatial.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/System.Spatial.xml", + "lib/portable-net40+sl5+wp8+win8+wpa/de/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/es/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/fr/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/it/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ja/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ko/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/ru/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hans/System.Spatial.resources.dll", + "lib/portable-net40+sl5+wp8+win8+wpa/zh-Hant/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/System.Spatial.dll", + "lib/portable-net45+wp8+win8+wpa/System.Spatial.xml", + "lib/portable-net45+wp8+win8+wpa/de/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/es/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/fr/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/it/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ja/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ko/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/ru/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hans/System.Spatial.resources.dll", + "lib/portable-net45+wp8+win8+wpa/zh-Hant/System.Spatial.resources.dll", + "lib/sl4/System.Spatial.dll", + "lib/sl4/System.Spatial.xml", + "lib/sl4/de/System.Spatial.resources.dll", + "lib/sl4/es/System.Spatial.resources.dll", + "lib/sl4/fr/System.Spatial.resources.dll", + "lib/sl4/it/System.Spatial.resources.dll", + "lib/sl4/ja/System.Spatial.resources.dll", + "lib/sl4/ko/System.Spatial.resources.dll", + "lib/sl4/ru/System.Spatial.resources.dll", + "lib/sl4/zh-Hans/System.Spatial.resources.dll", + "lib/sl4/zh-Hant/System.Spatial.resources.dll", + "system.spatial.5.8.4.nupkg.sha512", + "system.spatial.nuspec" + ] + }, + "System.Text.Encoding/4.3.0": { + "sha512": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "type": "package", + "path": "system.text.encoding/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Text.Encoding.dll", + "ref/netcore50/System.Text.Encoding.xml", + "ref/netcore50/de/System.Text.Encoding.xml", + "ref/netcore50/es/System.Text.Encoding.xml", + "ref/netcore50/fr/System.Text.Encoding.xml", + "ref/netcore50/it/System.Text.Encoding.xml", + "ref/netcore50/ja/System.Text.Encoding.xml", + "ref/netcore50/ko/System.Text.Encoding.xml", + "ref/netcore50/ru/System.Text.Encoding.xml", + "ref/netcore50/zh-hans/System.Text.Encoding.xml", + "ref/netcore50/zh-hant/System.Text.Encoding.xml", + "ref/netstandard1.0/System.Text.Encoding.dll", + "ref/netstandard1.0/System.Text.Encoding.xml", + "ref/netstandard1.0/de/System.Text.Encoding.xml", + "ref/netstandard1.0/es/System.Text.Encoding.xml", + "ref/netstandard1.0/fr/System.Text.Encoding.xml", + "ref/netstandard1.0/it/System.Text.Encoding.xml", + "ref/netstandard1.0/ja/System.Text.Encoding.xml", + "ref/netstandard1.0/ko/System.Text.Encoding.xml", + "ref/netstandard1.0/ru/System.Text.Encoding.xml", + "ref/netstandard1.0/zh-hans/System.Text.Encoding.xml", + "ref/netstandard1.0/zh-hant/System.Text.Encoding.xml", + "ref/netstandard1.3/System.Text.Encoding.dll", + "ref/netstandard1.3/System.Text.Encoding.xml", + "ref/netstandard1.3/de/System.Text.Encoding.xml", + "ref/netstandard1.3/es/System.Text.Encoding.xml", + "ref/netstandard1.3/fr/System.Text.Encoding.xml", + "ref/netstandard1.3/it/System.Text.Encoding.xml", + "ref/netstandard1.3/ja/System.Text.Encoding.xml", + "ref/netstandard1.3/ko/System.Text.Encoding.xml", + "ref/netstandard1.3/ru/System.Text.Encoding.xml", + "ref/netstandard1.3/zh-hans/System.Text.Encoding.xml", + "ref/netstandard1.3/zh-hant/System.Text.Encoding.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.text.encoding.4.3.0.nupkg.sha512", + "system.text.encoding.nuspec" + ] + }, + "System.Text.Encoding.CodePages/4.5.0": { + "sha512": "S0wEUiKcLvRlkFUXca8uio1UQ5bYQzYgOmOKtCqaBQC3GR9AJjh43otcM32IGsAyvadFTaAMw9Irm6dS4Evfng==", + "type": "package", + "path": "system.text.encoding.codepages/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Text.Encoding.CodePages.dll", + "lib/net461/System.Text.Encoding.CodePages.dll", + "lib/netstandard1.3/System.Text.Encoding.CodePages.dll", + "lib/netstandard2.0/System.Text.Encoding.CodePages.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/netstandard1.3/System.Text.Encoding.CodePages.dll", + "ref/netstandard1.3/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/de/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/es/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/fr/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/it/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/ja/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/ko/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/ru/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/zh-hans/System.Text.Encoding.CodePages.xml", + "ref/netstandard1.3/zh-hant/System.Text.Encoding.CodePages.xml", + "ref/netstandard2.0/System.Text.Encoding.CodePages.dll", + "ref/netstandard2.0/System.Text.Encoding.CodePages.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/win/lib/net461/System.Text.Encoding.CodePages.dll", + "runtimes/win/lib/netcoreapp2.0/System.Text.Encoding.CodePages.dll", + "runtimes/win/lib/netstandard1.3/System.Text.Encoding.CodePages.dll", + "runtimes/win/lib/netstandard2.0/System.Text.Encoding.CodePages.dll", + "system.text.encoding.codepages.4.5.0.nupkg.sha512", + "system.text.encoding.codepages.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Text.Encoding.Extensions/4.3.0": { + "sha512": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "type": "package", + "path": "system.text.encoding.extensions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Text.Encoding.Extensions.dll", + "ref/netcore50/System.Text.Encoding.Extensions.xml", + "ref/netcore50/de/System.Text.Encoding.Extensions.xml", + "ref/netcore50/es/System.Text.Encoding.Extensions.xml", + "ref/netcore50/fr/System.Text.Encoding.Extensions.xml", + "ref/netcore50/it/System.Text.Encoding.Extensions.xml", + "ref/netcore50/ja/System.Text.Encoding.Extensions.xml", + "ref/netcore50/ko/System.Text.Encoding.Extensions.xml", + "ref/netcore50/ru/System.Text.Encoding.Extensions.xml", + "ref/netcore50/zh-hans/System.Text.Encoding.Extensions.xml", + "ref/netcore50/zh-hant/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/System.Text.Encoding.Extensions.dll", + "ref/netstandard1.0/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/de/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/es/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/fr/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/it/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/ja/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/ko/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/ru/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/zh-hans/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.0/zh-hant/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/System.Text.Encoding.Extensions.dll", + "ref/netstandard1.3/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/de/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/es/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/fr/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/it/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/ja/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/ko/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/ru/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/zh-hans/System.Text.Encoding.Extensions.xml", + "ref/netstandard1.3/zh-hant/System.Text.Encoding.Extensions.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.text.encoding.extensions.4.3.0.nupkg.sha512", + "system.text.encoding.extensions.nuspec" + ] + }, + "System.Text.Encodings.Web/4.5.0": { + "sha512": "Xg4G4Indi4dqP1iuAiMSwpiWS54ZghzR644OtsRCm/m/lBMG8dUBhLVN7hLm8NNrNTR+iGbshCPTwrvxZPlm4g==", + "type": "package", + "path": "system.text.encodings.web/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netstandard1.0/System.Text.Encodings.Web.dll", + "lib/netstandard1.0/System.Text.Encodings.Web.xml", + "lib/netstandard2.0/System.Text.Encodings.Web.dll", + "lib/netstandard2.0/System.Text.Encodings.Web.xml", + "system.text.encodings.web.4.5.0.nupkg.sha512", + "system.text.encodings.web.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Text.RegularExpressions/4.3.0": { + "sha512": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "type": "package", + "path": "system.text.regularexpressions/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net463/System.Text.RegularExpressions.dll", + "lib/netcore50/System.Text.RegularExpressions.dll", + "lib/netstandard1.6/System.Text.RegularExpressions.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net463/System.Text.RegularExpressions.dll", + "ref/netcore50/System.Text.RegularExpressions.dll", + "ref/netcore50/System.Text.RegularExpressions.xml", + "ref/netcore50/de/System.Text.RegularExpressions.xml", + "ref/netcore50/es/System.Text.RegularExpressions.xml", + "ref/netcore50/fr/System.Text.RegularExpressions.xml", + "ref/netcore50/it/System.Text.RegularExpressions.xml", + "ref/netcore50/ja/System.Text.RegularExpressions.xml", + "ref/netcore50/ko/System.Text.RegularExpressions.xml", + "ref/netcore50/ru/System.Text.RegularExpressions.xml", + "ref/netcore50/zh-hans/System.Text.RegularExpressions.xml", + "ref/netcore50/zh-hant/System.Text.RegularExpressions.xml", + "ref/netcoreapp1.1/System.Text.RegularExpressions.dll", + "ref/netstandard1.0/System.Text.RegularExpressions.dll", + "ref/netstandard1.0/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/de/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/es/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/fr/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/it/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/ja/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/ko/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/ru/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/zh-hans/System.Text.RegularExpressions.xml", + "ref/netstandard1.0/zh-hant/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/System.Text.RegularExpressions.dll", + "ref/netstandard1.3/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/de/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/es/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/fr/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/it/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/ja/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/ko/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/ru/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/zh-hans/System.Text.RegularExpressions.xml", + "ref/netstandard1.3/zh-hant/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/System.Text.RegularExpressions.dll", + "ref/netstandard1.6/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/de/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/es/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/fr/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/it/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/ja/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/ko/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/ru/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/zh-hans/System.Text.RegularExpressions.xml", + "ref/netstandard1.6/zh-hant/System.Text.RegularExpressions.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.text.regularexpressions.4.3.0.nupkg.sha512", + "system.text.regularexpressions.nuspec" + ] + }, + "System.Threading/4.3.0": { + "sha512": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "type": "package", + "path": "system.threading/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Threading.dll", + "lib/netstandard1.3/System.Threading.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Threading.dll", + "ref/netcore50/System.Threading.xml", + "ref/netcore50/de/System.Threading.xml", + "ref/netcore50/es/System.Threading.xml", + "ref/netcore50/fr/System.Threading.xml", + "ref/netcore50/it/System.Threading.xml", + "ref/netcore50/ja/System.Threading.xml", + "ref/netcore50/ko/System.Threading.xml", + "ref/netcore50/ru/System.Threading.xml", + "ref/netcore50/zh-hans/System.Threading.xml", + "ref/netcore50/zh-hant/System.Threading.xml", + "ref/netstandard1.0/System.Threading.dll", + "ref/netstandard1.0/System.Threading.xml", + "ref/netstandard1.0/de/System.Threading.xml", + "ref/netstandard1.0/es/System.Threading.xml", + "ref/netstandard1.0/fr/System.Threading.xml", + "ref/netstandard1.0/it/System.Threading.xml", + "ref/netstandard1.0/ja/System.Threading.xml", + "ref/netstandard1.0/ko/System.Threading.xml", + "ref/netstandard1.0/ru/System.Threading.xml", + "ref/netstandard1.0/zh-hans/System.Threading.xml", + "ref/netstandard1.0/zh-hant/System.Threading.xml", + "ref/netstandard1.3/System.Threading.dll", + "ref/netstandard1.3/System.Threading.xml", + "ref/netstandard1.3/de/System.Threading.xml", + "ref/netstandard1.3/es/System.Threading.xml", + "ref/netstandard1.3/fr/System.Threading.xml", + "ref/netstandard1.3/it/System.Threading.xml", + "ref/netstandard1.3/ja/System.Threading.xml", + "ref/netstandard1.3/ko/System.Threading.xml", + "ref/netstandard1.3/ru/System.Threading.xml", + "ref/netstandard1.3/zh-hans/System.Threading.xml", + "ref/netstandard1.3/zh-hant/System.Threading.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Threading.dll", + "system.threading.4.3.0.nupkg.sha512", + "system.threading.nuspec" + ] + }, + "System.Threading.Channels/4.5.0": { + "sha512": "MEH06N0rIGmRT4LOKQ2BmUO0IxfvmIY/PaouSq+DFQku72OL8cxfw8W99uGpTCFf2vx2QHLRSh374iSM3asdTA==", + "type": "package", + "path": "system.threading.channels/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/netcoreapp2.1/System.Threading.Channels.dll", + "lib/netcoreapp2.1/System.Threading.Channels.xml", + "lib/netstandard1.3/System.Threading.Channels.dll", + "lib/netstandard1.3/System.Threading.Channels.xml", + "lib/netstandard2.0/System.Threading.Channels.dll", + "lib/netstandard2.0/System.Threading.Channels.xml", + "system.threading.channels.4.5.0.nupkg.sha512", + "system.threading.channels.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Threading.Tasks/4.3.0": { + "sha512": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "type": "package", + "path": "system.threading.tasks/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Threading.Tasks.dll", + "ref/netcore50/System.Threading.Tasks.xml", + "ref/netcore50/de/System.Threading.Tasks.xml", + "ref/netcore50/es/System.Threading.Tasks.xml", + "ref/netcore50/fr/System.Threading.Tasks.xml", + "ref/netcore50/it/System.Threading.Tasks.xml", + "ref/netcore50/ja/System.Threading.Tasks.xml", + "ref/netcore50/ko/System.Threading.Tasks.xml", + "ref/netcore50/ru/System.Threading.Tasks.xml", + "ref/netcore50/zh-hans/System.Threading.Tasks.xml", + "ref/netcore50/zh-hant/System.Threading.Tasks.xml", + "ref/netstandard1.0/System.Threading.Tasks.dll", + "ref/netstandard1.0/System.Threading.Tasks.xml", + "ref/netstandard1.0/de/System.Threading.Tasks.xml", + "ref/netstandard1.0/es/System.Threading.Tasks.xml", + "ref/netstandard1.0/fr/System.Threading.Tasks.xml", + "ref/netstandard1.0/it/System.Threading.Tasks.xml", + "ref/netstandard1.0/ja/System.Threading.Tasks.xml", + "ref/netstandard1.0/ko/System.Threading.Tasks.xml", + "ref/netstandard1.0/ru/System.Threading.Tasks.xml", + "ref/netstandard1.0/zh-hans/System.Threading.Tasks.xml", + "ref/netstandard1.0/zh-hant/System.Threading.Tasks.xml", + "ref/netstandard1.3/System.Threading.Tasks.dll", + "ref/netstandard1.3/System.Threading.Tasks.xml", + "ref/netstandard1.3/de/System.Threading.Tasks.xml", + "ref/netstandard1.3/es/System.Threading.Tasks.xml", + "ref/netstandard1.3/fr/System.Threading.Tasks.xml", + "ref/netstandard1.3/it/System.Threading.Tasks.xml", + "ref/netstandard1.3/ja/System.Threading.Tasks.xml", + "ref/netstandard1.3/ko/System.Threading.Tasks.xml", + "ref/netstandard1.3/ru/System.Threading.Tasks.xml", + "ref/netstandard1.3/zh-hans/System.Threading.Tasks.xml", + "ref/netstandard1.3/zh-hant/System.Threading.Tasks.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.tasks.4.3.0.nupkg.sha512", + "system.threading.tasks.nuspec" + ] + }, + "System.Threading.Tasks.Extensions/4.5.1": { + "sha512": "WSKUTtLhPR8gllzIWO2x6l4lmAIfbyMAiTlyXAis4QBDonXK4b4S6F8zGARX4/P8wH3DH+sLdhamCiHn+fTU1A==", + "type": "package", + "path": "system.threading.tasks.extensions/4.5.1", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/netcoreapp2.1/_._", + "lib/netstandard1.0/System.Threading.Tasks.Extensions.dll", + "lib/netstandard1.0/System.Threading.Tasks.Extensions.xml", + "lib/netstandard2.0/System.Threading.Tasks.Extensions.dll", + "lib/netstandard2.0/System.Threading.Tasks.Extensions.xml", + "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.dll", + "lib/portable-net45+win8+wp8+wpa81/System.Threading.Tasks.Extensions.xml", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/netcoreapp2.1/_._", + "ref/netstandard1.0/System.Threading.Tasks.Extensions.dll", + "ref/netstandard1.0/System.Threading.Tasks.Extensions.xml", + "ref/netstandard2.0/System.Threading.Tasks.Extensions.dll", + "ref/netstandard2.0/System.Threading.Tasks.Extensions.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.tasks.extensions.4.5.1.nupkg.sha512", + "system.threading.tasks.extensions.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Threading.Tasks.Parallel/4.3.0": { + "sha512": "cbjBNZHf/vQCfcdhzx7knsiygoCKgxL8mZOeocXZn5gWhCdzHIq6bYNKWX0LAJCWYP7bds4yBK8p06YkP0oa0g==", + "type": "package", + "path": "system.threading.tasks.parallel/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Threading.Tasks.Parallel.dll", + "lib/netstandard1.3/System.Threading.Tasks.Parallel.dll", + "lib/portable-net45+win8+wpa81/_._", + "lib/win8/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Threading.Tasks.Parallel.dll", + "ref/netcore50/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/de/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/es/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/fr/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/it/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/ja/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/ko/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/ru/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/zh-hans/System.Threading.Tasks.Parallel.xml", + "ref/netcore50/zh-hant/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/System.Threading.Tasks.Parallel.dll", + "ref/netstandard1.1/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/de/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/es/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/fr/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/it/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/ja/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/ko/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/ru/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/zh-hans/System.Threading.Tasks.Parallel.xml", + "ref/netstandard1.1/zh-hant/System.Threading.Tasks.Parallel.xml", + "ref/portable-net45+win8+wpa81/_._", + "ref/win8/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.tasks.parallel.4.3.0.nupkg.sha512", + "system.threading.tasks.parallel.nuspec" + ] + }, + "System.Threading.Thread/4.3.0": { + "sha512": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "type": "package", + "path": "system.threading.thread/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Threading.Thread.dll", + "lib/netcore50/_._", + "lib/netstandard1.3/System.Threading.Thread.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Threading.Thread.dll", + "ref/netstandard1.3/System.Threading.Thread.dll", + "ref/netstandard1.3/System.Threading.Thread.xml", + "ref/netstandard1.3/de/System.Threading.Thread.xml", + "ref/netstandard1.3/es/System.Threading.Thread.xml", + "ref/netstandard1.3/fr/System.Threading.Thread.xml", + "ref/netstandard1.3/it/System.Threading.Thread.xml", + "ref/netstandard1.3/ja/System.Threading.Thread.xml", + "ref/netstandard1.3/ko/System.Threading.Thread.xml", + "ref/netstandard1.3/ru/System.Threading.Thread.xml", + "ref/netstandard1.3/zh-hans/System.Threading.Thread.xml", + "ref/netstandard1.3/zh-hant/System.Threading.Thread.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.thread.4.3.0.nupkg.sha512", + "system.threading.thread.nuspec" + ] + }, + "System.Threading.ThreadPool/4.3.0": { + "sha512": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "type": "package", + "path": "system.threading.threadpool/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Threading.ThreadPool.dll", + "lib/netcore50/_._", + "lib/netstandard1.3/System.Threading.ThreadPool.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Threading.ThreadPool.dll", + "ref/netstandard1.3/System.Threading.ThreadPool.dll", + "ref/netstandard1.3/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/de/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/es/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/fr/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/it/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/ja/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/ko/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/ru/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/zh-hans/System.Threading.ThreadPool.xml", + "ref/netstandard1.3/zh-hant/System.Threading.ThreadPool.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.threadpool.4.3.0.nupkg.sha512", + "system.threading.threadpool.nuspec" + ] + }, + "System.Threading.Timer/4.3.0": { + "sha512": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "type": "package", + "path": "system.threading.timer/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net451/_._", + "lib/portable-net451+win81+wpa81/_._", + "lib/win81/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net451/_._", + "ref/netcore50/System.Threading.Timer.dll", + "ref/netcore50/System.Threading.Timer.xml", + "ref/netcore50/de/System.Threading.Timer.xml", + "ref/netcore50/es/System.Threading.Timer.xml", + "ref/netcore50/fr/System.Threading.Timer.xml", + "ref/netcore50/it/System.Threading.Timer.xml", + "ref/netcore50/ja/System.Threading.Timer.xml", + "ref/netcore50/ko/System.Threading.Timer.xml", + "ref/netcore50/ru/System.Threading.Timer.xml", + "ref/netcore50/zh-hans/System.Threading.Timer.xml", + "ref/netcore50/zh-hant/System.Threading.Timer.xml", + "ref/netstandard1.2/System.Threading.Timer.dll", + "ref/netstandard1.2/System.Threading.Timer.xml", + "ref/netstandard1.2/de/System.Threading.Timer.xml", + "ref/netstandard1.2/es/System.Threading.Timer.xml", + "ref/netstandard1.2/fr/System.Threading.Timer.xml", + "ref/netstandard1.2/it/System.Threading.Timer.xml", + "ref/netstandard1.2/ja/System.Threading.Timer.xml", + "ref/netstandard1.2/ko/System.Threading.Timer.xml", + "ref/netstandard1.2/ru/System.Threading.Timer.xml", + "ref/netstandard1.2/zh-hans/System.Threading.Timer.xml", + "ref/netstandard1.2/zh-hant/System.Threading.Timer.xml", + "ref/portable-net451+win81+wpa81/_._", + "ref/win81/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.threading.timer.4.3.0.nupkg.sha512", + "system.threading.timer.nuspec" + ] + }, + "System.ValueTuple/4.5.0": { + "sha512": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==", + "type": "package", + "path": "system.valuetuple/4.5.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "LICENSE.TXT", + "THIRD-PARTY-NOTICES.TXT", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net461/System.ValueTuple.dll", + "lib/net461/System.ValueTuple.xml", + "lib/net47/System.ValueTuple.dll", + "lib/net47/System.ValueTuple.xml", + "lib/netcoreapp2.0/_._", + "lib/netstandard1.0/System.ValueTuple.dll", + "lib/netstandard1.0/System.ValueTuple.xml", + "lib/netstandard2.0/_._", + "lib/portable-net40+sl4+win8+wp8/System.ValueTuple.dll", + "lib/portable-net40+sl4+win8+wp8/System.ValueTuple.xml", + "lib/uap10.0.16299/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net461/System.ValueTuple.dll", + "ref/net47/System.ValueTuple.dll", + "ref/netcoreapp2.0/_._", + "ref/netstandard2.0/_._", + "ref/portable-net40+sl4+win8+wp8/System.ValueTuple.dll", + "ref/uap10.0.16299/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.valuetuple.4.5.0.nupkg.sha512", + "system.valuetuple.nuspec", + "useSharedDesignerContext.txt", + "version.txt" + ] + }, + "System.Xml.ReaderWriter/4.3.0": { + "sha512": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "type": "package", + "path": "system.xml.readerwriter/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/net46/System.Xml.ReaderWriter.dll", + "lib/netcore50/System.Xml.ReaderWriter.dll", + "lib/netstandard1.3/System.Xml.ReaderWriter.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/net46/System.Xml.ReaderWriter.dll", + "ref/netcore50/System.Xml.ReaderWriter.dll", + "ref/netcore50/System.Xml.ReaderWriter.xml", + "ref/netcore50/de/System.Xml.ReaderWriter.xml", + "ref/netcore50/es/System.Xml.ReaderWriter.xml", + "ref/netcore50/fr/System.Xml.ReaderWriter.xml", + "ref/netcore50/it/System.Xml.ReaderWriter.xml", + "ref/netcore50/ja/System.Xml.ReaderWriter.xml", + "ref/netcore50/ko/System.Xml.ReaderWriter.xml", + "ref/netcore50/ru/System.Xml.ReaderWriter.xml", + "ref/netcore50/zh-hans/System.Xml.ReaderWriter.xml", + "ref/netcore50/zh-hant/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/System.Xml.ReaderWriter.dll", + "ref/netstandard1.0/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/de/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/es/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/fr/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/it/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/ja/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/ko/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/ru/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/zh-hans/System.Xml.ReaderWriter.xml", + "ref/netstandard1.0/zh-hant/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/System.Xml.ReaderWriter.dll", + "ref/netstandard1.3/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/de/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/es/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/fr/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/it/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/ja/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/ko/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/ru/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/zh-hans/System.Xml.ReaderWriter.xml", + "ref/netstandard1.3/zh-hant/System.Xml.ReaderWriter.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.xml.readerwriter.4.3.0.nupkg.sha512", + "system.xml.readerwriter.nuspec" + ] + }, + "System.Xml.XDocument/4.3.0": { + "sha512": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "type": "package", + "path": "system.xml.xdocument/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Xml.XDocument.dll", + "lib/netstandard1.3/System.Xml.XDocument.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Xml.XDocument.dll", + "ref/netcore50/System.Xml.XDocument.xml", + "ref/netcore50/de/System.Xml.XDocument.xml", + "ref/netcore50/es/System.Xml.XDocument.xml", + "ref/netcore50/fr/System.Xml.XDocument.xml", + "ref/netcore50/it/System.Xml.XDocument.xml", + "ref/netcore50/ja/System.Xml.XDocument.xml", + "ref/netcore50/ko/System.Xml.XDocument.xml", + "ref/netcore50/ru/System.Xml.XDocument.xml", + "ref/netcore50/zh-hans/System.Xml.XDocument.xml", + "ref/netcore50/zh-hant/System.Xml.XDocument.xml", + "ref/netstandard1.0/System.Xml.XDocument.dll", + "ref/netstandard1.0/System.Xml.XDocument.xml", + "ref/netstandard1.0/de/System.Xml.XDocument.xml", + "ref/netstandard1.0/es/System.Xml.XDocument.xml", + "ref/netstandard1.0/fr/System.Xml.XDocument.xml", + "ref/netstandard1.0/it/System.Xml.XDocument.xml", + "ref/netstandard1.0/ja/System.Xml.XDocument.xml", + "ref/netstandard1.0/ko/System.Xml.XDocument.xml", + "ref/netstandard1.0/ru/System.Xml.XDocument.xml", + "ref/netstandard1.0/zh-hans/System.Xml.XDocument.xml", + "ref/netstandard1.0/zh-hant/System.Xml.XDocument.xml", + "ref/netstandard1.3/System.Xml.XDocument.dll", + "ref/netstandard1.3/System.Xml.XDocument.xml", + "ref/netstandard1.3/de/System.Xml.XDocument.xml", + "ref/netstandard1.3/es/System.Xml.XDocument.xml", + "ref/netstandard1.3/fr/System.Xml.XDocument.xml", + "ref/netstandard1.3/it/System.Xml.XDocument.xml", + "ref/netstandard1.3/ja/System.Xml.XDocument.xml", + "ref/netstandard1.3/ko/System.Xml.XDocument.xml", + "ref/netstandard1.3/ru/System.Xml.XDocument.xml", + "ref/netstandard1.3/zh-hans/System.Xml.XDocument.xml", + "ref/netstandard1.3/zh-hant/System.Xml.XDocument.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.xml.xdocument.4.3.0.nupkg.sha512", + "system.xml.xdocument.nuspec" + ] + }, + "System.Xml.XmlDocument/4.3.0": { + "sha512": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "type": "package", + "path": "system.xml.xmldocument/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Xml.XmlDocument.dll", + "lib/netstandard1.3/System.Xml.XmlDocument.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Xml.XmlDocument.dll", + "ref/netstandard1.3/System.Xml.XmlDocument.dll", + "ref/netstandard1.3/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/de/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/es/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/fr/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/it/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/ja/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/ko/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/ru/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/zh-hans/System.Xml.XmlDocument.xml", + "ref/netstandard1.3/zh-hant/System.Xml.XmlDocument.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.xml.xmldocument.4.3.0.nupkg.sha512", + "system.xml.xmldocument.nuspec" + ] + }, + "System.Xml.XmlSerializer/4.3.0": { + "sha512": "MYoTCP7EZ98RrANESW05J5ZwskKDoN0AuZ06ZflnowE50LTpbR5yRg3tHckTVm5j/m47stuGgCrCHWePyHS70Q==", + "type": "package", + "path": "system.xml.xmlserializer/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net45/_._", + "lib/netcore50/System.Xml.XmlSerializer.dll", + "lib/netstandard1.3/System.Xml.XmlSerializer.dll", + "lib/portable-net45+win8+wp8+wpa81/_._", + "lib/win8/_._", + "lib/wp80/_._", + "lib/wpa81/_._", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net45/_._", + "ref/netcore50/System.Xml.XmlSerializer.dll", + "ref/netcore50/System.Xml.XmlSerializer.xml", + "ref/netcore50/de/System.Xml.XmlSerializer.xml", + "ref/netcore50/es/System.Xml.XmlSerializer.xml", + "ref/netcore50/fr/System.Xml.XmlSerializer.xml", + "ref/netcore50/it/System.Xml.XmlSerializer.xml", + "ref/netcore50/ja/System.Xml.XmlSerializer.xml", + "ref/netcore50/ko/System.Xml.XmlSerializer.xml", + "ref/netcore50/ru/System.Xml.XmlSerializer.xml", + "ref/netcore50/zh-hans/System.Xml.XmlSerializer.xml", + "ref/netcore50/zh-hant/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/System.Xml.XmlSerializer.dll", + "ref/netstandard1.0/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/de/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/es/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/fr/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/it/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/ja/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/ko/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/ru/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/zh-hans/System.Xml.XmlSerializer.xml", + "ref/netstandard1.0/zh-hant/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/System.Xml.XmlSerializer.dll", + "ref/netstandard1.3/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/de/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/es/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/fr/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/it/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/ja/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/ko/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/ru/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/zh-hans/System.Xml.XmlSerializer.xml", + "ref/netstandard1.3/zh-hant/System.Xml.XmlSerializer.xml", + "ref/portable-net45+win8+wp8+wpa81/_._", + "ref/win8/_._", + "ref/wp80/_._", + "ref/wpa81/_._", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "runtimes/aot/lib/netcore50/System.Xml.XmlSerializer.dll", + "system.xml.xmlserializer.4.3.0.nupkg.sha512", + "system.xml.xmlserializer.nuspec" + ] + }, + "System.Xml.XPath/4.3.0": { + "sha512": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "type": "package", + "path": "system.xml.xpath/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Xml.XPath.dll", + "lib/netstandard1.3/System.Xml.XPath.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Xml.XPath.dll", + "ref/netstandard1.3/System.Xml.XPath.dll", + "ref/netstandard1.3/System.Xml.XPath.xml", + "ref/netstandard1.3/de/System.Xml.XPath.xml", + "ref/netstandard1.3/es/System.Xml.XPath.xml", + "ref/netstandard1.3/fr/System.Xml.XPath.xml", + "ref/netstandard1.3/it/System.Xml.XPath.xml", + "ref/netstandard1.3/ja/System.Xml.XPath.xml", + "ref/netstandard1.3/ko/System.Xml.XPath.xml", + "ref/netstandard1.3/ru/System.Xml.XPath.xml", + "ref/netstandard1.3/zh-hans/System.Xml.XPath.xml", + "ref/netstandard1.3/zh-hant/System.Xml.XPath.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.xml.xpath.4.3.0.nupkg.sha512", + "system.xml.xpath.nuspec" + ] + }, + "System.Xml.XPath.XDocument/4.3.0": { + "sha512": "jw9oHHEIVW53mHY9PgrQa98Xo2IZ0ZjrpdOTmtvk+Rvg4tq7dydmxdNqUvJ5YwjDqhn75mBXWttWjiKhWP53LQ==", + "type": "package", + "path": "system.xml.xpath.xdocument/4.3.0", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "ThirdPartyNotices.txt", + "dotnet_library_license.txt", + "lib/MonoAndroid10/_._", + "lib/MonoTouch10/_._", + "lib/net46/System.Xml.XPath.XDocument.dll", + "lib/netstandard1.3/System.Xml.XPath.XDocument.dll", + "lib/xamarinios10/_._", + "lib/xamarinmac20/_._", + "lib/xamarintvos10/_._", + "lib/xamarinwatchos10/_._", + "ref/MonoAndroid10/_._", + "ref/MonoTouch10/_._", + "ref/net46/System.Xml.XPath.XDocument.dll", + "ref/netstandard1.3/System.Xml.XPath.XDocument.dll", + "ref/netstandard1.3/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/de/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/es/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/fr/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/it/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/ja/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/ko/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/ru/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/zh-hans/System.Xml.XPath.XDocument.xml", + "ref/netstandard1.3/zh-hant/System.Xml.XPath.XDocument.xml", + "ref/xamarinios10/_._", + "ref/xamarinmac20/_._", + "ref/xamarintvos10/_._", + "ref/xamarinwatchos10/_._", + "system.xml.xpath.xdocument.4.3.0.nupkg.sha512", + "system.xml.xpath.xdocument.nuspec" + ] + }, + "WindowsAzure.Storage/8.1.4": { + "sha512": "W6ZZ0/o7+3Qb77mRAQyLjPudHG3OMeeQ4p9yY13PUdJArmRCx2cLMm5F4tpIjJXxzHC0ew0oK7DMDGILMdfCnw==", + "type": "package", + "path": "windowsazure.storage/8.1.4", + "files": [ + ".nupkg.metadata", + ".signature.p7s", + "lib/net45/Microsoft.WindowsAzure.Storage.dll", + "lib/net45/Microsoft.WindowsAzure.Storage.pdb", + "lib/net45/Microsoft.WindowsAzure.Storage.xml", + "lib/netstandard1.0/Microsoft.WindowsAzure.Storage.dll", + "lib/netstandard1.0/Microsoft.WindowsAzure.Storage.pdb", + "lib/netstandard1.3/Microsoft.WindowsAzure.Storage.dll", + "lib/netstandard1.3/Microsoft.WindowsAzure.Storage.pdb", + "lib/win8/Microsoft.WindowsAzure.Storage.dll", + "lib/win8/Microsoft.WindowsAzure.Storage.pdb", + "lib/wp8/Microsoft.WindowsAzure.Storage.dll", + "lib/wp8/Microsoft.WindowsAzure.Storage.pdb", + "lib/wpa/Microsoft.WindowsAzure.Storage.dll", + "lib/wpa/Microsoft.WindowsAzure.Storage.pdb", + "windowsazure.storage.8.1.4.nupkg.sha512", + "windowsazure.storage.nuspec" + ] + }, + "FSO.Common/1.0.0": { + "type": "project", + "path": "../tso.common/FSO.Common.csproj", + "msbuildProject": "../tso.common/FSO.Common.csproj" + }, + "FSO.Server.Common/1.0.0": { + "type": "project", + "path": "../FSO.Server.Common/FSO.Server.Common.csproj", + "msbuildProject": "../FSO.Server.Common/FSO.Server.Common.csproj" + }, + "FSO.Server.Database/1.0.0": { + "type": "project", + "path": "../FSO.Server.Database/FSO.Server.Database.csproj", + "msbuildProject": "../FSO.Server.Database/FSO.Server.Database.csproj" + }, + "FSO.Server.Domain/1.0.0": { + "type": "project", + "path": "../FSO.Server.Domain/FSO.Server.Domain.csproj", + "msbuildProject": "../FSO.Server.Domain/FSO.Server.Domain.csproj" + }, + "FSO.Server.Protocol/1.0.0": { + "type": "project", + "path": "../FSO.Server.Protocol/FSO.Server.Protocol.csproj", + "msbuildProject": "../FSO.Server.Protocol/FSO.Server.Protocol.csproj" + } + }, + "projectFileDependencyGroups": { + ".NETCoreApp,Version=v2.2": [ + "AWSSDK.Core >= 3.3.103.48", + "AWSSDK.S3 >= 3.3.104.36", + "FSO.Common >= 1.0.0", + "FSO.Server.Common >= 1.0.0", + "FSO.Server.Database >= 1.0.0", + "FSO.Server.Domain >= 1.0.0", + "FSO.Server.Protocol >= 1.0.0", + "Microsoft.AspNetCore.All >= 2.2.7", + "Microsoft.AspNetCore.App >= 2.2.8", + "Microsoft.AspNetCore.Cors >= 2.2.0", + "Microsoft.NETCore.App >= 2.2.8", + "Octokit >= 0.36.0", + "System.Security.Cryptography.Algorithms >= 4.3.1" + ] + }, + "packageFolders": { + "/Volumes/TheD/.nuget": {} + }, + "project": { + "version": "1.0.0", + "restore": { + "projectUniqueName": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj", + "projectName": "FSO.Server.Api.Core", + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj", + "packagesPath": "/Volumes/TheD/.nuget", + "outputPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/obj/", + "projectStyle": "PackageReference", + "configFilePaths": [ + "/Users/tonytins/.nuget/NuGet/NuGet.Config" + ], + "originalTargetFrameworks": [ + "netcoreapp2.2" + ], + "sources": { + "/Volumes/TheD/.dotnet/library-packs": {}, + "https://api.nuget.org/v3/index.json": {} + }, + "frameworks": { + "netcoreapp2.2": { + "targetAlias": "netcoreapp2.2", + "projectReferences": { + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Common/FSO.Server.Common.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Database/FSO.Server.Database.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Domain/FSO.Server.Domain.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj" + }, + "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj": { + "projectPath": "/Volumes/TheD/Projects/ztso/server/tso.common/FSO.Common.csproj" + } + } + } + }, + "warningProperties": { + "warnAsError": [ + "NU1605" + ] + }, + "restoreAuditProperties": { + "enableAudit": "true", + "auditLevel": "low", + "auditMode": "direct" + } + }, + "frameworks": { + "netcoreapp2.2": { + "targetAlias": "netcoreapp2.2", + "dependencies": { + "AWSSDK.Core": { + "target": "Package", + "version": "[3.3.103.48, )" + }, + "AWSSDK.S3": { + "target": "Package", + "version": "[3.3.104.36, )" + }, + "Microsoft.AspNetCore.All": { + "target": "Package", + "version": "[2.2.7, )" + }, + "Microsoft.AspNetCore.App": { + "suppressParent": "All", + "target": "Package", + "version": "[2.2.8, )", + "autoReferenced": true + }, + "Microsoft.AspNetCore.Cors": { + "target": "Package", + "version": "[2.2.0, )" + }, + "Microsoft.NETCore.App": { + "suppressParent": "All", + "target": "Package", + "version": "[2.2.8, )", + "autoReferenced": true + }, + "Octokit": { + "target": "Package", + "version": "[0.36.0, )" + }, + "System.Security.Cryptography.Algorithms": { + "target": "Package", + "version": "[4.3.1, )" + } + }, + "imports": [ + "net461", + "net462", + "net47", + "net471", + "net472", + "net48", + "net481" + ], + "assetTargetFallback": true, + "warn": true, + "runtimeIdentifierGraphPath": "/Volumes/TheD/.dotnet/sdk/8.0.204/RuntimeIdentifierGraph.json" + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Api.Core/obj/project.nuget.cache b/server/FSO.Server.Api.Core/obj/project.nuget.cache new file mode 100644 index 0000000..99bb084 --- /dev/null +++ b/server/FSO.Server.Api.Core/obj/project.nuget.cache @@ -0,0 +1,343 @@ +{ + "version": 2, + "dgSpecHash": "O9uTcc8ul7R5Oy7wU0RviTvK+nfjiri5q/zad3hfpvfdHyjPko5E7PeIbBSDiQiPyuONvNRmcuzEhHPbXoSo6Q==", + "success": true, + "projectFilePath": "/Volumes/TheD/Projects/ztso/server/FSO.Server.Api.Core/FSO.Server.Api.Core.csproj", + "expectedPackageFiles": [ + "/Volumes/TheD/.nuget/awssdk.core/3.3.103.48/awssdk.core.3.3.103.48.nupkg.sha512", + "/Volumes/TheD/.nuget/awssdk.s3/3.3.104.36/awssdk.s3.3.3.104.36.nupkg.sha512", + "/Volumes/TheD/.nuget/libuv/1.10.0/libuv.1.10.0.nupkg.sha512", + "/Volumes/TheD/.nuget/messagepack/1.7.3.7/messagepack.1.7.3.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.applicationinsights/2.4.0/microsoft.applicationinsights.2.4.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.applicationinsights.aspnetcore/2.1.1/microsoft.applicationinsights.aspnetcore.2.1.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.applicationinsights.dependencycollector/2.4.1/microsoft.applicationinsights.dependencycollector.2.4.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnet.webapi.client/5.2.6/microsoft.aspnet.webapi.client.5.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore/2.2.0/microsoft.aspnetcore.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.all/2.2.7/microsoft.aspnetcore.all.2.2.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.antiforgery/2.2.0/microsoft.aspnetcore.antiforgery.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.app/2.2.8/microsoft.aspnetcore.app.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.applicationinsights.hostingstartup/2.2.0/microsoft.aspnetcore.applicationinsights.hostingstartup.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication/2.2.0/microsoft.aspnetcore.authentication.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.abstractions/2.2.0/microsoft.aspnetcore.authentication.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.cookies/2.2.0/microsoft.aspnetcore.authentication.cookies.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.core/2.2.0/microsoft.aspnetcore.authentication.core.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.facebook/2.2.0/microsoft.aspnetcore.authentication.facebook.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.google/2.2.2/microsoft.aspnetcore.authentication.google.2.2.2.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.jwtbearer/2.2.0/microsoft.aspnetcore.authentication.jwtbearer.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.microsoftaccount/2.2.0/microsoft.aspnetcore.authentication.microsoftaccount.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.oauth/2.2.0/microsoft.aspnetcore.authentication.oauth.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.openidconnect/2.2.0/microsoft.aspnetcore.authentication.openidconnect.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.twitter/2.2.0/microsoft.aspnetcore.authentication.twitter.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authentication.wsfederation/2.2.0/microsoft.aspnetcore.authentication.wsfederation.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authorization/2.2.0/microsoft.aspnetcore.authorization.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.authorization.policy/2.2.0/microsoft.aspnetcore.authorization.policy.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.azureappservices.hostingstartup/2.2.5/microsoft.aspnetcore.azureappservices.hostingstartup.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.azureappservicesintegration/2.2.5/microsoft.aspnetcore.azureappservicesintegration.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.connections.abstractions/2.2.0/microsoft.aspnetcore.connections.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.cookiepolicy/2.2.8/microsoft.aspnetcore.cookiepolicy.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.cors/2.2.0/microsoft.aspnetcore.cors.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.cryptography.internal/2.2.0/microsoft.aspnetcore.cryptography.internal.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.cryptography.keyderivation/2.2.0/microsoft.aspnetcore.cryptography.keyderivation.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.dataprotection/2.2.0/microsoft.aspnetcore.dataprotection.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.dataprotection.abstractions/2.2.0/microsoft.aspnetcore.dataprotection.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.dataprotection.azurekeyvault/2.2.0/microsoft.aspnetcore.dataprotection.azurekeyvault.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.dataprotection.azurestorage/2.2.7/microsoft.aspnetcore.dataprotection.azurestorage.2.2.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.dataprotection.extensions/2.2.0/microsoft.aspnetcore.dataprotection.extensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.diagnostics/2.2.0/microsoft.aspnetcore.diagnostics.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.diagnostics.abstractions/2.2.0/microsoft.aspnetcore.diagnostics.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.diagnostics.entityframeworkcore/2.2.1/microsoft.aspnetcore.diagnostics.entityframeworkcore.2.2.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.diagnostics.healthchecks/2.2.0/microsoft.aspnetcore.diagnostics.healthchecks.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.hostfiltering/2.2.0/microsoft.aspnetcore.hostfiltering.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.hosting/2.2.7/microsoft.aspnetcore.hosting.2.2.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.hosting.abstractions/2.2.0/microsoft.aspnetcore.hosting.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.hosting.server.abstractions/2.2.0/microsoft.aspnetcore.hosting.server.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.html.abstractions/2.2.0/microsoft.aspnetcore.html.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http/2.2.2/microsoft.aspnetcore.http.2.2.2.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http.abstractions/2.2.0/microsoft.aspnetcore.http.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http.connections/1.1.0/microsoft.aspnetcore.http.connections.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http.connections.common/1.1.0/microsoft.aspnetcore.http.connections.common.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http.extensions/2.2.0/microsoft.aspnetcore.http.extensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.http.features/2.2.0/microsoft.aspnetcore.http.features.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.httpoverrides/2.2.0/microsoft.aspnetcore.httpoverrides.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.httpspolicy/2.2.0/microsoft.aspnetcore.httpspolicy.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.identity/2.2.0/microsoft.aspnetcore.identity.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.identity.entityframeworkcore/2.2.0/microsoft.aspnetcore.identity.entityframeworkcore.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.identity.ui/2.2.5/microsoft.aspnetcore.identity.ui.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.jsonpatch/2.2.0/microsoft.aspnetcore.jsonpatch.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.localization/2.2.0/microsoft.aspnetcore.localization.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.localization.routing/2.2.0/microsoft.aspnetcore.localization.routing.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.middlewareanalysis/2.2.0/microsoft.aspnetcore.middlewareanalysis.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc/2.2.0/microsoft.aspnetcore.mvc.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.abstractions/2.2.0/microsoft.aspnetcore.mvc.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.analyzers/2.2.0/microsoft.aspnetcore.mvc.analyzers.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.apiexplorer/2.2.0/microsoft.aspnetcore.mvc.apiexplorer.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.core/2.2.5/microsoft.aspnetcore.mvc.core.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.cors/2.2.0/microsoft.aspnetcore.mvc.cors.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.dataannotations/2.2.0/microsoft.aspnetcore.mvc.dataannotations.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.formatters.json/2.2.0/microsoft.aspnetcore.mvc.formatters.json.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.formatters.xml/2.2.0/microsoft.aspnetcore.mvc.formatters.xml.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.localization/2.2.0/microsoft.aspnetcore.mvc.localization.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.razor/2.2.0/microsoft.aspnetcore.mvc.razor.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.razor.extensions/2.2.0/microsoft.aspnetcore.mvc.razor.extensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.razor.viewcompilation/2.2.0/microsoft.aspnetcore.mvc.razor.viewcompilation.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.razorpages/2.2.5/microsoft.aspnetcore.mvc.razorpages.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.taghelpers/2.2.0/microsoft.aspnetcore.mvc.taghelpers.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.mvc.viewfeatures/2.2.0/microsoft.aspnetcore.mvc.viewfeatures.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.nodeservices/2.2.0/microsoft.aspnetcore.nodeservices.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.owin/2.2.0/microsoft.aspnetcore.owin.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.razor/2.2.0/microsoft.aspnetcore.razor.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.razor.design/2.2.0/microsoft.aspnetcore.razor.design.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.razor.language/2.2.0/microsoft.aspnetcore.razor.language.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.razor.runtime/2.2.0/microsoft.aspnetcore.razor.runtime.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.responsecaching/2.2.0/microsoft.aspnetcore.responsecaching.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.responsecaching.abstractions/2.2.0/microsoft.aspnetcore.responsecaching.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.responsecompression/2.2.0/microsoft.aspnetcore.responsecompression.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.rewrite/2.2.0/microsoft.aspnetcore.rewrite.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.routing/2.2.2/microsoft.aspnetcore.routing.2.2.2.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.routing.abstractions/2.2.0/microsoft.aspnetcore.routing.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.httpsys/2.2.6/microsoft.aspnetcore.server.httpsys.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.iis/2.2.6/microsoft.aspnetcore.server.iis.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.iisintegration/2.2.1/microsoft.aspnetcore.server.iisintegration.2.2.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel/2.2.0/microsoft.aspnetcore.server.kestrel.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel.core/2.2.0/microsoft.aspnetcore.server.kestrel.core.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel.https/2.2.0/microsoft.aspnetcore.server.kestrel.https.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel.transport.abstractions/2.2.0/microsoft.aspnetcore.server.kestrel.transport.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel.transport.libuv/2.2.0/microsoft.aspnetcore.server.kestrel.transport.libuv.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.server.kestrel.transport.sockets/2.2.1/microsoft.aspnetcore.server.kestrel.transport.sockets.2.2.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.session/2.2.0/microsoft.aspnetcore.session.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.signalr/1.1.0/microsoft.aspnetcore.signalr.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.signalr.common/1.1.0/microsoft.aspnetcore.signalr.common.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.signalr.core/1.1.0/microsoft.aspnetcore.signalr.core.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.signalr.protocols.json/1.1.0/microsoft.aspnetcore.signalr.protocols.json.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.signalr.redis/1.1.5/microsoft.aspnetcore.signalr.redis.1.1.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.spaservices/2.2.7/microsoft.aspnetcore.spaservices.2.2.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.spaservices.extensions/2.2.0/microsoft.aspnetcore.spaservices.extensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.staticfiles/2.2.0/microsoft.aspnetcore.staticfiles.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.websockets/2.2.1/microsoft.aspnetcore.websockets.2.2.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.aspnetcore.webutilities/2.2.0/microsoft.aspnetcore.webutilities.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.azure.keyvault/2.3.2/microsoft.azure.keyvault.2.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.azure.keyvault.webkey/2.0.7/microsoft.azure.keyvault.webkey.2.0.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.azure.services.appauthentication/1.0.1/microsoft.azure.services.appauthentication.1.0.1.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.codeanalysis.analyzers/1.1.0/microsoft.codeanalysis.analyzers.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.codeanalysis.common/2.8.0/microsoft.codeanalysis.common.2.8.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.codeanalysis.csharp/2.8.0/microsoft.codeanalysis.csharp.2.8.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.codeanalysis.razor/2.2.0/microsoft.codeanalysis.razor.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.csharp/4.5.0/microsoft.csharp.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.data.edm/5.8.4/microsoft.data.edm.5.8.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.data.odata/5.8.4/microsoft.data.odata.5.8.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.data.sqlite/2.2.6/microsoft.data.sqlite.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.data.sqlite.core/2.2.6/microsoft.data.sqlite.core.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.dotnet.platformabstractions/2.1.0/microsoft.dotnet.platformabstractions.2.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore/2.2.6/microsoft.entityframeworkcore.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.abstractions/2.2.6/microsoft.entityframeworkcore.abstractions.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.analyzers/2.2.6/microsoft.entityframeworkcore.analyzers.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.design/2.2.6/microsoft.entityframeworkcore.design.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.inmemory/2.2.6/microsoft.entityframeworkcore.inmemory.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.relational/2.2.6/microsoft.entityframeworkcore.relational.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.sqlite/2.2.6/microsoft.entityframeworkcore.sqlite.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.sqlite.core/2.2.6/microsoft.entityframeworkcore.sqlite.core.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.sqlserver/2.2.6/microsoft.entityframeworkcore.sqlserver.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.entityframeworkcore.tools/2.2.6/microsoft.entityframeworkcore.tools.2.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.caching.abstractions/2.2.0/microsoft.extensions.caching.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.caching.memory/2.2.0/microsoft.extensions.caching.memory.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.caching.redis/2.2.0/microsoft.extensions.caching.redis.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.caching.sqlserver/2.2.0/microsoft.extensions.caching.sqlserver.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration/2.2.0/microsoft.extensions.configuration.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.abstractions/2.2.0/microsoft.extensions.configuration.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.azurekeyvault/2.2.0/microsoft.extensions.configuration.azurekeyvault.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.binder/2.2.4/microsoft.extensions.configuration.binder.2.2.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.commandline/2.2.0/microsoft.extensions.configuration.commandline.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.environmentvariables/2.2.4/microsoft.extensions.configuration.environmentvariables.2.2.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.fileextensions/2.2.0/microsoft.extensions.configuration.fileextensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.ini/2.2.0/microsoft.extensions.configuration.ini.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.json/2.2.0/microsoft.extensions.configuration.json.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.keyperfile/2.2.4/microsoft.extensions.configuration.keyperfile.2.2.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.usersecrets/2.2.0/microsoft.extensions.configuration.usersecrets.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.configuration.xml/2.2.0/microsoft.extensions.configuration.xml.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.dependencyinjection/2.2.0/microsoft.extensions.dependencyinjection.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.dependencyinjection.abstractions/2.2.0/microsoft.extensions.dependencyinjection.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.dependencymodel/2.1.0/microsoft.extensions.dependencymodel.2.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.diagnosticadapter/2.2.0/microsoft.extensions.diagnosticadapter.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.diagnostics.healthchecks/2.2.5/microsoft.extensions.diagnostics.healthchecks.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.diagnostics.healthchecks.abstractions/2.2.0/microsoft.extensions.diagnostics.healthchecks.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.fileproviders.abstractions/2.2.0/microsoft.extensions.fileproviders.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.fileproviders.composite/2.2.0/microsoft.extensions.fileproviders.composite.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.fileproviders.embedded/2.2.0/microsoft.extensions.fileproviders.embedded.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.fileproviders.physical/2.2.0/microsoft.extensions.fileproviders.physical.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.filesystemglobbing/2.2.0/microsoft.extensions.filesystemglobbing.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.hosting/2.2.0/microsoft.extensions.hosting.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.hosting.abstractions/2.2.0/microsoft.extensions.hosting.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.http/2.2.0/microsoft.extensions.http.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.identity.core/2.2.0/microsoft.extensions.identity.core.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.identity.stores/2.2.0/microsoft.extensions.identity.stores.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.localization/2.2.0/microsoft.extensions.localization.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.localization.abstractions/2.2.0/microsoft.extensions.localization.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging/2.2.0/microsoft.extensions.logging.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.abstractions/2.2.0/microsoft.extensions.logging.abstractions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.azureappservices/2.2.5/microsoft.extensions.logging.azureappservices.2.2.5.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.configuration/2.2.0/microsoft.extensions.logging.configuration.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.console/2.2.0/microsoft.extensions.logging.console.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.debug/2.2.0/microsoft.extensions.logging.debug.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.eventsource/2.2.0/microsoft.extensions.logging.eventsource.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.logging.tracesource/2.2.0/microsoft.extensions.logging.tracesource.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.objectpool/2.2.0/microsoft.extensions.objectpool.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.options/2.2.0/microsoft.extensions.options.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.options.configurationextensions/2.2.0/microsoft.extensions.options.configurationextensions.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.options.dataannotations/2.2.0/microsoft.extensions.options.dataannotations.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.platformabstractions/1.1.0/microsoft.extensions.platformabstractions.1.1.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.primitives/2.2.0/microsoft.extensions.primitives.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.extensions.webencoders/2.2.0/microsoft.extensions.webencoders.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.clients.activedirectory/3.19.8/microsoft.identitymodel.clients.activedirectory.3.19.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.jsonwebtokens/5.3.0/microsoft.identitymodel.jsonwebtokens.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.logging/5.3.0/microsoft.identitymodel.logging.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.protocols/5.3.0/microsoft.identitymodel.protocols.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.protocols.openidconnect/5.3.0/microsoft.identitymodel.protocols.openidconnect.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.protocols.wsfederation/5.3.0/microsoft.identitymodel.protocols.wsfederation.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.tokens/5.3.0/microsoft.identitymodel.tokens.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.tokens.saml/5.3.0/microsoft.identitymodel.tokens.saml.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.identitymodel.xml/5.3.0/microsoft.identitymodel.xml.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.net.http.headers/2.2.8/microsoft.net.http.headers.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.app/2.2.8/microsoft.netcore.app.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.dotnetapphost/2.2.8/microsoft.netcore.dotnetapphost.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.dotnethostpolicy/2.2.8/microsoft.netcore.dotnethostpolicy.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.dotnethostresolver/2.2.8/microsoft.netcore.dotnethostresolver.2.2.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.platforms/2.2.4/microsoft.netcore.platforms.2.2.4.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.netcore.targets/2.0.0/microsoft.netcore.targets.2.0.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.rest.clientruntime/2.3.8/microsoft.rest.clientruntime.2.3.8.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.rest.clientruntime.azure/3.3.7/microsoft.rest.clientruntime.azure.3.3.7.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.visualstudio.web.browserlink/2.2.0/microsoft.visualstudio.web.browserlink.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.win32.primitives/4.3.0/microsoft.win32.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/microsoft.win32.registry/4.5.0/microsoft.win32.registry.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/netstandard.library/2.0.3/netstandard.library.2.0.3.nupkg.sha512", + "/Volumes/TheD/.nuget/newtonsoft.json/11.0.2/newtonsoft.json.11.0.2.nupkg.sha512", + "/Volumes/TheD/.nuget/newtonsoft.json.bson/1.0.1/newtonsoft.json.bson.1.0.1.nupkg.sha512", + "/Volumes/TheD/.nuget/octokit/0.36.0/octokit.0.36.0.nupkg.sha512", + "/Volumes/TheD/.nuget/remotion.linq/2.2.0/remotion.linq.2.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.debian.8-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.fedora.23-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.fedora.24-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system/4.3.0/runtime.native.system.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.data.sqlclient.sni/4.5.0/runtime.native.system.data.sqlclient.sni.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.io.compression/4.3.0/runtime.native.system.io.compression.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.net.http/4.3.0/runtime.native.system.net.http.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.net.security/4.3.0/runtime.native.system.net.security.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.security.cryptography.apple/4.3.1/runtime.native.system.security.cryptography.apple.4.3.1.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.native.system.security.cryptography.openssl/4.3.2/runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.opensuse.13.2-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.opensuse.42.1-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple/4.3.1/runtime.osx.10.10-x64.runtime.native.system.security.cryptography.apple.4.3.1.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.osx.10.10-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.rhel.7-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.ubuntu.14.04-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.ubuntu.16.04-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl/4.3.2/runtime.ubuntu.16.10-x64.runtime.native.system.security.cryptography.openssl.4.3.2.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.win-arm64.runtime.native.system.data.sqlclient.sni/4.4.0/runtime.win-arm64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.win-x64.runtime.native.system.data.sqlclient.sni/4.4.0/runtime.win-x64.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "/Volumes/TheD/.nuget/runtime.win-x86.runtime.native.system.data.sqlclient.sni/4.4.0/runtime.win-x86.runtime.native.system.data.sqlclient.sni.4.4.0.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.bundle_green/1.1.12/sqlitepclraw.bundle_green.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.core/1.1.12/sqlitepclraw.core.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.lib.e_sqlite3.linux/1.1.12/sqlitepclraw.lib.e_sqlite3.linux.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.lib.e_sqlite3.osx/1.1.12/sqlitepclraw.lib.e_sqlite3.osx.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.lib.e_sqlite3.v110_xp/1.1.12/sqlitepclraw.lib.e_sqlite3.v110_xp.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/sqlitepclraw.provider.e_sqlite3.netstandard11/1.1.12/sqlitepclraw.provider.e_sqlite3.netstandard11.1.1.12.nupkg.sha512", + "/Volumes/TheD/.nuget/stackexchange.redis.strongname/1.2.6/stackexchange.redis.strongname.1.2.6.nupkg.sha512", + "/Volumes/TheD/.nuget/system.appcontext/4.3.0/system.appcontext.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.buffers/4.5.0/system.buffers.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.collections/4.3.0/system.collections.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.collections.concurrent/4.3.0/system.collections.concurrent.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.collections.immutable/1.5.0/system.collections.immutable.1.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.collections.nongeneric/4.3.0/system.collections.nongeneric.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.collections.specialized/4.3.0/system.collections.specialized.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.componentmodel.annotations/4.5.0/system.componentmodel.annotations.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.console/4.3.0/system.console.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.data.sqlclient/4.6.1/system.data.sqlclient.4.6.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.contracts/4.3.0/system.diagnostics.contracts.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.debug/4.3.0/system.diagnostics.debug.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.diagnosticsource/4.5.1/system.diagnostics.diagnosticsource.4.5.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.fileversioninfo/4.3.0/system.diagnostics.fileversioninfo.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.process/4.3.0/system.diagnostics.process.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.stacktrace/4.3.0/system.diagnostics.stacktrace.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.tools/4.3.0/system.diagnostics.tools.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.diagnostics.tracing/4.3.0/system.diagnostics.tracing.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.dynamic.runtime/4.3.0/system.dynamic.runtime.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.globalization/4.3.0/system.globalization.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.globalization.calendars/4.3.0/system.globalization.calendars.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.globalization.extensions/4.3.0/system.globalization.extensions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.identitymodel.tokens.jwt/5.3.0/system.identitymodel.tokens.jwt.5.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.interactive.async/3.2.0/system.interactive.async.3.2.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.io/4.3.0/system.io.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.io.compression/4.3.0/system.io.compression.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.io.filesystem/4.3.0/system.io.filesystem.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.io.filesystem.primitives/4.3.0/system.io.filesystem.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.io.pipelines/4.5.3/system.io.pipelines.4.5.3.nupkg.sha512", + "/Volumes/TheD/.nuget/system.linq/4.3.0/system.linq.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.linq.expressions/4.3.0/system.linq.expressions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.linq.queryable/4.0.1/system.linq.queryable.4.0.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.memory/4.5.1/system.memory.4.5.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.http/4.3.0/system.net.http.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.nameresolution/4.3.0/system.net.nameresolution.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.primitives/4.3.0/system.net.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.security/4.3.0/system.net.security.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.sockets/4.3.0/system.net.sockets.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.net.websockets.websocketprotocol/4.5.3/system.net.websockets.websocketprotocol.4.5.3.nupkg.sha512", + "/Volumes/TheD/.nuget/system.numerics.vectors/4.5.0/system.numerics.vectors.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.objectmodel/4.3.0/system.objectmodel.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.private.datacontractserialization/4.3.0/system.private.datacontractserialization.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection/4.3.0/system.reflection.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.emit/4.3.0/system.reflection.emit.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.emit.ilgeneration/4.3.0/system.reflection.emit.ilgeneration.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.emit.lightweight/4.3.0/system.reflection.emit.lightweight.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.extensions/4.3.0/system.reflection.extensions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.metadata/1.6.0/system.reflection.metadata.1.6.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.primitives/4.3.0/system.reflection.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.reflection.typeextensions/4.3.0/system.reflection.typeextensions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.resources.resourcemanager/4.3.0/system.resources.resourcemanager.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime/4.3.0/system.runtime.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.compilerservices.unsafe/4.5.1/system.runtime.compilerservices.unsafe.4.5.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.extensions/4.3.0/system.runtime.extensions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.handles/4.3.0/system.runtime.handles.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.interopservices/4.3.0/system.runtime.interopservices.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.interopservices.runtimeinformation/4.3.0/system.runtime.interopservices.runtimeinformation.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.numerics/4.3.0/system.runtime.numerics.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.serialization.json/4.3.0/system.runtime.serialization.json.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.serialization.primitives/4.3.0/system.runtime.serialization.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.runtime.serialization.xml/4.3.0/system.runtime.serialization.xml.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.accesscontrol/4.5.0/system.security.accesscontrol.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.claims/4.3.0/system.security.claims.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.algorithms/4.3.1/system.security.cryptography.algorithms.4.3.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.cng/4.5.0/system.security.cryptography.cng.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.csp/4.3.0/system.security.cryptography.csp.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.encoding/4.3.0/system.security.cryptography.encoding.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.openssl/4.3.0/system.security.cryptography.openssl.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.pkcs/4.5.0/system.security.cryptography.pkcs.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.primitives/4.3.0/system.security.cryptography.primitives.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.x509certificates/4.3.0/system.security.cryptography.x509certificates.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.cryptography.xml/4.5.0/system.security.cryptography.xml.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.permissions/4.5.0/system.security.permissions.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.principal/4.3.0/system.security.principal.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.security.principal.windows/4.5.0/system.security.principal.windows.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.spatial/5.8.4/system.spatial.5.8.4.nupkg.sha512", + "/Volumes/TheD/.nuget/system.text.encoding/4.3.0/system.text.encoding.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.text.encoding.codepages/4.5.0/system.text.encoding.codepages.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.text.encoding.extensions/4.3.0/system.text.encoding.extensions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.text.encodings.web/4.5.0/system.text.encodings.web.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.text.regularexpressions/4.3.0/system.text.regularexpressions.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading/4.3.0/system.threading.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.channels/4.5.0/system.threading.channels.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.tasks/4.3.0/system.threading.tasks.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.tasks.extensions/4.5.1/system.threading.tasks.extensions.4.5.1.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.tasks.parallel/4.3.0/system.threading.tasks.parallel.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.thread/4.3.0/system.threading.thread.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.threadpool/4.3.0/system.threading.threadpool.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.threading.timer/4.3.0/system.threading.timer.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.valuetuple/4.5.0/system.valuetuple.4.5.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.readerwriter/4.3.0/system.xml.readerwriter.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.xdocument/4.3.0/system.xml.xdocument.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.xmldocument/4.3.0/system.xml.xmldocument.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.xmlserializer/4.3.0/system.xml.xmlserializer.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.xpath/4.3.0/system.xml.xpath.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/system.xml.xpath.xdocument/4.3.0/system.xml.xpath.xdocument.4.3.0.nupkg.sha512", + "/Volumes/TheD/.nuget/windowsazure.storage/8.1.4/windowsazure.storage.8.1.4.nupkg.sha512" + ], + "logs": [] +} \ No newline at end of file diff --git a/server/FSO.Server.Common/ApiAbstract.cs b/server/FSO.Server.Common/ApiAbstract.cs new file mode 100755 index 0000000..098569f --- /dev/null +++ b/server/FSO.Server.Common/ApiAbstract.cs @@ -0,0 +1,46 @@ +namespace FSO.Server.Common +{ + public class ApiAbstract + { + public event APIRequestShutdownDelegate OnRequestShutdown; + public event APIBroadcastMessageDelegate OnBroadcastMessage; + public event APIRequestUserDisconnectDelegate OnRequestUserDisconnect; + public event APIRequestMailNotifyDelegate OnRequestMailNotify; + + public delegate void APIRequestShutdownDelegate(uint time, ShutdownType type); + public delegate void APIBroadcastMessageDelegate(string sender, string title, string message); + public delegate void APIRequestUserDisconnectDelegate(uint user_id); + public delegate void APIRequestMailNotifyDelegate(int message_id, string subject, string body, uint target_id); + + public void RequestShutdown(uint time, ShutdownType type) + { + OnRequestShutdown?.Invoke(time, type); + } + + /// + /// Asks the server to disconnect a user. + /// + /// + public void RequestUserDisconnect(uint user_id) + { + OnRequestUserDisconnect?.Invoke(user_id); + } + + /// + /// Asks the server to notify the client about the new message. + /// + /// + /// + /// + /// + public void RequestMailNotify(int message_id, string subject, string body, uint target_id) + { + OnRequestMailNotify(message_id, subject, body, target_id); + } + + public void BroadcastMessage(string sender, string title, string message) + { + OnBroadcastMessage?.Invoke(sender, title, message); + } + } +} diff --git a/server/FSO.Server.Common/Config/AWSConfig.cs b/server/FSO.Server.Common/Config/AWSConfig.cs new file mode 100755 index 0000000..ebd5343 --- /dev/null +++ b/server/FSO.Server.Common/Config/AWSConfig.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Common.Config +{ + public class AWSConfig + { + public string Region { get; set; } = "eu-west-2"; + public string Bucket { get; set; } = "fso-updates"; + public string AccessKeyID { get; set; } + public string SecretAccessKey { get; set; } + } +} diff --git a/server/FSO.Server.Common/Config/GithubConfig.cs b/server/FSO.Server.Common/Config/GithubConfig.cs new file mode 100755 index 0000000..965c062 --- /dev/null +++ b/server/FSO.Server.Common/Config/GithubConfig.cs @@ -0,0 +1,16 @@ +namespace FSO.Server.Common.Config +{ + public class GithubConfig + { + public string AppName { get; set; } = "FreeSO"; + public string User { get; set; } = "riperiperi"; + public string Repository { get; set; } = "FreeSO"; + public string ClientID { get; set; } + public string ClientSecret { get; set; } + + /// + /// Must be generated by installing the app on your user account. Browse to the /github/ API endpoint when this is null. (yes, on this server) + /// + public string AccessToken { get; set; } + } +} diff --git a/server/FSO.Server.Common/Epoch.cs b/server/FSO.Server.Common/Epoch.cs new file mode 100755 index 0000000..14141c1 --- /dev/null +++ b/server/FSO.Server.Common/Epoch.cs @@ -0,0 +1,39 @@ +using System; + +namespace FSO.Server.Common +{ + public class Epoch + { + public static uint Now + { + get + { + uint epoch = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + return epoch; + } + } + + public static uint FromDate(DateTime time) + { + return (uint)(time.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds; + } + + public static DateTime ToDate(uint time) + { + var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + return epoch.AddSeconds(time); + } + + public static string HMSRemaining(uint date) + { + TimeSpan span = (ToDate(date) - ToDate(Epoch.Now)); + + return String.Format("{0} hours, {1} minutes and {2} seconds", span.Hours, span.Minutes, span.Seconds); + } + + public static uint Default + { + get { return 0; } + } + } +} diff --git a/server/FSO.Server.Common/FSO.Server.Common.csproj b/server/FSO.Server.Common/FSO.Server.Common.csproj new file mode 100755 index 0000000..b0cdb96 --- /dev/null +++ b/server/FSO.Server.Common/FSO.Server.Common.csproj @@ -0,0 +1,104 @@ + + + + + Debug + AnyCPU + {39B61962-FE43-4B64-8E57-8F793737FFFE} + Library + Properties + FSO.Server.Common + FSO.Server.Common + v4.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Portable.BouncyCastle.1.8.0\lib\net45\crypto.dll + + + ..\packages\Portable.JWT.1.0.5\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+xamarinios10+MonoTouch10\JWT.dll + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {c42962a1-8796-4f47-9dcd-79ed5904d8ca} + FSO.Common + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Common/IAPIController.cs b/server/FSO.Server.Common/IAPIController.cs new file mode 100755 index 0000000..2c86293 --- /dev/null +++ b/server/FSO.Server.Common/IAPIController.cs @@ -0,0 +1,7 @@ +namespace FSO.Server.Common +{ + public interface IAPILifetime + { + void Stop(); + } +} diff --git a/server/FSO.Server.Common/IPAddress.cs b/server/FSO.Server.Common/IPAddress.cs new file mode 100755 index 0000000..69b33df --- /dev/null +++ b/server/FSO.Server.Common/IPAddress.cs @@ -0,0 +1,21 @@ +using System.Net; + +namespace FSO.Server.Common +{ + public class IPAddress + { + public static string Get(HttpListenerRequest httpRequest) + { + if (httpRequest.Headers["X-Forwarded-For"] != null) + { + return httpRequest.Headers["X-Forwarded-For"]; + } + return Get(httpRequest.RemoteEndPoint); + } + + public static string Get(IPEndPoint endpoint) + { + return endpoint.Address.ToString(); + } + } +} diff --git a/server/FSO.Server.Common/IPEndPointUtils.cs b/server/FSO.Server.Common/IPEndPointUtils.cs new file mode 100755 index 0000000..71f71e9 --- /dev/null +++ b/server/FSO.Server.Common/IPEndPointUtils.cs @@ -0,0 +1,32 @@ +using System; +using System.Globalization; +using System.Net; + +namespace FSO.Server.Common +{ + public class IPEndPointUtils + { + public static IPEndPoint CreateIPEndPoint(string endPoint) + { + string[] ep = endPoint.Split(':'); + if (ep.Length != 2) throw new FormatException("Invalid endpoint format"); + System.Net.IPAddress ip; + if (!System.Net.IPAddress.TryParse(ep[0], out ip)) + { + var addrs = Dns.GetHostEntry(ep[0]).AddressList; + if (addrs.Length == 0) + { + throw new FormatException("Invalid ip-address"); + } + else ip = addrs[0]; + } + + int port; + if (!int.TryParse(ep[1], NumberStyles.None, NumberFormatInfo.CurrentInfo, out port)) + { + throw new FormatException("Invalid port"); + } + return new IPEndPoint(ip, port); + } + } +} diff --git a/server/FSO.Server.Common/IServerDebugger.cs b/server/FSO.Server.Common/IServerDebugger.cs new file mode 100755 index 0000000..9f88f5e --- /dev/null +++ b/server/FSO.Server.Common/IServerDebugger.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace FSO.Server.Common +{ + public interface IServerDebugger + { + IPacketLogger GetPacketLogger(); + void AddSocketServer(ISocketServer server); + } + + + public interface ISocketServer + { + List GetSocketSessions(); + } + + + public interface ISocketSession + { + void Write(params object[] data); + } +} diff --git a/server/FSO.Server.Common/JsonWebToken/JWTConfiguration.cs b/server/FSO.Server.Common/JsonWebToken/JWTConfiguration.cs new file mode 100755 index 0000000..280999e --- /dev/null +++ b/server/FSO.Server.Common/JsonWebToken/JWTConfiguration.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Servers.Api.JsonWebToken +{ + public class JWTConfiguration + { + public byte[] Key; + public int TokenDuration = 3600; + } +} diff --git a/server/FSO.Server.Common/JsonWebToken/JWTUser.cs b/server/FSO.Server.Common/JsonWebToken/JWTUser.cs new file mode 100755 index 0000000..faaab61 --- /dev/null +++ b/server/FSO.Server.Common/JsonWebToken/JWTUser.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace FSO.Server.Servers.Api.JsonWebToken +{ + public class JWTUser + { + public uint UserID { get; set; } + + public IEnumerable Claims + { + get; set; + } + + public string UserName + { + get; set; + } + } +} diff --git a/server/FSO.Server.Common/JsonWebToken/JWTokenFactory.cs b/server/FSO.Server.Common/JsonWebToken/JWTokenFactory.cs new file mode 100755 index 0000000..03ccf24 --- /dev/null +++ b/server/FSO.Server.Common/JsonWebToken/JWTokenFactory.cs @@ -0,0 +1,48 @@ +using FSO.Server.Common; +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace FSO.Server.Servers.Api.JsonWebToken +{ + public class JWTInstance + { + public string Token; + public int ExpiresIn; + } + + public class JWTFactory + { + private JWTConfiguration Config; + + public JWTFactory(JWTConfiguration config) + { + this.Config = config; + } + + public JWTUser DecodeToken(string token) + { + var payload = JWT.JsonWebToken.Decode(token, Config.Key, true); + Dictionary payloadParsed = JsonConvert.DeserializeObject>(payload); + return Newtonsoft.Json.JsonConvert.DeserializeObject(payloadParsed["data"]); + } + + public JWTInstance CreateToken(JWTUser data) + { + var tokenData = Newtonsoft.Json.JsonConvert.SerializeObject(data); + return CreateToken(tokenData, Config.TokenDuration); + } + + private JWTInstance CreateToken(string data, int expiresIn) + { + var expires = Epoch.Now + expiresIn; + var payload = new Dictionary() + { + { "exp", expires }, + { "data", data } + }; + + var token = JWT.JsonWebToken.Encode(payload, Config.Key, JWT.JwtHashAlgorithm.HS384); + return new JWTInstance { Token = token, ExpiresIn = expiresIn }; + } + } +} diff --git a/server/FSO.Server.Common/PacketLogger.cs b/server/FSO.Server.Common/PacketLogger.cs new file mode 100755 index 0000000..bdc8c07 --- /dev/null +++ b/server/FSO.Server.Common/PacketLogger.cs @@ -0,0 +1,29 @@ +namespace FSO.Server.Common +{ + public interface IPacketLogger + { + void OnPacket(Packet packet); + } + + public class Packet + { + public PacketType Type; + public uint SubType; + + public byte[] Data; + public PacketDirection Direction; + } + + public enum PacketType + { + ARIES, + VOLTRON, + ELECTRON + } + + public enum PacketDirection + { + OUTPUT, + INPUT + } +} diff --git a/server/FSO.Server.Common/PasswordHasher.cs b/server/FSO.Server.Common/PasswordHasher.cs new file mode 100755 index 0000000..57307f3 --- /dev/null +++ b/server/FSO.Server.Common/PasswordHasher.cs @@ -0,0 +1,103 @@ +using System; +using System.Linq; +using System.Security.Cryptography; + +namespace FSO.Server.Common +{ + public class PasswordHasher + { + public static PasswordHash Hash(string password) + { + return Hash(password, "Rfc2898"); + } + + public static PasswordHash Hash(string password, string scheme) + { + var schemeImpl = GetScheme(scheme); + return schemeImpl.Hash(password); + } + + public static bool Verify(string password, PasswordHash hash) + { + return Verify(password, hash, "Rfc2898"); + } + + public static bool Verify(string password, PasswordHash hash, string scheme) + { + var schemeImpl = GetScheme(scheme); + return schemeImpl.Verify(password, hash); + } + + private static IPasswordHashScheme GetScheme(string scheme) + { + switch (scheme) + { + case "Rfc2898": + return new DefaultPasswordHashScheme(); + } + + throw new Exception("Unknown password hash scheme: " + scheme); + } + } + + public class PasswordHash + { + public byte[] data; + public string scheme; + } + + public class DefaultPasswordHashScheme : IPasswordHashScheme + { + public PasswordHash Hash(string password) + { + var salt_input = GetStrongRandomBytes(16); + + + return new PasswordHash() + { + scheme = "Rfc2898", + data = Hash(salt_input, password) + }; + } + + private byte[] Hash(byte[] salt_input, string password) + { + var hasher = new Rfc2898DeriveBytes(System.Text.Encoding.UTF8.GetBytes(password), salt_input, 1000); + var hash = hasher.GetBytes(64); + + //Encode the salt + hash together + var result = new byte[1 + 16 + hash.Length]; + result[0] = (byte)16; + Array.Copy(salt_input, 0, result, 1, salt_input.Length); + Array.Copy(hash, 0, result, salt_input.Length + 1, hash.Length); + + return result; + } + + public bool Verify(string password, PasswordHash hash) + { + var salt_length = hash.data[0]; + var salt_input = new byte[salt_length]; + Array.Copy(hash.data, 1, salt_input, 0, salt_length); + + var expected = Hash(salt_input, password); + return expected.SequenceEqual(hash.data); + } + + private byte[] GetStrongRandomBytes(int numBytes) + { + var random_bytes = new byte[numBytes]; + using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider()) + { + rngCsp.GetBytes(random_bytes); + } + return random_bytes; + } + } + + public interface IPasswordHashScheme + { + PasswordHash Hash(string password); + bool Verify(string password, PasswordHash hash); + } +} diff --git a/server/FSO.Server.Common/Properties/AssemblyInfo.cs b/server/FSO.Server.Common/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..957c5f7 --- /dev/null +++ b/server/FSO.Server.Common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FSO.Server.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FSO.Server.Common")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("39b61962-fe43-4b64-8e57-8f793737fffe")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/FSO.Server.Common/ServerVersion.cs b/server/FSO.Server.Common/ServerVersion.cs new file mode 100755 index 0000000..3caa3c1 --- /dev/null +++ b/server/FSO.Server.Common/ServerVersion.cs @@ -0,0 +1,48 @@ +using System.IO; + +namespace FSO.Server.Common +{ + public class ServerVersion + { + public string Name; + public string Number; + public int? UpdateID; + + public static ServerVersion Get() + { + var result = new ServerVersion() + { + Name = "unknown", + Number = "0" + }; + + if (File.Exists("version.txt")) + { + using (StreamReader Reader = new StreamReader(File.Open("version.txt", FileMode.Open, FileAccess.Read, FileShare.Read))) + { + var str = Reader.ReadLine(); + var split = str.LastIndexOf('-'); + + result.Name = str; + if (split != -1) + { + result.Name = str.Substring(0, split); + result.Number = str.Substring(split + 1); + } + } + } + + if (File.Exists("updateID.txt")) + { + var stringID = File.ReadAllText("updateID.txt"); + int id; + if (int.TryParse(stringID, out id)) + { + result.UpdateID = id; + } + } + + return result; + } + } +} diff --git a/server/FSO.Server.Common/Session/IAriesSession.cs b/server/FSO.Server.Common/Session/IAriesSession.cs new file mode 100755 index 0000000..079ecfe --- /dev/null +++ b/server/FSO.Server.Common/Session/IAriesSession.cs @@ -0,0 +1,17 @@ +using FSO.Server.Common; + +namespace FSO.Server.Framework.Aries +{ + public interface IAriesSession : ISocketSession + { + bool IsAuthenticated { get; } + uint LastRecv { get; set; } + bool Connected { get; } + + void Write(params object[] messages); + void Close(); + + object GetAttribute(string key); + void SetAttribute(string key, object value); + } +} diff --git a/server/FSO.Server.Common/Session/IGluonSession.cs b/server/FSO.Server.Common/Session/IGluonSession.cs new file mode 100755 index 0000000..ef3c138 --- /dev/null +++ b/server/FSO.Server.Common/Session/IGluonSession.cs @@ -0,0 +1,12 @@ +using FSO.Common.Security; +using FSO.Server.Framework.Aries; + +namespace FSO.Server.Framework.Gluon +{ + public interface IGluonSession : IAriesSession, ISecurityContext + { + string CallSign { get; } + string PublicHost { get; } + string InternalHost { get; } + } +} diff --git a/server/FSO.Server.Common/ShutdownType.cs b/server/FSO.Server.Common/ShutdownType.cs new file mode 100755 index 0000000..1e9dc32 --- /dev/null +++ b/server/FSO.Server.Common/ShutdownType.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Common +{ + public enum ShutdownType : byte + { + SHUTDOWN = 0, + RESTART = 1, + UPDATE = 2 //restart but runs an update task + } +} diff --git a/server/FSO.Server.Common/app.config b/server/FSO.Server.Common/app.config new file mode 100755 index 0000000..51e422b --- /dev/null +++ b/server/FSO.Server.Common/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Common/packages.config b/server/FSO.Server.Common/packages.config new file mode 100755 index 0000000..e81fbed --- /dev/null +++ b/server/FSO.Server.Common/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Database/DA/AbstractSqlDA.cs b/server/FSO.Server.Database/DA/AbstractSqlDA.cs new file mode 100755 index 0000000..6f8bd64 --- /dev/null +++ b/server/FSO.Server.Database/DA/AbstractSqlDA.cs @@ -0,0 +1,12 @@ +namespace FSO.Server.Database.DA +{ + public class AbstractSqlDA + { + protected ISqlContext Context; + + public AbstractSqlDA(ISqlContext context) + { + this.Context = context; + } + } +} diff --git a/server/FSO.Server.Database/DA/AuthTickets/AuthTicket.cs b/server/FSO.Server.Database/DA/AuthTickets/AuthTicket.cs new file mode 100755 index 0000000..45ece5b --- /dev/null +++ b/server/FSO.Server.Database/DA/AuthTickets/AuthTicket.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.AuthTickets +{ + public class AuthTicket + { + public string ticket_id { get; set; } + public uint user_id { get; set; } + public uint date { get; set; } + public string ip { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/AuthTickets/IAuthTickets.cs b/server/FSO.Server.Database/DA/AuthTickets/IAuthTickets.cs new file mode 100755 index 0000000..0840eaa --- /dev/null +++ b/server/FSO.Server.Database/DA/AuthTickets/IAuthTickets.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.AuthTickets +{ + public interface IAuthTickets + { + void Create(AuthTicket ticket); + AuthTicket Get(string id); + void Delete(string id); + void Purge(uint time); + } +} diff --git a/server/FSO.Server.Database/DA/AuthTickets/SqlAuthTickets.cs b/server/FSO.Server.Database/DA/AuthTickets/SqlAuthTickets.cs new file mode 100755 index 0000000..1312f73 --- /dev/null +++ b/server/FSO.Server.Database/DA/AuthTickets/SqlAuthTickets.cs @@ -0,0 +1,33 @@ +using System.Linq; +using Dapper; + +namespace FSO.Server.Database.DA.AuthTickets +{ + public class SqlAuthTickets : AbstractSqlDA, IAuthTickets + { + public SqlAuthTickets(ISqlContext context) : base(context) + { + } + + public void Create(AuthTicket ticket) + { + Context.Connection.Execute("INSERT INTO fso_auth_tickets VALUES (@ticket_id, @user_id, @date, @ip)", ticket); + } + + public void Delete(string id) + { + Context.Connection.Execute("DELETE FROM fso_auth_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }); + } + + public AuthTicket Get(string id) + { + return + Context.Connection.Query("SELECT * FROM fso_auth_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }).FirstOrDefault(); + } + + public void Purge(uint time) + { + Context.Connection.Execute("DELETE FROM fso_auth_tickets WHERE date < @time", new { time = time }); + } + } +} diff --git a/server/FSO.Server.Database/DA/AvatarClaims/DbAvatarClaim.cs b/server/FSO.Server.Database/DA/AvatarClaims/DbAvatarClaim.cs new file mode 100755 index 0000000..ad56424 --- /dev/null +++ b/server/FSO.Server.Database/DA/AvatarClaims/DbAvatarClaim.cs @@ -0,0 +1,17 @@ +namespace FSO.Server.Database.DA.AvatarClaims +{ + public class DbAvatarClaim + { + public int avatar_claim_id { get; set; } + public uint avatar_id { get; set; } + public string owner { get; set; } + public uint location { get; set; } + } + public class DbAvatarActive + { + public uint avatar_id { get; set; } + public string name { get; set; } + public byte privacy_mode { get; set; } + public uint location { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/AvatarClaims/IAvatarClaims.cs b/server/FSO.Server.Database/DA/AvatarClaims/IAvatarClaims.cs new file mode 100755 index 0000000..1a4fe4e --- /dev/null +++ b/server/FSO.Server.Database/DA/AvatarClaims/IAvatarClaims.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.AvatarClaims +{ + public interface IAvatarClaims + { + DbAvatarClaim Get(int id); + IEnumerable GetAll(); + IEnumerable GetAllActiveAvatars(); + int? GetAllActiveAvatarsCount(); + DbAvatarClaim GetByAvatarID(uint id); + IEnumerable GetAllByOwner(string owner); + + int? TryCreate(DbAvatarClaim claim); + bool Claim(int id, string previousOwner, string newOwner, uint location); + void RemoveRemaining(string previousOwner, uint location); + + void Delete(int id, string owner); + void DeleteAll(string owner); + } +} diff --git a/server/FSO.Server.Database/DA/AvatarClaims/SqlAvatarClaims.cs b/server/FSO.Server.Database/DA/AvatarClaims/SqlAvatarClaims.cs new file mode 100755 index 0000000..aa5bca4 --- /dev/null +++ b/server/FSO.Server.Database/DA/AvatarClaims/SqlAvatarClaims.cs @@ -0,0 +1,84 @@ +using Dapper; +using MySql.Data.MySqlClient; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.AvatarClaims +{ + public class SqlAvatarClaims : AbstractSqlDA, IAvatarClaims + { + public SqlAvatarClaims(ISqlContext context) : base(context) + { + } + + public bool Claim(int id, string previousOwner, string newOwner, uint location) + { + try + { + Context.Connection.Query("UPDATE fso_avatar_claims SET owner = @owner, location = @location WHERE avatar_claim_id = @claim_id AND owner = @previous_owner", new { claim_id = (int)id, previous_owner = previousOwner, owner = newOwner, location = location }); + var newClaim = Context.Connection.Query("SELECT * FROM fso_avatar_claims WHERE avatar_claim_id = @claim_id AND owner = @owner", new { claim_id = (int)id, owner = newOwner }).FirstOrDefault(); + return newClaim != null; + } + catch (MySqlException ex) + { + return false; + } + } + + public void RemoveRemaining(string previousOwner, uint location) + { + Context.Connection.Query("DELETE FROM fso_avatar_claims WHERE location = @location AND owner = @previous_owner", new { previous_owner = previousOwner, location = location }); + } + + + public void Delete(int id, string owner) + { + Context.Connection.Query("DELETE FROM fso_avatar_claims WHERE owner = @owner AND avatar_claim_id = @claim_id", new { owner = owner, claim_id = (int)id }); + } + + public void DeleteAll(string owner) + { + Context.Connection.Query("DELETE FROM fso_avatar_claims WHERE owner = @owner", new { owner = owner }); + } + + public DbAvatarClaim Get(int id) + { + return Context.Connection.Query("SELECT * FROM fso_avatar_claims WHERE avatar_claim_id = @claim_id", new { claim_id = (int)id }).FirstOrDefault(); + } + public IEnumerable GetAll() + { + return Context.Connection.Query("SELECT * FROM fso_avatar_claims"); + } + public IEnumerable GetAllActiveAvatars() + { + return Context.Connection.Query("SELECT b.*, a.location FROM fso.fso_avatar_claims as a "+ + "inner join fso.fso_avatars as b ON a.avatar_id = b.avatar_id;"); + } + public int? GetAllActiveAvatarsCount() + { + return Context.Connection.Query("SELECT COUNT(*) FROM fso_avatar_claims").FirstOrDefault(); + } + public DbAvatarClaim GetByAvatarID(uint id) + { + return Context.Connection.Query("SELECT * FROM fso_avatar_claims WHERE avatar_id = @id", new { id = id }).FirstOrDefault(); + } + + public IEnumerable GetAllByOwner(string owner) + { + return Context.Connection.Query("SELECT * FROM fso_avatar_claims WHERE owner = @owner", new { owner = owner }); + } + + public int? TryCreate(DbAvatarClaim claim) + { + try + { + return Context.Connection.Query("INSERT INTO fso_avatar_claims (avatar_id, owner, location) " + + " VALUES (@avatar_id, @owner, @location); SELECT LAST_INSERT_ID();", claim).First(); + } + catch (MySqlException ex) + { + return null; + } + } + } +} diff --git a/server/FSO.Server.Database/DA/Avatars/DbAvatar.cs b/server/FSO.Server.Database/DA/Avatars/DbAvatar.cs new file mode 100755 index 0000000..e06ab8f --- /dev/null +++ b/server/FSO.Server.Database/DA/Avatars/DbAvatar.cs @@ -0,0 +1,70 @@ +namespace FSO.Server.Database.DA.Avatars +{ + public class DbAvatar + { + public uint avatar_id { get; set; } + public int shard_id { get; set; } + public uint user_id { get; set; } + public string name { get; set; } + public DbAvatarGender gender { get; set; } + public uint date { get; set; } + public byte skin_tone { get; set; } + public ulong head { get; set; } + public ulong body { get; set; } + public string description { get; set; } + public int budget { get; set; } + public byte privacy_mode { get; set; } + + //lot persist state beyond this point (very mutable) + + public byte[] motive_data { get; set; } + //locks + + public byte skilllock { get; set; } //number of skill locks we had at last avatar save. this is usually handled by data service. + public ushort lock_mechanical { get; set; } + public ushort lock_cooking { get; set; } + public ushort lock_charisma { get; set; } + public ushort lock_logic { get; set; } + public ushort lock_body { get; set; } + public ushort lock_creativity { get; set; } + //skills + public ushort skill_mechanical { get; set; } + public ushort skill_cooking { get; set; } + public ushort skill_charisma { get; set; } + public ushort skill_logic { get; set; } + public ushort skill_body { get; set; } + public ushort skill_creativity { get; set; } + + public ulong body_swimwear { get; set; } + public ulong body_sleepwear { get; set; } + public ulong body_current { get; set; } + + public ushort current_job { get; set; } + public ushort is_ghost { get; set; } + public ushort ticker_death { get; set; } + public ushort ticker_gardener { get; set; } + public ushort ticker_maid { get; set; } + public ushort ticker_repairman { get; set; } + + public byte moderation_level { get; set; } + public uint? custom_guid { get; set; } + public uint move_date { get; set; } + public uint name_date { get; set; } + public int? mayor_nhood { get; set; } + } + + + public class DbTransactionResult + { + public bool success { get; set; } + public int source_budget { get; set; } + public int dest_budget { get; set; } + public int amount { get; set; } + } + + public enum DbAvatarGender + { + male, + female + } +} diff --git a/server/FSO.Server.Database/DA/Avatars/DbAvatarSummary.cs b/server/FSO.Server.Database/DA/Avatars/DbAvatarSummary.cs new file mode 100755 index 0000000..20accec --- /dev/null +++ b/server/FSO.Server.Database/DA/Avatars/DbAvatarSummary.cs @@ -0,0 +1,22 @@ +namespace FSO.Server.Database.DA.Avatars +{ + public class DbAvatarSummary + { + //fso_avatar data + public uint avatar_id { get; set; } + public int shard_id { get; set; } + public uint user_id { get; set; } + public string name { get; set; } + public DbAvatarGender gender { get; set; } + public uint date { get; set; } + public byte skin_tone { get; set; } + public ulong head { get; set; } + public ulong body { get; set; } + public string description { get; set; } + + //fso_lots + public uint? lot_id { get; set; } + public uint? lot_location { get; set; } + public string lot_name { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Avatars/DbJobLevel.cs b/server/FSO.Server.Database/DA/Avatars/DbJobLevel.cs new file mode 100755 index 0000000..4fa67c6 --- /dev/null +++ b/server/FSO.Server.Database/DA/Avatars/DbJobLevel.cs @@ -0,0 +1,12 @@ +namespace FSO.Server.Database.DA.Avatars +{ + public class DbJobLevel + { + public uint avatar_id { get; set; } + public ushort job_type { get; set; } + public ushort job_experience { get; set; } + public ushort job_level { get; set; } + public ushort job_sickdays { get; set; } + public ushort job_statusflags { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Avatars/IAvatars.cs b/server/FSO.Server.Database/DA/Avatars/IAvatars.cs new file mode 100755 index 0000000..dbbcea5 --- /dev/null +++ b/server/FSO.Server.Database/DA/Avatars/IAvatars.cs @@ -0,0 +1,51 @@ +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Avatars +{ + public interface IAvatars + { + uint Create(DbAvatar avatar); + + DbAvatar Get(uint id); + List GetMultiple(uint[] id); + bool Delete(uint id); + int GetPrivacyMode(uint id); + int GetModerationLevel(uint id); + DbJobLevel GetCurrentJobLevel(uint avatar_id); + List GetJobLevels(uint avatar_id); + IEnumerable All(); + IEnumerable All(int shard_id); + PagedList AllByPage(int shard_id, int offset, int limit, string orderBy); + List GetLivingInNhood(uint nhood_id); + List GetPossibleCandidatesNhood(uint nhood_id); + + List GetByUserId(uint user_id); + List GetSummaryByUserId(uint user_id); + + int GetOtherLocks(uint avatar_id, string except); + + int GetBudget(uint avatar_id); + DbTransactionResult Transaction(uint source_id, uint avatar_id, int amount, short reason); + DbTransactionResult Transaction(uint source_id, uint avatar_id, int amount, short reason, Func transactionInject); + DbTransactionResult TestTransaction(uint source_id, uint avatar_id, int amount, short reason); + + void UpdateDescription(uint id, string description); + void UpdatePrivacyMode(uint id, byte privacy); + void UpdateAvatarLotSave(uint id, DbAvatar avatar); + void UpdateAvatarJobLevel(DbJobLevel jobLevel); + void UpdateMoveDate(uint id, uint date); + void UpdateMayorNhood(uint id, uint? nhood); + + List SearchExact(int shard_id, string name, int limit); + List SearchWildcard(int shard_id, string name, int limit); + } + + public class AvatarRating + { + public uint avatar_id { get; set; } + public string name { get; set; } + public float? rating { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Avatars/SqlAvatars.cs b/server/FSO.Server.Database/DA/Avatars/SqlAvatars.cs new file mode 100755 index 0000000..bd37c35 --- /dev/null +++ b/server/FSO.Server.Database/DA/Avatars/SqlAvatars.cs @@ -0,0 +1,401 @@ +using Dapper; +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Avatars +{ + public class SqlAvatars : AbstractSqlDA, IAvatars + { + public SqlAvatars(ISqlContext context) : base(context){ + } + public PagedList AllByPage(int shard_id,int offset = 1, int limit = 100, string orderBy = "avatar_id") + { + var total = Context.Connection.Query("SELECT COUNT(*) FROM fso_avatars WHERE shard_id = @shard_id",new { shard_id = shard_id }).FirstOrDefault(); + var results = Context.Connection.Query("SELECT * FROM fso_avatars WHERE shard_id = @shard_id ORDER BY @order DESC LIMIT @offset, @limit", new { shard_id = shard_id, order = orderBy, offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + public IEnumerable All() + { + return Context.Connection.Query("SELECT * FROM fso_avatars"); + } + + public IEnumerable All(int shard_id){ + return Context.Connection.Query("SELECT * FROM fso_avatars WHERE shard_id = @shard_id", new { shard_id = shard_id }); + } + + public List GetLivingInNhood(uint neigh_id) + { + return Context.Connection.Query("SELECT avatar_id FROM fso_roommates r JOIN fso_lots l ON r.lot_id = l.lot_id " + + "WHERE neighborhood_id = @neigh_id", new { neigh_id = neigh_id }).ToList(); + } + + public List GetPossibleCandidatesNhood(uint neigh_id) + { + return Context.Connection.Query("SELECT r.avatar_id, a.name, AVG(CAST(v.rating as DECIMAL(10,6))) AS rating " + + "FROM (fso_roommates r JOIN fso_lots l ON r.lot_id = l.lot_id) " + + "LEFT JOIN fso_mayor_ratings v ON v.to_avatar_id = r.avatar_id " + + "JOIN fso_avatars a ON r.avatar_id = a.avatar_id " + + "WHERE l.neighborhood_id = @neigh_id " + + "GROUP BY avatar_id", new { neigh_id = neigh_id }).ToList(); + } + + public DbAvatar Get(uint id){ + return Context.Connection.Query("SELECT * FROM fso_avatars WHERE avatar_id = @id", new { id = id }).FirstOrDefault(); + } + + public bool Delete(uint id) + { + return Context.Connection.Execute("DELETE FROM fso_avatars WHERE avatar_id = @id", new { id = id }) > 0; + } + + public int GetPrivacyMode(uint id) + { + return Context.Connection.Query("SELECT privacy_mode FROM fso_avatars WHERE avatar_id = @id", new { id = id }).FirstOrDefault(); + } + + public int GetModerationLevel(uint id) + { + return Context.Connection.Query("SELECT moderation_level FROM fso_avatars WHERE avatar_id = @id", new { id = id }).FirstOrDefault(); + } + + public uint Create(DbAvatar avatar) + { + return (uint)Context.Connection.Query("INSERT INTO fso_avatars (shard_id, user_id, name, " + + "gender, date, skin_tone, head, body, description, budget, moderation_level, " + + " body_swimwear, body_sleepwear) " + + " VALUES (@shard_id, @user_id, @name, @gender, @date, " + + " @skin_tone, @head, @body, @description, @budget, @moderation_level, "+ + " @body_swimwear, @body_sleepwear); SELECT LAST_INSERT_ID();", new + { + shard_id = avatar.shard_id, + user_id = avatar.user_id, + name = avatar.name, + gender = avatar.gender.ToString(), + date = avatar.date, + skin_tone = avatar.skin_tone, + head = avatar.head, + body = avatar.body, + description = avatar.description, + budget = avatar.budget, + moderation_level = avatar.moderation_level, + body_swimwear = avatar.body_swimwear, + body_sleepwear = avatar.body_sleepwear + }).First(); + //for now, everything else assumes default values. + } + + + public List GetByUserId(uint user_id) + { + return Context.Connection.Query( + "SELECT * FROM fso_avatars WHERE user_id = @user_id", + new { user_id = user_id } + ).ToList(); + } + + public List GetMultiple(uint[] id) + { + String inClause = "IN ("; + for (int i = 0; i < id.Length; i++) + { + inClause = inClause + "'" + id.ElementAt(i) + "'" + ","; + } + inClause = inClause.Substring(0, inClause.Length - 1); + inClause = inClause + ")"; + + return Context.Connection.Query( + "Select * from fso_avatars Where avatar_id "+ inClause + ).ToList(); + } + + public List SearchExact(int shard_id, string name, int limit) + { + return Context.Connection.Query( + "SELECT avatar_id, name FROM fso_avatars WHERE shard_id = @shard_id AND name = @name LIMIT @limit", + new { name = name, limit = limit, shard_id = shard_id } + ).ToList(); + } + + public List SearchWildcard(int shard_id, string name, int limit) + { + name = name + .Replace("!", "!!") + .Replace("%", "!%") + .Replace("_", "!_") + .Replace("[", "!["); //must sanitize format... + return Context.Connection.Query( + "SELECT avatar_id, name FROM fso_avatars WHERE shard_id = @shard_id AND name LIKE @name LIMIT @limit", + new { name = "%" + name + "%", limit = limit, shard_id = shard_id } + ).ToList(); + } + + public void UpdateDescription(uint id, string description) + { + Context.Connection.Query("UPDATE fso_avatars SET description = @desc WHERE avatar_id = @id", new { id = id, desc = description }); + } + + public void UpdatePrivacyMode(uint id, byte mode) + { + Context.Connection.Query("UPDATE fso_avatars SET privacy_mode = @privacy_mode WHERE avatar_id = @id", new { id = id, privacy_mode = mode }); + } + + public void UpdateMoveDate(uint id, uint date) + { + Context.Connection.Query("UPDATE fso_avatars SET move_date = @date WHERE avatar_id = @id", new { id = id, date = date }); + } + + public void UpdateMayorNhood(uint id, uint? nhood) + { + Context.Connection.Query("UPDATE fso_avatars SET mayor_nhood = @nhood WHERE avatar_id = @id", new { id = id, nhood = nhood }); + } + + + public void UpdateAvatarLotSave(uint id, DbAvatar avatar) + { + avatar.avatar_id = id; + Context.Connection.Query("UPDATE fso_avatars SET " + + "motive_data = @motive_data, " + + "skilllock = @skilllock, " + + "lock_mechanical = @lock_mechanical, " + + "lock_cooking = @lock_cooking, " + + "lock_charisma = @lock_charisma, " + + "lock_logic = @lock_logic, " + + "lock_body = @lock_body, " + + "lock_creativity = @lock_creativity, " + + "skill_mechanical = @skill_mechanical, " + + "skill_cooking = @skill_cooking, " + + "skill_charisma = @skill_charisma, " + + "skill_logic = @skill_logic, " + + "skill_body = @skill_body, " + + "skill_creativity = @skill_creativity, " + + "body = @body, " + + "body_swimwear = @body_swimwear, " + + "body_sleepwear = @body_sleepwear, " + + "body_current = @body_current, " + + "current_job = @current_job, " + + "is_ghost = @is_ghost, " + + "ticker_death = @ticker_death, " + + "ticker_gardener = @ticker_gardener, " + + "ticker_maid = @ticker_maid, " + + "ticker_repairman = @ticker_repairman WHERE avatar_id = @avatar_id", avatar); + } + + private static string[] LockNames = new string[] + { + "lock_mechanical", + "lock_cooking", + "lock_charisma", + "lock_logic", + "lock_body", + "lock_creativity" + }; + + public int GetOtherLocks(uint avatar_id, string except) + { + string columns = "("; + foreach (var l in LockNames) + { + if (l == except) continue; + columns += l; + columns += " + "; + } + columns += "0) AS Sum"; + + return Context.Connection.Query("SELECT "+columns+" FROM fso_avatars WHERE avatar_id = @id", new { id = avatar_id }).FirstOrDefault(); + } + + //budget and transactions + public int GetBudget(uint avatar_id) + { + return Context.Connection.Query("SELECT budget FROM fso_avatars WHERE avatar_id = @id", new { id = avatar_id }).FirstOrDefault(); + } + + public DbTransactionResult Transaction(uint source_id, uint dest_id, int amount, short reason) + { + return Transaction(source_id, dest_id, amount, reason, null); + } + + public DbTransactionResult Transaction(uint source_id, uint dest_id, int amount, short reason, Func transactionInject) + { + var t = Context.Connection.BeginTransaction(); + var srcObj = (source_id >= 16777216); + var dstObj = (dest_id >= 16777216); + var success = true; + try { + int srcRes, dstRes; + if (source_id != uint.MaxValue) + { + if (srcObj) + { + srcRes = Context.Connection.Execute("UPDATE fso_objects SET budget = budget - @amount WHERE object_id = @source_id;", + new { source_id = source_id, amount = amount }); + } + else + { + srcRes = Context.Connection.Execute("UPDATE fso_avatars SET budget = budget - @amount WHERE avatar_id = @source_id;", + new { source_id = source_id, amount = amount }); + } + if (srcRes == 0) throw new Exception("Source avatar/object does not exist!"); + } + + if (dest_id != uint.MaxValue) + { + if (dstObj) + { + dstRes = Context.Connection.Execute("UPDATE fso_objects SET budget = budget + @amount WHERE object_id = @dest_id;", + new { dest_id = dest_id, amount = amount }); + } + else + { + dstRes = Context.Connection.Execute("UPDATE fso_avatars SET budget = budget + @amount WHERE avatar_id = @dest_id;", + new { dest_id = dest_id, amount = amount }); + } + if (dstRes == 0) throw new Exception("Dest avatar/object does not exist!"); + } + + if (transactionInject != null) + { + if (!transactionInject()) throw new Exception("Transaction Cancelled"); + } + + t.Commit(); + } catch (Exception) + { + success = false; + t.Rollback(); + } + + if (success && ((reason > 7 && reason != 9) || (source_id != uint.MaxValue && dest_id != uint.MaxValue))) { + var days = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalDays; + Context.Connection.Execute("INSERT INTO fso_transactions (from_id, to_id, transaction_type, day, value, count) "+ + "VALUES (@from_id, @to_id, @transaction_type, @day, @value, @count) " + + "ON DUPLICATE KEY UPDATE value = value + @value, count = count+1", new + { + from_id = (amount>0)?source_id:dest_id, + to_id = (amount>0)?dest_id:source_id, + transaction_type = reason, + day = (int)days, + value = Math.Abs(amount), + count = 1 + }); + } + + var result = Context.Connection.Query("SELECT a1.budget AS source_budget, a2.budget AS dest_budget " + + "FROM" + + "(SELECT budget, count(budget) FROM " + (srcObj ? "fso_objects" : "fso_avatars") + " WHERE " + (srcObj ? "object_id" : "avatar_id") + " = @source_id) a1," + + "(SELECT budget, count(budget) FROM " + (dstObj ? "fso_objects" : "fso_avatars") + " WHERE " + (dstObj ? "object_id" : "avatar_id") + " = @avatar_id) a2; ", + new { avatar_id = dest_id, source_id = source_id }).FirstOrDefault(); + if (result != null) + { + result.amount = amount; + result.success = success; + } + return result; + } + + public DbTransactionResult TestTransaction(uint source_id, uint dest_id, int amount, short reason) + { + var success = true; + var srcObj = (source_id >= 16777216); + var dstObj = (dest_id >= 16777216); + try + { + int? srcVal, dstVal; + if (srcObj) + { + srcVal = Context.Connection.Query("SELECT budget FROM fso_objects WHERE object_id = @source_id;", + new { source_id = source_id }).FirstOrDefault(); + } + else + { + srcVal = Context.Connection.Query("SELECT budget FROM fso_avatars WHERE avatar_id = @source_id;", + new { source_id = source_id }).FirstOrDefault(); + } + if (source_id != uint.MaxValue) + { + if (srcVal == null) throw new Exception("Source avatar/object does not exist!"); + if (srcVal.Value - amount < 0) throw new Exception("Source does not have enough money!"); + } + if (dstObj) + { + dstVal = Context.Connection.Query("SELECT budget FROM fso_objects WHERE object_id = @dest_id;", + new { dest_id = dest_id }).FirstOrDefault(); + } + else + { + dstVal = Context.Connection.Query("SELECT budget FROM fso_avatars WHERE avatar_id = @dest_id;", + new { dest_id = dest_id }).FirstOrDefault(); + } + if (dest_id != uint.MaxValue) + { + if (dstVal == null) throw new Exception("Dest avatar/object does not exist!"); + if (dstVal.Value + amount < 0) throw new Exception("Destination does not have enough money! (transaction accidentally debits)"); + } + } + catch (Exception) + { + success = false; + } + var result = Context.Connection.Query("SELECT a1.budget AS source_budget, a2.budget AS dest_budget " + + "FROM" + + "(SELECT budget, count(budget) FROM "+(srcObj?"fso_objects":"fso_avatars")+" WHERE "+(srcObj?"object_id":"avatar_id")+" = @source_id) a1," + + "(SELECT budget, count(budget) FROM " + (dstObj ? "fso_objects" : "fso_avatars") + " WHERE " + (dstObj ? "object_id" : "avatar_id") + " = @avatar_id) a2; ", + new { avatar_id = dest_id, source_id = source_id }).FirstOrDefault(); + if (result != null) + { + result.amount = amount; + result.success = success; + } + return result; + } + + //JOB LEVELS + + public DbJobLevel GetCurrentJobLevel(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_avatars a JOIN fso_joblevels b " + + "ON a.avatar_id = b.avatar_id AND a.current_job = b.job_type WHERE a.avatar_id = @id", + new { id = avatar_id }).FirstOrDefault(); + } + + public List GetJobLevels(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_avatars a JOIN fso_joblevels b ON a.avatar_id = b.avatar_id WHERE a.avatar_id = @id", new { id = avatar_id }).ToList(); + } + + public void UpdateAvatarJobLevel(DbJobLevel jobLevel) + { + Context.Connection.Query("INSERT INTO fso_joblevels (avatar_id, job_type, job_experience, job_level, job_sickdays, job_statusflags) " + + "VALUES (@avatar_id, @job_type, @job_experience, @job_level, @job_sickdays, @job_statusflags) " + + "ON DUPLICATE KEY UPDATE job_experience=VALUES(`job_experience`), job_level=VALUES(`job_level`), " + +" job_sickdays=VALUES(`job_sickdays`), job_statusflags=VALUES(`job_statusflags`); ", jobLevel); + return; + } + + public List GetSummaryByUserId(uint user_id) + { + return Context.Connection.Query( + @"SELECT a.avatar_id, + a.shard_id, + a.user_id, + a.name, + a.gender, + a.date, + a.skin_tone, + a.head, + a.body, + a.description, + r.lot_id, + l.name as lot_name, + l.location as lot_location + FROM fso_avatars a + LEFT OUTER JOIN fso_roommates r on r.avatar_id = a.avatar_id + LEFT OUTER JOIN fso_lots l on l.lot_id = r.lot_id AND r.is_pending = 0 + WHERE a.user_id = @user_id + ORDER BY a.date ASC", new { user_id = user_id }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/Bans/DbBan.cs b/server/FSO.Server.Database/DA/Bans/DbBan.cs new file mode 100755 index 0000000..0cba25b --- /dev/null +++ b/server/FSO.Server.Database/DA/Bans/DbBan.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.Bans +{ + public class DbBan + { + public uint user_id { get; set; } + public string ip_address { get; set; } + public string ban_reason { get; set; } + public int end_date { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Bans/IBans.cs b/server/FSO.Server.Database/DA/Bans/IBans.cs new file mode 100755 index 0000000..1f1d438 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bans/IBans.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Database.DA.Bans +{ + public interface IBans + { + DbBan GetByIP(string ip); + void Add(string ip, uint userid, string reason, int enddate, string client_id); + + DbBan GetByClientId(string client_id); + void Remove(uint user_id); + } +} diff --git a/server/FSO.Server.Database/DA/Bans/SqlBans.cs b/server/FSO.Server.Database/DA/Bans/SqlBans.cs new file mode 100755 index 0000000..1653116 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bans/SqlBans.cs @@ -0,0 +1,51 @@ +using Dapper; +using System.Linq; + +namespace FSO.Server.Database.DA.Bans +{ + public class SqlBans : AbstractSqlDA, IBans + { + public SqlBans(ISqlContext context) : base(context) + { + } + + public DbBan GetByIP(string ip) + { + return Context.Connection.Query("SELECT * FROM fso_ip_ban WHERE ip_address = @ip", new { ip = ip }).FirstOrDefault(); + } + + /// + /// Finds a ban by MAC Address. + /// + /// + /// + public DbBan GetByClientId(string client_id) + { + return Context.Connection.Query("SELECT * FROM fso_ip_ban WHERE client_id = @client_id", new { client_id = client_id }).FirstOrDefault(); + } + + public void Add(string ip, uint userid, string reason, int enddate, string client_id) + { + Context.Connection.Execute( + "REPLACE INTO fso_ip_ban (user_id, ip_address, banreason, end_date, client_id) " + + "VALUES (@user_id, @ip_address, @banreason, @end_date, @client_id)", + new + { + user_id = userid, + ip_address = ip, + banreason = reason, + end_date = enddate + } + ); + } + + /// + /// Remove ban by user_id. + /// + /// + public void Remove(uint user_id) + { + Context.Connection.Query("DELETE FROM fso_ip_ban WHERE user_id = @user_id", new { user_id = user_id }); + } + } +} diff --git a/server/FSO.Server.Database/DA/Bonus/DbBonus.cs b/server/FSO.Server.Database/DA/Bonus/DbBonus.cs new file mode 100755 index 0000000..24d208f --- /dev/null +++ b/server/FSO.Server.Database/DA/Bonus/DbBonus.cs @@ -0,0 +1,14 @@ +using System; + +namespace FSO.Server.Database.DA.Bonus +{ + public class DbBonus + { + public int bonus_id { get; set; } + public uint avatar_id { get; set; } + public DateTime period { get; set; } + public int? bonus_visitor { get; set; } + public int? bonus_property { get; set; } + public int? bonus_sim { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Bonus/DbBonusMetrics.cs b/server/FSO.Server.Database/DA/Bonus/DbBonusMetrics.cs new file mode 100755 index 0000000..91fe769 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bonus/DbBonusMetrics.cs @@ -0,0 +1,14 @@ +using FSO.Common.Enum; + +namespace FSO.Server.Database.DA.Bonus +{ + public class DbBonusMetrics + { + public uint avatar_id { get; set; } + public int lot_id { get; set; } + public LotCategory category { get; set; } + public int? visitor_minutes { get; set; } + public byte? property_rank { get; set; } + public byte? sim_rank { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Bonus/IBonus.cs b/server/FSO.Server.Database/DA/Bonus/IBonus.cs new file mode 100755 index 0000000..b31dff7 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bonus/IBonus.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Bonus +{ + public interface IBonus + { + IEnumerable GetByAvatarId(uint avatar_id); + IEnumerable GetMetrics(DateTime date, int shard_id); + void Insert(IEnumerable bonus); + void Purge(DateTime date); + } +} diff --git a/server/FSO.Server.Database/DA/Bonus/SqlBonus.cs b/server/FSO.Server.Database/DA/Bonus/SqlBonus.cs new file mode 100755 index 0000000..8a78b1a --- /dev/null +++ b/server/FSO.Server.Database/DA/Bonus/SqlBonus.cs @@ -0,0 +1,50 @@ +using Dapper; +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Bonus +{ + public class SqlBonus : AbstractSqlDA, IBonus + { + public SqlBonus(ISqlContext context) : base(context) + { + } + + public IEnumerable GetByAvatarId(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_bonus WHERE avatar_id = @avatar_id ORDER BY period DESC LIMIT 14", new { avatar_id = avatar_id }); + } + + public IEnumerable GetMetrics(DateTime date, int shard_id) + { + return Context.Connection.Query( + @"SELECT * FROM ( + SELECT a.avatar_id, + r.lot_id, + l.category, + (SELECT lvt.minutes from fso_lot_visit_totals lvt where lvt.lot_id = r.lot_id AND lvt.date = CAST(@p_date as DATE)) as visitor_minutes, + (SELECT rank from fso_lot_top_100 lt100 WHERE lt100.lot_id = r.lot_id) as property_rank, + NULL as sim_rank + FROM fso_avatars a + LEFT JOIN fso_roommates r ON r.avatar_id = a.avatar_id + LEFT JOIN fso_lots l ON r.lot_id = l.lot_id + WHERE a.shard_id = @p_shard_id + ) as bonusPayments + WHERE visitor_minutes IS NOT NULL + OR property_rank IS NOT NULL + OR sim_rank IS NOT NULL" + , new { p_date = date, p_shard_id = shard_id }, buffered: false); + } + + public void Insert(IEnumerable bonus) + { + Context.Connection.ExecuteBufferedInsert("INSERT INTO fso_bonus (avatar_id, period, bonus_visitor, bonus_property, bonus_sim) VALUES (@avatar_id, @period, @bonus_visitor, @bonus_property, @bonus_sim) ON DUPLICATE KEY UPDATE fso_bonus.avatar_id = fso_bonus.avatar_id", bonus, 100); + } + + public void Purge(DateTime date) + { + Context.Connection.Execute("DELETE FROM fso_bonus WHERE period < @date", new { date = date }); + } + } +} diff --git a/server/FSO.Server.Database/DA/Bookmarks/DbBookmark.cs b/server/FSO.Server.Database/DA/Bookmarks/DbBookmark.cs new file mode 100755 index 0000000..f295f2a --- /dev/null +++ b/server/FSO.Server.Database/DA/Bookmarks/DbBookmark.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Bookmarks +{ + public class DbBookmark + { + public uint avatar_id { get; set; } + public byte type { get; set; } + public uint target_id { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Bookmarks/IBookmarks.cs b/server/FSO.Server.Database/DA/Bookmarks/IBookmarks.cs new file mode 100755 index 0000000..00beb2e --- /dev/null +++ b/server/FSO.Server.Database/DA/Bookmarks/IBookmarks.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Bookmarks +{ + public interface IBookmarks + { + List GetByAvatarId(uint avatar_id); + List GetAvatarIgnore(uint avatar_id); + void Create(DbBookmark bookmark); + bool Delete(DbBookmark bookmark); + } +} diff --git a/server/FSO.Server.Database/DA/Bookmarks/SqlBookmarks.cs b/server/FSO.Server.Database/DA/Bookmarks/SqlBookmarks.cs new file mode 100755 index 0000000..2adfe47 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bookmarks/SqlBookmarks.cs @@ -0,0 +1,35 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Bookmarks +{ + public class SqlBookmarks : AbstractSqlDA, IBookmarks + { + public SqlBookmarks(ISqlContext context) : base(context) + { + } + + public void Create(DbBookmark bookmark) + { + Context.Connection.Execute("INSERT INTO fso_bookmarks (avatar_id, type, target_id) " + + " VALUES (@avatar_id, @type, @target_id)" + , bookmark); + } + + public bool Delete(DbBookmark bookmark) + { + return Context.Connection.Execute("DELETE FROM fso_bookmarks WHERE avatar_id = @avatar_id AND type = @type AND target_id = @target_id", bookmark) > 0; + } + + public List GetByAvatarId(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_bookmarks WHERE avatar_id = @avatar_id", new { avatar_id = avatar_id }).ToList(); + } + + public List GetAvatarIgnore(uint avatar_id) + { + return Context.Connection.Query("SELECT target_id FROM fso_bookmarks WHERE avatar_id = @avatar_id AND type = 5", new { avatar_id = avatar_id }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/Bulletin/DbBulletinPost.cs b/server/FSO.Server.Database/DA/Bulletin/DbBulletinPost.cs new file mode 100755 index 0000000..6341517 --- /dev/null +++ b/server/FSO.Server.Database/DA/Bulletin/DbBulletinPost.cs @@ -0,0 +1,29 @@ +namespace FSO.Server.Database.DA.Bulletin +{ + public class DbBulletinPost + { + public uint bulletin_id { get; set; } + public int neighborhood_id { get; set; } + public uint? avatar_id { get; set; } + public string title { get; set; } + public string body { get; set; } + public uint date { get; set; } + public uint flags { get; set; } + public int? lot_id { get; set; } + public DbBulletinType type { get; set; } + public byte deleted { get; set; } + + public string string_type { get + { + return type.ToString(); + } + } + } + + public enum DbBulletinType + { + mayor, + system, + community + } +} diff --git a/server/FSO.Server.Database/DA/Bulletin/IBulletinPosts.cs b/server/FSO.Server.Database/DA/Bulletin/IBulletinPosts.cs new file mode 100755 index 0000000..f52be0d --- /dev/null +++ b/server/FSO.Server.Database/DA/Bulletin/IBulletinPosts.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Bulletin +{ + public interface IBulletinPosts + { + DbBulletinPost Get(uint bulletin_id); + int CountPosts(uint neighborhood_id, uint timeAfter); + uint LastPostID(uint neighborhood_id); + DbBulletinPost LastUserPost(uint user_id, uint neighborhood_id); + List GetByNhoodId(uint neighborhood_id, uint timeAfter); + uint Create(DbBulletinPost bulletin); + bool Delete(uint bulletin_id); + bool SoftDelete(uint bulletin_id); + bool SetTypeFlag(uint bulletin_id, DbBulletinType type, int flag); + } +} diff --git a/server/FSO.Server.Database/DA/Bulletin/SqlBulletinPosts.cs b/server/FSO.Server.Database/DA/Bulletin/SqlBulletinPosts.cs new file mode 100755 index 0000000..596b0fd --- /dev/null +++ b/server/FSO.Server.Database/DA/Bulletin/SqlBulletinPosts.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Linq; +using Dapper; + +namespace FSO.Server.Database.DA.Bulletin +{ + public class SqlBulletinPosts : AbstractSqlDA, IBulletinPosts + { + public SqlBulletinPosts(ISqlContext context) : base(context) + { + } + + public uint Create(DbBulletinPost bulletin) + { + return Context.Connection.Query("INSERT INTO fso_bulletin_posts (neighborhood_id, avatar_id, title, body, date, flags, lot_id, type) " + + " VALUES (@neighborhood_id, @avatar_id, @title, @body, @date, @flags, @lot_id, @string_type); SELECT LAST_INSERT_ID();" + , bulletin).First(); + } + + public bool Delete(uint bulletin_id) + { + return Context.Connection.Execute("DELETE FROM fso_bulletin_posts WHERE bulletin_id = @bulletin_id", new { bulletin_id }) > 0; + } + + public bool SoftDelete(uint bulletin_id) + { + return Context.Connection.Execute("UPDATE fso_bulletin_posts SET deleted = 1 WHERE bulletin_id = @bulletin_id", + new { bulletin_id }) > 0; + } + + public bool SetTypeFlag(uint bulletin_id, DbBulletinType type, int flags) + { + return Context.Connection.Execute("UPDATE fso_bulletin_posts SET flags = @flags, type = @type WHERE bulletin_id = @bulletin_id", + new { bulletin_id, type = type.ToString(), flags }) > 0; + } + + public List GetByNhoodId(uint neighborhood_id, uint timeAfter) + { + return Context.Connection.Query("SELECT * FROM fso_bulletin_posts WHERE deleted = 0 AND neighborhood_id = @neighborhood_id AND date > @timeAfter", + new { neighborhood_id, timeAfter }).ToList(); + } + + public int CountPosts(uint neighborhood_id, uint timeAfter) + { + return Context.Connection.Query("SELECT count(*) FROM fso_bulletin_posts WHERE neighborhood_id = @neighborhood_id AND deleted = 0 AND date > @timeAfter", + new { neighborhood_id, timeAfter }).FirstOrDefault(); + } + + public uint LastPostID(uint neighborhood_id) + { + return Context.Connection.Query("SELECT bulletin_id FROM fso_bulletin_posts WHERE deleted = 0 AND neighborhood_id = @neighborhood_id ORDER BY bulletin_id DESC LIMIT 1", + new { neighborhood_id }).FirstOrDefault(); + } + + public DbBulletinPost Get(uint bulletin_id) + { + return Context.Connection.Query("SELECT * FROM fso_bulletin_posts WHERE bulletin_id = @bulletin_id", + new { bulletin_id }).FirstOrDefault(); + } + + public DbBulletinPost LastUserPost(uint user_id, uint neighborhood_id) + { + return Context.Connection.Query("SELECT b.* FROM fso_bulletin_posts b " + + "JOIN fso_avatars a ON b.avatar_id = a.avatar_id WHERE a.user_id = @user_id AND b.neighborhood_id = @neighborhood_id " + + "ORDER BY b.date DESC " + + "LIMIT 1", + new { user_id, neighborhood_id }).FirstOrDefault(); + } + } +} diff --git a/server/FSO.Server.Database/DA/DbChanges/DbChange.cs b/server/FSO.Server.Database/DA/DbChanges/DbChange.cs new file mode 100755 index 0000000..66e1ea7 --- /dev/null +++ b/server/FSO.Server.Database/DA/DbChanges/DbChange.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.DbChanges +{ + public class DbChange + { + public string id { get; set; } + public string filename { get; set; } + public uint date { get; set; } + public string hash { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/DbEvents/DbEvent.cs b/server/FSO.Server.Database/DA/DbEvents/DbEvent.cs new file mode 100755 index 0000000..b20f66c --- /dev/null +++ b/server/FSO.Server.Database/DA/DbEvents/DbEvent.cs @@ -0,0 +1,41 @@ +using System; + +namespace FSO.Server.Database.DA.DbEvents +{ + public class DbEvent + { + public int event_id { get; set; } + public string title { get; set; } + public string description { get; set; } + public DateTime start_day { get; set; } + public DateTime end_day { get; set; } + public DbEventType type { get; set; } + public int value { get; set; } + public int value2 { get; set; } + public string mail_subject { get; set; } + public string mail_message { get; set; } + public int? mail_sender { get; set; } + public string mail_sender_name { get; set; } + + public string type_str { + get { + return type.ToString(); + } + } + } + + public class DbEventParticipation + { + public int event_id { get; set; } + public uint user_id { get; set; } + } + + public enum DbEventType + { + mail_only, + free_object, + free_money, + free_green, + obj_tuning + } +} diff --git a/server/FSO.Server.Database/DA/DbEvents/DbGenericAvatarParticipation.cs b/server/FSO.Server.Database/DA/DbEvents/DbGenericAvatarParticipation.cs new file mode 100755 index 0000000..d0f7a3e --- /dev/null +++ b/server/FSO.Server.Database/DA/DbEvents/DbGenericAvatarParticipation.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Database.DA.DbEvents +{ + public class DbGenericAvatarParticipation + { + public string participation_name { get; set; } + public uint participation_avatar { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/DbEvents/IEvents.cs b/server/FSO.Server.Database/DA/DbEvents/IEvents.cs new file mode 100755 index 0000000..2e22109 --- /dev/null +++ b/server/FSO.Server.Database/DA/DbEvents/IEvents.cs @@ -0,0 +1,24 @@ +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.DbEvents +{ + public interface IEvents + { + PagedList All(int offset = 0, int limit = 20, string orderBy = "start_day"); + List GetActive(DateTime time); + int Add(DbEvent evt); + bool Delete(int event_id); + + bool TryParticipate(DbEventParticipation p); + bool Participated(DbEventParticipation p); + List GetParticipatingUsers(int event_id); + + bool GenericAvaTryParticipate(DbGenericAvatarParticipation p); + bool GenericAvaParticipated(DbGenericAvatarParticipation p); + List GetGenericParticipatingAvatars(string genericName); + + List GetLatestNameDesc(int limit); + } +} diff --git a/server/FSO.Server.Database/DA/DbEvents/SqlEvents.cs b/server/FSO.Server.Database/DA/DbEvents/SqlEvents.cs new file mode 100755 index 0000000..7448126 --- /dev/null +++ b/server/FSO.Server.Database/DA/DbEvents/SqlEvents.cs @@ -0,0 +1,95 @@ +using System; +using Dapper; +using System.Collections.Generic; +using System.Linq; +using FSO.Server.Database.DA.Utils; + +namespace FSO.Server.Database.DA.DbEvents +{ + public class SqlEvents : AbstractSqlDA, IEvents + { + public SqlEvents(ISqlContext context) : base(context){ + } + + public PagedList All(int offset = 1, int limit = 20, string orderBy = "start_day") + { + var connection = Context.Connection; + var total = connection.Query("SELECT COUNT(*) FROM fso_events").FirstOrDefault(); + var results = connection.Query("SELECT * FROM fso_events ORDER BY @order DESC LIMIT @offset, @limit", new { order = orderBy, offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + public int Add(DbEvent evt) + { + var result = Context.Connection.Query("INSERT INTO fso_events (title, description, start_day, " + + "end_day, type, value, value2, mail_subject, mail_message, mail_sender, mail_sender_name) " + + " VALUES (@title, @description, @start_day, @end_day, @type_str, @value, @value2, " + + " @mail_subject, @mail_message, @mail_sender, @mail_sender_name); SELECT LAST_INSERT_ID();", evt).First(); + return result; + } + + public bool Delete(int event_id) + { + return Context.Connection.Execute("DELETE FROM fso_events WHERE event_id = @event_id", new { event_id = event_id }) > 0; + } + + public List GetActive(DateTime time) + { + return Context.Connection.Query("SELECT * FROM fso_events WHERE start_day <= @time AND end_day >= @time", new { time = time }).ToList(); + } + + public List GetLatestNameDesc(int limit) + { + return Context.Connection.Query("SELECT * FROM fso_events WHERE title IS NOT NULL AND description IS NOT NULL ORDER BY start_day DESC LIMIT "+limit).ToList(); + } + + public List GetParticipatingUsers(int event_id) + { + return Context.Connection.Query("SELECT user_id FROM fso_event_participation WHERE event_id = @event_id", new { event_id = event_id }).ToList(); + } + + public bool Participated(DbEventParticipation p) + { + return Context.Connection.Query("SELECT count(*) FROM fso_event_participation WHERE event_id = @event_id AND user_id = @user_id", p).First() > 0; + } + + public bool TryParticipate(DbEventParticipation p) + { + try + { + return (Context.Connection.Execute("INSERT INTO fso_event_participation (event_id, user_id) VALUES (@event_id, @user_id)", p) > 0); + } + catch + { + //already exists, or foreign key fails + return false; + } + } + + public bool GenericAvaTryParticipate(DbGenericAvatarParticipation p) + { + try + { + return (Context.Connection.Execute("INSERT INTO fso_generic_avatar_participation (participation_name, participation_avatar) " + + "VALUES (@participation_name, @participation_avatar)", p) > 0); + } + catch + { + //already exists, or foreign key fails + return false; + } + } + + public bool GenericAvaParticipated(DbGenericAvatarParticipation p) + { + return Context.Connection.Query("SELECT count(*) FROM fso_generic_avatar_participation " + + "WHERE participation_name = @participation_name AND participation_avatar = @participation_avatar", p).First() > 0; + } + + public List GetGenericParticipatingAvatars(string genericName) + { + return Context.Connection.Query("SELECT participation_avatar FROM fso_generic_avatar_participation " + + "WHERE participation_name = @participation_name", new { participation_name = genericName }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/DynPayouts/DbDynPayout.cs b/server/FSO.Server.Database/DA/DynPayouts/DbDynPayout.cs new file mode 100755 index 0000000..9b5cf0c --- /dev/null +++ b/server/FSO.Server.Database/DA/DynPayouts/DbDynPayout.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.DynPayouts +{ + public class DbDynPayout + { + public int day { get; set; } + public int skilltype { get; set; } + public float multiplier { get; set; } + public int flags { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/DynPayouts/DbTransSummary.cs b/server/FSO.Server.Database/DA/DynPayouts/DbTransSummary.cs new file mode 100755 index 0000000..6514106 --- /dev/null +++ b/server/FSO.Server.Database/DA/DynPayouts/DbTransSummary.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.DynPayouts +{ + public class DbTransSummary + { + public int transaction_type { get; set; } + public int value { get; set; } + public int sum { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/DynPayouts/IDynPayouts.cs b/server/FSO.Server.Database/DA/DynPayouts/IDynPayouts.cs new file mode 100755 index 0000000..7faf9a1 --- /dev/null +++ b/server/FSO.Server.Database/DA/DynPayouts/IDynPayouts.cs @@ -0,0 +1,15 @@ +using FSO.Server.Database.DA.Tuning; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.DynPayouts +{ + public interface IDynPayouts + { + List GetSummary(int limitDay); + bool InsertDynRecord(List dynPayout); + bool ReplaceDynTuning(List dynTuning); + + List GetPayoutHistory(int limitDay); + bool Purge(int limitDay); + } +} diff --git a/server/FSO.Server.Database/DA/DynPayouts/SqlDynPayouts.cs b/server/FSO.Server.Database/DA/DynPayouts/SqlDynPayouts.cs new file mode 100755 index 0000000..58d3e61 --- /dev/null +++ b/server/FSO.Server.Database/DA/DynPayouts/SqlDynPayouts.cs @@ -0,0 +1,59 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; +using FSO.Server.Database.DA.Tuning; +using FSO.Server.Database.DA.Utils; +using System.Data.SqlClient; + +namespace FSO.Server.Database.DA.DynPayouts +{ + public class SqlDynPayouts : AbstractSqlDA, IDynPayouts + { + public SqlDynPayouts(ISqlContext context) : base(context) + { + } + + public List GetPayoutHistory(int limitDay) + { + return Context.Connection.Query("SELECT * FROM fso_dyn_payouts ORDER BY day DESC LIMIT 56", new { limitDay = limitDay }).ToList(); + } + + public List GetSummary(int limitDay) + { + return Context.Connection.Query("SELECT transaction_type, sum(value) AS value, sum(count) AS sum FROM fso.fso_transactions " + +"WHERE transaction_type > 40 AND transaction_type < 51 AND day >= @limitDay GROUP BY transaction_type", new { limitDay = limitDay }).ToList(); + } + + public bool InsertDynRecord(List dynPayout) + { + try + { + Context.Connection.ExecuteBufferedInsert("INSERT INTO fso_dyn_payouts (day, skilltype, multiplier, flags) VALUES (@day, @skilltype, @multiplier, @flags) ON DUPLICATE KEY UPDATE multiplier = @multiplier", dynPayout, 100); + } + catch (SqlException) + { + return false; + } + return true; + } + + public bool Purge(int limitDay) + { + Context.Connection.Query("DELETE FROM fso_dyn_payouts WHERE day < @day", new { day = limitDay }); + return true; + } + + public bool ReplaceDynTuning(List dynTuning) + { + try + { + var deleted = Context.Connection.Execute("DELETE FROM fso_tuning WHERE owner_type = 'DYNAMIC' AND owner_id = 1"); + Context.Connection.ExecuteBufferedInsert("INSERT INTO fso_tuning (tuning_type, tuning_table, tuning_index, value, owner_type, owner_id) VALUES (@tuning_type, @tuning_table, @tuning_index, @value, @owner_type, @owner_id)", dynTuning, 100); + } catch (SqlException) + { + return false; + } + return true; + } + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbElectionCandidate.cs b/server/FSO.Server.Database/DA/Elections/DbElectionCandidate.cs new file mode 100755 index 0000000..1c74ac4 --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbElectionCandidate.cs @@ -0,0 +1,19 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbElectionCandidate + { + public uint election_cycle_id { get; set; } + public uint candidate_avatar_id { get; set; } + public string comment { get; set; } + public DbCandidateState state { get; set; } + } + + public enum DbCandidateState + { + informed, + running, + disqualified, + lost, + won + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbElectionCycle.cs b/server/FSO.Server.Database/DA/Elections/DbElectionCycle.cs new file mode 100755 index 0000000..91aa8bb --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbElectionCycle.cs @@ -0,0 +1,30 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbElectionCycle + { + public uint cycle_id { get; set; } + public uint start_date { get; set; } + public uint end_date { get; set; } + public DbElectionCycleState current_state { get; set; } + public DbElectionCycleType election_type { get; set; } + + //for free vote + public string name { get; set; } + public int nhood_id { get; set; } + } + + public enum DbElectionCycleState : byte + { + shutdown, + nomination, + election, + ended, + failsafe + } + + public enum DbElectionCycleType : byte + { + election, + shutdown + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbElectionCycleMail.cs b/server/FSO.Server.Database/DA/Elections/DbElectionCycleMail.cs new file mode 100755 index 0000000..9ca1f01 --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbElectionCycleMail.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbElectionCycleMail + { + public uint avatar_id { get; set; } + public uint cycle_id { get; set; } + public DbElectionCycleState cycle_state { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbElectionFreeVote.cs b/server/FSO.Server.Database/DA/Elections/DbElectionFreeVote.cs new file mode 100755 index 0000000..f30cc46 --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbElectionFreeVote.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbElectionFreeVote + { + public uint avatar_id { get; set; } + public int neighborhood_id { get; set; } + public uint cycle_id { get; set; } + public uint date { get; set; } + public uint expire_date { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbElectionVote.cs b/server/FSO.Server.Database/DA/Elections/DbElectionVote.cs new file mode 100755 index 0000000..764bcb2 --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbElectionVote.cs @@ -0,0 +1,18 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbElectionVote + { + public uint election_cycle_id { get; set; } + public uint from_avatar_id { get; set; } + public DbElectionVoteType type { get; set; } + public uint target_avatar_id { get; set; } + public uint date { get; set; } + public int value { get; set; } + } + + public enum DbElectionVoteType + { + vote, + nomination + } +} diff --git a/server/FSO.Server.Database/DA/Elections/DbMayorRating.cs b/server/FSO.Server.Database/DA/Elections/DbMayorRating.cs new file mode 100755 index 0000000..93d2abc --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/DbMayorRating.cs @@ -0,0 +1,18 @@ +namespace FSO.Server.Database.DA.Elections +{ + public class DbMayorRating + { + public uint rating_id { get; set; } + public uint from_user_id { get; set; } + public uint to_user_id { get; set; } + + public uint rating { get; set; } + public string comment { get; set; } + public uint date { get; set; } + + public uint from_avatar_id { get; set; } + public uint to_avatar_id { get; set; } + public byte anonymous { get; set; } + public uint neighborhood { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Elections/IElections.cs b/server/FSO.Server.Database/DA/Elections/IElections.cs new file mode 100755 index 0000000..bd33faf --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/IElections.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Elections +{ + public interface IElections + { + DbElectionCycle GetCycle(uint cycle_id); + DbElectionCandidate GetCandidate(uint avatar_id, uint cycle_id, DbCandidateState state); + List GetActiveCycles(int shard_id); + List GetCandidates(uint cycle_id, DbCandidateState state); + List GetCandidates(uint cycle_id); + List GetCycleVotes(uint cycle_id, DbElectionVoteType type); + List GetCycleVotesForAvatar(uint avatar_id, uint cycle_id, DbElectionVoteType type); + DbElectionVote GetMyVote(uint avatar_id, uint cycle_id, DbElectionVoteType type); + DbMayorRating GetSpecificRating(uint from_user_id, uint to_avatar_id); + DbMayorRating GetRating(uint rating_id); + List GetRatings(uint to_avatar_id); + float? GetAvgRating(uint to_avatar_id); + bool CreateCandidate(DbElectionCandidate candidate); + bool SetCandidateState(DbElectionCandidate candidate); + bool DeleteCandidate(uint election_cycle_id, uint candidate_avatar_id); + uint CreateCycle(DbElectionCycle cycle); + bool CreateVote(DbElectionVote vote); + void UpdateCycleState(uint cycle_id, DbElectionCycleState state); + uint SetRating(DbMayorRating rating); + bool DeleteRating(uint id); + + bool EmailRegistered(DbElectionCycleMail p); + bool TryRegisterMail(DbElectionCycleMail p); + + bool EnrollFreeVote(DbElectionFreeVote entry); + DbElectionFreeVote GetFreeVote(uint avatar_id); + + DbElectionWin FindLastWin(uint avatar_id); + } + + public class DbElectionWin + { + public uint nhood_id { get; set; } + public string nhood_name { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Elections/SqlElections.cs b/server/FSO.Server.Database/DA/Elections/SqlElections.cs new file mode 100755 index 0000000..873385c --- /dev/null +++ b/server/FSO.Server.Database/DA/Elections/SqlElections.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dapper; +using FSO.Server.Common; + +namespace FSO.Server.Database.DA.Elections +{ + public class SqlElections : AbstractSqlDA, IElections + { + public SqlElections(ISqlContext context) : base(context) + { + } + + public DbElectionCandidate GetCandidate(uint avatar_id, uint cycle_id, DbCandidateState state) + { + return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE candidate_avatar_id = @avatar_id " + + "AND election_cycle_id = @cycle_id AND state = @state", + new { avatar_id, cycle_id, state = state.ToString() }).FirstOrDefault(); + } + + public List GetCandidates(uint cycle_id, DbCandidateState state) + { + return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE election_cycle_id = @cycle_id AND state = @state", + new { cycle_id, state = state.ToString() }).ToList(); + } + + public List GetCandidates(uint cycle_id) + { + return Context.Connection.Query("SELECT * FROM fso_election_candidates WHERE election_cycle_id = @cycle_id", + new { cycle_id }).ToList(); + } + + public List GetActiveCycles(int shard_id) + { + + return Context.Connection.Query("SELECT *, n.neighborhood_id AS 'nhood_id' " + + "FROM fso_election_cycles JOIN fso_neighborhoods n ON election_cycle_id = cycle_id " + + "WHERE current_state != 'shutdown' " + + "AND cycle_id IN (SELECT election_cycle_id FROM fso_neighborhoods WHERE shard_id = @shard_id)", + new { shard_id }).ToList(); + } + + public DbElectionCycle GetCycle(uint cycle_id) + { + return Context.Connection.Query("SELECT * FROM fso_election_cycles WHERE cycle_id = @cycle_id", + new { cycle_id = cycle_id }).FirstOrDefault(); + } + + public List GetCycleVotes(uint cycle_id, DbElectionVoteType type) + { + return Context.Connection.Query("SELECT * FROM fso_election_votes WHERE election_cycle_id = @cycle_id AND type = @type", + new { cycle_id = cycle_id, type = type.ToString() }).ToList(); + } + + public List GetCycleVotesForAvatar(uint avatar_id, uint cycle_id, DbElectionVoteType type) + { + return Context.Connection.Query("SELECT * FROM fso_election_votes WHERE election_cycle_id = @cycle_id AND type = @type " + + "AND target_avatar_id = @avatar_id", + new { avatar_id = avatar_id, cycle_id = cycle_id, type = type.ToString() }).ToList(); + } + + public DbElectionVote GetMyVote(uint avatar_id, uint cycle_id, DbElectionVoteType type) + { + //this isn't as straightforward as you might think. + //we also need to include votes from: + // - other sims on our user + // - other sims on other users that share login ip + //note that this criteria is duplicated in the database in the form of a BEFORE INSERT check. + + var query = "SELECT * from fso_election_votes v INNER JOIN fso_avatars va ON v.from_avatar_id = va.avatar_id " + + "WHERE v.election_cycle_id = @cycle_id AND v.type = @type AND va.user_id IN " + + "(SELECT user_id FROM fso_users WHERE last_ip = " + + "(SELECT last_ip FROM fso_avatars a JOIN fso_users u on a.user_id = u.user_id WHERE avatar_id = @avatar_id)" + + ")"; + + return Context.Connection.Query(query, + new { avatar_id = avatar_id, cycle_id = cycle_id, type = type.ToString() }).FirstOrDefault(); + } + + public bool CreateCandidate(DbElectionCandidate candidate) + { + try + { + var result = Context.Connection.Execute("INSERT INTO fso_election_candidates (election_cycle_id, candidate_avatar_id, comment) " + + "VALUES (@election_cycle_id, @candidate_avatar_id, @comment)", candidate); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool SetCandidateState(DbElectionCandidate candidate) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_election_candidates SET state = @state, comment = @comment " + + "WHERE election_cycle_id = @election_cycle_id AND candidate_avatar_id = @candidate_avatar_id" + , new { state = candidate.state.ToString(), candidate.comment, + candidate.election_cycle_id, candidate.candidate_avatar_id}); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool DeleteCandidate(uint election_cycle_id, uint candidate_avatar_id) + { + try + { + var result = Context.Connection.Execute("DELETE FROM fso_election_candidates " + + "WHERE election_cycle_id = @election_cycle_id AND candidate_avatar_id = @candidate_avatar_id", + new { election_cycle_id = election_cycle_id, candidate_avatar_id = candidate_avatar_id }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public uint CreateCycle(DbElectionCycle cycle) + { + var result = Context.Connection.Query("INSERT INTO fso_election_cycles (start_date, end_date, current_state, election_type) " + + "VALUES (@start_date, @end_date, @current_state, @election_type); SELECT LAST_INSERT_ID();", + new { cycle.start_date, cycle.end_date, + current_state = cycle.current_state.ToString(), + election_type = cycle.election_type.ToString() }).FirstOrDefault(); + return result; + } + + public bool CreateVote(DbElectionVote vote) + { + try + { + var result = Context.Connection.Execute("INSERT INTO fso_election_votes (election_cycle_id, from_avatar_id, type, target_avatar_id, date) " + + "VALUES (@election_cycle_id, @from_avatar_id, @type, @target_avatar_id, @date)", new + { + vote.election_cycle_id, + vote.from_avatar_id, + type = vote.type.ToString(), + vote.target_avatar_id, + vote.date + }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public void UpdateCycleState(uint cycle_id, DbElectionCycleState state) + { + Context.Connection.Query("UPDATE fso_election_cycles SET current_state = @state WHERE cycle_id = @cycle_id", + new { cycle_id = cycle_id, state = state.ToString() }).ToList(); + } + + public DbMayorRating GetSpecificRating(uint from_user_id, uint to_avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_mayor_ratings WHERE from_user_id = @from_user_id " + + "AND to_avatar_id = @to_avatar_id", + new { from_user_id = from_user_id, to_avatar_id = to_avatar_id }).FirstOrDefault(); + } + + public DbMayorRating GetRating(uint rating_id) + { + return Context.Connection.Query("SELECT * FROM fso_mayor_ratings WHERE rating_id = @rating_id ", + new { rating_id = rating_id }).FirstOrDefault(); + } + + + public List GetRatings(uint to_avatar_id) + { + return Context.Connection.Query("SELECT rating_id FROM fso_mayor_ratings WHERE to_avatar_id = @to_avatar_id ORDER BY rating", + new { to_avatar_id = to_avatar_id }).ToList(); + } + + public float? GetAvgRating(uint to_avatar_id) + { + return Context.Connection.Query("SELECT AVG(CAST(rating as DECIMAL(10,6))) FROM fso_mayor_ratings WHERE to_avatar_id = @to_avatar_id", + new { to_avatar_id = to_avatar_id }).FirstOrDefault(); + } + + public uint SetRating(DbMayorRating rating) + { + //first let's try insert our rating. + try + { + var result = Context.Connection.Execute("INSERT INTO fso_mayor_ratings (from_user_id, to_user_id, rating, comment, " + + "date, from_avatar_id, to_avatar_id, anonymous, neighborhood) " + + "VALUES (@from_user_id, @to_user_id, @rating, @comment, " + + "@date, @from_avatar_id, @to_avatar_id, @anonymous, @neighborhood)", rating); + return 0; + } + catch (Exception) + { + //didn't work? probably because the rating is already there. try updating instead. + + Context.Connection.Execute("UPDATE fso_mayor_ratings SET rating = @rating, comment = @comment, date = @date " + + "WHERE from_user_id = @from_user_id AND to_user_id = @to_user_id", rating); + + var id = Context.Connection.Query("SELECT rating_id FROM fso_mayor_ratings WHERE from_user_id = @from_user_id " + + "AND to_user_id = @to_user_id", rating).FirstOrDefault(); + + return id; + } + } + + public bool DeleteRating(uint id) + { + var result = Context.Connection.Execute("DELETE FROM fso_mayor_ratings " + + "WHERE rating_id = @id", new { id = id }); + return (result > 0); + } + + public bool EmailRegistered(DbElectionCycleMail p) + { + return Context.Connection.Query("SELECT count(*) FROM fso_election_cyclemail WHERE cycle_id = @cycle_id AND avatar_id = @avatar_id AND cycle_state = @cycle_state", + new { p.avatar_id, p.cycle_id, cycle_state = p.cycle_state.ToString() }).First() > 0; + } + + public bool TryRegisterMail(DbElectionCycleMail p) + { + try + { + return (Context.Connection.Execute("INSERT INTO fso_election_cyclemail (cycle_id, avatar_id, cycle_state) VALUES (@cycle_id, @avatar_id, @cycle_state)", + new { p.avatar_id, p.cycle_id, cycle_state = p.cycle_state.ToString() }) > 0); + } + catch + { + //already exists, or foreign key fails + return false; + } + } + + public bool EnrollFreeVote(DbElectionFreeVote entry) + { + try + { + return (Context.Connection.Execute("INSERT INTO fso_election_freevotes (avatar_id, neighborhood_id, cycle_id, date, expire_date) " + + "VALUES (@avatar_id, @neighborhood_id, @cycle_id, @date, @expire_date)", + entry) > 0); + } + catch + { + //already exists, or foreign key fails + return false; + } + } + + public DbElectionFreeVote GetFreeVote(uint avatar_id) + { + var result = Context.Connection.Query("SELECT * FROM fso_election_freevotes WHERE avatar_id = @avatar_id", + new { avatar_id }).FirstOrDefault(); + if (result != null && result.expire_date < Epoch.Now) + { + //outdated. delete and set null. + try + { + Context.Connection.Execute("DELETE FROM fso_election_freevotes WHERE avatar_id = @avatar_id", new { avatar_id }); + } + catch (Exception) + { + } + result = null; + } + return result; + } + + public DbElectionWin FindLastWin(uint avatar_id) + { + return Context.Connection.Query("SELECT n.neighborhood_id AS nhood_id, n.name AS nhood_name " + + "FROM (fso_election_candidates e JOIN fso_election_cycles c ON e.election_cycle_id = c.cycle_id) " + + "JOIN fso_neighborhoods n ON c.neighborhood_id = n.neighborhood_id " + + "WHERE e.candidate_avatar_id = @avatar_id AND state = 'won' " + + "ORDER BY e.election_cycle_id DESC LIMIT 1", + new { avatar_id = avatar_id }).FirstOrDefault(); + } + } +} diff --git a/server/FSO.Server.Database/DA/EmailConfirmations/EmailConfirmation.cs b/server/FSO.Server.Database/DA/EmailConfirmations/EmailConfirmation.cs new file mode 100755 index 0000000..1d81bc7 --- /dev/null +++ b/server/FSO.Server.Database/DA/EmailConfirmations/EmailConfirmation.cs @@ -0,0 +1,32 @@ +namespace FSO.Server.Database.DA.EmailConfirmation +{ + /// + /// EmailConfirmation model + /// + public class EmailConfirmation + { + /// + /// Confirmation type. Can be an email confirmation or password + /// reset confirmation. + /// + public ConfirmationType type { get; set; } + /// + /// The user email address. + /// + public string email { get; set; } + /// + /// Randomized token. + /// + public string token { get; set; } + /// + /// Timestamp when the confirmation token will expire. + /// + public uint expires { get; set; } + } + + public enum ConfirmationType + { + email = 1, + password + } +} diff --git a/server/FSO.Server.Database/DA/EmailConfirmations/IEmailConfirmations.cs b/server/FSO.Server.Database/DA/EmailConfirmations/IEmailConfirmations.cs new file mode 100755 index 0000000..c1eb1de --- /dev/null +++ b/server/FSO.Server.Database/DA/EmailConfirmations/IEmailConfirmations.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.EmailConfirmation +{ + public interface IEmailConfirmations + { + string Create(EmailConfirmation confirm); + EmailConfirmation GetByEmail(string email, ConfirmationType type); + EmailConfirmation GetByToken(string token); + void Remove(string token); + } +} \ No newline at end of file diff --git a/server/FSO.Server.Database/DA/EmailConfirmations/SqlEmailConfirmations.cs b/server/FSO.Server.Database/DA/EmailConfirmations/SqlEmailConfirmations.cs new file mode 100755 index 0000000..2bee082 --- /dev/null +++ b/server/FSO.Server.Database/DA/EmailConfirmations/SqlEmailConfirmations.cs @@ -0,0 +1,57 @@ +using System; +using System.Linq; +using Dapper; +using FSO.Server.Common; + +namespace FSO.Server.Database.DA.EmailConfirmation +{ + public class SqlEmailConfirmations : AbstractSqlDA, IEmailConfirmations + { + public SqlEmailConfirmations(ISqlContext context) : base(context) + { + + } + + public EmailConfirmation GetByToken(string token) + { + var confirm = Context.Connection.Query("SELECT * FROM fso_email_confirm WHERE token = @token", new { token = token }).FirstOrDefault(); + + if(confirm==null) { return null; } + + if(Epoch.Now > confirm.expires) + { + Remove(confirm.token); + return null; + } + + return confirm; + } + + public EmailConfirmation GetByEmail(string email, ConfirmationType type) + { + var confirm = Context.Connection.Query("SELECT * FROM fso_email_confirm WHERE email = @email AND type = @type", new { email = email, type = type }).FirstOrDefault(); + + if (confirm == null) { return null; } + + if (Epoch.Now > confirm.expires) + { + Remove(confirm.token); + return null; + } + + return confirm; + } + + public string Create(EmailConfirmation confirm) + { + confirm.token = Guid.NewGuid().ToString().ToUpper(); + Context.Connection.Execute("INSERT INTO fso_email_confirm (type, email, token, expires) VALUES (@type, @email, @token, @expires)", confirm); + return confirm.token; + } + + public void Remove(string token) + { + Context.Connection.Execute("DELETE FROM fso_email_confirm WHERE token = @token", new { token = token }); + } + } +} diff --git a/server/FSO.Server.Database/DA/GlobalCooldowns/DbGlobalCooldowns.cs b/server/FSO.Server.Database/DA/GlobalCooldowns/DbGlobalCooldowns.cs new file mode 100755 index 0000000..db48dc0 --- /dev/null +++ b/server/FSO.Server.Database/DA/GlobalCooldowns/DbGlobalCooldowns.cs @@ -0,0 +1,13 @@ +using System; + +namespace FSO.Server.Database.DA.GlobalCooldowns +{ + public class DbGlobalCooldowns + { + public uint object_guid { get; set; } + public uint avatar_id { get; set; } + public uint user_id { get; set; } + public uint category { get; set; } + public DateTime expiry { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/GlobalCooldowns/IGlobalCooldowns.cs b/server/FSO.Server.Database/DA/GlobalCooldowns/IGlobalCooldowns.cs new file mode 100755 index 0000000..8083ab2 --- /dev/null +++ b/server/FSO.Server.Database/DA/GlobalCooldowns/IGlobalCooldowns.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.GlobalCooldowns +{ + public interface IGlobalCooldowns + { + DbGlobalCooldowns Get(uint objguid, uint avatarid, bool useAccount, uint category); + List GetAllByObj(uint objguid); + List GetAllByAvatar(uint avatarid); + List GetAllByObjectAndAvatar(uint objguid, uint avatarid); + bool Create(DbGlobalCooldowns cooldown); + bool Update(DbGlobalCooldowns cooldown); + } +} diff --git a/server/FSO.Server.Database/DA/GlobalCooldowns/SqlGlobalCooldowns.cs b/server/FSO.Server.Database/DA/GlobalCooldowns/SqlGlobalCooldowns.cs new file mode 100755 index 0000000..a3ab841 --- /dev/null +++ b/server/FSO.Server.Database/DA/GlobalCooldowns/SqlGlobalCooldowns.cs @@ -0,0 +1,49 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.GlobalCooldowns +{ + public class SqlGlobalCooldowns : AbstractSqlDA, IGlobalCooldowns + { + public SqlGlobalCooldowns(ISqlContext context) : base(context) + { + } + + public DbGlobalCooldowns Get(uint objguid, uint avatarOrUserid, bool useAccount, uint category) + { + if (useAccount) + return Context.Connection.Query("SELECT * FROM fso_global_cooldowns WHERE object_guid = @guid AND " + + "user_id = @id AND category = @category", new { guid = objguid, id = avatarOrUserid, category = category }).FirstOrDefault(); + else + return Context.Connection.Query("SELECT * FROM fso_global_cooldowns WHERE object_guid = @guid AND " + + "avatar_id = @id AND category = @category", new { guid = objguid, id = avatarOrUserid, category = category }).FirstOrDefault(); + } + + public List GetAllByObj(uint objguid) + { + return Context.Connection.Query("SELECT * FROM fso_global_cooldowns WHERE object_guid = @guid", new { guid = objguid }).ToList(); + } + + public List GetAllByAvatar(uint avatarid) + { + return Context.Connection.Query("SELECT * FROM fso_global_cooldowns WHERE avatar_id = @avatarid", new { avatarid = avatarid }).ToList(); + } + + public List GetAllByObjectAndAvatar(uint objguid, uint avatarid) + { + return Context.Connection.Query("SELECT * FROM fso_global_cooldowns WHERE object_guid = @guid AND " + + "avatar_id = @avatarid", new { guid = objguid, avatarid = avatarid }).ToList(); + } + public bool Create(DbGlobalCooldowns newCooldown) + { + return Context.Connection.Execute("INSERT INTO fso_global_cooldowns (object_guid, avatar_id, user_id, category, expiry) " + + "VALUES (@object_guid, @avatar_id, @user_id, @category, @expiry)", newCooldown) > 0; + } + public bool Update(DbGlobalCooldowns updatedCooldown) + { + return Context.Connection.Execute("UPDATE fso_global_cooldowns SET expiry = @expiry WHERE object_guid = @object_guid AND " + + "avatar_id = @avatar_id AND user_id = @user_id AND category = @category", updatedCooldown) > 0; + } + } +} diff --git a/server/FSO.Server.Database/DA/Hosts/DbHost.cs b/server/FSO.Server.Database/DA/Hosts/DbHost.cs new file mode 100755 index 0000000..036ef5c --- /dev/null +++ b/server/FSO.Server.Database/DA/Hosts/DbHost.cs @@ -0,0 +1,28 @@ +using System; + +namespace FSO.Server.Database.DA.Hosts +{ + public class DbHost + { + public string call_sign { get; set; } + public DbHostRole role { get; set; } + public DbHostStatus status { get; set; } + public string internal_host { get; set; } + public string public_host { get; set; } + public DateTime time_boot { get; set; } + public int? shard_id { get; set; } + } + + public enum DbHostRole + { + city, + lot, + task + } + + public enum DbHostStatus + { + up, + down + } +} diff --git a/server/FSO.Server.Database/DA/Hosts/IHosts.cs b/server/FSO.Server.Database/DA/Hosts/IHosts.cs new file mode 100755 index 0000000..4d5511f --- /dev/null +++ b/server/FSO.Server.Database/DA/Hosts/IHosts.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Hosts +{ + public interface IHosts + { + IEnumerable All(); + DbHost Get(string call_sign); + void CreateHost(DbHost host); + void SetStatus(string call_sign, DbHostStatus status); + } +} diff --git a/server/FSO.Server.Database/DA/Hosts/SqlHosts.cs b/server/FSO.Server.Database/DA/Hosts/SqlHosts.cs new file mode 100755 index 0000000..8a119bf --- /dev/null +++ b/server/FSO.Server.Database/DA/Hosts/SqlHosts.cs @@ -0,0 +1,49 @@ +using Dapper; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Hosts +{ + public class SqlHosts : AbstractSqlDA, IHosts + { + public SqlHosts(ISqlContext context) : base(context) + { + } + + public IEnumerable All() + { + return Context.Connection.Query("SELECT * FROM fso_hosts"); + } + + public void CreateHost(DbHost host) + { + Context.Connection.Execute( + "REPLACE INTO fso_hosts (call_sign, role, status, internal_host, public_host, time_boot, shard_id) " + + "VALUES (@call_sign, @role, @status, @internal_host, @public_host, @time_boot, @shard_id)", + new + { + call_sign = host.call_sign, + role = host.role.ToString(), + status = host.status.ToString(), + internal_host = host.internal_host, + public_host = host.public_host, + time_boot = host.time_boot, + shard_id = host.shard_id + } + ); + } + + public DbHost Get(string call_sign) + { + throw new NotImplementedException(); + } + + public void SetStatus(string call_sign, DbHostStatus status) + { + Context.Connection.Execute("UPDATE fso_hosts SET status = @status WHERE call_sign = @call_sign", new { + call_sign = call_sign, + status = status.ToString() + }); + } + } +} diff --git a/server/FSO.Server.Database/DA/IDA.cs b/server/FSO.Server.Database/DA/IDA.cs new file mode 100755 index 0000000..9d4762a --- /dev/null +++ b/server/FSO.Server.Database/DA/IDA.cs @@ -0,0 +1,73 @@ +using FSO.Server.Database.DA.AuthTickets; +using FSO.Server.Database.DA.AvatarClaims; +using FSO.Server.Database.DA.Avatars; +using FSO.Server.Database.DA.Bans; +using FSO.Server.Database.DA.Bonus; +using FSO.Server.Database.DA.Bookmarks; +using FSO.Server.Database.DA.DbEvents; +using FSO.Server.Database.DA.Hosts; +using FSO.Server.Database.DA.Inbox; +using FSO.Server.Database.DA.LotAdmit; +using FSO.Server.Database.DA.LotClaims; +using FSO.Server.Database.DA.Lots; +using FSO.Server.Database.DA.LotTop100; +using FSO.Server.Database.DA.LotVisitors; +using FSO.Server.Database.DA.LotVisitTotals; +using FSO.Server.Database.DA.Objects; +using FSO.Server.Database.DA.Outfits; +using FSO.Server.Database.DA.Relationships; +using FSO.Server.Database.DA.Roommates; +using FSO.Server.Database.DA.Shards; +using FSO.Server.Database.DA.Tasks; +using FSO.Server.Database.DA.Users; +using FSO.Server.Database.DA.Tuning; +using System; +using FSO.Server.Database.DA.Transactions; +using FSO.Server.Database.DA.DynPayouts; +using FSO.Server.Database.DA.EmailConfirmation; +using FSO.Server.Database.DA.Neighborhoods; +using FSO.Server.Database.DA.Elections; +using FSO.Server.Database.DA.Bulletin; +using FSO.Server.Database.DA.Updates; +using FSO.Server.Database.DA.GlobalCooldowns; + +namespace FSO.Server.Database.DA +{ + public interface IDA : IDisposable + { + IUsers Users { get; } + IBans Bans { get; } + IAuthTickets AuthTickets { get; } + IShards Shards { get; } + IAvatars Avatars { get; } + IObjects Objects { get; } + IRelationships Relationships { get; } + IRoommates Roommates { get; } + ILots Lots { get; } + ILotAdmit LotAdmit { get; } + ILotClaims LotClaims { get; } + INeighborhoods Neighborhoods { get; } + IElections Elections { get; } + IBulletinPosts BulletinPosts { get; } + IAvatarClaims AvatarClaims { get; } + IBookmarks Bookmarks { get; } + IOutfits Outfits { get; } + ILotVisits LotVisits { get; } + ILotVisitTotals LotVisitTotals { get; } + ILotTop100 LotTop100 { get; } + IBonus Bonus { get; } + IInbox Inbox { get; } + IEvents Events { get; } + ITuning Tuning { get; } + IDynPayouts DynPayouts { get; } + ITransactions Transactions { get; } + + //System tables + IHosts Hosts { get; } + ITasks Tasks { get; } + IEmailConfirmations EmailConfirmations { get; } + IUpdates Updates { get; } + IGlobalCooldowns GlobalCooldowns { get; } + void Flush(); + } +} diff --git a/server/FSO.Server.Database/DA/IDAFactory.cs b/server/FSO.Server.Database/DA/IDAFactory.cs new file mode 100755 index 0000000..7c2632e --- /dev/null +++ b/server/FSO.Server.Database/DA/IDAFactory.cs @@ -0,0 +1,7 @@ +namespace FSO.Server.Database.DA +{ + public interface IDAFactory + { + IDA Get(); + } +} diff --git a/server/FSO.Server.Database/DA/ISqlContext.cs b/server/FSO.Server.Database/DA/ISqlContext.cs new file mode 100755 index 0000000..65c59b8 --- /dev/null +++ b/server/FSO.Server.Database/DA/ISqlContext.cs @@ -0,0 +1,11 @@ +using System; +using System.Data.Common; + +namespace FSO.Server.Database.DA +{ + public interface ISqlContext : IDisposable + { + DbConnection Connection { get; } + void Flush(); + } +} diff --git a/server/FSO.Server.Database/DA/Inbox/DbInboxMsg.cs b/server/FSO.Server.Database/DA/Inbox/DbInboxMsg.cs new file mode 100755 index 0000000..3b3fb0d --- /dev/null +++ b/server/FSO.Server.Database/DA/Inbox/DbInboxMsg.cs @@ -0,0 +1,19 @@ +using System; + +namespace FSO.Server.Database.DA.Inbox +{ + public class DbInboxMsg + { + public int message_id { get; set; } + public uint sender_id { get; set; } + public uint target_id { get; set; } + public string subject { get; set; } + public string body { get; set; } + public string sender_name { get; set; } + public DateTime time { get; set; } + public int msg_type { get; set; } + public int msg_subtype { get; set; } + public int read_state { get; set; } + public int? reply_id { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Inbox/IInbox.cs b/server/FSO.Server.Database/DA/Inbox/IInbox.cs new file mode 100755 index 0000000..0c0d820 --- /dev/null +++ b/server/FSO.Server.Database/DA/Inbox/IInbox.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Inbox +{ + public interface IInbox + { + List GetMessages(uint avatarID); + List GetMessagesAfter(uint avatarID, DateTime after); + DbInboxMsg Get(int msgID); + int CreateMessage(DbInboxMsg msg); + bool DeleteMessage(int msgID, uint avatarID); + bool DeleteMessage(int msgID); + } +} diff --git a/server/FSO.Server.Database/DA/Inbox/SqlInbox.cs b/server/FSO.Server.Database/DA/Inbox/SqlInbox.cs new file mode 100755 index 0000000..f727358 --- /dev/null +++ b/server/FSO.Server.Database/DA/Inbox/SqlInbox.cs @@ -0,0 +1,47 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Inbox +{ + public class SqlInbox : AbstractSqlDA, IInbox + { + public SqlInbox(ISqlContext context) : base(context){ + } + + public int CreateMessage(DbInboxMsg msg) + { + var result = Context.Connection.Query("INSERT INTO fso_inbox (sender_id, target_id, subject, " + + "body, sender_name, time, msg_type, msg_subtype, read_state) " + + " VALUES (@sender_id, @target_id, @subject, @body, @sender_name, " + + " @time, @msg_type, @msg_subtype, @read_state); SELECT LAST_INSERT_ID();", msg).First(); + return result; + } + + public bool DeleteMessage(int msgID) + { + return Context.Connection.Execute("DELETE FROM fso_inbox WHERE message_id = @id", new { id = msgID }) > 0; + } + + public bool DeleteMessage(int msgID, uint avatarID) + { + return Context.Connection.Execute("DELETE FROM fso_inbox WHERE message_id = @id AND target_id = @aid", new { id = msgID, aid = avatarID }) > 0; + } + + public DbInboxMsg Get(int msgID) + { + return Context.Connection.Query("SELECT * FROM fso_inbox WHERE message_id = @id", new { id = msgID }).FirstOrDefault(); + } + + public List GetMessages(uint avatarID) + { + return Context.Connection.Query("SELECT * FROM fso_inbox WHERE target_id = @id", new { id = avatarID }).ToList(); + } + + public List GetMessagesAfter(uint avatarID, DateTime after) + { + return Context.Connection.Query("SELECT * FROM fso_inbox WHERE target_id = @id AND time > @after", new { id = avatarID, after = after }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/LotAdmit/DbLotAdmit.cs b/server/FSO.Server.Database/DA/LotAdmit/DbLotAdmit.cs new file mode 100755 index 0000000..78f8e4c --- /dev/null +++ b/server/FSO.Server.Database/DA/LotAdmit/DbLotAdmit.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.LotAdmit +{ + public class DbLotAdmit + { + public int lot_id { get; set; } + public uint avatar_id { get; set; } + public byte admit_type { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/LotAdmit/ILotAdmit.cs b/server/FSO.Server.Database/DA/LotAdmit/ILotAdmit.cs new file mode 100755 index 0000000..21382ae --- /dev/null +++ b/server/FSO.Server.Database/DA/LotAdmit/ILotAdmit.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotAdmit +{ + public interface ILotAdmit + { + List GetLotInfo(int lot_id); + List GetLotAdmitDeny(int lot_id, byte admit_mode); + void Create(DbLotAdmit bookmark); + bool Delete(DbLotAdmit bookmark); + } +} diff --git a/server/FSO.Server.Database/DA/LotAdmit/SqlLotAdmit.cs b/server/FSO.Server.Database/DA/LotAdmit/SqlLotAdmit.cs new file mode 100755 index 0000000..c74098a --- /dev/null +++ b/server/FSO.Server.Database/DA/LotAdmit/SqlLotAdmit.cs @@ -0,0 +1,35 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.LotAdmit +{ + public class SqlLotAdmit : AbstractSqlDA, ILotAdmit + { + public SqlLotAdmit(ISqlContext context) : base(context) + { + } + + public void Create(DbLotAdmit bookmark) + { + Context.Connection.Execute("INSERT INTO fso_lot_admit (lot_id, avatar_id, admit_type) " + + " VALUES (@lot_id, @avatar_id, @admit_type)" + , bookmark); + } + + public bool Delete(DbLotAdmit bookmark) + { + return Context.Connection.Execute("DELETE FROM fso_lot_admit WHERE lot_id = @lot_id AND admit_type = @admit_type AND avatar_id = @avatar_id", bookmark) > 0; + } + + public List GetLotInfo(int lot_id) + { + return Context.Connection.Query("SELECT * FROM fso_lot_admit WHERE lot_id = @lot_id", new { lot_id = lot_id }).ToList(); + } + + public List GetLotAdmitDeny(int lot_id, byte admit_type) + { + return Context.Connection.Query("SELECT avatar_id FROM fso_lot_admit WHERE lot_id = @lot_id AND admit_type = @admit_type", new { lot_id = lot_id, admit_type = admit_type }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/LotClaims/DbLotClaim.cs b/server/FSO.Server.Database/DA/LotClaims/DbLotClaim.cs new file mode 100755 index 0000000..cba550b --- /dev/null +++ b/server/FSO.Server.Database/DA/LotClaims/DbLotClaim.cs @@ -0,0 +1,29 @@ +namespace FSO.Server.Database.DA.LotClaims +{ + public class DbLotClaim + { + public int claim_id { get; set; } + public int shard_id { get; set; } + public int lot_id { get; set; } + public string owner { get; set; } + } + + public class DbLotStatus + { + public uint location { get; set; } + public int active { get; set; } + } + + public class DbLotActive + { + public int lot_id { get; set; } + public int shard_id { get; set; } + public string name { get; set; } + public string description { get; set; } + public uint location { get; set; } + public uint neighborhood_id { get; set; } + public uint admit_mode { get; set; } + public FSO.Common.Enum.LotCategory category { get; set; } + public int active { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/LotClaims/ILotClaims.cs b/server/FSO.Server.Database/DA/LotClaims/ILotClaims.cs new file mode 100755 index 0000000..d159332 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotClaims/ILotClaims.cs @@ -0,0 +1,22 @@ +using FSO.Common.Enum; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotClaims +{ + public interface ILotClaims + { + uint? TryCreate(DbLotClaim claim); + IEnumerable GetAllByOwner(string owner); + + bool Claim(uint id, string previousOwner, string newOwner); + DbLotClaim Get(uint id); + DbLotClaim GetByLotID(int id); + + void RemoveAllByOwner(string owner); + void Delete(uint id, string owner); + List AllLocations(int shardId); + List AllActiveLots(int shardId); + List Top100Filter(int shard_id, LotCategory category, int limit); + List RecentsFilter(uint avatar_id, int limit); + } +} diff --git a/server/FSO.Server.Database/DA/LotClaims/SqlLotsClaims.cs b/server/FSO.Server.Database/DA/LotClaims/SqlLotsClaims.cs new file mode 100755 index 0000000..cbbdda3 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotClaims/SqlLotsClaims.cs @@ -0,0 +1,105 @@ +using Dapper; +using FSO.Common.Enum; +using MySql.Data.MySqlClient; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.LotClaims +{ + public class SqlLotClaims : AbstractSqlDA, ILotClaims + { + public SqlLotClaims(ISqlContext context) : base(context){ + } + + public bool Claim(uint id, string previousOwner, string newOwner) + { + try + { + Context.Connection.Query("UPDATE fso_lot_claims SET owner = @owner WHERE claim_id = @claim_id AND owner = @previous_owner", new { claim_id = (int)id, previous_owner = previousOwner, owner = newOwner }); + var newClaim = Context.Connection.Query("SELECT * FROM fso_lot_claims WHERE claim_id = @claim_id AND owner = @owner", new { claim_id = (int)id, owner = newOwner }).FirstOrDefault(); + return newClaim != null; + } + catch (MySqlException ex) + { + return false; + } + } + + public void Delete(uint id, string owner) + { + Context.Connection.Query("DELETE FROM fso_lot_claims WHERE owner = @owner AND claim_id = @claim_id", new { owner = owner, claim_id = (int)id }); + } + + public DbLotClaim Get(uint id) + { + return Context.Connection.Query("SELECT * FROM fso_lot_claims WHERE claim_id = @claim_id", new { claim_id = (int)id }).FirstOrDefault(); + } + + public DbLotClaim GetByLotID(int id) + { + return Context.Connection.Query("SELECT * FROM fso_lot_claims WHERE lot_id = @lot_id", new { lot_id = id }).FirstOrDefault(); + } + + public IEnumerable GetAllByOwner(string owner) + { + return Context.Connection.Query("SELECT * FROM fso_lot_claims WHERE owner = @owner", new { owner = owner }); + } + + public void RemoveAllByOwner(string owner) + { + Context.Connection.Query("DELETE FROM fso_lot_claims WHERE owner = @owner", new { owner = owner }); + } + + public uint? TryCreate(DbLotClaim claim){ + + try { + return (uint)Context.Connection.Query("INSERT INTO fso_lot_claims (shard_id, lot_id, owner) " + + " VALUES (@shard_id, @lot_id, @owner); SELECT LAST_INSERT_ID();", claim).First(); + }catch(MySqlException ex){ + return null; + } + } + + public List AllLocations(int shard_id) + { + return Context.Connection.Query("SELECT b.location AS location, active " + + "FROM fso.fso_lot_claims AS a " + + "JOIN fso.fso_lots AS b " + + "ON a.lot_id = b.lot_id " + + "JOIN(SELECT location, COUNT(*) as active FROM fso_avatar_claims GROUP BY location) AS c " + + "ON b.location = c.location WHERE a.shard_id = @shard_id", new { shard_id = shard_id }).ToList(); + } + + public List AllActiveLots(int shard_id) + { + return Context.Connection.Query("SELECT b.*, active "+ + "FROM fso.fso_lot_claims as a "+ + "right JOIN fso.fso_lots as b ON a.lot_id = b.lot_id "+ + "JOIN (select location, count(*) as active FROM fso.fso_avatar_claims group by location) as c "+ + "on b.location = c.location where a.shard_id = @shard_id", new { shard_id = shard_id }).ToList(); + } + + public List Top100Filter(int shard_id, LotCategory category, int limit) + { + return Context.Connection.Query("SELECT b.location AS location, active " + + "FROM fso.fso_lot_claims AS a " + + "JOIN fso.fso_lots AS b " + + "ON a.lot_id = b.lot_id " + + "JOIN(SELECT location, COUNT(*) as active FROM fso_avatar_claims GROUP BY location) AS c " + + "ON b.location = c.location WHERE a.shard_id = @shard_id " + + "AND category = @category AND active > 0 " + + "ORDER BY active DESC " + + "LIMIT @limit", new { shard_id = shard_id, category = category.ToString(), limit = limit }).ToList(); + } + + public List RecentsFilter(uint avatar_id, int limit) + { + return Context.Connection.Query("SELECT b.location " + + "FROM fso_lot_visits a JOIN fso_lots b ON a.lot_id = b.lot_id " + + "WHERE avatar_id = @avatar_id " + + "GROUP BY a.lot_id " + + "ORDER BY MAX(time_created) DESC " + + "LIMIT @limit", new { avatar_id = avatar_id, limit = limit }).ToList(); + } + } +} diff --git a/server/FSO.Server.Database/DA/LotTop100/DbLotTop100.cs b/server/FSO.Server.Database/DA/LotTop100/DbLotTop100.cs new file mode 100755 index 0000000..aad2b8a --- /dev/null +++ b/server/FSO.Server.Database/DA/LotTop100/DbLotTop100.cs @@ -0,0 +1,19 @@ +using FSO.Common.Enum; +using System; + +namespace FSO.Server.Database.DA.LotTop100 +{ + public class DbLotTop100 + { + public LotCategory category { get; set; } + public byte rank { get; set; } + public int shard_id { get; set; } + public int? lot_id { get; set; } + public int? minutes { get; set; } + public DateTime date { get; set; } + + //Joins + public string lot_name { get; set; } + public uint? lot_location { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/LotTop100/ILotTop100.cs b/server/FSO.Server.Database/DA/LotTop100/ILotTop100.cs new file mode 100755 index 0000000..56b9711 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotTop100/ILotTop100.cs @@ -0,0 +1,15 @@ +using FSO.Common.Enum; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotTop100 +{ + public interface ILotTop100 + { + void Replace(IEnumerable values); + IEnumerable All(); + IEnumerable GetAllByShard(int shard_id); + IEnumerable GetByCategory(int shard_id, LotCategory category); + bool Calculate(DateTime date, int shard_id); + } +} diff --git a/server/FSO.Server.Database/DA/LotTop100/SqlLotTop100.cs b/server/FSO.Server.Database/DA/LotTop100/SqlLotTop100.cs new file mode 100755 index 0000000..8cc9c59 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotTop100/SqlLotTop100.cs @@ -0,0 +1,67 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Linq; +using FSO.Common.Enum; + +namespace FSO.Server.Database.DA.LotTop100 +{ + public class SqlLotTop100 : AbstractSqlDA, ILotTop100 + { + public SqlLotTop100(ISqlContext context) : base(context) + { + } + + public IEnumerable All() + { + return Context.Connection.Query("SELECT top.*, l.name as lot_name, l.location as lot_location FROM fso_lot_top_100 top LEFT JOIN fso_lots l ON top.lot_id = l.lot_id"); + } + + public bool Calculate(DateTime date, int shard_id) + { + try + { + Context.Connection.Execute("CALL fso_lot_top_100_calc_all(@date, @shard_id);", new { date = date, shard_id = shard_id }); + return true; + }catch(Exception ex) + { + return false; + } + } + public IEnumerable GetAllByShard(int shard_id) + { + return Context.Connection.Query("SELECT top.*, l.name as lot_name, l.location as lot_location FROM fso_lot_top_100 top LEFT JOIN fso_lots l ON top.lot_id = l.lot_id WHERE top.shard_id = @shard_id", new + { + shard_id = shard_id + }); + } + public IEnumerable GetByCategory(int shard_id, LotCategory category) + { + return Context.Connection.Query("SELECT top.*, l.name as lot_name, l.location as lot_location FROM fso_lot_top_100 top LEFT JOIN fso_lots l ON top.lot_id = l.lot_id WHERE top.category = @category AND top.shard_id = @shard_id", new + { + category = category.ToString(), + shard_id = shard_id + }); + } + + public void Replace(IEnumerable values) + { + try { + var valuesConverted = values.Select(x => { + return new + { + category = x.category.ToString(), + rank = x.rank, + shard_id = x.shard_id, + lot_id = x.lot_id, + minutes = x.minutes + }; + }); + + Context.Connection.Execute("REPLACE INTO fso_lot_top_100 (category, rank, shard_id, lot_id, minutes) VALUES (@category, @rank, @shard_id, @lot_id, @minutes)", valuesConverted); + }catch(Exception ex) + { + } + } + } +} diff --git a/server/FSO.Server.Database/DA/LotVisitTotals/DbLotVisitTotal.cs b/server/FSO.Server.Database/DA/LotVisitTotals/DbLotVisitTotal.cs new file mode 100755 index 0000000..a158c89 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisitTotals/DbLotVisitTotal.cs @@ -0,0 +1,11 @@ +using System; + +namespace FSO.Server.Database.DA.LotVisitTotals +{ + public class DbLotVisitTotal + { + public int lot_id { get; set; } + public DateTime date { get; set; } + public int minutes { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/LotVisitTotals/ILotVisitTotals.cs b/server/FSO.Server.Database/DA/LotVisitTotals/ILotVisitTotals.cs new file mode 100755 index 0000000..a061977 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisitTotals/ILotVisitTotals.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotVisitTotals +{ + public interface ILotVisitTotals + { + void Insert(IEnumerable input); + void Purge(DateTime date); + } +} diff --git a/server/FSO.Server.Database/DA/LotVisitTotals/SqlLotVisitTotals.cs b/server/FSO.Server.Database/DA/LotVisitTotals/SqlLotVisitTotals.cs new file mode 100755 index 0000000..98e68ac --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisitTotals/SqlLotVisitTotals.cs @@ -0,0 +1,28 @@ +using Dapper; +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotVisitTotals +{ + public class SqlLotVisitTotals : AbstractSqlDA, ILotVisitTotals + { + public SqlLotVisitTotals(ISqlContext context) : base(context) + { + } + + public void Insert(IEnumerable input) + { + try { + Context.Connection.ExecuteBufferedInsert("INSERT INTO fso_lot_visit_totals (lot_id, date, minutes) VALUES (@lot_id, @date, @minutes) ON DUPLICATE KEY UPDATE minutes=VALUES(minutes)", input, 100); + }catch(Exception ex) + { + } + } + + public void Purge(DateTime date) + { + Context.Connection.Execute("DELETE FROM fso_lot_visit_totals WHERE date < @date", new { date = date }); + } + } +} diff --git a/server/FSO.Server.Database/DA/LotVisits/DbLotVisit.cs b/server/FSO.Server.Database/DA/LotVisits/DbLotVisit.cs new file mode 100755 index 0000000..604c47f --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisits/DbLotVisit.cs @@ -0,0 +1,37 @@ +using FSO.Common.Enum; +using System; + +namespace FSO.Server.Database.DA.LotVisitors +{ + public class DbLotVisit + { + public int lot_visit_id { get; set; } + public uint avatar_id { get; set; } + public int lot_id { get; set; } + public DbLotVisitorType type { get; set; } + public DbLotVisitorStatus status { get; set; } + public DateTime time_created { get; set; } + public DateTime? time_closed { get; set; } + } + + public class DbLotVisitNhood : DbLotVisit + { + public uint neighborhood_id { get; set; } + public uint location { get; set; } + public LotCategory category { get; set; } + } + + public enum DbLotVisitorType + { + owner, + roommate, + visitor + } + + public enum DbLotVisitorStatus + { + active, + closed, + failed + } +} diff --git a/server/FSO.Server.Database/DA/LotVisits/ILotVisits.cs b/server/FSO.Server.Database/DA/LotVisits/ILotVisits.cs new file mode 100755 index 0000000..519e34c --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisits/ILotVisits.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.LotVisitors +{ + public interface ILotVisits + { + /// + /// Records a new visit to a lot. A visit id is returned which can be used to record + /// when the visit ends + /// + /// + /// + /// + /// + int? Visit(uint avatar_id, DbLotVisitorType visitor_type, int lot_id); + + /// + /// Records that a visit has ended + /// + /// + void Leave(int visit_id); + + /// + /// Updates the timestamp on active visits. This helps detect the difference between + /// a long visit and an error where the visit did not get closed. + /// + /// This also lets us calculate Top 100 without downtime as we can be inclusive + /// of active tickets + /// + /// + void Renew(IEnumerable visit_ids); + + /// + /// Purge data older than the date given + /// + /// + void PurgeByDate(DateTime date); + + /// + /// + /// + /// + /// + /// + IEnumerable StreamBetween(int shard_id, DateTime start, DateTime end); + + /// + /// + /// + /// + /// + /// + IEnumerable StreamBetweenPlusNhood(int shard_id, DateTime start, DateTime end); + + /// + /// + /// + /// + /// + /// + IEnumerable StreamBetweenOneNhood(uint nhood_id, DateTime start, DateTime end); + + + } +} diff --git a/server/FSO.Server.Database/DA/LotVisits/LotVisitUtils.cs b/server/FSO.Server.Database/DA/LotVisits/LotVisitUtils.cs new file mode 100755 index 0000000..36b2d90 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisits/LotVisitUtils.cs @@ -0,0 +1,50 @@ +using System; + +namespace FSO.Server.Database.DA.LotVisits +{ + public static class LotVisitUtils + { + /// + /// Calculates the overlap between two date ranges. + /// Useful utility function for calculating visit hours. + /// + /// + /// + /// + public static TimeSpan CalculateDateOverlap(DateTime r1_start, DateTime r1_end, DateTime r2_start, DateTime r2_end) + { + var startsInRange = r2_start >= r1_start && r2_start <= r1_end; + var endsInRange = r2_end <= r1_end && r2_end >= r1_start; + + if (startsInRange && endsInRange) + { + //Within the range / equal + return r2_end.Subtract(r2_start); + } + else if (startsInRange) + { + //Starts within range but does not end in range + return r1_end.Subtract(r2_start); + } + else if (endsInRange) + { + //Ends in range but does not start in range + return r2_end.Subtract(r1_start); + } + else + { + return new TimeSpan(0); + } + } + + /// + /// Returns midnight of the current day. + /// Useful utility function for calculating visit hours. + /// + public static DateTime Midnight() + { + var now = DateTime.UtcNow; + return new DateTime(now.Year, now.Month, now.Day, 0, 0, 0); + } + } +} diff --git a/server/FSO.Server.Database/DA/LotVisits/SqlLotVisits.cs b/server/FSO.Server.Database/DA/LotVisits/SqlLotVisits.cs new file mode 100755 index 0000000..2ac75b5 --- /dev/null +++ b/server/FSO.Server.Database/DA/LotVisits/SqlLotVisits.cs @@ -0,0 +1,82 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.LotVisitors +{ + public class SqlLotVisits : AbstractSqlDA, ILotVisits + { + public SqlLotVisits(ISqlContext context) : base(context){ + } + + public int? Visit(uint avatar_id, DbLotVisitorType visitor_type, int lot_id) + { + try { + //Stored procedure will handle erroring any active visits that should no longer be active + return Context.Connection.Query("SELECT `fso_lot_visits_create`(@avatar_id, @lot_id, @type)", new { + avatar_id = avatar_id, + lot_id = lot_id, + type = visitor_type.ToString() + }).First(); + }catch(Exception ex){ + return null; + } + } + + public void Leave(int visit_id) + { + try + { + Context.Connection.Query("UPDATE `fso_lot_visits` SET status = 'closed', time_closed = current_timestamp WHERE lot_visit_id = @visit_id AND `status` = 'active'", new { visit_id = visit_id }); + }catch(Exception ex){ + } + } + + public void Renew(IEnumerable visit_ids) + { + try{ + Context.Connection.Query("UPDATE `fso_lot_visits` SET time_closed = current_timestamp WHERE lot_visit_id IN @visit_ids AND `status` = 'active'", new { visit_ids = visit_ids }); + }catch (Exception ex){ + } + } + + public void PurgeByDate(DateTime date) + { + Context.Connection.Query("DELETE FROM `fso_lot_visits` WHERE time_closed IS NOT NULL AND time_closed < @date", new { date = date }); + Context.Connection.Query("DELETE FROM `fso_lot_visits` WHERE time_closed IS NULL AND time_created < @date", new { date = date }); + } + + public IEnumerable StreamBetween(int shard_id, DateTime start, DateTime end) + { + return Context.Connection.Query( + "SELECT * FROM `fso_lot_visits` v INNER JOIN fso_lots l ON v.lot_id = l.lot_id " + + "WHERE l.shard_id = @shard_id AND status != 'failed' " + + "AND time_closed IS NOT NULL " + + "AND type = 'visitor' " + + "AND (time_created BETWEEN @start AND @end OR time_closed BETWEEN @start and @end)", + new { start = start, end = end, shard_id = shard_id }, buffered: false); + } + + public IEnumerable StreamBetweenPlusNhood(int shard_id, DateTime start, DateTime end) + { + return Context.Connection.Query( + "SELECT * FROM `fso_lot_visits` v INNER JOIN fso_lots l ON v.lot_id = l.lot_id " + + "WHERE l.shard_id = @shard_id AND status != 'failed' " + + "AND time_closed IS NOT NULL " + + "AND (time_created BETWEEN @start AND @end OR time_closed BETWEEN @start and @end)", + new { start = start, end = end, shard_id = shard_id }, buffered: false); + } + + public IEnumerable StreamBetweenOneNhood(uint neighborhood_id, DateTime start, DateTime end) + { + return Context.Connection.Query( + "SELECT * FROM `fso_lot_visits` v INNER JOIN fso_lots l ON v.lot_id = l.lot_id " + + "WHERE l.neighborhood_id = @neighborhood_id AND status != 'failed' " + + "AND time_closed IS NOT NULL " + + "AND type = 'visitor' " + + "AND (time_created BETWEEN @start AND @end OR time_closed BETWEEN @start and @end)", + new { start = start, end = end, neighborhood_id = neighborhood_id }, buffered: false); + } + } +} diff --git a/server/FSO.Server.Database/DA/Lots/DbLot.cs b/server/FSO.Server.Database/DA/Lots/DbLot.cs new file mode 100755 index 0000000..937c98f --- /dev/null +++ b/server/FSO.Server.Database/DA/Lots/DbLot.cs @@ -0,0 +1,51 @@ +using FSO.Common.Enum; + +namespace FSO.Server.Database.DA.Lots +{ + public class DbLot + { + public int lot_id { get; set; } + public int shard_id { get; set; } + public uint? owner_id { get; set; } + + public string name { get; set; } + public string description { get; set; } + public uint location { get; set; } + public uint neighborhood_id { get; set; } + public uint created_date { get; set; } + public uint category_change_date { get; set; } + public LotCategory category { get; set; } + public byte skill_mode { get; set; } + public uint buildable_area { get; set; } + public sbyte ring_backup_num { get; set; } + public byte admit_mode { get; set; } + public byte move_flags { get; set; } + + public byte thumb3d_dirty { get; set; } + public uint thumb3d_time { get; set; } + } + + /**Lot + Lot_BuildableArea : Uint32 (0) + Lot_NumOccupants : Uint8 (0) + Lot_SpotLightText : string (0) + Lot_Location : Location (0) + Lot_NeighborhoodCentered : Uint32 (0) + Lot_Thumbnail : iunknown (0) + Lot_NeighborhoodName : string (0) + Lot_NeighborhoodID : Uint32 (0) + Lot_OwnerVec : Uint32 (2) + Lot_IsOnline : bool (0) + Lot_TerrainType : Uint32 (0) + Lot_LeaderID : Uint32 (0) + Lot_Name : string (0) + Lot_DBID : Uint32 (0) + Lot_PossibleNeighborhoodsVector : Uint32 (2) + Lot_RoommateVec : Uint32 (2) + Lot_LotAdmitInfo : LotAdmitInfo (0) + Lot_Description : string (0) + Lot_Price : Uint32 (0) + Lot_HoursSinceLastLotCatChange : Uint32 (0) + Lot_ThumbnailCheckSum : Uint32 (0) + Lot_Category : Uint8 (0)**/ +} diff --git a/server/FSO.Server.Database/DA/Lots/DbLotServerTicket.cs b/server/FSO.Server.Database/DA/Lots/DbLotServerTicket.cs new file mode 100755 index 0000000..04d3761 --- /dev/null +++ b/server/FSO.Server.Database/DA/Lots/DbLotServerTicket.cs @@ -0,0 +1,15 @@ +namespace FSO.Server.Database.DA.Lots +{ + public class DbLotServerTicket + { + public string ticket_id { get; set; } + public uint user_id { get; set; } + public uint date { get; set; } + public string ip { get; set; } + public uint avatar_id { get; set; } + public int lot_id { get; set; } + public int avatar_claim_id { get; set; } + public string avatar_claim_owner { get; set; } + public string lot_owner { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Lots/ILots.cs b/server/FSO.Server.Database/DA/Lots/ILots.cs new file mode 100755 index 0000000..9725129 --- /dev/null +++ b/server/FSO.Server.Database/DA/Lots/ILots.cs @@ -0,0 +1,47 @@ +using FSO.Common.Enum; +using FSO.Server.Database.DA.Utils; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Lots +{ + public interface ILots + { + IEnumerable All(int shard_id); + PagedList AllByPage(int shard_id, int offset, int limit, string orderBy); + List GetLocationsInNhood(uint nhood_id); + List GetCommunityLocations(int shard_id); + List AllLocations(int shard_id); + DbLot GetByName(int shard_id, string name); + DbLot GetByLocation(int shard_id, uint location); + List GetAdjToLocation(int shard_id, uint location); + DbLot GetByOwner(uint owner_id); + DbLot Get(int id); + List GetMultiple(int[] ids); + List Get(IEnumerable ids); + uint Create(DbLot lot); + bool Delete(int id); + + void RenameLot(int id, string newName); + void SetDirty(int id, byte dirty); + DbLot Get3DWork(); + + List SearchExact(int shard_id, string name, int limit); + List SearchWildcard(int shard_id, string name, int limit); + + void UpdateRingBackup(int lot_id, sbyte ring_backup_num); + void UpdateDescription(int lot_id, string description); + void UpdateLotCategory(int lot_id, LotCategory category, uint skillMode); + void UpdateLotSkillMode(int lot_id, uint skillMode); + void UpdateLotAdmitMode(int lot_id, byte admit_mode); + bool UpdateLocation(int lot_id, uint location, bool startFresh); + void UpdateOwner(int lot_id, uint? avatar_id); + void ReassignOwner(int lot_id); + + void CreateLotServerTicket(DbLotServerTicket ticket); + void DeleteLotServerTicket(string id); + DbLotServerTicket GetLotServerTicket(string id); + List GetLotServerTicketsForClaimedAvatar(int claim_id); + + int UpdateAllNeighborhoods(int shard_id); + } +} diff --git a/server/FSO.Server.Database/DA/Lots/SqlLots.cs b/server/FSO.Server.Database/DA/Lots/SqlLots.cs new file mode 100755 index 0000000..aa12b21 --- /dev/null +++ b/server/FSO.Server.Database/DA/Lots/SqlLots.cs @@ -0,0 +1,296 @@ +using Dapper; +using FSO.Common.Enum; +using FSO.Server.Common; +using FSO.Server.Database.DA.Roommates; +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Lots +{ + public class SqlLots : AbstractSqlDA, ILots + { + public SqlLots(ISqlContext context) : base(context){ + } + + public DbLot Get(int id){ + return Context.Connection.Query("SELECT * FROM fso_lots WHERE lot_id = @id", new { id = id }).FirstOrDefault(); + } + public List GetMultiple(int[] id) + { + String inClause = "IN ("; + for (int i = 0; i < id.Length; i++) + { + inClause = inClause + "'" + id.ElementAt(i) + "'" + ","; + } + inClause = inClause.Substring(0, inClause.Length - 1); + inClause = inClause + ")"; + + return Context.Connection.Query( + "SELECT * FROM fso_lots WHERE lot_id " + inClause + ).ToList(); + } + + public List Get(IEnumerable ids) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE lot_id in @ids", new { ids = ids }).ToList(); + } + + /// + /// Special. We need to create the lot and assign an owner level roommate entry immediately, so we need to use a transaction. + /// + /// + /// + public uint Create(DbLot lot) + { + string failReason = "NAME"; + var t = Context.Connection.BeginTransaction(); + try + { + var result = (uint)Context.Connection.Query("INSERT INTO fso_lots (shard_id, name, description, " + + "owner_id, location, neighborhood_id, created_date, category_change_date, category, buildable_area) " + + " VALUES (@shard_id, @name, @description, @owner_id, @location, " + + " @neighborhood_id, @created_date, @category_change_date, @category, @buildable_area); SELECT LAST_INSERT_ID();", new + { + shard_id = lot.shard_id, + name = lot.name, + description = lot.description, + owner_id = lot.owner_id, + location = lot.location, + neighborhood_id = lot.neighborhood_id, + created_date = lot.created_date, + category_change_date = lot.category_change_date, + category = lot.category.ToString(), + buildable_area = lot.buildable_area + }).First(); + failReason = "NHOOD"; + UpdateNeighborhood((int)result); + if (lot.category != LotCategory.community) + { + failReason = "ROOMIE"; + var roomie = new DbRoommate() + { + avatar_id = lot.owner_id ?? 0, + is_pending = 0, + lot_id = (int)result, + permissions_level = 2 + }; + var result2 = Context.Connection.Execute("INSERT INTO fso_roommates (avatar_id, lot_id, permissions_level, is_pending) " + + " VALUES (@avatar_id, @lot_id, @permissions_level, @is_pending);", roomie) > 0; + if (result2) + { + t.Commit(); + return result; + } + } else + { + t.Commit(); + return result; + } + } catch (Exception) + { + } + t.Rollback(); + throw new Exception(failReason); + } + + public bool Delete(int id) + { + return Context.Connection.Execute("DELETE FROM fso_lots WHERE lot_id = @id", new { id = id }) > 0; + } + + public DbLot GetByOwner(uint owner_id) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE owner_id = @id AND category != 'community'", new { id = owner_id }).FirstOrDefault(); + } + + public IEnumerable All(int shard_id) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE shard_id = @shard_id", new { shard_id = shard_id }); + } + public PagedList AllByPage(int shard_id, int offset = 1, int limit = 100, string orderBy = "lot_id") + { + var total = Context.Connection.Query("SELECT COUNT(*) FROM fso_lots WHERE shard_id = @shard_id", new { shard_id = shard_id }).FirstOrDefault(); + var results = Context.Connection.Query("SELECT * FROM fso_lots WHERE shard_id = @shard_id ORDER BY @order DESC LIMIT @offset, @limit", new { shard_id = shard_id, order = orderBy, offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + public List AllLocations(int shard_id) + { + return Context.Connection.Query("SELECT location, name FROM fso_lots WHERE shard_id = @shard_id", new { shard_id = shard_id }).ToList(); + } + + public List GetLocationsInNhood(uint nhood_id) + { + return Context.Connection.Query("SELECT location FROM fso_lots WHERE neighborhood_id = @nhood_id", new { nhood_id = nhood_id }).ToList(); + } + + public List GetCommunityLocations(int shard_id) + { + return Context.Connection.Query("SELECT location FROM fso_lots WHERE shard_id = @shard_id AND (category = 'community' OR category = 'recent')", new { shard_id = shard_id }).ToList(); + } + + public List AllNames(int shard_id) + { + return Context.Connection.Query("SELECT name FROM fso_lots WHERE shard_id = @shard_id", new { shard_id = shard_id }).ToList(); + } + + public DbLot GetByName(int shard_id, string name) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE name = @name AND shard_id = @shard_id", new { name, shard_id = shard_id }).FirstOrDefault(); + } + + public DbLot GetByLocation(int shard_id, uint location) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE location = @location AND shard_id = @shard_id", new { location = location, shard_id = shard_id }).FirstOrDefault(); + } + + public List GetAdjToLocation(int shard_id, uint location) + { + return Context.Connection.Query("SELECT * FROM fso_lots WHERE " + + "(ABS(CAST((location&65535) AS SIGNED) - CAST((@location&65535) AS SIGNED)) = 1 OR ABS(CAST((location/65536) AS SIGNED) - CAST((@location/65536) AS SIGNED)) = 1) " + + "AND shard_id = @shard_id AND move_flags = 0", new { location = location, shard_id = shard_id }).ToList(); + } + + public void RenameLot(int id, string newName) + { + Context.Connection.Query("UPDATE fso_lots SET name = @name WHERE lot_id = @id", new { name = newName, id = id }); + } + + public void SetDirty(int id, byte dirty) + { + if (dirty == 0) + { + Context.Connection.Query("UPDATE fso_lots SET thumb3d_dirty = @dirty, thumb3d_time = @time WHERE lot_id = @id", new { time = Epoch.Now, dirty = dirty, id = id }); + } else + { + Context.Connection.Query("UPDATE fso_lots SET thumb3d_dirty = @dirty WHERE lot_id = @id", new { dirty = dirty, id = id }); + } + } + + public DbLot Get3DWork() + { + var item = Context.Connection.Query("SELECT * FROM fso_lots WHERE thumb3d_dirty = 1 AND thumb3d_time < @time ORDER BY thumb3d_time LIMIT 1", new { time = Epoch.Now - 300 }).FirstOrDefault(); + if (item != null) + { + SetDirty(item.lot_id, 0); + } + return item; + } + + public List SearchExact(int shard_id, string name, int limit) + { + return Context.Connection.Query( + "SELECT lot_id, location, name FROM fso_lots WHERE shard_id = @shard_id AND name = @name LIMIT @limit", + new { shard_id = shard_id, name = name, limit = limit } + ).ToList(); + } + + public List SearchWildcard(int shard_id, string name, int limit) + { + name = name + .Replace("!", "!!") + .Replace("%", "!%") + .Replace("_", "!_") + .Replace("[", "!["); //must sanitize format... + return Context.Connection.Query( + "SELECT lot_id, location, name FROM fso_lots WHERE shard_id = @shard_id AND name LIKE @name LIMIT @limit", + new { shard_id = shard_id, name = "%" + name + "%", limit = limit } + ).ToList(); + } + + public void UpdateRingBackup(int lot_id, sbyte ring_backup_num) + { + Context.Connection.Query("UPDATE fso_lots SET ring_backup_num = @ring_backup_num, move_flags = 0 WHERE lot_id = @id", + new { ring_backup_num = ring_backup_num, id = lot_id }); + } + + + public void CreateLotServerTicket(DbLotServerTicket ticket) + { + Context.Connection.Execute("INSERT INTO fso_lot_server_tickets VALUES (@ticket_id, @user_id, @date, @ip, @avatar_id, @lot_id, @avatar_claim_id, @avatar_claim_owner, @lot_owner)", ticket); + } + + public void DeleteLotServerTicket(string id) + { + Context.Connection.Execute("DELETE FROM fso_lot_server_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }); + } + + public DbLotServerTicket GetLotServerTicket(string id) + { + return Context.Connection.Query("SELECT * FROM fso_lot_server_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }).FirstOrDefault(); + } + + public List GetLotServerTicketsForClaimedAvatar(int claim_id) + { + return Context.Connection.Query("SELECT * FROM fso_lot_server_tickets WHERE avatar_claim_id = @claim_id", new { claim_id = claim_id }).ToList(); + } + + public void UpdateDescription(int lot_id, string description) + { + Context.Connection.Query("UPDATE fso_lots SET description = @desc WHERE lot_id = @id", new { id = lot_id, desc = description }); + } + + public void UpdateOwner(int lot_id, uint? avatar_id) + { + Context.Connection.Query("UPDATE fso_lots SET owner_id = @owner_id WHERE lot_id = @id", new { id = lot_id, owner_id = avatar_id }); + } + + public void ReassignOwner(int lot_id) + { + Context.Connection.Query("UPDATE fso_lots SET owner_id = (SELECT avatar_id FROM fso_roommates WHERE is_pending = 0 AND lot_id = @id LIMIT 1) WHERE lot_id = @id", new { id = lot_id }); + Context.Connection.Query("UPDATE fso_roommates SET permissions_level = 2 WHERE avatar_id = (SELECT owner_id FROM fso_lots WHERE lot_id = @id LIMIT 1) AND lot_id = @id", new { id = lot_id }); + } + + public void UpdateLotSkillMode(int lot_id, uint skillMode) + { + Context.Connection.Query("UPDATE fso_lots SET skill_mode = @skillMode WHERE lot_id = @id", + new { id = lot_id, skillMode = skillMode }); + } + + public void UpdateLotCategory(int lot_id, LotCategory category, uint skillMode) + { + Context.Connection.Query("UPDATE fso_lots SET category = @category, category_change_date = @time, skill_mode = @skillMode WHERE lot_id = @id", + new { id = lot_id, category = category.ToString(), time = Epoch.Now, skillMode = skillMode }); + } + + public void UpdateLotAdmitMode(int lot_id, byte admit_mode) + { + Context.Connection.Query("UPDATE fso_lots SET admit_mode = @admit_mode WHERE lot_id = @id", new { id = lot_id, admit_mode = admit_mode }); + } + + public bool UpdateLocation(int lot_id, uint location, bool startFresh) + { + var success = Context.Connection.Execute("UPDATE fso_lots SET location = @location, move_flags = @move WHERE lot_id = @id", new { id = lot_id, location = location, move = (byte)(startFresh?2:1) }) > 0; + if (success) + UpdateNeighborhood(lot_id); + return success; + } + + private static string NHoodQuery = + "UPDATE fso.fso_lots l " + + "SET neighborhood_id = " + + "COALESCE((SELECT neighborhood_id " + + "FROM fso.fso_neighborhoods n " + + "ORDER BY(POWER(((l.location & 65535) + 0.0) - ((n.location & 65535) + 0.0), 2) + " + + "POWER((FLOOR(l.location / 65536) + 0.0) - (FLOOR(n.location / 65536) + 0.0), 2)) " + + "LIMIT 1), 0) "; + + public int UpdateAllNeighborhoods(int shard_id) + { + return Context.Connection.Execute( + NHoodQuery + + "WHERE l.shard_id = @shard_id" + , new { shard_id = shard_id }); + } + + public bool UpdateNeighborhood(int lot_id) + { + return (Context.Connection.Execute( + NHoodQuery + + "WHERE l.lot_id = @lot_id" + , new { lot_id = lot_id })) > 0; + } + } +} diff --git a/server/FSO.Server.Database/DA/MySqlContext.cs b/server/FSO.Server.Database/DA/MySqlContext.cs new file mode 100755 index 0000000..44e7f3a --- /dev/null +++ b/server/FSO.Server.Database/DA/MySqlContext.cs @@ -0,0 +1,46 @@ +using MySql.Data.MySqlClient; +using System; +using System.Data; +using System.Data.Common; + +namespace FSO.Server.Database.DA +{ + public class MySqlContext : ISqlContext, IDisposable + { + private readonly string _connectionString; + private DbConnection _connection; + + public MySqlContext(string connectionString) + { + this._connectionString = connectionString; + } + + public DbConnection Connection + { + get + { + if (_connection == null) + _connection = new MySqlConnection(_connectionString); + + if (_connection.State != ConnectionState.Open) + _connection.Open(); + + return _connection; + } + } + + public void Dispose() + { + if (_connection != null) + { + _connection.Dispose(); + _connection = null; + } + } + + public void Flush() + { + Dispose(); + } + } +} diff --git a/server/FSO.Server.Database/DA/MySqlDAFactory.cs b/server/FSO.Server.Database/DA/MySqlDAFactory.cs new file mode 100755 index 0000000..ddb0d64 --- /dev/null +++ b/server/FSO.Server.Database/DA/MySqlDAFactory.cs @@ -0,0 +1,17 @@ +namespace FSO.Server.Database.DA +{ + public class MySqlDAFactory : IDAFactory + { + private DatabaseConfiguration Config; + + public MySqlDAFactory(DatabaseConfiguration config) + { + this.Config = config; + } + + public IDA Get() + { + return new SqlDA(new MySqlContext(Config.ConnectionString)); + } + } +} diff --git a/server/FSO.Server.Database/DA/Neighborhoods/DbNeighborhood.cs b/server/FSO.Server.Database/DA/Neighborhoods/DbNeighborhood.cs new file mode 100755 index 0000000..e33798e --- /dev/null +++ b/server/FSO.Server.Database/DA/Neighborhoods/DbNeighborhood.cs @@ -0,0 +1,22 @@ +namespace FSO.Server.Database.DA.Neighborhoods +{ + public class DbNeighborhood + { + public int neighborhood_id { get; set; } + public string name { get; set; } + public string description { get; set; } + public int shard_id { get; set; } + + public uint location { get; set; } + public uint color { get; set; } + public uint flag { get; set; } + + public int? town_hall_id { get; set; } + public string icon_url { get; set; } + public string guid { get; set; } + + public uint? mayor_id { get; set; } + public uint mayor_elected_date { get; set; } + public uint? election_cycle_id { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Neighborhoods/DbNhoodBan.cs b/server/FSO.Server.Database/DA/Neighborhoods/DbNhoodBan.cs new file mode 100755 index 0000000..9818fe4 --- /dev/null +++ b/server/FSO.Server.Database/DA/Neighborhoods/DbNhoodBan.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Neighborhoods +{ + public class DbNhoodBan + { + public uint user_id { get; set; } + public string ban_reason { get; set; } + public uint end_date { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Neighborhoods/INeighborhoods.cs b/server/FSO.Server.Database/DA/Neighborhoods/INeighborhoods.cs new file mode 100755 index 0000000..ef0573f --- /dev/null +++ b/server/FSO.Server.Database/DA/Neighborhoods/INeighborhoods.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Neighborhoods +{ + public interface INeighborhoods + { + List All(int shard_id); + DbNeighborhood Get(uint neighborhood_id); + DbNeighborhood GetByMayor(uint mayor_id); + DbNeighborhood GetByLocation(uint location); + int DeleteMissing(int shard_id, List AllGUIDs); + int UpdateFromJSON(DbNeighborhood update); + int AddNhood(DbNeighborhood update); + void UpdateDescription(uint neighborhood_id, string description); + void UpdateMayor(uint neigh_id, uint? mayor_id); + void UpdateTownHall(uint neigh_id, uint? lot_id); + void UpdateCycle(uint neigh_id, uint? cycle_id); + void UpdateName(uint neighborhood_id, string name); + void UpdateFlag(uint neighborhood_id, uint flag); + + DbNhoodBan GetNhoodBan(uint user_id); + bool AddNhoodBan(DbNhoodBan ban); + + List SearchExact(int shard_id, string name, int limit); + List SearchWildcard(int shard_id, string name, int limit); + } +} diff --git a/server/FSO.Server.Database/DA/Neighborhoods/SqlNeighborhoods.cs b/server/FSO.Server.Database/DA/Neighborhoods/SqlNeighborhoods.cs new file mode 100755 index 0000000..90a3a1e --- /dev/null +++ b/server/FSO.Server.Database/DA/Neighborhoods/SqlNeighborhoods.cs @@ -0,0 +1,150 @@ +using Dapper; +using FSO.Server.Common; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FSO.Server.Database.DA.Neighborhoods +{ + public class SqlNeighborhoods : AbstractSqlDA, INeighborhoods + { + public SqlNeighborhoods(ISqlContext context) : base(context) + { + } + + public int AddNhood(DbNeighborhood hood) + { + var result = Context.Connection.Query("INSERT INTO fso_neighborhoods (name, description, " + + "shard_id, location, color, guid) " + + " VALUES (@name, @description, " + + " @shard_id, @location, @color, @guid); SELECT LAST_INSERT_ID();", hood).First(); + return result; + } + + public int DeleteMissing(int shard_id, List AllGUIDs) + { + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in AllGUIDs) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append("'"+item+"'"); + first = false; + } + sCommand.Append(")"); + + var deleted = Context.Connection.Execute("DELETE FROM fso_neighborhoods WHERE shard_id = @shard_id AND guid NOT IN " + + sCommand.ToString(), new { shard_id = shard_id }); + + return deleted; + } + + public List All(int shard_id) + { + return Context.Connection.Query("SELECT * FROM fso_neighborhoods WHERE shard_id = @shard_id", + new { shard_id = shard_id }).ToList(); + } + + public DbNeighborhood Get(uint neighborhood_id) + { + return Context.Connection.Query("SELECT * FROM fso_neighborhoods WHERE neighborhood_id = @neighborhood_id", + new { neighborhood_id = neighborhood_id}).FirstOrDefault(); + } + + public DbNeighborhood GetByMayor(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_neighborhoods WHERE mayor_id = @avatar_id", + new { avatar_id = avatar_id }).FirstOrDefault(); + } + + public DbNeighborhood GetByLocation(uint location) + { + return Context.Connection.Query( + "SELECT neighborhood_id " + + "FROM fso.fso_neighborhoods n " + + "ORDER BY(POWER(((@location & 65535) + 0.0) - ((n.location & 65535) + 0.0), 2) + " + + "POWER((FLOOR(@location / 65536) + 0.0) - (FLOOR(n.location / 65536) + 0.0), 2)) " + + "LIMIT 1", new { location = location }).FirstOrDefault(); + } + + public int UpdateFromJSON(DbNeighborhood update) + { + if (update.description != null) + return Context.Connection.Execute("UPDATE fso_neighborhoods SET name = @name, description = @description, " + + "location = @location, color = @color WHERE guid = @guid AND shard_id = @shard_id", update); + else + return Context.Connection.Execute("UPDATE fso_neighborhoods SET name = @name, location = @location, " + + "color = @color WHERE guid = @guid AND shard_id = @shard_id", update); + } + + public void UpdateDescription(uint neigh_id, string description) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET description = @desc WHERE neighborhood_id = @id", new { id = neigh_id, desc = description }); + } + + public void UpdateMayor(uint neigh_id, uint? mayor_id) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET mayor_id = @mayor_id, mayor_elected_date = @date WHERE neighborhood_id = @id", + new { id = neigh_id, mayor_id = mayor_id, date = Epoch.Now }); + } + + public void UpdateTownHall(uint neigh_id, uint? lot_id) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET town_hall_id = @lot_id WHERE neighborhood_id = @id", new { id = neigh_id, lot_id = lot_id }); + } + + public void UpdateCycle(uint neigh_id, uint? cycle_id) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET election_cycle_id = @cycle_id WHERE neighborhood_id = @id", new { id = neigh_id, cycle_id = cycle_id }); + } + + public void UpdateName(uint neigh_id, string name) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET name = @name WHERE neighborhood_id = @id", new { id = neigh_id, name = name }); + } + + public void UpdateFlag(uint neigh_id, uint flag) + { + Context.Connection.Query("UPDATE fso_neighborhoods SET flag = @flag WHERE neighborhood_id = @id", new { id = neigh_id, flag = flag }); + } + + public DbNhoodBan GetNhoodBan(uint user_id) + { + var date = Epoch.Now; + return Context.Connection.Query("SELECT * FROM fso_nhood_ban WHERE user_id = @user_id AND end_date > @date", + new { user_id = user_id, date = date }).FirstOrDefault(); + } + + public bool AddNhoodBan(DbNhoodBan ban) + { + var result = Context.Connection.Query("INSERT INTO fso_nhood_ban (user_id, ban_reason, end_date) " + + "VALUES (@user_id, @ban_reason, @end_date) " + + "ON DUPLICATE KEY UPDATE ban_reason = @ban_reason, end_date = @end_date; " + + "SELECT LAST_INSERT_ID();", ban).First(); + return result > 0; + } + + public List SearchExact(int shard_id, string name, int limit) + { + return Context.Connection.Query( + "SELECT neighborhood_id, location, name FROM fso_neighborhoods WHERE shard_id = @shard_id AND name = @name LIMIT @limit", + new { shard_id = shard_id, name = name, limit = limit } + ).ToList(); + } + + public List SearchWildcard(int shard_id, string name, int limit) + { + name = name + .Replace("!", "!!") + .Replace("%", "!%") + .Replace("_", "!_") + .Replace("[", "!["); //must sanitize format... + return Context.Connection.Query( + "SELECT neighborhood_id, location, name FROM fso_neighborhoods WHERE shard_id = @shard_id AND name LIKE @name LIMIT @limit", + new { shard_id = shard_id, name = "%" + name + "%", limit = limit } + ).ToList(); + } + + } +} diff --git a/server/FSO.Server.Database/DA/Objects/DbObject.cs b/server/FSO.Server.Database/DA/Objects/DbObject.cs new file mode 100755 index 0000000..c724eb7 --- /dev/null +++ b/server/FSO.Server.Database/DA/Objects/DbObject.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Objects +{ + public class DbObject + { + //general persist idenfification + public uint object_id { get; set; } + public int shard_id { get; set; } + public uint? owner_id { get; set; } + public int? lot_id { get; set; } + + //object info. most of this is unused, but can be used to show state for inventory objects + public string dyn_obj_name { get; set; } + public uint type { get; set; } //guid + public ushort graphic { get; set; } + public uint value { get; set; } + public int budget { get; set; } + public ulong dyn_flags_1 { get; set; } + public ulong dyn_flags_2 { get; set; } + + //upgrades + public uint upgrade_level { get; set; } + + //token system + //if >0, attributes are stored on db rather than in state. + //if 2, we're a value token. (attr 0 contains number that should be displayed in UI) + public byte has_db_attributes { get; set; } + + public List AugmentedAttributes; + } +} diff --git a/server/FSO.Server.Database/DA/Objects/DbObjectAttribute.cs b/server/FSO.Server.Database/DA/Objects/DbObjectAttribute.cs new file mode 100755 index 0000000..b318413 --- /dev/null +++ b/server/FSO.Server.Database/DA/Objects/DbObjectAttribute.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Objects +{ + public class DbObjectAttribute + { + public uint object_id { get; set; } + public int index { get; set; } + public int value { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Objects/IObjects.cs b/server/FSO.Server.Database/DA/Objects/IObjects.cs new file mode 100755 index 0000000..c694897 --- /dev/null +++ b/server/FSO.Server.Database/DA/Objects/IObjects.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Objects +{ + public interface IObjects + { + uint Create(DbObject obj); + + DbObject Get(uint id); + bool Delete(uint id); + IEnumerable All(int shard_id); + List GetAvatarInventory(uint avatar_id); + List GetAvatarInventoryWithAttrs(uint avatar_id); + List ObjOfTypeForAvatar(uint avatar_id, uint guid); + List ObjOfTypeInAvatarInventory(uint avatar_id, uint guid); + List GetObjectOwners(IEnumerable object_ids); + int ReturnLostObjects(uint lot_id, IEnumerable object_ids); + bool ConsumeObjsOfTypeInAvatarInventory(uint avatar_id, uint guid, int num); + List GetByAvatarId(uint avatar_id); + List GetByAvatarIdLot(uint avatar_id, uint lot_id); + int UpdateObjectOwnerLot(uint avatar_id, int lot_id, uint targ_avatar_id, List untradableGUIDs); + + bool UpdatePersistState(uint id, DbObject obj); + bool SetInLot(uint id, uint? lot_id); + + int ChangeInventoryOwners(IEnumerable object_ids, uint oldOwner, uint newOwner); + + List GetObjectAttributes(List objects); + int GetSpecificObjectAttribute(uint objectID, int index); + void SetObjectAttributes(List attrs); + int TotalObjectAttributes(uint guid, int index); + } +} diff --git a/server/FSO.Server.Database/DA/Objects/SqlObjects.cs b/server/FSO.Server.Database/DA/Objects/SqlObjects.cs new file mode 100755 index 0000000..1b91144 --- /dev/null +++ b/server/FSO.Server.Database/DA/Objects/SqlObjects.cs @@ -0,0 +1,225 @@ +using Dapper; +using FSO.Server.Database.DA.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FSO.Server.Database.DA.Objects +{ + public class SqlObjects : AbstractSqlDA, IObjects + { + public SqlObjects(ISqlContext context) : base(context){ + } + + public IEnumerable All(int shard_id) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE shard_id = @shard_id", new { shard_id = shard_id }); + } + + public uint Create(DbObject obj) + { + return (uint)Context.Connection.Query("INSERT INTO fso_objects (shard_id, owner_id, lot_id, " + + "dyn_obj_name, type, graphic, value, budget, upgrade_level, has_db_attributes) " + + " VALUES (@shard_id, @owner_id, @lot_id, @dyn_obj_name, @type," + + " @graphic, @value, @budget, @upgrade_level, @has_db_attributes); SELECT LAST_INSERT_ID();" + , obj).First(); + } + + public DbObject Get(uint id) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE object_id = @object_id", new { object_id = id }).FirstOrDefault(); + } + + public bool Delete(uint id) + { + return Context.Connection.Execute("DELETE FROM fso_objects WHERE object_id = @object_id", new { object_id = id }) > 0; + } + + public List GetAvatarInventory(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE owner_id = @avatar_id AND lot_id IS NULL", new { avatar_id = avatar_id }).ToList(); + } + + public List GetAvatarInventoryWithAttrs(uint avatar_id) + { + var inventory = GetAvatarInventory(avatar_id); + var toLoad = inventory.Where(x => x.has_db_attributes > 0); + if (toLoad.Count() == 0) return inventory; + var attrs = GetObjectAttributes(toLoad.Select(x => x.object_id).ToList()); + foreach (var attr in attrs) + { + var target = toLoad.FirstOrDefault(x => x.object_id == attr.object_id); + if (target == null) continue; + if (target.AugmentedAttributes == null) target.AugmentedAttributes = new List(); + var targList = target.AugmentedAttributes; + while (targList.Count <= attr.index) targList.Add(0); + targList[attr.index] = attr.value; + } + + return inventory; + } + + public List ObjOfTypeForAvatar(uint avatar_id, uint guid) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE owner_id = @avatar_id AND type = @guid", + new { avatar_id = avatar_id, guid = guid }).ToList(); + } + + public List ObjOfTypeInAvatarInventory(uint avatar_id, uint guid) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE owner_id = @avatar_id AND lot_id IS NULL AND type = @guid", + new { avatar_id = avatar_id, guid = guid}).ToList(); + } + + public int ReturnLostObjects(uint lot_id, IEnumerable object_ids) + { + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in object_ids) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append(item); + first = false; + } + sCommand.Append(")"); + + return Context.Connection.Execute("UPDATE fso_objects SET lot_id = NULL WHERE lot_id = @lot_id AND object_id NOT IN " + sCommand.ToString(), new { lot_id = lot_id }); + } + + public List GetObjectOwners(IEnumerable object_ids) + { + if (object_ids.Count() == 0) return new List(); + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in object_ids) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append(item); + first = false; + } + sCommand.Append(")"); + + return Context.Connection.Query("SELECT object_id, lot_id, owner_id FROM fso_objects WHERE object_id IN " + sCommand.ToString()).ToList(); + } + + public bool ConsumeObjsOfTypeInAvatarInventory(uint avatar_id, uint guid, int num) + { + var objs = ObjOfTypeInAvatarInventory(avatar_id, guid); + if (objs.Count < num) return false; + //perform transaction to remove correct number of items from inventory. + var t = Context.Connection.BeginTransaction(); + try + { + var sel = new List(); + for (int i = 0; i < num; i++) sel.Add(objs[i]); + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in sel) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append(item.object_id); + first = false; + } + sCommand.Append(");"); + var deleted = Context.Connection.Execute("DELETE FROM fso_objects WHERE object_id IN "+sCommand.ToString()); + if (deleted != num) throw new Exception("Inventory modified while attempting to delete objects!"); + } catch (Exception) + { + t.Rollback(); + return false; + } + t.Commit(); + return true; + } + + public List GetByAvatarId(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE owner_id = @avatar_id", new { avatar_id = avatar_id }).ToList(); + } + + public List GetByAvatarIdLot(uint avatar_id, uint lot_id) + { + return Context.Connection.Query("SELECT * FROM fso_objects WHERE owner_id = @avatar_id AND lot_id = @lot_id", new { avatar_id = avatar_id, lot_id = lot_id }).ToList(); + } + + public int UpdateObjectOwnerLot(uint avatar_id, int lot_id, uint targ_avatar_id, List untradableGUIDs) + { + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in untradableGUIDs) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append(item); + first = false; + } + sCommand.Append(")"); + + return Context.Connection.Execute("UPDATE fso_objects SET owner_id = @targ_avatar_id WHERE lot_id = @lot_id AND owner_id = @avatar_id AND type NOT IN " + sCommand.ToString(), + new { avatar_id = avatar_id, lot_id = lot_id, targ_avatar_id = targ_avatar_id }); + } + + public bool SetInLot(uint id, uint? lot_id) + { + return Context.Connection.Execute("UPDATE fso_objects SET lot_id = @lot_id WHERE object_id = @object_id AND ((@lot_id IS NULL) OR (lot_id IS NULL))", new { lot_id = lot_id, object_id = id }) > 0; + } + + public bool UpdatePersistState(uint id, DbObject obj) + { + return Context.Connection.Execute("UPDATE fso_objects " + +"SET lot_id = @lot_id, " + + "owner_id = @owner_id, " + + "dyn_obj_name = @dyn_obj_name, " + + "graphic = @graphic, " + + "value = @value, " + + "dyn_flags_1 = @dyn_flags_1, " + + "dyn_flags_2 = @dyn_flags_2, " + + "upgrade_level = @upgrade_level, " + + "has_db_attributes = @has_db_attributes " + + "WHERE object_id = @object_id AND (@lot_id IS NULL OR lot_id = @lot_id);", obj) > 0; + } + + public int ChangeInventoryOwners(IEnumerable object_ids, uint oldOwner, uint newOwner) + { + if (object_ids.Count() == 0) return 0; + var sCommand = new StringBuilder(); + bool first = true; + foreach (var item in object_ids) + { + if (first) sCommand.Append("("); + else sCommand.Append(","); + sCommand.Append(item); + first = false; + } + sCommand.Append(")"); + + return Context.Connection.Execute("UPDATE fso_objects SET owner_id = @newOwner WHERE owner_id = @oldOwner AND object_id IN " + sCommand.ToString(), new { oldOwner = oldOwner, newOwner = newOwner }); + } + + public List GetObjectAttributes(List objects) + { + return Context.Connection.Query("SELECT * FROM fso_object_attributes WHERE object_id in @ids", new { ids = objects }).ToList(); + } + + public int GetSpecificObjectAttribute(uint objectID, int index) + { + return Context.Connection.Query("SELECT value FROM fso_object_attributes WHERE object_id = @object_id AND `index` = @index", new { object_id = objectID, index }).FirstOrDefault(); + } + + public void SetObjectAttributes(List attrs) + { + Context.Connection.ExecuteBufferedInsert("INSERT INTO fso_object_attributes (object_id, `index`, value) VALUES (@object_id, @index, @value) ON DUPLICATE KEY UPDATE value = @value", attrs, 100); + } + + public int TotalObjectAttributes(uint guid, int index) + { + return Context.Connection.Query("SELECT SUM(a.value) " + + "FROM fso_object_attributes a JOIN fso_objects o ON a.object_id = o.object_id " + + "WHERE `type` = @guid AND `index` = @index", new { guid, index }).FirstOrDefault(); + } + } +} diff --git a/server/FSO.Server.Database/DA/Outfits/DbOutfit.cs b/server/FSO.Server.Database/DA/Outfits/DbOutfit.cs new file mode 100755 index 0000000..eb275e9 --- /dev/null +++ b/server/FSO.Server.Database/DA/Outfits/DbOutfit.cs @@ -0,0 +1,22 @@ +using System; + +namespace FSO.Server.Database.DA.Outfits +{ + public class DbOutfit + { + public uint outfit_id { get; set; } + public Nullable avatar_owner { get; set; } + public Nullable object_owner { get; set; } + public ulong asset_id { get; set; } + public int sale_price { get; set; } + public int purchase_price { get; set; } + public byte outfit_type { get; set; } + public DbOutfitSource outfit_source { get; set; } + } + + public enum DbOutfitSource + { + cas, + rack + } +} diff --git a/server/FSO.Server.Database/DA/Outfits/IOutfits.cs b/server/FSO.Server.Database/DA/Outfits/IOutfits.cs new file mode 100755 index 0000000..9af8220 --- /dev/null +++ b/server/FSO.Server.Database/DA/Outfits/IOutfits.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Outfits +{ + public interface IOutfits + { + uint Create(DbOutfit outfit); + List GetByObjectId(uint object_id); + List GetByAvatarId(uint avatar_id); + + bool UpdatePrice(uint outfit_id, uint object_id, int new_price); + bool ChangeOwner(uint outfit_id, uint object_owner, uint new_avatar_owner); + bool DeleteFromObject(uint outfit_id, uint object_id); + bool DeleteFromAvatar(uint outfit_id, uint avatar_id); + } +} diff --git a/server/FSO.Server.Database/DA/Outfits/SqlOutfits.cs b/server/FSO.Server.Database/DA/Outfits/SqlOutfits.cs new file mode 100755 index 0000000..9ae6dfd --- /dev/null +++ b/server/FSO.Server.Database/DA/Outfits/SqlOutfits.cs @@ -0,0 +1,64 @@ +using Dapper; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Outfits +{ + public class SqlOutfits : AbstractSqlDA, IOutfits + { + public SqlOutfits(ISqlContext context) : base(context){ + } + + public uint Create(DbOutfit outfit) + { + try { + return (uint)Context.Connection.Query("INSERT INTO fso_outfits (avatar_owner, object_owner, asset_id, sale_price, purchase_price, outfit_type, outfit_source) " + + " VALUES (@avatar_owner, @object_owner, @asset_id, @sale_price, @purchase_price, @outfit_type, @outfit_source); " + + " SELECT LAST_INSERT_ID();" + , new { + avatar_owner = outfit.avatar_owner, + object_owner = outfit.object_owner, + asset_id = outfit.asset_id, + sale_price = outfit.sale_price, + purchase_price = outfit.purchase_price, + outfit_type = outfit.outfit_type, + outfit_source = outfit.outfit_source.ToString() + }).First(); + }catch(Exception ex){ + return uint.MaxValue; + } + } + + public bool ChangeOwner(uint outfit_id, uint object_owner, uint new_avatar_owner) + { + return Context.Connection.Execute("UPDATE fso_outfits SET avatar_owner = @avatar_owner, object_owner = NULL WHERE outfit_id = @outfit_id and object_owner = @object_owner", new { outfit_id = outfit_id, object_owner = object_owner, avatar_owner = new_avatar_owner }) > 0; + } + + public bool UpdatePrice(uint outfit_id, uint object_owner, int new_price) + { + return Context.Connection.Execute("UPDATE fso_outfits SET sale_price = @sale_price WHERE outfit_id = @outfit_id AND object_owner = @object_owner", new { outfit_id = outfit_id, object_owner = object_owner, sale_price = new_price }) > 0; + } + + public bool DeleteFromObject(uint outfit_id, uint object_id) + { + return Context.Connection.Execute("DELETE FROM fso_outfits WHERE outfit_id = @outfit_id AND object_owner = @object_owner", new { outfit_id = outfit_id, object_owner = object_id }) > 0; + } + + public bool DeleteFromAvatar(uint outfit_id, uint avatar_id) + { + return Context.Connection.Execute("DELETE FROM fso_outfits WHERE outfit_id = @outfit_id AND avatar_owner = @avatar_owner", new { outfit_id = outfit_id, avatar_owner = avatar_id }) > 0; + } + + public List GetByAvatarId(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_outfits WHERE avatar_owner = @avatar_id", new { avatar_id = avatar_id }).ToList(); + } + + public List GetByObjectId(uint object_id) + { + return Context.Connection.Query("SELECT * FROM fso_outfits WHERE object_owner = @object_id", new { object_id = object_id }).ToList(); + } + + } +} diff --git a/server/FSO.Server.Database/DA/Relationships/DbRelationship.cs b/server/FSO.Server.Database/DA/Relationships/DbRelationship.cs new file mode 100755 index 0000000..0439ede --- /dev/null +++ b/server/FSO.Server.Database/DA/Relationships/DbRelationship.cs @@ -0,0 +1,12 @@ +namespace FSO.Server.Database.DA.Relationships +{ + public class DbRelationship + { + public uint from_id { get; set; } + public uint to_id { get; set; } + public int value { get; set; } + public uint index { get; set; } + public uint? comment_id { get; set; } + public uint date { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Relationships/IRelationships.cs b/server/FSO.Server.Database/DA/Relationships/IRelationships.cs new file mode 100755 index 0000000..cda52c2 --- /dev/null +++ b/server/FSO.Server.Database/DA/Relationships/IRelationships.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Relationships +{ + public interface IRelationships + { + int UpdateMany(List entries); + List GetOutgoing(uint entity_id); + List GetBidirectional(uint entity_id); + int Delete(uint entity_id); + } +} diff --git a/server/FSO.Server.Database/DA/Relationships/SqlRelationships.cs b/server/FSO.Server.Database/DA/Relationships/SqlRelationships.cs new file mode 100755 index 0000000..d419f28 --- /dev/null +++ b/server/FSO.Server.Database/DA/Relationships/SqlRelationships.cs @@ -0,0 +1,84 @@ +using Dapper; +using FSO.Server.Common; +using MySql.Data.MySqlClient; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FSO.Server.Database.DA.Relationships +{ + public class SqlRelationships : AbstractSqlDA, IRelationships + { + + public SqlRelationships(ISqlContext context) : base(context) + { + + } + public int Delete(uint entity_id) + { + return Context.Connection.ExecuteScalar( + "DELETE FROM fso_relationships WHERE from_id = @entity_id OR to_id = @entity_id", + new { entity_id = entity_id } + ); + } + + public List GetBidirectional(uint entity_id) + { + return Context.Connection.Query( + "SELECT * FROM fso_relationships WHERE (from_id = @entity_id AND to_id < 16777216) OR (to_id = @entity_id AND from_id < 16777216)", + new { entity_id = entity_id } + ).ToList(); + } + + public List GetOutgoing(uint entity_id) + { + return Context.Connection.Query( + "SELECT * FROM fso_relationships WHERE from_id = @entity_id", + new { entity_id = entity_id } + ).ToList(); + } + + public int UpdateMany(List entries) + { + var date = Epoch.Now; + var conn = (MySqlConnection)Context.Connection; + int rows; + using (MySqlCommand cmd = new MySqlCommand("", conn)) + { + try + { + StringBuilder sCommand = new StringBuilder("INSERT INTO fso_relationships (from_id, to_id, value, `index`, `date`) VALUES "); + + bool first = true; + foreach (var item in entries) + { + if (!first) sCommand.Append(","); + first = false; + sCommand.Append("("); + sCommand.Append(item.from_id); + sCommand.Append(","); + sCommand.Append(item.to_id); + sCommand.Append(","); + sCommand.Append(item.value); + sCommand.Append(","); + sCommand.Append(item.index); + sCommand.Append(","); + sCommand.Append(date); + sCommand.Append(")"); + } + sCommand.Append(" ON DUPLICATE KEY UPDATE value = VALUES(`value`); "); + + cmd.CommandTimeout = 300; + cmd.CommandText = sCommand.ToString(); + rows = cmd.ExecuteNonQuery(); + } + catch (Exception e) + { + return -1; + } + return rows; + } + } + } +} diff --git a/server/FSO.Server.Database/DA/Roommates/DbRoommate.cs b/server/FSO.Server.Database/DA/Roommates/DbRoommate.cs new file mode 100755 index 0000000..1b22ed5 --- /dev/null +++ b/server/FSO.Server.Database/DA/Roommates/DbRoommate.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Database.DA.Roommates +{ + public class DbRoommate + { + public uint avatar_id { get; set; } + public int lot_id { get; set; } + public byte permissions_level { get; set; } + public byte is_pending { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Roommates/IRoommates.cs b/server/FSO.Server.Database/DA/Roommates/IRoommates.cs new file mode 100755 index 0000000..727715c --- /dev/null +++ b/server/FSO.Server.Database/DA/Roommates/IRoommates.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Roommates +{ + public interface IRoommates + { + bool Create(DbRoommate roomie); + bool CreateOrUpdate(DbRoommate roomie); + DbRoommate Get(uint avatar_id, int lot_id); + List GetAvatarsLots(uint avatar_id); + List GetLotRoommates(int lot_id); + uint RemoveRoommate(uint avatar_id, int lot_id); + bool DeclineRoommateRequest(uint avatar_id, int lot_id); + bool AcceptRoommateRequest(uint avatar_id, int lot_id); + bool UpdatePermissionsLevel(uint avatar_id, int lot_id, byte level); + } +} diff --git a/server/FSO.Server.Database/DA/Roommates/SqlRoommates.cs b/server/FSO.Server.Database/DA/Roommates/SqlRoommates.cs new file mode 100755 index 0000000..1d267a1 --- /dev/null +++ b/server/FSO.Server.Database/DA/Roommates/SqlRoommates.cs @@ -0,0 +1,77 @@ +using Dapper; +using System.Collections.Generic; +using System.Data.SqlClient; +using System.Linq; + +namespace FSO.Server.Database.DA.Roommates +{ + public class SqlRoommates : AbstractSqlDA, IRoommates + { + public SqlRoommates(ISqlContext context) : base(context) + { + } + + public bool Create(DbRoommate roomie) + { + try + { + return (uint)Context.Connection.Execute("INSERT INTO fso_roommates (avatar_id, lot_id, permissions_level, is_pending) " + + " VALUES (@avatar_id, @lot_id, @permissions_level, @is_pending);", roomie) > 0; + } catch (SqlException) + { + return false; + } + } + + public bool CreateOrUpdate(DbRoommate roomie) + { + try + { + return (uint)Context.Connection.Execute("INSERT INTO fso_roommates (avatar_id, lot_id, permissions_level, is_pending) " + + "VALUES (@avatar_id, @lot_id, @permissions_level, @is_pending) " + + "ON DUPLICATE KEY UPDATE permissions_level = @permissions_level, is_pending = 0", roomie) > 0; + } + catch (SqlException) + { + return false; + } + } + + public DbRoommate Get(uint avatar_id, int lot_id) + { + return Context.Connection.Query("SELECT * FROM fso_roommates WHERE avatar_id = @avatar_id AND lot_id = @lot_id", + new { avatar_id = avatar_id, lot_id = lot_id }).FirstOrDefault(); + } + public List GetAvatarsLots(uint avatar_id) + { + return Context.Connection.Query("SELECT * FROM fso_roommates WHERE avatar_id = @avatar_id", + new { avatar_id = avatar_id }).ToList(); + } + public List GetLotRoommates(int lot_id) + { + return Context.Connection.Query("SELECT * FROM fso_roommates WHERE lot_id = @lot_id", + new { lot_id = lot_id }).ToList(); + } + public uint RemoveRoommate(uint avatar_id, int lot_id) + { + return (uint)Context.Connection.Execute("DELETE FROM fso_roommates WHERE avatar_id = @avatar_id AND lot_id = @lot_id", + new { avatar_id = avatar_id, lot_id = lot_id }); + } + + public bool DeclineRoommateRequest(uint avatar_id, int lot_id) + { + return Context.Connection.Execute("DELETE FROM fso_roommates WHERE avatar_id = @avatar_id AND lot_id = @lot_id AND is_pending = 1", + new { avatar_id = avatar_id, lot_id = lot_id }) > 0; + } + public bool AcceptRoommateRequest(uint avatar_id, int lot_id) + { + return Context.Connection.Execute("UPDATE fso_roommates SET is_pending = 0 WHERE avatar_id = @avatar_id AND lot_id = @lot_id AND is_pending = 1", + new { avatar_id = avatar_id, lot_id = lot_id }) > 0; + } + public bool UpdatePermissionsLevel(uint avatar_id, int lot_id, byte level) + { + return Context.Connection.Execute("UPDATE fso_roommates SET permissions_level = @level WHERE avatar_id = @avatar_id AND lot_id = @lot_id", + new { level = level, avatar_id = avatar_id, lot_id = lot_id }) > 0; + } + } +} diff --git a/server/FSO.Server.Database/DA/Shards/IShards.cs b/server/FSO.Server.Database/DA/Shards/IShards.cs new file mode 100755 index 0000000..57f17b8 --- /dev/null +++ b/server/FSO.Server.Database/DA/Shards/IShards.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Shards +{ + public interface IShards + { + List All(); + + void CreateTicket(ShardTicket ticket); + void DeleteTicket(string ticket_id); + ShardTicket GetTicket(string ticket_id); + void PurgeTickets(uint time); + void UpdateVersion(int shard_id, string name, string number, int? update_id); + } +} diff --git a/server/FSO.Server.Database/DA/Shards/Shard.cs b/server/FSO.Server.Database/DA/Shards/Shard.cs new file mode 100755 index 0000000..3e445ad --- /dev/null +++ b/server/FSO.Server.Database/DA/Shards/Shard.cs @@ -0,0 +1,26 @@ +namespace FSO.Server.Database.DA.Shards +{ + public class Shard + { + public int shard_id; + public string name; + public int rank; + public string map; + public ShardStatus status; + public string internal_host; + public string public_host; + public string version_name; + public string version_number; + public int? update_id; //new update system. set by whichever server is running the shard. + } + + public enum ShardStatus + { + Up, + Down, + Busy, + Full, + Closed, + Frontier + } +} diff --git a/server/FSO.Server.Database/DA/Shards/ShardTicket.cs b/server/FSO.Server.Database/DA/Shards/ShardTicket.cs new file mode 100755 index 0000000..c93f0fc --- /dev/null +++ b/server/FSO.Server.Database/DA/Shards/ShardTicket.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Database.DA.Shards +{ + public class ShardTicket + { + public string ticket_id { get; set; } + public uint user_id { get; set; } + public uint date { get; set; } + public string ip { get; set; } + public uint avatar_id { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Shards/SqlShards.cs b/server/FSO.Server.Database/DA/Shards/SqlShards.cs new file mode 100755 index 0000000..68f785a --- /dev/null +++ b/server/FSO.Server.Database/DA/Shards/SqlShards.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; +using System.Linq; +using Dapper; + +namespace FSO.Server.Database.DA.Shards +{ + public class SqlShards : AbstractSqlDA, IShards + { + public SqlShards(ISqlContext context) : base(context) { + } + + public List All() + { + return Context.Connection.Query("SELECT * FROM fso_shards").ToList(); + } + + public void CreateTicket(ShardTicket ticket) + { + Context.Connection.Execute("INSERT INTO fso_shard_tickets VALUES (@ticket_id, @user_id, @date, @ip, @avatar_id)", ticket); + } + + public void DeleteTicket(string id) + { + Context.Connection.Execute("DELETE FROM fso_shard_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }); + } + + public ShardTicket GetTicket(string id) + { + return + Context.Connection.Query("SELECT * FROM fso_shard_tickets WHERE ticket_id = @ticket_id", new { ticket_id = id }).FirstOrDefault(); + } + + public void PurgeTickets(uint time) + { + Context.Connection.Query("DELETE FROM fso_shard_tickets WHERE date < @time", new { time = time }); + } + + public void UpdateVersion(int shard_id, string name, string number, int? update_id) + { + Context.Connection.Query("UPDATE fso_shards SET version_name = @version_name, version_number = @version_number, update_id = @update_id WHERE shard_id = @shard_id", new + { + version_name = name, + version_number = number, + update_id = update_id, + shard_id = shard_id + }); + } + } +} diff --git a/server/FSO.Server.Database/DA/SqlDA.cs b/server/FSO.Server.Database/DA/SqlDA.cs new file mode 100755 index 0000000..56d036a --- /dev/null +++ b/server/FSO.Server.Database/DA/SqlDA.cs @@ -0,0 +1,436 @@ +using FSO.Server.Database.DA.Users; +using FSO.Server.Database.DA.AuthTickets; +using FSO.Server.Database.DA.Shards; +using FSO.Server.Database.DA.Avatars; +using FSO.Server.Database.DA.Lots; +using FSO.Server.Database.DA.LotClaims; +using FSO.Server.Database.DA.AvatarClaims; +using FSO.Server.Database.DA.Objects; +using FSO.Server.Database.DA.Relationships; +using FSO.Server.Database.DA.Roommates; +using FSO.Server.Database.DA.Bookmarks; +using FSO.Server.Database.DA.LotAdmit; +using FSO.Server.Database.DA.Outfits; +using FSO.Server.Database.DA.LotVisitors; +using FSO.Server.Database.DA.LotTop100; +using FSO.Server.Database.DA.Hosts; +using FSO.Server.Database.DA.Tasks; +using FSO.Server.Database.DA.Bonus; +using FSO.Server.Database.DA.LotVisitTotals; +using FSO.Server.Database.DA.Bans; +using FSO.Server.Database.DA.Inbox; +using FSO.Server.Database.DA.DbEvents; +using FSO.Server.Database.DA.Tuning; +using FSO.Server.Database.DA.Transactions; +using FSO.Server.Database.DA.DynPayouts; +using FSO.Server.Database.DA.EmailConfirmation; +using FSO.Server.Database.DA.Neighborhoods; +using FSO.Server.Database.DA.Elections; +using FSO.Server.Database.DA.Bulletin; +using FSO.Server.Database.DA.Updates; +using FSO.Server.Database.DA.GlobalCooldowns; + +namespace FSO.Server.Database.DA +{ + public class SqlDA : IDA + { + public ISqlContext Context; + + public SqlDA(ISqlContext context) + { + this.Context = context; + } + + private IUsers _users; + public IUsers Users + { + get + { + if(_users == null) + { + _users = new SqlUsers(Context); + } + return _users; + } + } + + private IBans _bans; + public IBans Bans + { + get + { + if (_bans == null) + { + _bans = new SqlBans(Context); + } + return _bans; + } + } + + private IAuthTickets _authTickets; + public IAuthTickets AuthTickets + { + get + { + if (_authTickets == null) + { + _authTickets = new SqlAuthTickets(Context); + } + return _authTickets; + } + } + + private IShards _shards; + public IShards Shards + { + get + { + if(_shards == null) + { + _shards = new SqlShards(Context); + } + return _shards; + } + } + + private IAvatars _avatars; + public IAvatars Avatars + { + get + { + if (_avatars == null) + { + _avatars = new SqlAvatars(Context); + } + return _avatars; + } + } + + private IObjects _objects; + public IObjects Objects + { + get + { + if (_objects == null) + { + _objects = new SqlObjects(Context); + } + return _objects; + } + } + + private IRelationships _relationships; + public IRelationships Relationships + { + get + { + if (_relationships == null) + { + _relationships = new SqlRelationships(Context); + } + return _relationships; + } + } + + private IRoommates _roommates; + public IRoommates Roommates + { + get + { + if (_roommates == null) + { + _roommates = new SqlRoommates(Context); + } + return _roommates; + } + } + + private ILots _lots; + public ILots Lots + { + get + { + if(_lots == null){ + _lots = new SqlLots(Context); + } + return _lots; + } + } + + private ILotAdmit _LotAdmit; + public ILotAdmit LotAdmit + { + get + { + if (_LotAdmit == null) + { + _LotAdmit = new SqlLotAdmit(Context); + } + return _LotAdmit; + } + } + + private ILotClaims _LotClaims; + public ILotClaims LotClaims + { + get + { + if(_LotClaims == null){ + _LotClaims = new SqlLotClaims(Context); + } + return _LotClaims; + } + } + + private INeighborhoods _Neighborhoods; + public INeighborhoods Neighborhoods + { + get + { + if (_Neighborhoods == null) + { + _Neighborhoods = new SqlNeighborhoods(Context); + } + return _Neighborhoods; + } + } + + private IElections _Elections; + public IElections Elections + { + get + { + if (_Elections == null) + { + _Elections = new SqlElections(Context); + } + return _Elections; + } + } + + private IBulletinPosts _BulletinPosts; + public IBulletinPosts BulletinPosts + { + get + { + if (_BulletinPosts == null) + { + _BulletinPosts = new SqlBulletinPosts(Context); + } + return _BulletinPosts; + } + } + + private IAvatarClaims _AvatarClaims; + public IAvatarClaims AvatarClaims + { + get + { + if(_AvatarClaims == null){ + _AvatarClaims = new SqlAvatarClaims(Context); + } + return _AvatarClaims; + } + } + + private IBookmarks _Bookmarks; + public IBookmarks Bookmarks + { + get + { + if(_Bookmarks == null) + { + _Bookmarks = new SqlBookmarks(Context); + } + return _Bookmarks; + } + } + + private IOutfits _Outfits; + public IOutfits Outfits + { + get + { + if(_Outfits == null) + { + _Outfits = new SqlOutfits(Context); + } + return _Outfits; + } + } + + private ILotVisits _Visits; + public ILotVisits LotVisits + { + get + { + if(_Visits == null) + { + _Visits = new SqlLotVisits(Context); + } + return _Visits; + } + } + + private ILotTop100 _LotTop100; + public ILotTop100 LotTop100 + { + get + { + if(_LotTop100 == null) + { + _LotTop100 = new SqlLotTop100(Context); + } + return _LotTop100; + } + } + + private IHosts _Hosts; + public IHosts Hosts + { + get + { + if(_Hosts == null) + { + _Hosts = new SqlHosts(Context); + } + return _Hosts; + } + } + + private ITasks _Tasks; + public ITasks Tasks + { + get + { + if(_Tasks == null){ + _Tasks = new SqlTasks(Context); + } + return _Tasks; + } + } + + private IBonus _Bonus; + public IBonus Bonus + { + get + { + if(_Bonus == null) + { + _Bonus = new SqlBonus(Context); + } + return _Bonus; + } + } + + private IInbox _Inbox; + public IInbox Inbox + { + get + { + if (_Inbox == null) _Inbox = new SqlInbox(Context); + return _Inbox; + } + } + + private IEvents _Events; + public IEvents Events + { + get + { + if (_Events == null) _Events = new SqlEvents(Context); + return _Events; + } + } + + private ITuning _Tuning; + public ITuning Tuning + { + get + { + if (_Tuning == null) _Tuning = new SqlTuning(Context); + return _Tuning; + } + } + + + private IDynPayouts _DynPayouts; + public IDynPayouts DynPayouts + { + get + { + if (_DynPayouts == null) _DynPayouts = new SqlDynPayouts(Context); + return _DynPayouts; + } + } + + private ITransactions _Transactions; + public ITransactions Transactions + { + get + { + if (_Transactions == null) _Transactions = new SqlTransactions(Context); + return _Transactions; + } + } + + private IUpdates _Updates; + public IUpdates Updates + { + get + { + if (_Updates == null) _Updates = new SqlUpdates(Context); + return _Updates; + } + } + + private ILotVisitTotals _Totals; + public ILotVisitTotals LotVisitTotals + { + get + { + if(_Totals == null) + { + _Totals = new SqlLotVisitTotals(Context); + } + return _Totals; + } + } + + private IEmailConfirmations _Confirmations; + public IEmailConfirmations EmailConfirmations + { + get + { + if (_Confirmations == null) + { + _Confirmations = new SqlEmailConfirmations(Context); + } + return _Confirmations; + } + } + + private IGlobalCooldowns _Cooldowns; + public IGlobalCooldowns GlobalCooldowns + { + get + { + if (_Cooldowns == null) + { + _Cooldowns = new SqlGlobalCooldowns(Context); + } + return _Cooldowns; + } + } + + public void Flush() + { + Context.Flush(); + } + + public void Dispose() + { + Context.Dispose(); + } + } +} diff --git a/server/FSO.Server.Database/DA/Tasks/DbTask.cs b/server/FSO.Server.Database/DA/Tasks/DbTask.cs new file mode 100755 index 0000000..2fe7d12 --- /dev/null +++ b/server/FSO.Server.Database/DA/Tasks/DbTask.cs @@ -0,0 +1,34 @@ +using System; + +namespace FSO.Server.Database.DA.Tasks +{ + public class DbTask + { + public int task_id { get; set; } + public DbTaskType task_type { get; set; } + public DbTaskStatus task_status { get; set; } + public DateTime time_created { get; set; } + public DateTime? time_completed { get; set; } + public int? shard_id { get; set; } + public string shard_name { get; set; } + } + + public enum DbTaskType + { + prune_database, + bonus, + shutdown, + job_balance, + multi_check, + prune_abandoned_lots, + neighborhood_tick, + birthday_gift + } + + public enum DbTaskStatus + { + in_progress, + completed, + failed + } +} diff --git a/server/FSO.Server.Database/DA/Tasks/ITasks.cs b/server/FSO.Server.Database/DA/Tasks/ITasks.cs new file mode 100755 index 0000000..0533f65 --- /dev/null +++ b/server/FSO.Server.Database/DA/Tasks/ITasks.cs @@ -0,0 +1,14 @@ +using FSO.Server.Database.DA.Utils; +using System; + +namespace FSO.Server.Database.DA.Tasks +{ + public interface ITasks + { + int Create(DbTask task); + void CompleteTask(int task_id, DbTaskStatus status); + void SetStatus(int task_id, DbTaskStatus status); + DbTask CompletedAfter(DbTaskType type, DateTime time); + PagedList All(int offset = 1, int limit = 20); + } +} diff --git a/server/FSO.Server.Database/DA/Tasks/SqlTasks.cs b/server/FSO.Server.Database/DA/Tasks/SqlTasks.cs new file mode 100755 index 0000000..a45b9df --- /dev/null +++ b/server/FSO.Server.Database/DA/Tasks/SqlTasks.cs @@ -0,0 +1,59 @@ +using Dapper; +using FSO.Server.Database.DA.Utils; +using System; +using System.Linq; + +namespace FSO.Server.Database.DA.Tasks +{ + public class SqlTasks : AbstractSqlDA, ITasks + { + public SqlTasks(ISqlContext context) : base(context) + { + } + + public int Create(DbTask task) + { + return Context.Connection.Query( + "INSERT INTO fso_tasks (task_type, task_status, shard_id) " + + "VALUES (@task_type, @task_status, @shard_id); SELECT LAST_INSERT_ID();", new + { + task_type = task.task_type.ToString(), + task_status = task.task_status.ToString(), + shard_id = task.shard_id + }).First(); + } + + + public void CompleteTask(int task_id, DbTaskStatus status) + { + Context.Connection.Execute("UPDATE fso_tasks set task_status = @task_status, time_completed = current_timestamp WHERE task_id = @task_id", new + { + task_id = task_id, + task_status = status.ToString() + }); + } + + public void SetStatus(int task_id, DbTaskStatus status) + { + Context.Connection.Execute("UPDATE fso_tasks set task_status = @task_status WHERE task_id = @task_id", new { + task_id = task_id, + task_status = status.ToString() + }); + } + + public DbTask CompletedAfter(DbTaskType type, DateTime time) + { + return Context.Connection.Query("SELECT * FROM fso_tasks WHERE task_type = @type AND task_status = 'completed' AND time_completed >= @time", + new { type = type.ToString(), time }).FirstOrDefault(); + } + + public PagedList All(int offset = 1, int limit = 20) + { + var connection = Context.Connection; + var total = connection.Query("SELECT COUNT(*) FROM fso_tasks").FirstOrDefault(); + var results = connection.Query("SELECT t.*, s.name as shard_name FROM fso_tasks t LEFT JOIN fso_shards s ON s.shard_id = t.shard_id ORDER BY time_created DESC LIMIT @offset, @limit", new { offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + } +} diff --git a/server/FSO.Server.Database/DA/Transactions/ITransactions.cs b/server/FSO.Server.Database/DA/Transactions/ITransactions.cs new file mode 100755 index 0000000..8a94634 --- /dev/null +++ b/server/FSO.Server.Database/DA/Transactions/ITransactions.cs @@ -0,0 +1,7 @@ +namespace FSO.Server.Database.DA.Transactions +{ + public interface ITransactions + { + void Purge(int day); + } +} diff --git a/server/FSO.Server.Database/DA/Transactions/SqlTransactions.cs b/server/FSO.Server.Database/DA/Transactions/SqlTransactions.cs new file mode 100755 index 0000000..2e0859f --- /dev/null +++ b/server/FSO.Server.Database/DA/Transactions/SqlTransactions.cs @@ -0,0 +1,16 @@ +using Dapper; + +namespace FSO.Server.Database.DA.Transactions +{ + public class SqlTransactions : AbstractSqlDA, ITransactions + { + public SqlTransactions(ISqlContext context) : base(context) + { + } + + public void Purge(int day) + { + Context.Connection.Query("DELETE FROM fso_transactions WHERE day < @day", new { day = day }); + } + } +} diff --git a/server/FSO.Server.Database/DA/Tuning/DbTuning.cs b/server/FSO.Server.Database/DA/Tuning/DbTuning.cs new file mode 100755 index 0000000..4f33f64 --- /dev/null +++ b/server/FSO.Server.Database/DA/Tuning/DbTuning.cs @@ -0,0 +1,17 @@ +using FSO.Common.Model; + +namespace FSO.Server.Database.DA.Tuning +{ + public class DbTuning : DynTuningEntry + { + public DbTuningType owner_type { get; set; } + public int owner_id { get; set; } + } + + public enum DbTuningType + { + STATIC = 1, + DYNAMIC = 2, + EVENT = 3 + } +} diff --git a/server/FSO.Server.Database/DA/Tuning/DbTuningPreset.cs b/server/FSO.Server.Database/DA/Tuning/DbTuningPreset.cs new file mode 100755 index 0000000..f7b065b --- /dev/null +++ b/server/FSO.Server.Database/DA/Tuning/DbTuningPreset.cs @@ -0,0 +1,20 @@ +namespace FSO.Server.Database.DA.Tuning +{ + public class DbTuningPreset + { + public int preset_id; + public string name; + public string description; + public int flags; + } + + public class DbTuningPresetItem + { + public int item_id; + public int preset_id; + public string tuning_type; + public int tuning_table; + public int tuning_index; + public float value; + } +} diff --git a/server/FSO.Server.Database/DA/Tuning/ITuning.cs b/server/FSO.Server.Database/DA/Tuning/ITuning.cs new file mode 100755 index 0000000..79fad89 --- /dev/null +++ b/server/FSO.Server.Database/DA/Tuning/ITuning.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Tuning +{ + public interface ITuning + { + IEnumerable All(); + IEnumerable AllCategory(string type, int table); + IEnumerable GetAllPresets(); + IEnumerable GetPresetItems(int preset_id); + + bool ActivatePreset(int preset_id, int owner_id); + bool ClearPresetTuning(int owner_id); + bool ClearInactiveTuning(int[] active_ids); + + int CreatePreset(DbTuningPreset preset); + int CreatePresetItem(DbTuningPresetItem item); + bool DeletePreset(int preset_id); + } +} diff --git a/server/FSO.Server.Database/DA/Tuning/SqlTuning.cs b/server/FSO.Server.Database/DA/Tuning/SqlTuning.cs new file mode 100755 index 0000000..f0a711e --- /dev/null +++ b/server/FSO.Server.Database/DA/Tuning/SqlTuning.cs @@ -0,0 +1,72 @@ +using Dapper; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Server.Database.DA.Tuning +{ + public class SqlTuning : AbstractSqlDA, ITuning + { + public SqlTuning(ISqlContext context) : base(context) + { + } + + public IEnumerable All() + { + return Context.Connection.Query("SELECT * FROM fso_tuning"); + } + + public IEnumerable AllCategory(string type, int table) + { + return Context.Connection.Query("SELECT * FROM fso_tuning WHERE tuning_type = @type AND tuning_table = @table", new { type = type, table = table }); + } + + public IEnumerable GetAllPresets() + { + return Context.Connection.Query("SELECT * FROM fso_tuning_presets"); + } + + public IEnumerable GetPresetItems(int preset_id) + { + return Context.Connection.Query("SELECT * FROM fso_tuning_preset_items WHERE preset_id = @preset_id", new { preset_id }); + } + + public bool ActivatePreset(int preset_id, int owner_id) + { + return Context.Connection.Execute("INSERT IGNORE INTO fso_tuning (tuning_type, tuning_table, tuning_index, value, owner_type, owner_id) " + + "SELECT p.tuning_type, p.tuning_table, p.tuning_index, p.value, 'EVENT' as owner_type, @owner_id as owner_id " + + "FROM fso_tuning_preset_items as p " + + "WHERE p.preset_id = @preset_id", new { preset_id, owner_id }) > 0; + } + + public bool ClearPresetTuning(int owner_id) + { + return Context.Connection.Execute("DELETE FROM fso_tuning WHERE owner_type = 'EVENT' AND owner_id = owner_id", new { owner_id } ) > 0; + } + + public bool ClearInactiveTuning(int[] active_ids) + { + return Context.Connection.Execute("DELETE FROM fso_tuning WHERE owner_type = 'EVENT' AND owner_id NOT IN @active_ids", new { active_ids }) > 0; + } + + public int CreatePreset(DbTuningPreset preset) + { + var result = Context.Connection.Query("INSERT INTO fso_tuning_presets (name, description, flags) " + + "VALUES (@name, @description, @flags); SELECT LAST_INSERT_ID();", + preset).FirstOrDefault(); + return result; + } + + public int CreatePresetItem(DbTuningPresetItem item) + { + var result = Context.Connection.Query("INSERT INTO fso_tuning_preset_items (preset_id, tuning_type, tuning_table, tuning_index, value) " + + "VALUES (@preset_id, @tuning_type, @tuning_table, @tuning_index, @value); SELECT LAST_INSERT_ID();", + item).FirstOrDefault(); + return result; + } + + public bool DeletePreset(int preset_id) + { + return Context.Connection.Execute("DELETE FROM fso_tuning_presets WHERE preset_id = @preset_id", new { preset_id }) > 0; + } + } +} diff --git a/server/FSO.Server.Database/DA/Updates/DbUpdate.cs b/server/FSO.Server.Database/DA/Updates/DbUpdate.cs new file mode 100755 index 0000000..bad801c --- /dev/null +++ b/server/FSO.Server.Database/DA/Updates/DbUpdate.cs @@ -0,0 +1,21 @@ +using System; + +namespace FSO.Server.Database.DA.Updates +{ + public class DbUpdate + { + public int update_id { get; set; } + public string version_name { get; set; } + public int? addon_id { get; set; } + public int branch_id { get; set; } + public string full_zip { get; set; } + public string incremental_zip { get; set; } + public string manifest_url { get; set; } + public string server_zip { get; set; } + public int? last_update_id { get; set; } + public int flags { get; set; } + public DateTime date { get; set; } + public DateTime? publish_date { get; set; } + public DateTime? deploy_after { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Updates/DbUpdateAddon.cs b/server/FSO.Server.Database/DA/Updates/DbUpdateAddon.cs new file mode 100755 index 0000000..05852fc --- /dev/null +++ b/server/FSO.Server.Database/DA/Updates/DbUpdateAddon.cs @@ -0,0 +1,14 @@ +using System; + +namespace FSO.Server.Database.DA.Updates +{ + public class DbUpdateAddon + { + public int addon_id { get; set; } + public string name { get; set; } + public string description { get; set; } + public string addon_zip_url { get; set; } + public string server_zip_url { get; set; } + public DateTime date { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Updates/DbUpdateBranch.cs b/server/FSO.Server.Database/DA/Updates/DbUpdateBranch.cs new file mode 100755 index 0000000..6b7c91c --- /dev/null +++ b/server/FSO.Server.Database/DA/Updates/DbUpdateBranch.cs @@ -0,0 +1,23 @@ +namespace FSO.Server.Database.DA.Updates +{ + public class DbUpdateBranch + { + public int branch_id { get; set; } + public string branch_name { get; set; } + public string version_format { get; set; } + public int last_version_number { get; set; } + public int minor_version_number { get; set; } + public int? current_dist_id { get; set; } + public int? addon_id { get; set; } + public string base_build_url { get; set; } + public string base_server_build_url { get; set; } + public DbUpdateBuildMode build_mode { get; set; } + public int flags { get; set; } + } + + public enum DbUpdateBuildMode + { + zip, + teamcity + } +} diff --git a/server/FSO.Server.Database/DA/Updates/IUpdates.cs b/server/FSO.Server.Database/DA/Updates/IUpdates.cs new file mode 100755 index 0000000..dde4032 --- /dev/null +++ b/server/FSO.Server.Database/DA/Updates/IUpdates.cs @@ -0,0 +1,29 @@ +using FSO.Server.Database.DA.Utils; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Updates +{ + public interface IUpdates + { + DbUpdate GetUpdate(int update_id); + IEnumerable GetRecentUpdatesForBranchByID(int branch_id, int limit); + IEnumerable GetRecentUpdatesForBranchByName(string branch_name, int limit); + IEnumerable GetPublishableByBranchName(string branch_name); + PagedList All(int offset = 0, int limit = 20, string orderBy = "date"); + int AddUpdate(DbUpdate update); + bool MarkUpdatePublished(int update_id); + + DbUpdateAddon GetAddon(int addon_id); + IEnumerable GetAddons(int limit); + bool AddAddon(DbUpdateAddon addon); + + DbUpdateBranch GetBranch(int branch_id); + DbUpdateBranch GetBranch(string branch_name); + IEnumerable GetBranches(); + bool AddBranch(DbUpdateBranch branch); + bool UpdateBranchLatest(int branch_id, int last_version_number, int minor_version_number); + bool UpdateBranchLatestDeployed(int branch_id, int current_dist_id); + bool UpdateBranchAddon(int branch_id, int addon_id); + bool UpdateBranchInfo(DbUpdateBranch branch); + } +} diff --git a/server/FSO.Server.Database/DA/Updates/SqlUpdates.cs b/server/FSO.Server.Database/DA/Updates/SqlUpdates.cs new file mode 100755 index 0000000..6c831f8 --- /dev/null +++ b/server/FSO.Server.Database/DA/Updates/SqlUpdates.cs @@ -0,0 +1,192 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using FSO.Server.Database.DA.Utils; +using Dapper; + +namespace FSO.Server.Database.DA.Updates +{ + public class SqlUpdates : AbstractSqlDA, IUpdates + { + public SqlUpdates(ISqlContext context) : base(context) + { + } + + public bool AddAddon(DbUpdateAddon addon) + { + try + { + var result = Context.Connection.Execute("INSERT INTO fso_update_addons (name, description, addon_zip_url, server_zip_url) " + + "VALUES (@name, @description, @addon_zip_url, @server_zip_url)", addon); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool AddBranch(DbUpdateBranch branch) + { + try + { + var result = Context.Connection.Execute("INSERT INTO fso_update_branch " + + "(branch_name, version_format, last_version_number, current_dist_id, addon_id, base_build_url, base_server_build_url, build_mode, flags) " + + "VALUES (@branch_name, @version_format, @last_version_number, @current_dist_id, @addon_id, @base_build_url, @base_server_build_url, @build_mode, @flags)", + branch); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public int AddUpdate(DbUpdate update) + { + var result = Context.Connection.Query("INSERT INTO fso_updates " + + "(version_name, addon_id, branch_id, full_zip, incremental_zip, manifest_url, server_zip, last_update_id, flags, publish_date, deploy_after) " + + "VALUES (@version_name, @addon_id, @branch_id, @full_zip, @incremental_zip, @manifest_url, @server_zip, @last_update_id, @flags, @publish_date, @deploy_after); " + + "SELECT LAST_INSERT_ID();", + update).FirstOrDefault(); + return result; + } + + public PagedList All(int offset = 1, int limit = 20, string orderBy = "date") + { + var connection = Context.Connection; + var total = connection.Query("SELECT COUNT(*) FROM fso_updates").FirstOrDefault(); + var results = connection.Query("SELECT * FROM fso_updates ORDER BY @order DESC LIMIT @offset, @limit", new { order = orderBy, offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + public DbUpdateAddon GetAddon(int addon_id) + { + return Context.Connection.Query("SELECT * FROM fso_update_addons WHERE addon_id = @addon_id", new { addon_id }).FirstOrDefault(); + } + + public IEnumerable GetAddons(int limit) + { + return Context.Connection.Query("SELECT * FROM fso_update_addons ORDER BY date DESC"); + } + + public DbUpdateBranch GetBranch(int branch_id) + { + return Context.Connection.Query("SELECT * FROM fso_update_branch WHERE branch_id = @branch_id", new { branch_id }).FirstOrDefault(); + } + + public DbUpdateBranch GetBranch(string branch_name) + { + return Context.Connection.Query("SELECT * FROM fso_update_branch WHERE branch_name = @branch_name", new { branch_name }).FirstOrDefault(); + } + + public IEnumerable GetBranches() + { + return Context.Connection.Query("SELECT * FROM fso_update_branch"); + } + + public IEnumerable GetRecentUpdatesForBranchByID(int branch_id, int limit) + { + return Context.Connection.Query("SELECT * FROM fso_updates WHERE branch_id = @branch_id AND publish_date IS NOT NULL " + + "ORDER BY date DESC " + + "LIMIT @limit", new { branch_id, limit }); + } + + public IEnumerable GetRecentUpdatesForBranchByName(string branch_name, int limit) + { + return Context.Connection.Query("SELECT * FROM fso_updates u JOIN fso_update_branch b ON u.branch_id = b.branch_id " + + "WHERE b.branch_name = @branch_name AND publish_date IS NOT NULL AND deploy_after IS NOT NULL AND deploy_after < NOW() " + + "ORDER BY publish_date DESC " + + "LIMIT @limit", new { branch_name, limit }); + } + + public IEnumerable GetPublishableByBranchName(string branch_name) + { + return Context.Connection.Query("SELECT * FROM fso_updates u JOIN fso_update_branch b ON u.branch_id = b.branch_id " + + "WHERE b.branch_name = @branch_name AND publish_date IS NULL " + + "ORDER BY date DESC", new { branch_name }); + } + + public DbUpdate GetUpdate(int update_id) + { + return Context.Connection.Query("SELECT * FROM fso_updates WHERE update_id = @update_id", new { update_id }).FirstOrDefault(); + } + + public bool UpdateBranchAddon(int branch_id, int addon_id) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_update_branch SET addon_id = @addon_id " + + "WHERE branch_id = @branch_id" + , new { branch_id, addon_id }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool UpdateBranchInfo(DbUpdateBranch branch) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_update_branch SET " + + "branch_name = @branch_name, version_format = @version_format, last_version_number = @last_version_number, " + + "minor_version_number = @minor_version_number, addon_id = @addon_id, base_build_url = @base_build_url, " + + "base_server_build_url = @base_server_build_url, build_mode = @build_mode, flags = @flags " + + "WHERE branch_id = @branch_id" + , branch); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool UpdateBranchLatest(int branch_id, int last_version_number, int minor_version_number) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_update_branch SET last_version_number = @last_version_number, " + + "minor_version_number = @minor_version_number WHERE branch_id = @branch_id" + , new { branch_id, last_version_number, minor_version_number }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool UpdateBranchLatestDeployed(int branch_id, int current_dist_id) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_update_branch SET current_dist_id = @current_dist_id WHERE branch_id = @branch_id" + , new { branch_id, current_dist_id }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + + public bool MarkUpdatePublished(int update_id) + { + try + { + var result = Context.Connection.Execute("UPDATE fso_updates SET publish_date = CURRENT_TIMESTAMP " + + "WHERE update_id = @update_id" + , new { update_id }); + return (result > 0); + } + catch (Exception) + { + return false; + } + } + } +} diff --git a/server/FSO.Server.Database/DA/Users/DbAuthAttempt.cs b/server/FSO.Server.Database/DA/Users/DbAuthAttempt.cs new file mode 100755 index 0000000..f4d297c --- /dev/null +++ b/server/FSO.Server.Database/DA/Users/DbAuthAttempt.cs @@ -0,0 +1,13 @@ +namespace FSO.Server.Database.DA.Users +{ + public class DbAuthAttempt + { + public uint attempt_id { get; set; } + public string ip { get; set; } + public uint user_id { get; set; } + public uint expire_time { get; set; } + public int count { get; set; } + public bool active { get; set; } + public bool invalidated { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Users/IUsers.cs b/server/FSO.Server.Database/DA/Users/IUsers.cs new file mode 100755 index 0000000..6c7c0be --- /dev/null +++ b/server/FSO.Server.Database/DA/Users/IUsers.cs @@ -0,0 +1,28 @@ +using FSO.Server.Database.DA.Utils; +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Users +{ + public interface IUsers + { + User GetById(uint id); + List GetByRegisterIP(string ip); + void UpdateConnectIP(uint id, string ip); + void UpdateBanned(uint id, bool banned); + void UpdateClientID(uint id, string cid); + User GetByUsername(string username); + UserAuthenticate GetAuthenticationSettings(uint userId); + PagedList All(int offset = 0, int limit = 20, string orderBy = "register_date"); + uint Create(User user); + void CreateAuth(UserAuthenticate auth); + User GetByEmail(string email); + void UpdateAuth(UserAuthenticate auth); + void UpdateLastLogin(uint id, uint last_login); + + DbAuthAttempt GetRemainingAuth(uint user_id, string ip); + int FailedConsecutive(uint user_id, string ip); + int FailedAuth(uint attempt_id, uint delay, int failLimit); + void NewFailedAuth(uint user_id, string ip, uint delay); + void SuccessfulAuth(uint user_id, string ip); + } +} diff --git a/server/FSO.Server.Database/DA/Users/SqlUsers.cs b/server/FSO.Server.Database/DA/Users/SqlUsers.cs new file mode 100755 index 0000000..def7108 --- /dev/null +++ b/server/FSO.Server.Database/DA/Users/SqlUsers.cs @@ -0,0 +1,153 @@ +using System.Collections.Generic; +using System.Linq; +using Dapper; +using FSO.Server.Common; +using FSO.Server.Database.DA.Utils; + +namespace FSO.Server.Database.DA.Users +{ + public class SqlUsers : AbstractSqlDA, IUsers + { + public SqlUsers(ISqlContext context) : base(context) + { + } + + public User GetByUsername(string username) + { + return Context.Connection.Query("SELECT * FROM fso_users WHERE username = @username", new { username = username }).FirstOrDefault(); + } + + public UserAuthenticate GetAuthenticationSettings(uint userId) + { + return Context.Connection.Query("SELECT * FROM fso_user_authenticate WHERE user_id = @user_id", new { user_id = userId }).FirstOrDefault(); + } + + public User GetById(uint id) + { + return Context.Connection.Query("SELECT * FROM fso_users WHERE user_id = @user_id", new { user_id = id }).FirstOrDefault(); + } + + public User GetByEmail(string email) + { + return Context.Connection.Query("SELECT * FROM fso_users WHERE email = @email", new { email = email }).FirstOrDefault(); + } + public List GetByRegisterIP(string ip) + { + return Context.Connection.Query("SELECT * FROM fso_users WHERE register_ip = @ip ORDER BY register_date DESC", new { ip = ip }).AsList(); + } + + public void UpdateConnectIP(uint id, string ip) + { + Context.Connection.Execute("UPDATE fso_users SET last_ip = @ip WHERE user_id = @user_id", new { user_id = id, ip = ip }); + } + + public void UpdateClientID(uint id, string uid) + { + Context.Connection.Execute("UPDATE fso_users SET client_id = @id WHERE user_id = @user_id", new { user_id = id, id = uid }); + } + + public void UpdateBanned(uint id, bool banned) + { + Context.Connection.Execute("UPDATE fso_users SET is_banned = @ban WHERE user_id = @user_id", new { user_id = id, ban = banned }); + } + + public void UpdateLastLogin(uint id, uint last_login) + { + Context.Connection.Execute("UPDATE fso_users SET last_login = @last_login WHERE user_id = @user_id", new { user_id = id, last_login = last_login }); + } + + public PagedList All(int offset = 1, int limit = 20, string orderBy = "register_date") + { + var connection = Context.Connection; + var total = connection.Query("SELECT COUNT(*) FROM fso_users").FirstOrDefault(); + var results = connection.Query("SELECT * FROM fso_users ORDER BY @order LIMIT @offset, @limit", new { order = orderBy, offset = offset, limit = limit }); + return new PagedList(results, offset, total); + } + + public uint Create(User user) + { + return Context.Connection.Query( + "insert into fso_users set username = @username, email = @email, register_date = @register_date, register_ip = @register_ip, last_ip = @last_ip, " + + "is_admin = @is_admin, is_moderator = @is_moderator, is_banned = @is_banned; select LAST_INSERT_ID();", + user + ).First(); + } + + public void CreateAuth(UserAuthenticate auth) + { + Context.Connection.Execute( + "insert into fso_user_authenticate set user_id = @user_id, scheme_class = @scheme_class, data = @data;", + auth + ); + } + + public void UpdateAuth(UserAuthenticate auth) + { + Context.Connection.Execute( + "UPDATE fso_user_authenticate SET scheme_class = @scheme_class, data = @data WHERE user_id = @user_id;", + new { auth.scheme_class, auth.data, auth.user_id } + ); + } + + public DbAuthAttempt GetRemainingAuth(uint user_id, string ip) + { + var result = Context.Connection.Query( + "SELECT * FROM fso_auth_attempts WHERE user_id = @user_id AND ip = @ip AND invalidated = 0 ORDER BY expire_time DESC", + new { user_id, ip } + ).FirstOrDefault(); + if (result != null && result.active && result.expire_time < Epoch.Now) return null; + else return result; + } + + public int FailedConsecutive(uint user_id, string ip) + { + return Context.Connection.Query( + "SELECT COUNT(*) FROM fso_auth_attempts WHERE user_id = @user_id AND ip = @ip AND active = 1 AND invalidated = 0", + new { user_id, ip } + ).First(); + } + + public int FailedAuth(uint attempt_id, uint delay, int failLimit) + { + Context.Connection.Execute( + "UPDATE fso_auth_attempts SET count = count + 1, expire_time = @time WHERE attempt_id = @attempt_id", + new { attempt_id, time = Epoch.Now + delay } + ); + var result = Context.Connection.Query( + "SELECT * FROM fso_auth_attempts WHERE attempt_id = @attempt_id", new { attempt_id }).FirstOrDefault(); + if (result != null) + { + if (result.count >= failLimit) + { + Context.Connection.Execute( + "UPDATE fso_auth_attempts SET active = 1 WHERE attempt_id = @attempt_id", + new { attempt_id }); + return 0; + } else + { + return failLimit - result.count; + } + } else + { + return failLimit; + } + } + + public void NewFailedAuth(uint user_id, string ip, uint delay) + { + //create a new entry + Context.Connection.Execute( + "INSERT INTO fso_auth_attempts (ip, user_id, expire_time, count) VALUES (@ip, @user_id, @time, 1)", + new { user_id, ip, time = Epoch.Now + delay } + ); + } + + public void SuccessfulAuth(uint user_id, string ip) + { + Context.Connection.Execute( + "UPDATE fso_auth_attempts SET invalidated = 1 WHERE user_id = @user_id AND ip = @ip", + new { user_id, ip } + ); + } + } +} diff --git a/server/FSO.Server.Database/DA/Users/User.cs b/server/FSO.Server.Database/DA/Users/User.cs new file mode 100755 index 0000000..fab2e41 --- /dev/null +++ b/server/FSO.Server.Database/DA/Users/User.cs @@ -0,0 +1,25 @@ +namespace FSO.Server.Database.DA.Users +{ + public class User + { + public uint user_id { get; set; } + public string username { get; set; } + public string email { get; set; } + public UserState user_state { get; set; } + public uint register_date { get; set; } + public bool is_admin { get; set; } + public bool is_moderator { get; set; } + public bool is_banned { get; set; } + public string register_ip { get; set; } + public string last_ip { get; set; } + public string client_id { get; set; } + public uint last_login { get; set; } + } + + public enum UserState + { + valid, + email_confirm, + moderated + } +} diff --git a/server/FSO.Server.Database/DA/Users/UserAuthenticate.cs b/server/FSO.Server.Database/DA/Users/UserAuthenticate.cs new file mode 100755 index 0000000..98d6e16 --- /dev/null +++ b/server/FSO.Server.Database/DA/Users/UserAuthenticate.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Users +{ + public class UserAuthenticate + { + public uint user_id { get; set; } + public string scheme_class { get; set; } + public byte[] data { get; set; } + } +} diff --git a/server/FSO.Server.Database/DA/Utils/BufferedInsert.cs b/server/FSO.Server.Database/DA/Utils/BufferedInsert.cs new file mode 100755 index 0000000..db5f8c8 --- /dev/null +++ b/server/FSO.Server.Database/DA/Utils/BufferedInsert.cs @@ -0,0 +1,31 @@ +using Dapper; +using System.Collections.Generic; +using System.Data.Common; + +namespace FSO.Server.Database.DA.Utils +{ + public static class BufferedInsert + { + public static void ExecuteBufferedInsert(this DbConnection connection, string query, IEnumerable param, int batches) + { + var buffer = new List(); + var enumerator = param.GetEnumerator(); + + while (enumerator.MoveNext()) + { + buffer.Add(enumerator.Current); + + if(buffer.Count >= batches) + { + connection.Execute(query, buffer); + buffer.Clear(); + } + } + + if(buffer.Count > 0) + { + connection.Execute(query, buffer); + } + } + } +} diff --git a/server/FSO.Server.Database/DA/Utils/FilterOptions.cs b/server/FSO.Server.Database/DA/Utils/FilterOptions.cs new file mode 100755 index 0000000..d758e50 --- /dev/null +++ b/server/FSO.Server.Database/DA/Utils/FilterOptions.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Database.DA.Utils +{ + public class FilterOptions + { + public int Start = 0; + public int NumResults = 20; + public string Search; + } +} diff --git a/server/FSO.Server.Database/DA/Utils/PagedList.cs b/server/FSO.Server.Database/DA/Utils/PagedList.cs new file mode 100755 index 0000000..a21fce9 --- /dev/null +++ b/server/FSO.Server.Database/DA/Utils/PagedList.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace FSO.Server.Database.DA.Utils +{ + public class PagedList : List + { + public int Offset; + public int Total; + + public PagedList(IEnumerable items, int offset, int total) : base(items) + { + this.Offset = offset; + this.Total = total; + } + + } +} diff --git a/server/FSO.Server.Database/DatabaseConfiguration.cs b/server/FSO.Server.Database/DatabaseConfiguration.cs new file mode 100755 index 0000000..be97706 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseConfiguration.cs @@ -0,0 +1,7 @@ +namespace FSO.Server.Database +{ + public class DatabaseConfiguration + { + public string ConnectionString { get; set; } + } +} diff --git a/server/FSO.Server.Database/DatabaseModule.cs b/server/FSO.Server.Database/DatabaseModule.cs new file mode 100755 index 0000000..25030d2 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseModule.cs @@ -0,0 +1,14 @@ +using FSO.Server.Database.DA; +using Ninject.Modules; + +namespace FSO.Server.Database +{ + public class DatabaseModule : NinjectModule + { + public override void Load() + { + //TODO: If we add more drivers make this a provider + this.Bind().To().InSingletonScope(); + } + } +} diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0001_3_max_avatars.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0001_3_max_avatars.sql new file mode 100755 index 0000000..0b8c914 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0001_3_max_avatars.sql @@ -0,0 +1,6 @@ +CREATE TRIGGER `fso_avatars_BEFORE_INSERT` BEFORE INSERT ON `fso_avatars` FOR EACH ROW BEGIN + IF (SELECT COUNT(*) FROM fso_avatars a WHERE NEW.user_id = a.user_id) >= 3 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Cannot own more than 3 avatars.'; + END IF; +END \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0002_budget_cant_be_negative.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0002_budget_cant_be_negative.sql new file mode 100755 index 0000000..7236f95 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0002_budget_cant_be_negative.sql @@ -0,0 +1,13 @@ +CREATE TRIGGER `fso_avatars_BEFORE_UPDATE` BEFORE UPDATE ON `fso_avatars` FOR EACH ROW BEGIN + IF NEW.budget<0 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Transaction would cause avatar to have negative budget.'; + END IF; +END; + +CREATE TRIGGER `fso_objects_BEFORE_UPDATE` BEFORE UPDATE ON `fso_objects` FOR EACH ROW BEGIN + IF NEW.budget<0 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Transaction would cause object to have negative budget.'; + END IF; +END; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0003_max_roomates.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0003_max_roomates.sql new file mode 100755 index 0000000..c13fb58 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0003_max_roomates.sql @@ -0,0 +1,10 @@ +CREATE TRIGGER `fso_roommates_BEFORE_INSERT` BEFORE INSERT ON `fso_roommates` FOR EACH ROW BEGIN + IF (SELECT COUNT(*) FROM fso_roommates a WHERE NEW.avatar_id = a.avatar_id) > 0 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Cannot be a roommate of more than one lot. (currently, will likely change in future.)'; + END IF; + IF (SELECT COUNT(*) FROM fso_roommates a WHERE NEW.lot_id = a.lot_id) >= 8 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Cannot have more than 8 roommates in a lot.'; + END IF; +END; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0004_bookmarks.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0004_bookmarks.sql new file mode 100755 index 0000000..97f5366 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0004_bookmarks.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS `fso_bookmarks` ( + `avatar_id` int(10) unsigned NOT NULL, + `type` tinyint(3) unsigned NOT NULL, + `target_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`avatar_id`,`type`,`target_id`), + KEY `FK_fso_bookmarks_fso_avatars_target` (`target_id`), + CONSTRAINT `FK_fso_bookmarks_fso_avatars_src` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`), + CONSTRAINT `FK_fso_bookmarks_fso_avatars_target` FOREIGN KEY (`target_id`) REFERENCES `fso_avatars` (`avatar_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0005_lotadmit_primarykey.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0005_lotadmit_primarykey.sql new file mode 100755 index 0000000..fed8fab --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0005_lotadmit_primarykey.sql @@ -0,0 +1,3 @@ +ALTER TABLE `fso_lot_admit` +DROP PRIMARY KEY, +ADD PRIMARY KEY (`avatar_id`, `lot_id`, `admit_type`); diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0006_outfits.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0006_outfits.sql new file mode 100755 index 0000000..27e1c45 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0006_outfits.sql @@ -0,0 +1,47 @@ +CREATE TABLE IF NOT EXISTS `fso_outfits` ( + `outfit_id` int(11) NOT NULL AUTO_INCREMENT, + `avatar_owner` int(10) unsigned DEFAULT NULL, + `object_owner` int(11) unsigned DEFAULT NULL, + `asset_id` bigint(20) unsigned DEFAULT NULL, + `sale_price` int(11) NOT NULL, + `purchase_price` int(11) NOT NULL, + `outfit_type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT 'See VMPersonSuits', + `outfit_source` enum('cas','rack') NOT NULL DEFAULT 'cas', + PRIMARY KEY (`outfit_id`), + KEY `FK_fso_outfits_fso_avatars` (`avatar_owner`), + KEY `FK_fso_outfits_fso_objects` (`object_owner`), + CONSTRAINT `FK_fso_outfits_fso_avatars` FOREIGN KEY (`avatar_owner`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE, + CONSTRAINT `FK_fso_outfits_fso_objects` FOREIGN KEY (`object_owner`) REFERENCES `fso_objects` (`object_id`) ON DELETE CASCADE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TRIGGER `fso_outfits_before_insert` BEFORE INSERT ON `fso_outfits` FOR EACH ROW BEGIN + IF NEW.object_owner IS NOT NULL THEN + IF (SELECT COUNT(*) FROM fso_outfits o WHERE NEW.object_owner = o.object_owner) >= 20 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Cannot have more than 20 outfits in a rack.'; + END IF; + END IF; +END; + +CREATE TRIGGER `fso_outfits_before_update` BEFORE UPDATE ON `fso_outfits` FOR EACH ROW BEGIN + IF NEW.avatar_owner IS NOT NULL THEN + IF (SELECT COUNT(*) FROM fso_outfits o WHERE NEW.avatar_owner = o.avatar_owner AND o.outfit_type = NEW.outfit_type) >= 5 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'Cannot have more than 5 outfits per category in backpack.'; + END IF; + END IF; +END; + +-- Migrate existing daywear -- +INSERT INTO fso_outfits (avatar_owner, asset_id, sale_price, purchase_price, outfit_type, outfit_source) +SELECT avatar_id, body, 0, 0, 0, 'cas' FROM fso_avatars; + +-- Give everyone default sleepswear -- +INSERT INTO fso_outfits (avatar_owner, asset_id, sale_price, purchase_price, outfit_type, outfit_source) +SELECT avatar_id, if(gender = 'male', CAST(0x5440000000D as UNSIGNED), CAST(0x5150000000D as UNSIGNED)), 0, 0, 5, 'cas' FROM fso_avatars; + +-- Give everyone default swimwear -- +INSERT INTO fso_outfits (avatar_owner, asset_id, sale_price, purchase_price, outfit_type, outfit_source) +SELECT avatar_id, if(gender = 'male', CAST(0x5470000000D as UNSIGNED), CAST(0x620000000D as UNSIGNED)), 0, 0, 2, 'cas' FROM fso_avatars; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0007_fso_lot_visits.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0007_fso_lot_visits.sql new file mode 100755 index 0000000..83a572e --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0007_fso_lot_visits.sql @@ -0,0 +1,41 @@ +CREATE TABLE IF NOT EXISTS `fso_lot_visits` ( + `lot_visit_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `avatar_id` int(11) unsigned NOT NULL, + `lot_id` int(11) NOT NULL, + `type` enum('owner','roommate','visitor') DEFAULT NULL, + `status` enum('active','closed','failed') NOT NULL, + `time_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `time_closed` datetime DEFAULT NULL, + PRIMARY KEY (`lot_visit_id`), + KEY `FK_fso_avatar_audits_fso_avatars` (`avatar_id`), + KEY `FK_fso_lot_visitors_fso_lots` (`lot_id`), + CONSTRAINT `FK_fso_avatar_audits_fso_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_fso_lot_visitors_fso_lots` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE CASCADE ON UPDATE CASCADE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE FUNCTION `fso_lot_visits_create`(`p_avatar_id` INT, `p_lot_id` INT, `p_visitor_type` VARCHAR(50)) RETURNS int(11) + READS SQL DATA +BEGIN + #Error any open active visit, can only have one active + UPDATE fso_lot_visits SET `status` = 'failed', time_closed = current_timestamp WHERE avatar_id = p_avatar_id AND `status` = 'active'; + #Record visit + INSERT INTO fso_lot_visits (avatar_id, lot_id, type, status) VALUES (p_avatar_id, p_lot_id, p_visitor_type, 'active'); + RETURN LAST_INSERT_ID(); +END; + +CREATE TABLE IF NOT EXISTS `fso_lot_top_100` ( + `category` enum('none','welcome','money','skills','services','entertainment','romance','shopping','games','offbeat','residence') NOT NULL, + `rank` tinyint(4) unsigned NOT NULL, + `shard_id` int(11) NOT NULL, + `lot_id` int(11) DEFAULT NULL, + `minutes` int(11) DEFAULT NULL, + `date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`category`,`rank`,`shard_id`), + KEY `FK_fso_lots_top_100_fso_shards` (`shard_id`), + KEY `FK_fso_lots_top_100_fso_lots` (`lot_id`), + CONSTRAINT `FK_fso_lots_top_100_fso_lots` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_fso_lots_top_100_fso_shards` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) +) COLLATE='utf8_general_ci' + ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0008_fso_hosts.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0008_fso_hosts.sql new file mode 100755 index 0000000..7b03f3f --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0008_fso_hosts.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS `fso_hosts` ( + `call_sign` varchar(50) NOT NULL, + `role` enum('city','lot','task') NOT NULL, + `status` enum('up','down') NOT NULL, + `internal_host` varchar(100) NOT NULL, + `public_host` varchar(100) NOT NULL, + `time_boot` datetime NOT NULL, + `shard_id` int(11) DEFAULT NULL, + PRIMARY KEY (`call_sign`), + KEY `FK_fso_hosts_fso_shards` (`shard_id`), + CONSTRAINT `FK_fso_hosts_fso_shards` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) ON DELETE CASCADE ON UPDATE CASCADE +) COLLATE='utf8_general_ci' + ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0009_fso_tasks.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0009_fso_tasks.sql new file mode 100755 index 0000000..5cb0462 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0009_fso_tasks.sql @@ -0,0 +1,12 @@ +CREATE TABLE IF NOT EXISTS `fso_tasks` ( + `task_id` int(11) NOT NULL AUTO_INCREMENT, + `task_type` enum('prune_database','bonus') NOT NULL, + `task_status` enum('in_progress','completed','failed') NOT NULL, + `time_created` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `time_completed` datetime DEFAULT NULL, + `shard_id` int(11) DEFAULT NULL, + PRIMARY KEY (`task_id`), + KEY `FK_fso_tasks_fso_shards` (`shard_id`), + CONSTRAINT `FK_fso_tasks_fso_shards` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) ON DELETE CASCADE ON UPDATE CASCADE +) COLLATE='utf8_general_ci' + ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0010_fso_top100.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0010_fso_top100.sql new file mode 100755 index 0000000..97c08dc --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0010_fso_top100.sql @@ -0,0 +1,65 @@ +CREATE TABLE IF NOT EXISTS `fso_lot_visit_totals` ( + `lot_id` int(11) NOT NULL, + `date` date NOT NULL, + `minutes` int(11) NOT NULL, + PRIMARY KEY (`lot_id`,`date`), + CONSTRAINT `FK_fso_lot_visit_totals_fso_lots` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE CASCADE ON UPDATE CASCADE +) COLLATE='utf8_general_ci' + ENGINE=InnoDB; + + + CREATE PROCEDURE `fso_lot_top_100_calc_category`(IN `p_category` VARCHAR(50), IN `p_date` DATE, IN `p_shard_id` INT) + SQL SECURITY INVOKER +BEGIN + + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + ROLLBACK; + END; + + SET @date = p_date; + SET @start_date = DATE_SUB(@date, INTERVAL 4 DAY); + SET @timestamp = current_timestamp; + SET @row_number = 0; + + START TRANSACTION; + # Remove old + DELETE FROM fso_lot_top_100 WHERE shard_id = p_shard_id AND category = p_category; + + + # Insert new + INSERT INTO fso_lot_top_100 (category, rank, shard_id, lot_id, minutes, date) + SELECT category, + (@row_number:=@row_number + 1) AS rank, + shard_id, + lot_id, + minutes, + date + FROM ( + SELECT lot.category, lot.lot_id, lot.shard_id, FLOOR(AVG(visits.minutes)) as minutes, @timestamp as date + FROM fso_lot_visit_totals visits + INNER JOIN fso_lots lot ON visits.lot_id = lot.lot_id + WHERE lot.category = p_category + AND date BETWEEN @start_date AND @date + AND lot.shard_id = p_shard_id + GROUP BY lot_id + ORDER BY minutes DESC + LIMIT 100 + ) as top100; + COMMIT; +END; + +CREATE PROCEDURE `fso_lot_top_100_calc_all`(IN `p_date` DATE, IN `p_shard_id` INT) + SQL SECURITY INVOKER +BEGIN + CALL fso_lot_top_100_calc_category('money', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('offbeat', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('romance', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('services', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('shopping', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('skills', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('welcome', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('games', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('entertainment', p_date, p_shard_id); + CALL fso_lot_top_100_calc_category('residence', p_date, p_shard_id); +END; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0011_fso_bonus.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0011_fso_bonus.sql new file mode 100755 index 0000000..76ab0e9 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0011_fso_bonus.sql @@ -0,0 +1,14 @@ +CREATE TABLE IF NOT EXISTS `fso_bonus` ( + `avatar_id` int(10) unsigned NOT NULL DEFAULT '0', + `period` date NOT NULL, + `bonus_visitor` int(11) DEFAULT NULL, + `bonus_property` int(11) DEFAULT NULL, + `bonus_sim` int(11) DEFAULT NULL, + PRIMARY KEY (`avatar_id`,`period`), + CONSTRAINT `FK_fso_bonus_fso_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE +) COLLATE='utf8_general_ci' + ENGINE=InnoDB; + +CREATE TRIGGER `fso_bonus_after_insert` AFTER INSERT ON `fso_bonus` FOR EACH ROW BEGIN + UPDATE fso_avatars a SET budget = (budget + IFNULL(NEW.bonus_visitor,0) + IFNULL(NEW.bonus_property,0) + IFNULL(NEW.bonus_sim,0)) WHERE a.avatar_id = NEW.avatar_id; +END; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0012_fso_bans.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0012_fso_bans.sql new file mode 100755 index 0000000..87bb68e --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0012_fso_bans.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS `fso_ip_ban` ( + `user_id` INT UNSIGNED NOT NULL, + `ip_address` VARCHAR(100) NULL, + `banreason` VARCHAR(500) NULL, + `end_date` INT(10) NOT NULL DEFAULT 0, + PRIMARY KEY (`user_id`), + CONSTRAINT `fso_ban_user` + FOREIGN KEY (`user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE); \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0013_shard_version.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0013_shard_version.sql new file mode 100755 index 0000000..b51ec65 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0013_shard_version.sql @@ -0,0 +1,6 @@ + +ALTER TABLE `fso_shards` +ADD `version_name` varchar(100) NOT NULL DEFAULT 'unknown'; + +ALTER TABLE `fso_shards` +ADD `version_number` varchar(100) NOT NULL DEFAULT '0'; diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0014_client_id.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0014_client_id.sql new file mode 100755 index 0000000..cfe6fc8 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0014_client_id.sql @@ -0,0 +1,5 @@ +ALTER TABLE `fso_users` +ADD COLUMN `client_id` VARCHAR(100) NOT NULL DEFAULT 0 AFTER `last_ip`; + +ALTER TABLE `fso_ip_ban` +ADD COLUMN `client_id` VARCHAR(100) NOT NULL DEFAULT '0' AFTER `end_date`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0015_avatar_lot_retire.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0015_avatar_lot_retire.sql new file mode 100755 index 0000000..6c13829 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0015_avatar_lot_retire.sql @@ -0,0 +1,34 @@ +-- claims + +ALTER TABLE `fso_avatar_claims` +DROP FOREIGN KEY `FK_fso_avatar_claims_fso_avatars`; +ALTER TABLE `fso_avatar_claims` +ADD CONSTRAINT `FK_fso_avatar_claims_fso_avatars` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE; + + +-- bookmarks + +ALTER TABLE `fso_bookmarks` +DROP FOREIGN KEY `FK_fso_bookmarks_fso_avatars_src`, +DROP FOREIGN KEY `FK_fso_bookmarks_fso_avatars_target`; +ALTER TABLE `fso_bookmarks` +ADD CONSTRAINT `FK_fso_bookmarks_fso_avatars_src` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, +ADD CONSTRAINT `FK_fso_bookmarks_fso_avatars_target` + FOREIGN KEY (`target_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE; + + +-- lot owners - now nullable. null owner lots are deleted. + +ALTER TABLE `fso_lots` +CHANGE COLUMN `owner_id` `owner_id` INT(10) UNSIGNED NULL ; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0016_extra_tasks.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0016_extra_tasks.sql new file mode 100755 index 0000000..85479e2 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0016_extra_tasks.sql @@ -0,0 +1,2 @@ +ALTER TABLE `fso_tasks` +CHANGE COLUMN `task_type` `task_type` ENUM('prune_database', 'bonus', 'shutdown', 'job_balance', 'multi_check', 'prune_abandoned_lots') NOT NULL ; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0017_inbox_events.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0017_inbox_events.sql new file mode 100755 index 0000000..9c1c5ec --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0017_inbox_events.sql @@ -0,0 +1,50 @@ +CREATE TABLE `fso_inbox` ( + `message_id` INT NOT NULL AUTO_INCREMENT, + `sender_id` INT UNSIGNED NOT NULL, + `target_id` INT UNSIGNED NOT NULL, + `subject` VARCHAR(128) NOT NULL, + `body` VARCHAR(1500) NOT NULL, + `sender_name` VARCHAR(64) NOT NULL, + `time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `msg_type` INT NOT NULL DEFAULT 0, + `msg_subtype` INT NOT NULL DEFAULT 0, + `read_state` INT NOT NULL DEFAULT 0, + `reply_id` INT NULL DEFAULT NULL, + PRIMARY KEY (`message_id`), + INDEX `index_target_inbox` (`target_id` ASC), + CONSTRAINT `fso_target_avatar` + FOREIGN KEY (`target_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE); + +CREATE TABLE `fso_events` ( + `event_id` INT NOT NULL AUTO_INCREMENT, + `title` VARCHAR(128) NULL, + `description` VARCHAR(500) NULL, + `start_day` DATETIME NOT NULL, + `end_day` DATETIME NOT NULL, + `type` ENUM('mail_only', 'free_object', 'free_money', 'free_green', 'obj_tuning') NOT NULL, + `value` INT NOT NULL, + `value2` INT NOT NULL DEFAULT 0, + `mail_subject` VARCHAR(128) NULL, + `mail_message` VARCHAR(1000) NULL, + `mail_sender` INT NULL, + `mail_sender_name` VARCHAR(64) NULL, + PRIMARY KEY (`event_id`)); + +CREATE TABLE `fso_event_participation` ( + `event_id` INT NOT NULL, + `user_id` INT UNSIGNED NOT NULL, + PRIMARY KEY (`event_id`, `user_id`), + INDEX `fso_event_part_user_idx` (`user_id` ASC), + CONSTRAINT `fso_event_part_id` + FOREIGN KEY (`event_id`) + REFERENCES `fso_events` (`event_id`) + ON DELETE CASCADE + ON UPDATE NO ACTION, + CONSTRAINT `fso_event_part_user` + FOREIGN KEY (`user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE); \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0018_dyn_payout_tuning.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0018_dyn_payout_tuning.sql new file mode 100755 index 0000000..1d82f05 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0018_dyn_payout_tuning.sql @@ -0,0 +1,25 @@ +ALTER TABLE `fso_transactions` +DROP COLUMN `time_last`, +CHANGE COLUMN `time_first` `day` INT(11) UNSIGNED NOT NULL AFTER `transaction_type`, +CHANGE COLUMN `value_per_hour` `value_per_hour` DOUBLE UNSIGNED NULL , +DROP PRIMARY KEY, +ADD PRIMARY KEY (`from_id`, `to_id`, `transaction_type`, `day`), +ADD INDEX `fso_transaction_from` (`from_id` ASC), +ADD INDEX `fso_transaction_to` (`to_id` ASC), +ADD INDEX `fso_transaction_type` (`transaction_type` ASC); + +CREATE TABLE `fso_tuning` ( + `tuning_type` VARCHAR(128) NOT NULL, + `tuning_table` INT NOT NULL, + `tuning_index` INT NOT NULL, + `value` FLOAT NOT NULL, + `owner_type` ENUM('STATIC', 'DYNAMIC', 'EVENT') NOT NULL DEFAULT 'STATIC', + `owner_id` INT NULL DEFAULT NULL, + INDEX `tuning_by_owner` (`owner_type` ASC, `owner_id` ASC)); + +CREATE TABLE `fso_dyn_payouts` ( + `day` INT NOT NULL, + `skilltype` INT NOT NULL, + `multiplier` FLOAT NOT NULL DEFAULT 1, + `flags` INT NOT NULL DEFAULT 0, + PRIMARY KEY (`day`, `skilltype`)); \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0019_skillmode.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0019_skillmode.sql new file mode 100755 index 0000000..177232f --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0019_skillmode.sql @@ -0,0 +1,4 @@ +ALTER TABLE `fso_lots` +ADD COLUMN `skill_mode` TINYINT UNSIGNED NOT NULL DEFAULT '0' AFTER `move_flags`; + +UPDATE fso_lots SET skill_mode = 1 where category IN ("services", "entertainment", "romance"); \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0020_email_confirm.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0020_email_confirm.sql new file mode 100755 index 0000000..62ac110 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0020_email_confirm.sql @@ -0,0 +1,10 @@ +CREATE TABLE `fso_email_confirm` ( + `type` ENUM('email','password') NOT NULL DEFAULT 'email', + `email` VARCHAR(50) NULL DEFAULT NULL, + `token` VARCHAR(50) NULL DEFAULT NULL, + `expires` INT(11) NULL DEFAULT NULL +) +COMMENT='Table to control necessary email confirmation for registration or password reset.' +COLLATE='latin1_swedish_ci' +ENGINE=InnoDB +; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0021_3dthumb.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0021_3dthumb.sql new file mode 100755 index 0000000..0b7c161 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0021_3dthumb.sql @@ -0,0 +1,3 @@ +ALTER TABLE `fso_lots` +ADD COLUMN `thumb3d_dirty` TINYINT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `skill_mode`, +ADD COLUMN `thumb3d_time` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `thumb3d_dirty`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0022_lastlogin.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0022_lastlogin.sql new file mode 100755 index 0000000..f28eba2 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0022_lastlogin.sql @@ -0,0 +1,2 @@ +ALTER TABLE `fso_users` +ADD COLUMN `last_login` INT(10) UNSIGNED NOT NULL DEFAULT 0 AFTER `client_id`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0023_neighborhoods.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0023_neighborhoods.sql new file mode 100755 index 0000000..0236903 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0023_neighborhoods.sql @@ -0,0 +1,260 @@ +CREATE TABLE `fso_election_cycles` ( + `cycle_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `start_date` INT(10) UNSIGNED NOT NULL, + `end_date` INT(10) UNSIGNED NOT NULL, + `current_state` ENUM('shutdown', 'nomination', 'election', 'ended') NOT NULL, + `election_type` ENUM('election', 'shutdown') NOT NULL, + PRIMARY KEY (`cycle_id`)); + +CREATE TABLE `fso_neighborhoods` ( + `neighborhood_id` INT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(100) NOT NULL, + `description` VARCHAR(1000) NOT NULL DEFAULT '', + `shard_id` INT(11) NOT NULL, + `location` INT(10) ZEROFILL UNSIGNED NOT NULL, + `color` INT UNSIGNED NOT NULL DEFAULT 0xffffffff, + `flag` INT UNSIGNED NOT NULL DEFAULT 0, + `town_hall_id` INT(11) NULL, + `icon_url` VARCHAR(100) NULL, + `guid` VARCHAR(45) NOT NULL, + `mayor_id` INT(10) UNSIGNED NULL, + `mayor_elected_date` INT(10) UNSIGNED NOT NULL DEFAULT 0, + `election_cycle_id` INT(10) UNSIGNED NULL, + PRIMARY KEY (`neighborhood_id`), + UNIQUE INDEX `town_hall_id_UNIQUE` (`town_hall_id` ASC), + UNIQUE INDEX `guid_UNIQUE` (`guid` ASC), + UNIQUE INDEX `mayor_id_UNIQUE` (`mayor_id` ASC), + INDEX `fso_neigh_cycle_idx` (`election_cycle_id` ASC), + INDEX `fso_neigh_shard_idx` (`shard_id` ASC), + CONSTRAINT `fso_neigh_town_hall` + FOREIGN KEY (`town_hall_id`) + REFERENCES `fso_lots` (`lot_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_neigh_mayor` + FOREIGN KEY (`mayor_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_neigh_cycle` + FOREIGN KEY (`election_cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE RESTRICT + ON UPDATE CASCADE, + CONSTRAINT `fso_neigh_shard` + FOREIGN KEY (`shard_id`) + REFERENCES `fso_shards` (`shard_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Neighborhoods within each shard. Typically created ingame and then imported using `server import_nhood `.'; + +CREATE TABLE `fso_election_votes` ( + `election_cycle_id` INT(10) UNSIGNED NOT NULL, + `from_avatar_id` INT(10) UNSIGNED NOT NULL, + `type` ENUM('vote', 'nomination') NOT NULL, + `target_avatar_id` INT(10) UNSIGNED NOT NULL, + `date` INT(10) UNSIGNED NOT NULL, + PRIMARY KEY (`election_cycle_id`, `from_avatar_id`, `type`), + INDEX `fso_vote_from_idx` (`from_avatar_id` ASC), + INDEX `fso_vote_to_idx` (`target_avatar_id` ASC), + CONSTRAINT `fso_evote_cycle` + FOREIGN KEY (`election_cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_evote_from` + FOREIGN KEY (`from_avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_evote_to` + FOREIGN KEY (`target_avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Votes and Nominations for mayor election cycles. You can get the neighborhood id from the election cycle.'; + +CREATE TABLE `fso_election_candidates` ( + `election_cycle_id` INT UNSIGNED NOT NULL, + `candidate_avatar_id` INT UNSIGNED NOT NULL, + `comment` VARCHAR(200) NULL DEFAULT 'No comment.', + `disqualified` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'Boolean. True if this mayor has been disqualified for some reason.', + PRIMARY KEY (`election_cycle_id`, `candidate_avatar_id`), + INDEX `fso_candidate_avatar_idx` (`candidate_avatar_id` ASC), + CONSTRAINT `fso_candidate_cycle` + FOREIGN KEY (`election_cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_candidate_avatar` + FOREIGN KEY (`candidate_avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Candidates for an election cycle. You can get the neighborhood id from the election cycle.'; + +CREATE TABLE `fso_mayor_ratings` ( + `rating_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `from_user_id` INT UNSIGNED NOT NULL, + `to_user_id` INT UNSIGNED NOT NULL, + `rating` INT UNSIGNED NOT NULL DEFAULT 0, + `comment` VARCHAR(200) NOT NULL DEFAULT 'No Comment.', + `date` INT UNSIGNED NOT NULL DEFAULT 0, + `from_avatar_id` INT UNSIGNED NULL, + `to_avatar_id` INT UNSIGNED NULL, + `anonymous` TINYINT UNSIGNED NOT NULL DEFAULT 1, + PRIMARY KEY (`rating_id`), + INDEX `fso_mrating_to_idx` (`to_user_id` ASC), + INDEX `fso_mrating_from_idx` (`from_user_id` ASC), + INDEX `fso_mrating_froma_idx` (`from_avatar_id` ASC), + INDEX `fso_mrating_toa_idx` (`to_avatar_id` ASC), + CONSTRAINT `fso_mrating_from` + FOREIGN KEY (`from_user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_mrating_to` + FOREIGN KEY (`to_user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_mrating_froma` + FOREIGN KEY (`from_avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT `fso_mrating_toa` + FOREIGN KEY (`to_avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE SET NULL + ON UPDATE CASCADE) +COMMENT = 'User ID is used for ratings so people can\'t dodge their reviews by using another avatar or creating another account. Avatar IDs are still stored for possible visual reference, though the visual reference can be nulled if the avatar is deleted.'; + +CREATE TABLE `fso_bulletin_posts` ( + `bulletin_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `neighborhood_id` INT NOT NULL, + `avatar_id` INT UNSIGNED NOT NULL, + `title` VARCHAR(64) NOT NULL, + `body` VARCHAR(1000) NOT NULL, + `date` INT UNSIGNED NOT NULL, + `flags` INT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`bulletin_id`), + INDEX `fso_bulletin_neigh_idx` (`neighborhood_id` ASC), + INDEX `fso_bulletin_poster_idx` (`avatar_id` ASC), + CONSTRAINT `fso_bulletin_neigh` + FOREIGN KEY (`neighborhood_id`) + REFERENCES `fso_neighborhoods` (`neighborhood_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_bulletin_poster` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Posts for neighborhood bulletin boards. Can only be made by avatars that live in that neighborhood.'; + +ALTER TABLE `fso_avatars` +ADD COLUMN `custom_guid` INT UNSIGNED NULL AFTER `moderation_level`, +ADD COLUMN `move_date` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `custom_guid`, +ADD COLUMN `name_date` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `move_date`, +ADD COLUMN `mayor_nhood` INT NULL AFTER `name_date`, +ADD INDEX `FK_avatar_mayor_idx` (`mayor_nhood` ASC); +ALTER TABLE `fso_avatars` +ADD CONSTRAINT `FK_avatar_mayor` + FOREIGN KEY (`mayor_nhood`) + REFERENCES `fso_neighborhoods` (`neighborhood_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; + +ALTER TABLE `fso_mayor_ratings` +ADD COLUMN `neighborhood` INT(10) UNSIGNED NOT NULL AFTER `anonymous`; + +ALTER TABLE `fso_lots` +CHANGE COLUMN `category` `category` ENUM('none', 'welcome', 'money', 'skills', 'services', 'entertainment', 'romance', 'shopping', 'games', 'offbeat', 'residence', 'community') NOT NULL ; + +CREATE TABLE `fso_nhood_ban` ( + `user_id` INT UNSIGNED NOT NULL, + `ban_reason` VARCHAR(1000) NOT NULL DEFAULT 'You have been banned from using neighborhood gameplay for misuse. For more information, see http://freeso.org/nhoodrules/', + `end_date` INT UNSIGNED NOT NULL, + PRIMARY KEY (`user_id`), + CONSTRAINT `fso_nhood_ban_user` + FOREIGN KEY (`user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Table managing users who have been banned from Neighborhood Gameplay. (eg. inappropriate ratings, bribery in mayor campaign, abuse of bulletin board)'; + +ALTER TABLE `fso_events` +CHANGE COLUMN `description` `description` VARCHAR(1500) NULL DEFAULT NULL , +CHANGE COLUMN `mail_message` `mail_message` VARCHAR(1500) NULL DEFAULT NULL ; + +CREATE TRIGGER `fso_election_votes_BEFORE_INSERT` BEFORE INSERT ON `fso_election_votes` FOR EACH ROW BEGIN + IF (SELECT COUNT(*) from fso_election_votes v INNER JOIN fso_avatars va ON v.from_avatar_id = va.avatar_id + WHERE v.election_cycle_id = @cycle_id AND v.type = @type AND va.user_id IN + (SELECT user_id FROM fso_users WHERE last_ip = + (SELECT last_ip FROM fso_avatars a JOIN fso_users u on a.user_id = u.user_id WHERE avatar_id = @avatar_id) + )) > 0 THEN + SIGNAL SQLSTATE '45000' + SET MESSAGE_TEXT = 'A vote from this person or someone related already exists for this cycle.'; + END IF; +END; + +ALTER TABLE `fso_mayor_ratings` +ADD UNIQUE INDEX `fso_rating_user_to_ava` (`from_user_id` ASC, `to_avatar_id` ASC); + +ALTER TABLE `fso_tasks` +CHANGE COLUMN `task_type` `task_type` ENUM('prune_database', 'bonus', 'shutdown', 'job_balance', 'multi_check', 'prune_abandoned_lots', 'neighborhood_tick') NOT NULL ; + +CREATE TABLE `fso_election_cyclemail` ( + `avatar_id` INT UNSIGNED NOT NULL, + `cycle_id` INT UNSIGNED NOT NULL, + `cycle_state` ENUM('shutdown', 'nomination', 'election', 'ended', 'failsafe') NOT NULL, + PRIMARY KEY (`avatar_id`, `cycle_id`, `cycle_state`), + INDEX `fso_cmail_cycle_idx` (`cycle_id` ASC), + CONSTRAINT `fso_cmail_ava` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_cmail_cycle` + FOREIGN KEY (`cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE CASCADE + ON UPDATE CASCADE); + +ALTER TABLE `fso_election_cycles` +CHANGE COLUMN `current_state` `current_state` ENUM('shutdown', 'nomination', 'election', 'ended', 'failsafe') NOT NULL ; + +ALTER TABLE `fso_neighborhoods` +DROP FOREIGN KEY `fso_neigh_cycle`, +DROP FOREIGN KEY `fso_neigh_mayor`, +DROP FOREIGN KEY `fso_neigh_town_hall`; +ALTER TABLE `fso_neighborhoods` +ADD CONSTRAINT `fso_neigh_cycle` + FOREIGN KEY (`election_cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE SET NULL + ON UPDATE CASCADE, +ADD CONSTRAINT `fso_neigh_mayor` + FOREIGN KEY (`mayor_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE SET NULL + ON UPDATE CASCADE, +ADD CONSTRAINT `fso_neigh_town_hall` + FOREIGN KEY (`town_hall_id`) + REFERENCES `fso_lots` (`lot_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; + +ALTER TABLE `fso_election_candidates` +CHANGE COLUMN `disqualified` `state` ENUM('informed', 'running', 'disqualified', 'lost', 'won') NOT NULL DEFAULT 'informed' COMMENT 'Boolean. True if this mayor has been disqualified for some reason.' ; + +ALTER TABLE `fso_election_cycles` +ADD COLUMN `neighborhood_id` INT NULL AFTER `election_type`, +ADD INDEX `fso_cycle_nhood_idx` (`neighborhood_id` ASC); +ALTER TABLE `fso_election_cycles` +ADD CONSTRAINT `fso_cycle_nhood` + FOREIGN KEY (`neighborhood_id`) + REFERENCES `fso_neighborhoods` (`neighborhood_id`) + ON DELETE CASCADE + ON UPDATE CASCADE; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0024_bulletin.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0024_bulletin.sql new file mode 100755 index 0000000..ef94b0f --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0024_bulletin.sql @@ -0,0 +1,34 @@ +ALTER TABLE `fso_bulletin_posts` +DROP FOREIGN KEY `fso_bulletin_poster`; +ALTER TABLE `fso_bulletin_posts` +CHANGE COLUMN `avatar_id` `avatar_id` INT(10) UNSIGNED NULL , +ADD COLUMN `lot_id` INT(11) NULL AFTER `flags`, +ADD COLUMN `type` ENUM('mayor', 'system', 'community') NULL AFTER `lot_id`, +ADD INDEX `fso_bulletin_lot_idx` (`lot_id` ASC); +ALTER TABLE `fso_bulletin_posts` +ADD CONSTRAINT `fso_bulletin_poster` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, +ADD CONSTRAINT `fso_bulletin_lot` + FOREIGN KEY (`lot_id`) + REFERENCES `fso_lots` (`lot_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; + +ALTER TABLE `fso_bulletin_posts` +DROP FOREIGN KEY `fso_bulletin_lot`; +ALTER TABLE `fso_bulletin_posts` +CHANGE COLUMN `lot_id` `lot_id` INT(11) UNSIGNED NULL DEFAULT NULL , +ADD INDEX `fso_bulletin_lot_idx` (`lot_id` ASC), +DROP INDEX `fso_bulletin_lot_idx` ; +ALTER TABLE `fso_bulletin_posts` +ADD CONSTRAINT `fso_bulletin_lot` + FOREIGN KEY (`lot_id`) + REFERENCES `fso_lots` (`location`) + ON DELETE SET NULL + ON UPDATE CASCADE; + +ALTER TABLE `fso_bulletin_posts` +ADD COLUMN `deleted` TINYINT UNSIGNED NOT NULL DEFAULT 0 AFTER `type`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0025_updates.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0025_updates.sql new file mode 100755 index 0000000..d93bfa8 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0025_updates.sql @@ -0,0 +1,99 @@ +CREATE TABLE `fso_update_addons` ( + `addon_id` INT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(45) NOT NULL DEFAULT 'Untitled' COMMENT 'Name of the update addon.', + `description` VARCHAR(1000) NULL, + `addon_zip_url` VARCHAR(256) NOT NULL COMMENT 'Addon zip which is extracted on top of the client update base.', + `server_zip_url` VARCHAR(256) NULL COMMENT 'Addon zip which is extracted on top of the server update base. (optional)', + `date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Date the addon was created.', + PRIMARY KEY (`addon_id`)) +COMMENT = 'Update addons are additional resources which are combined with the base game version (from a buildbot) to create the final binary a server will update to and deploy.'; + +CREATE TABLE `fso_update_branch` ( + `branch_id` INT NOT NULL AUTO_INCREMENT, + `version_format` VARCHAR(128) NOT NULL DEFAULT 'dev/update-#' COMMENT 'Format string for version name. # is version number, $ is commit number (if available).', + `last_version_number` INT NOT NULL DEFAULT 0 COMMENT 'The last version number. This is incremented when a new build is generated for this branch.', + `current_dist_id` INT NULL COMMENT 'The current distribution in fso_updates.', + `addon_id` INT NULL COMMENT '(Optional) The addon to merge into the downloaded binary.', + `base_build_url` VARCHAR(256) NOT NULL COMMENT 'URL for client binary to base updates off of. If \"teamcity\" is enabled, the client AND server binary is found within the grouped artifacts zip this link points to.', + `base_server_build_url` VARCHAR(256) NULL COMMENT '(Optional) URL for server binary. Required for zip mode, not for teamcity.', + `build_mode` ENUM('zip', 'teamcity') NOT NULL DEFAULT 'zip' COMMENT 'The mode to use when obtaining binaries.', + `flags` INT NULL COMMENT '1 - Disable Incremental Updates', + PRIMARY KEY (`branch_id`), + INDEX `branch_addon_id_idx` (`addon_id` ASC), + CONSTRAINT `branch_addon_id` + FOREIGN KEY (`addon_id`) + REFERENCES `fso_update_addons` (`addon_id`) + ON DELETE SET NULL + ON UPDATE CASCADE) +COMMENT = 'Update branches for the server. Each branch points to a source to download new zips from, and can optionally point to an update addon to be merged into it. This also generates a version name.'; + +CREATE TABLE `fso_updates` ( + `update_id` INT NOT NULL AUTO_INCREMENT COMMENT 'The ID of this update.', + `version_name` VARCHAR(128) NOT NULL COMMENT 'The name of this version, generated from the format in the branch.', + `addon_id` INT NULL COMMENT 'The addon pack this update includes.', + `branch_id` INT NOT NULL COMMENT 'The branch this update was generated off of.', + `full_zip` VARCHAR(256) NOT NULL COMMENT 'URL for the zip file containing the full client distribution. Should be used for new users and fixing failed updates.', + `incremental_zip` VARCHAR(256) NULL COMMENT 'A zip containing the files that were added or modified since the last update (see last_update_id)', + `manfest_url` VARCHAR(256) NULL COMMENT 'Manifest file for the incremental zip.', + `server_zip` VARCHAR(256) NULL COMMENT 'URL to a zip containing the server distribution. Downloaded and applied by the Watchdog on server restart. (may also be used for rollbacks)', + `last_update_id` INT NULL COMMENT 'The update that the incremental update was created from.', + `flags` INT NOT NULL DEFAULT 0 COMMENT '1 - db-init required\n2 - force non-incremental\n4 - incremental on protected\n8 - rolled back', + `date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'The date the update was generated at.', + `publish_date` DATETIME NULL COMMENT 'The date the update was published at.', + `deploy_after` DATETIME NULL COMMENT '(Optional) The time after which to deploy this update to the server on restart. When an entry with this is set and the server shuts down, it starts the update process and sets this to NULL.', + PRIMARY KEY (`update_id`), + INDEX `fso_updates_addon_idx` (`addon_id` ASC), + INDEX `fso_updates_branch_fk_idx` (`branch_id` ASC), + CONSTRAINT `fso_updates_addon_fk` + FOREIGN KEY (`addon_id`) + REFERENCES `fso_update_addons` (`addon_id`) + ON DELETE SET NULL + ON UPDATE CASCADE, + CONSTRAINT `fso_updates_branch_fk` + FOREIGN KEY (`branch_id`) + REFERENCES `fso_update_branch` (`branch_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Updates generated by the server for branches. Should link to all published assets, and track incremental update paths. When deploy_after is set, the update will become the main update for that branch after the time elapses (on server restart).'; + +ALTER TABLE `fso_updates` +ADD INDEX `fso_updates_last_fk_idx` (`last_update_id` ASC); +ALTER TABLE `fso_updates` +ADD CONSTRAINT `fso_updates_last_fk` + FOREIGN KEY (`last_update_id`) + REFERENCES `fso_updates` (`update_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; + +ALTER TABLE `fso_update_branch` +CHANGE COLUMN `flags` `flags` INT(11) NOT NULL COMMENT '1 - Disable Incremental Updates' ; + +ALTER TABLE `fso_update_branch` +ADD COLUMN `branch_name` VARCHAR(128) NOT NULL DEFAULT 'dev' AFTER `branch_id`; + +ALTER TABLE `fso_updates` +CHANGE COLUMN `full_zip` `full_zip` VARCHAR(256) NULL DEFAULT NULL COMMENT 'URL for the zip file containing the full client distribution. Should be used for new users and fixing failed updates.' , +CHANGE COLUMN `manfest_url` `manifest_url` VARCHAR(256) NULL DEFAULT NULL COMMENT 'Manifest file for the incremental zip.' ; + +ALTER TABLE `fso_update_branch` +ADD COLUMN `minor_version_number` INT NOT NULL DEFAULT 0 AFTER `last_version_number`; + +ALTER TABLE `fso_shards` +ADD COLUMN `update_id` INT NULL DEFAULT NULL AFTER `version_number`, +ADD INDEX `fso_shard_update_id_idx` (`update_id` ASC); +ALTER TABLE `fso_shards` +ADD CONSTRAINT `fso_shard_update_id` + FOREIGN KEY (`update_id`) + REFERENCES `fso_updates` (`update_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; + + ALTER TABLE `fso_hosts` +ADD COLUMN `update_id` INT NULL DEFAULT NULL AFTER `shard_id`, +ADD INDEX `FK_fso_host_update_id_idx` (`update_id` ASC); +ALTER TABLE `fso_hosts` +ADD CONSTRAINT `FK_fso_host_update_id` + FOREIGN KEY (`update_id`) + REFERENCES `fso_updates` (`update_id`) + ON DELETE SET NULL + ON UPDATE CASCADE; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0026_freevote.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0026_freevote.sql new file mode 100755 index 0000000..5251893 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0026_freevote.sql @@ -0,0 +1,48 @@ +CREATE TABLE `fso_election_freevotes` ( + `avatar_id` INT UNSIGNED NOT NULL, + `neighborhood_id` INT NOT NULL, + `cycle_id` INT UNSIGNED NOT NULL, + `date` INT NOT NULL, + `expire_date` INT NOT NULL, + PRIMARY KEY (`avatar_id`), + INDEX `fso_freevote_cycle_idx` (`cycle_id` ASC), + INDEX `fso_freevote_nhood_idx` (`neighborhood_id` ASC), + CONSTRAINT `fso_freevote_avatar` + FOREIGN KEY (`avatar_id`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_freevote_cycle` + FOREIGN KEY (`cycle_id`) + REFERENCES `fso_election_cycles` (`cycle_id`) + ON DELETE CASCADE + ON UPDATE CASCADE, + CONSTRAINT `fso_freevote_nhood` + FOREIGN KEY (`neighborhood_id`) + REFERENCES `fso_neighborhoods` (`neighborhood_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'When a neighborhood is ineligible for an election, its residents get to choose a neighborhood election to participate in. Entries in this table allow avatars to vote in an election when they do not live in its neighborhood. Entries in this table should expire when the linked cycle ends.'; + +ALTER TABLE `fso_election_freevotes` +CHANGE COLUMN `date` `date` INT(11) UNSIGNED NOT NULL , +CHANGE COLUMN `expire_date` `expire_date` INT(11) UNSIGNED NOT NULL ; + +ALTER TABLE `fso_election_votes` +ADD COLUMN `value` INT NOT NULL DEFAULT 1 COMMENT 'The value of this vote. Some votes can be worth more than others (eg. free votes are worth less than normal ones)' AFTER `date`; + +CREATE TABLE `fso_auth_attempts` ( + `attempt_id` INT UNSIGNED NOT NULL AUTO_INCREMENT, + `ip` VARCHAR(100) NOT NULL, + `user_id` INT UNSIGNED NOT NULL, + `expire_time` INT UNSIGNED NOT NULL, + `count` INT NOT NULL DEFAULT 0, + `active` TINYINT UNSIGNED NOT NULL DEFAULT 0, + `invalidated` TINYINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`attempt_id`), + INDEX `fk_user_attempt_idx` (`user_id` ASC), + CONSTRAINT `fk_user_attempt` + FOREIGN KEY (`user_id`) + REFERENCES `fso_users` (`user_id`) + ON DELETE CASCADE + ON UPDATE CASCADE); \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0027_tuning_presets.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0027_tuning_presets.sql new file mode 100755 index 0000000..0c350e6 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0027_tuning_presets.sql @@ -0,0 +1,23 @@ +CREATE TABLE `fso_tuning_presets` ( + `preset_id` INT NOT NULL AUTO_INCREMENT, + `name` VARCHAR(128) NULL, + `description` VARCHAR(1000) NULL, + `flags` INT NOT NULL DEFAULT 0, + PRIMARY KEY (`preset_id`)) +COMMENT = 'Presets are collections of tuning info that can be applied and removed at the same time as part of an event.'; + +CREATE TABLE `fso_tuning_preset_items` ( + `item_id` INT NOT NULL AUTO_INCREMENT, + `preset_id` INT NOT NULL, + `tuning_type` VARCHAR(128) NOT NULL, + `tuning_table` INT NOT NULL, + `tuning_index` INT NOT NULL, + `value` FLOAT NOT NULL, + PRIMARY KEY (`item_id`), + INDEX `fso_preset_item_to_preset_fk_idx` (`preset_id` ASC), + CONSTRAINT `fso_preset_item_to_preset_fk` + FOREIGN KEY (`preset_id`) + REFERENCES `fso_tuning_presets` (`preset_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Individual tuning items that belong to a preset configuration, to be applied as a group. Similar to fso_tuning, built to copy right into it.'; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0028_upgradelevel.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0028_upgradelevel.sql new file mode 100755 index 0000000..f696f23 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0028_upgradelevel.sql @@ -0,0 +1,2 @@ +ALTER TABLE `fso_objects` +ADD COLUMN `upgrade_level` INT(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `dyn_flags_2`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0029_generic_participation.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0029_generic_participation.sql new file mode 100755 index 0000000..b1d7a89 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0029_generic_participation.sql @@ -0,0 +1,15 @@ +CREATE TABLE `fso_generic_avatar_participation` ( + `participation_name` TEXT(64) NOT NULL, + `participation_avatar` INT UNSIGNED NOT NULL, + PRIMARY KEY (`participation_name`(64), `participation_avatar`), + INDEX `fso_generic_ava_idx` (`participation_avatar` ASC), + INDEX `fso_generic_name_idx` (`participation_name`(64) ASC), + CONSTRAINT `fso_generic_avatarp_id` + FOREIGN KEY (`participation_avatar`) + REFERENCES `fso_avatars` (`avatar_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'If you need a generic way to track avatar participation in things, here it is. Useful for events and tasks that don\'t have their own per-avatar tracking and need it.'; + +ALTER TABLE `fso_tasks` +CHANGE COLUMN `task_type` `task_type` ENUM('prune_database', 'bonus', 'shutdown', 'job_balance', 'multi_check', 'prune_abandoned_lots', 'neighborhood_tick', 'birthday_gift') NOT NULL ; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0030_tokens.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0030_tokens.sql new file mode 100755 index 0000000..48665f6 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0030_tokens.sql @@ -0,0 +1,15 @@ +CREATE TABLE `fso_object_attributes` ( + `object_id` INT UNSIGNED NOT NULL COMMENT 'ID of the object this attribute is for.', + `index` INT UNSIGNED NOT NULL COMMENT 'Index of the Attribute.', + `value` INT NOT NULL COMMENT 'Value of the Attribute. Ingame these can only be short size, but I\'ve left them full int here just in case we need to expand.', + PRIMARY KEY (`object_id`, `index`), + INDEX `fso_object_id_attr_idx` (`object_id` ASC), + CONSTRAINT `fso_object_id_attr` + FOREIGN KEY (`object_id`) + REFERENCES `fso_objects` (`object_id`) + ON DELETE CASCADE + ON UPDATE CASCADE) +COMMENT = 'Attributes for objects in the fso_objects table. These are used for \'token\' objects, special objects which can track values such as secondary currencies and car keys (pointing to the car you are driving, for example)\nThese are only saved for objects of type token - other objects use filesystem objects to store attributes.'; + +ALTER TABLE `fso_objects` +ADD COLUMN `has_db_attributes` TINYINT UNSIGNED NOT NULL DEFAULT 0 COMMENT 'If >0, attributes should be fetched from fso_object_attributes rather than trusting NFS state. 2 indicates value token.' AFTER `upgrade_level`; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/changes/0031_global_cooldowns.sql b/server/FSO.Server.Database/DatabaseScripts/changes/0031_global_cooldowns.sql new file mode 100755 index 0000000..773995b --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/changes/0031_global_cooldowns.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS `fso_global_cooldowns` ( + `object_guid` int(11) unsigned NOT NULL, + `avatar_id` int(10) unsigned NOT NULL, + `user_id` int(10) unsigned NOT NULL, + `category` int(10) unsigned NOT NULL, + `expiry` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`object_guid`, `avatar_id`, `user_id`, `category`), + CONSTRAINT `FK_global_cooldowns_fso_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_global_cooldowns_fso_users` FOREIGN KEY (`user_id`) REFERENCES `fso_users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE +) \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_auth_tickets.sql b/server/FSO.Server.Database/DatabaseScripts/fso_auth_tickets.sql new file mode 100755 index 0000000..5805cb8 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_auth_tickets.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `fso_auth_tickets` ( + `ticket_id` VARCHAR(36) NOT NULL, + `user_id` INT(10) UNSIGNED NOT NULL, + `date` INT(10) UNSIGNED NOT NULL, + `ip` VARCHAR(50) NOT NULL, + PRIMARY KEY (`ticket_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_avatars.sql b/server/FSO.Server.Database/DatabaseScripts/fso_avatars.sql new file mode 100755 index 0000000..9169343 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_avatars.sql @@ -0,0 +1,81 @@ +CREATE TABLE IF NOT EXISTS `fso_avatars` ( + `avatar_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `shard_id` int(11) NOT NULL, + `user_id` int(10) unsigned NOT NULL, + `name` varchar(24) NOT NULL, + `gender` enum('male','female') NOT NULL, + `date` int(10) unsigned NOT NULL, + `skin_tone` tinyint(3) unsigned NOT NULL, + `head` bigint(20) unsigned NOT NULL, + `body` bigint(20) unsigned NOT NULL, + `body_swimwear` bigint(20) unsigned NOT NULL DEFAULT '2985002270733', + `body_sleepwear` bigint(20) unsigned NOT NULL DEFAULT '2980707303437', + `body_current` bigint(20) unsigned NOT NULL DEFAULT '0', + `description` varchar(500) NOT NULL, + `budget` int(11) NOT NULL DEFAULT '0', + `privacy_mode` tinyint(3) unsigned NOT NULL DEFAULT '0', + `motive_data` binary(32) NOT NULL DEFAULT '0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0', + `skilllock` tinyint(3) unsigned NOT NULL DEFAULT '0', + `lock_mechanical` smallint(5) unsigned NOT NULL DEFAULT '0', + `lock_cooking` smallint(5) unsigned NOT NULL DEFAULT '0', + `lock_charisma` smallint(5) unsigned NOT NULL DEFAULT '0', + `lock_logic` smallint(5) unsigned NOT NULL DEFAULT '0', + `lock_body` smallint(5) unsigned NOT NULL DEFAULT '0', + `lock_creativity` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_mechanical` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_cooking` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_charisma` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_logic` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_body` smallint(5) unsigned NOT NULL DEFAULT '0', + `skill_creativity` smallint(5) unsigned NOT NULL DEFAULT '0', + `current_job` smallint(5) unsigned NOT NULL DEFAULT '0', + `is_ghost` smallint(5) unsigned NOT NULL DEFAULT '0', + `ticker_death` smallint(5) unsigned NOT NULL DEFAULT '0', + `ticker_gardener` smallint(5) unsigned NOT NULL DEFAULT '0', + `ticker_maid` smallint(5) unsigned NOT NULL DEFAULT '0', + `ticker_repairman` smallint(5) unsigned NOT NULL DEFAULT '0', + `moderation_level` tinyint(3) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`avatar_id`), + UNIQUE KEY `shard_id_name` (`shard_id`,`name`), + KEY `FK_shard` (`shard_id`), + KEY `FK_avatar_users_idx` (`user_id`), + CONSTRAINT `FK_avatar_users` FOREIGN KEY (`user_id`) REFERENCES `fso_users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_shard` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TABLE `fso_avatar_claims` ( + `avatar_claim_id` INT(11) NOT NULL AUTO_INCREMENT, + `avatar_id` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `owner` VARCHAR(50) NOT NULL DEFAULT '0', + `location` INT(10) UNSIGNED NOT NULL DEFAULT '0', + PRIMARY KEY (`avatar_claim_id`), + UNIQUE INDEX `avatar_id` (`avatar_id`), + CONSTRAINT `FK_fso_avatar_claims_fso_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS `fso_joblevels` ( + `avatar_id` int(10) unsigned NOT NULL, + `job_type` smallint(5) unsigned NOT NULL, + `job_experience` smallint(5) unsigned NOT NULL, + `job_level` smallint(5) unsigned NOT NULL, + `job_sickdays` smallint(5) unsigned NOT NULL, + `job_statusflags` smallint(5) unsigned NOT NULL, + PRIMARY KEY (`avatar_id`,`job_type`), + CONSTRAINT `FK_job_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS `fso_relationships` ( + `from_id` int(10) unsigned NOT NULL, + `to_id` int(10) unsigned NOT NULL, + `value` int(10) NOT NULL, + `index` int(10) unsigned NOT NULL, + `comment_id` int(11) unsigned DEFAULT NULL, + `date` int(11) unsigned NOT NULL, + PRIMARY KEY (`from_id`,`to_id`,`index`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_db_changes.sql b/server/FSO.Server.Database/DatabaseScripts/fso_db_changes.sql new file mode 100755 index 0000000..18c4578 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_db_changes.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS `fso_db_changes` ( + `id` VARCHAR(100) NOT NULL, + `filename` VARCHAR(100) NOT NULL, + `date` INT UNSIGNED NOT NULL, + `hash` VARCHAR(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `filename` (`filename`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_lots.sql b/server/FSO.Server.Database/DatabaseScripts/fso_lots.sql new file mode 100755 index 0000000..b47a77a --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_lots.sql @@ -0,0 +1,73 @@ +CREATE TABLE IF NOT EXISTS `fso_lots` ( + `lot_id` int(11) NOT NULL AUTO_INCREMENT, + `shard_id` int(11) NOT NULL, + `name` varchar(50) NOT NULL, + `description` varchar(500) NOT NULL, + `owner_id` int(10) unsigned NOT NULL, + `location` int(10) unsigned zerofill NOT NULL, + `neighborhood_id` int(11) DEFAULT NULL, + `created_date` int(10) unsigned NOT NULL, + `category_change_date` int(11) unsigned NOT NULL, + `category` enum('none','welcome','money','skills','services','entertainment','romance','shopping','games','offbeat','residence') NOT NULL, + `buildable_area` int(10) unsigned NOT NULL, + `ring_backup_num` tinyint(4) NOT NULL DEFAULT '-1', + `admit_mode` tinyint(3) unsigned NOT NULL DEFAULT '0', + `move_flags` tinyint(3) DEFAULT '1', + PRIMARY KEY (`lot_id`), + UNIQUE KEY `shard_id_name` (`shard_id`,`name`), + UNIQUE KEY `shard_id_location` (`shard_id`,`location`), + UNIQUE KEY `location_UNIQUE` (`location`), + CONSTRAINT `FK_fso_lots_fso_shards` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS `fso_roommates` ( + `avatar_id` int(10) unsigned NOT NULL, + `lot_id` int(11) NOT NULL, + `permissions_level` tinyint(3) unsigned NOT NULL, + `is_pending` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`avatar_id`,`lot_id`), + KEY `FK_roommate_lots_idx` (`lot_id`), + CONSTRAINT `FK_roommate_avatars` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_roommate_lots` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `fso_lot_claims` ( + `claim_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `shard_id` int(11) NOT NULL, + `lot_id` int(10) NOT NULL, + `owner` varchar(50) NOT NULL, + PRIMARY KEY (`claim_id`), + UNIQUE KEY `shard_id_lot_id` (`shard_id`,`lot_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Represents a lot servers claim on a lot.'; + +CREATE TABLE IF NOT EXISTS `fso_lot_server_tickets` ( + `ticket_id` varchar(36) NOT NULL, + `user_id` int(10) unsigned NOT NULL, + `date` int(10) unsigned NOT NULL, + `ip` varchar(50) NOT NULL, + `avatar_id` int(10) unsigned NOT NULL, + `lot_id` int(10) NOT NULL COMMENT 'Note: need not necessarily be a real lot! Tickets can be granted for runtime lots, such as job lots. These are marked with the bit flag 0x40000000.', + `avatar_claim_id` int(11) NOT NULL, + `avatar_claim_owner` varchar(50) NOT NULL, + `lot_owner` varchar(50) NOT NULL, + PRIMARY KEY (`ticket_id`), + KEY `FK_fso_lot_server_tickets_fso_avatar_claims` (`avatar_claim_id`), + CONSTRAINT `FK_fso_lot_server_tickets_fso_avatar_claims` FOREIGN KEY (`avatar_claim_id`) REFERENCES `fso_avatar_claims` (`avatar_claim_id`) ON DELETE CASCADE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS `fso_lot_admit` ( + `lot_id` int(11) NOT NULL, + `avatar_id` int(10) unsigned NOT NULL, + `admit_type` tinyint(3) unsigned NOT NULL, + PRIMARY KEY (`avatar_id`,`lot_id`), + KEY `FK_lot_idx` (`lot_id`), + KEY `FK_avatar_idx` (`avatar_id`), + CONSTRAINT `FK_admit_avatar` FOREIGN KEY (`avatar_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `FK_admit_lot` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE CASCADE ON UPDATE CASCADE +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_objects.sql b/server/FSO.Server.Database/DatabaseScripts/fso_objects.sql new file mode 100755 index 0000000..11a5535 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_objects.sql @@ -0,0 +1,24 @@ +CREATE TABLE IF NOT EXISTS `fso_objects` ( + `object_id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `shard_id` int(11) NOT NULL, + `owner_id` int(11) unsigned DEFAULT NULL, + `lot_id` int(11) DEFAULT NULL, + `dyn_obj_name` varchar(64) NOT NULL, + `type` int(11) unsigned NOT NULL, + `graphic` smallint(5) unsigned NOT NULL, + `value` int(11) unsigned NOT NULL, + `wear` smallint(5) unsigned NOT NULL DEFAULT '0', + `budget` int(11) NOT NULL DEFAULT '0', + `dyn_flags_1` bigint(20) unsigned NOT NULL DEFAULT '0', + `dyn_flags_2` bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`object_id`), + KEY `FK_owner_idx` (`owner_id`), + KEY `FK_obj_shard_idx` (`shard_id`), + KEY `FK_obj_lot_idx` (`lot_id`), + CONSTRAINT `FK_obj_lot` FOREIGN KEY (`lot_id`) REFERENCES `fso_lots` (`lot_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `FK_obj_shard` FOREIGN KEY (`shard_id`) REFERENCES `fso_shards` (`shard_id`) ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT `FK_owner` FOREIGN KEY (`owner_id`) REFERENCES `fso_avatars` (`avatar_id`) ON DELETE SET NULL ON UPDATE CASCADE +) +AUTO_INCREMENT=16777216 +COLLATE='utf8_general_ci' +ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_shards.sql b/server/FSO.Server.Database/DatabaseScripts/fso_shards.sql new file mode 100755 index 0000000..0f28238 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_shards.sql @@ -0,0 +1,26 @@ +CREATE TABLE IF NOT EXISTS `fso_shards` ( + `shard_id` int(11) NOT NULL, + `name` varchar(100) NOT NULL, + `rank` int(11) NOT NULL, + `map` varchar(10) NOT NULL, + `status` enum('up','down','busy','full','closed','frontier') NOT NULL, + `internal_host` varchar(100) NOT NULL, + `public_host` varchar(100) NOT NULL, + PRIMARY KEY (`shard_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +-- Default shard +INSERT INTO fso_shards VALUES (1, 'Alphaville', 1, '0001', 'up', '127.0.0.1:7777', '127.0.0.1:7777') ON DUPLICATE KEY UPDATE shard_id = shard_id; + +CREATE TABLE IF NOT EXISTS `fso_shard_tickets` ( + `ticket_id` VARCHAR(36) NOT NULL, + `user_id` INT UNSIGNED NOT NULL, + `date` INT UNSIGNED NOT NULL, + `ip` VARCHAR(50) NOT NULL, + `avatar_id` INT UNSIGNED NOT NULL, + PRIMARY KEY (`ticket_id`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_transactions.sql b/server/FSO.Server.Database/DatabaseScripts/fso_transactions.sql new file mode 100755 index 0000000..527c770 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_transactions.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS `fso_transactions` ( + `from_id` int(11) unsigned NOT NULL, + `to_id` int(11) unsigned NOT NULL, + `transaction_type` int(11) unsigned NOT NULL, + `value` int(11) unsigned NOT NULL, + `time_first` int(11) unsigned NOT NULL, + `time_last` int(11) unsigned NOT NULL, + `count` int(11) unsigned NOT NULL, + `value_per_hour` double unsigned NOT NULL, + PRIMARY KEY (`from_id`,`to_id`,`transaction_type`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/server/FSO.Server.Database/DatabaseScripts/fso_users.sql b/server/FSO.Server.Database/DatabaseScripts/fso_users.sql new file mode 100755 index 0000000..bcaa649 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/fso_users.sql @@ -0,0 +1,33 @@ +-- User table, does not include password info so we dont return this into RAM unless we absolutely need to. Also will help do SSO eventually +CREATE TABLE IF NOT EXISTS `fso_users` ( + `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL, + `email` varchar(120) NOT NULL, + `user_state` enum('valid','email_confirm','moderated') NOT NULL DEFAULT 'email_confirm', + `register_date` int(10) NOT NULL, + `is_admin` tinyint(3) NOT NULL, + `is_moderator` tinyint(3) NOT NULL, + `is_banned` tinyint(3) NOT NULL, + `register_ip` varchar(50) NOT NULL DEFAULT '127.0.0.1', + `last_ip` varchar(50) NOT NULL DEFAULT '127.0.0.1', + PRIMARY KEY (`user_id`), + UNIQUE KEY `username` (`username`) +) +COLLATE='utf8_general_ci' +ENGINE=InnoDB; + +-- Stores password hashes +CREATE TABLE IF NOT EXISTS `fso_user_authenticate` ( + `user_id` int(10) unsigned NOT NULL, + `scheme_class` varchar(75) NOT NULL, + `data` mediumblob NOT NULL, + PRIMARY KEY (`user_id`), + CONSTRAINT `fk_users_pass` FOREIGN KEY (`user_id`) REFERENCES `fso_users` (`user_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Default user +INSERT INTO fso_users VALUES (1, 'admin', 'admin@freeso.org', 'valid', 1439646790, 1, 1, 0, '127.0.0.1', '127.0.0.1') ON DUPLICATE KEY UPDATE user_id = user_id; + +-- Default user password +INSERT INTO fso_user_authenticate VALUES (1, 'Rfc2898', 0x10E28CDC7DC433309503EC95A7222BF4CDE2C5DD386FB91CE632EBF9DC22B6EC398AA2FE6F2B0E60278493283CD6886A2C7072F97ACE3E06EF0EE1E93388A4A793A44DF0C124AF01364F55B28CCE1927B9) ON DUPLICATE KEY UPDATE user_id = user_id; + diff --git a/server/FSO.Server.Database/DatabaseScripts/manifest.json b/server/FSO.Server.Database/DatabaseScripts/manifest.json new file mode 100755 index 0000000..6106213 --- /dev/null +++ b/server/FSO.Server.Database/DatabaseScripts/manifest.json @@ -0,0 +1,290 @@ +{ + "changes": [ + { + "id": "585866d1-2330-4af2-bdd6-ff792e782d91", + "script": "fso_db_changes.sql", + "idempotent": false + }, + { + "id": "9a48f9fc-5950-4348-9ccf-318a263be4eb", + "script": "fso_users.sql", + "idempotent": false + }, + { + "id": "9e2e3527-1209-43b5-a579-b085d8965265", + "script": "fso_auth_tickets.sql", + "idempotent": false + }, + { + "id": "def48038-d0d6-4b10-a129-0b9c736e4d35", + "script": "fso_shards.sql", + "idempotent": false + }, + { + "id": "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "script": "fso_avatars.sql", + "idempotent": false + }, + { + "id": "52795d47-a25e-418f-a618-fb89300aab01", + "script": "fso_lots.sql", + "idempotent": false + }, + { + "id": "52795d47-a25e-418f-a618-fb89300aab02", + "script": "fso_objects.sql", + "idempotent": false + }, + { + "id": "9879997a-4b16-4733-aff4-d0178ce2afa5", + "script": "fso_transactions.sql", + "idempotent": false + }, + { + "id": "d19d4e3f-4177-43f7-b837-db61bdaf17cc", + "script": "changes/0001_3_max_avatars.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + }, + { + "id": "58e03211-785c-4d8e-88ae-86d49255503a", + "script": "changes/0002_budget_cant_be_negative.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "52795d47-a25e-418f-a618-fb89300aab02" + ] + }, + { + "id": "ce7b44fc-f58a-437e-ad7e-7a8f99c64b5f", + "script": "changes/0003_max_roomates.sql", + "idempotent": false, + "requires": [ + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "3b7c199c-c369-4f2c-855b-2554e93484bc", + "script": "changes/0004_bookmarks.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + }, + { + "id": "94ef1ab2-4cd8-4df3-8c8b-fa7421465a13", + "script": "changes/0005_lotadmit_primarykey.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "52795d47-a25e-418f-a618-fb89300aab02" + ] + }, + { + "id": "28b9a5c0-886c-4307-912b-05d4ddd5ba9e", + "script": "changes/0006_outfits.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "52795d47-a25e-418f-a618-fb89300aab02" + ] + }, + { + "id": "f9abf5f8-c9d5-4e3a-9c25-21b8ecbf64aa", + "script": "changes/0007_fso_lot_visits.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "52182afb-a175-430a-99ad-0c1c4db924ac", + "script": "changes/0008_fso_hosts.sql", + "idempotent": false, + "requires": [ + "def48038-d0d6-4b10-a129-0b9c736e4d35" + ] + }, + { + "id": "9e4dc7d8-06b7-4f2f-84a8-4da737072d55", + "script": "changes/0009_fso_tasks.sql", + "idempotent": false, + "requires": [ + "def48038-d0d6-4b10-a129-0b9c736e4d35" + ] + }, + { + "id": "2149dfea-970e-4161-901d-b59106fa484f", + "script": "changes/0010_fso_top100.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "4838258c-765d-42c9-8439-0505000b372f", + "script": "changes/0011_fso_bonus.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + }, + { + "id": "12cd7494-b6a8-4ea7-851f-96f35b22e783", + "script": "changes/0012_fso_bans.sql", + "idempotent": false, + "requires": [ + "9a48f9fc-5950-4348-9ccf-318a263be4eb" + ] + }, + { + "id": "64f80154-3d3b-434a-a516-5c385143dbfc", + "script": "changes/0013_shard_version.sql", + "idempotent": false, + "requires": [ + "def48038-d0d6-4b10-a129-0b9c736e4d35" + ] + }, + { + "id": "2b01bdbe-0c93-4ee1-afb8-43b6b2db840c", + "script": "changes/0014_client_id.sql", + "idempotent": false, + "requires": [ + "9a48f9fc-5950-4348-9ccf-318a263be4eb" + ] + }, + + { + "id": "17b82f41-7e0a-4ae8-b4ea-db383bced329", + "script": "changes/0015_avatar_lot_retire.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c", + "3b7c199c-c369-4f2c-855b-2554e93484bc", + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "c029ed22-e252-40a4-8950-95ea24da1454", + "script": "changes/0016_extra_tasks.sql", + "idempotent": false, + "requires": [ + "9e4dc7d8-06b7-4f2f-84a8-4da737072d55" + ] + }, + { + "id": "780dd09f-325b-4b85-8117-6d089ba88b23", + "script": "changes/0017_inbox_events.sql", + "idempotent": false, + "requires": [ + "9a48f9fc-5950-4348-9ccf-318a263be4eb", + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + }, + { + "id": "b21e29a1-8c25-465e-aa43-c7a0d6f44fb8", + "script": "changes/0018_dyn_payout_tuning.sql", + "idempotent": false, + "requires": [ + "9879997a-4b16-4733-aff4-d0178ce2afa5" + ] + }, + { + "id": "be3164d6-442e-4eb9-8a37-5cb23cca6b43", + "script": "changes/0019_skillmode.sql", + "idempotent": false, + "requires": [ + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "49b2791e-7e2d-4219-94d5-000ba8a53c47", + "script": "changes/0020_email_confirm.sql", + "idempotent": false + }, + { + "id": "b390f324-74f1-4a75-992e-e5a81ec3967a", + "script": "changes/0021_3dthumb.sql", + "idempotent": false, + "requires": [ + "52795d47-a25e-418f-a618-fb89300aab01" + ] + }, + { + "id": "0c3bb214-d47e-4efb-9d0e-d6127ccbd6ee", + "script": "changes/0022_lastlogin.sql", + "idempotent": false + }, + { + "id": "3b87e93a-5fae-437b-8ba5-1e46ebb4cd15", + "script": "changes/0023_neighborhoods.sql", + "idempotent": false + }, + { + "id": "19dbbb59-378d-4374-9ec6-eed6f7ff815a", + "script": "changes/0024_bulletin.sql", + "idempotent": false, + "requires": [ + "3b87e93a-5fae-437b-8ba5-1e46ebb4cd15" + ] + }, + { + "id": "1da5c115-35e3-4117-a2be-b874d0017700", + "script": "changes/0025_updates.sql", + "idempotent": false + }, + { + "id": "64dfb448-1a52-45b7-be2f-056d8ddfd305", + "script": "changes/0026_freevote.sql", + "idempotent": false, + "requires": [ + "3b87e93a-5fae-437b-8ba5-1e46ebb4cd15" + ] + }, + { + "id": "2b6e2b3f-81af-4f23-8a69-2428debcfcc5", + "script": "changes/0027_tuning_presets.sql", + "idempotent": false, + "requires": [ + "b21e29a1-8c25-465e-aa43-c7a0d6f44fb8" + ] + }, + { + "id": "500dbdd2-7d4d-4d68-a3a6-b6abbbe1f1e8", + "script": "changes/0028_upgradelevel.sql", + "idempotent": false, + "requires": [ + "52795d47-a25e-418f-a618-fb89300aab02" + ] + }, + { + "id": "992dfad3-9e31-4db9-8cd7-7d964951e5b5", + "script": "changes/0029_generic_participation.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + }, + { + "id": "6768dc20-7731-4bee-85c6-d2cd9b818a03", + "script": "changes/0030_tokens.sql", + "idempotent": false, + "requires": [ + "52795d47-a25e-418f-a618-fb89300aab02", + "500dbdd2-7d4d-4d68-a3a6-b6abbbe1f1e8" + ] + }, + { + "id": "1235b96c-5a75-2159-b49d-909cb3198cda", + "script": "changes/0031_global_cooldowns.sql", + "idempotent": false, + "requires": [ + "bec36bbc-1774-44cb-a7c5-03f4a00e801c" + ] + } + ] +} diff --git a/server/FSO.Server.Database/FSO.Server.Database.csproj b/server/FSO.Server.Database/FSO.Server.Database.csproj new file mode 100755 index 0000000..bb64af6 --- /dev/null +++ b/server/FSO.Server.Database/FSO.Server.Database.csproj @@ -0,0 +1,363 @@ + + + + + Debug + AnyCPU + {430ACD60-E798-43F0-AD61-8B5A35DF6AB2} + Library + Properties + FSO.Server.Database + FSO.Server.Database + v4.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + False + Libs\MyBatis\Castle.DynamicProxy.dll + + + ..\packages\Dapper.1.42\lib\net45\Dapper.dll + + + False + Libs\MyBatis\IBatisNet.Common.dll + + + False + Libs\MyBatis\IBatisNet.Common.Logging.Log4Net.dll + + + False + Libs\MyBatis\IBatisNet.DataAccess.dll + + + False + Libs\MyBatis\log4net.dll + + + ..\packages\MySql.Data.6.9.7\lib\net45\MySql.Data.dll + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Always + + + + + + {39b61962-fe43-4b64-8e57-8f793737fffe} + FSO.Server.Common + + + {c42962a1-8796-4f47-9dcd-79ed5904d8ca} + FSO.Common + + + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + Always + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Database/Management/DbChangeTool.cs b/server/FSO.Server.Database/Management/DbChangeTool.cs new file mode 100755 index 0000000..6eab649 --- /dev/null +++ b/server/FSO.Server.Database/Management/DbChangeTool.cs @@ -0,0 +1,163 @@ +using FSO.Server.Database.DA; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Dapper; +using System.IO; +using System.Security.Cryptography; +using System.Text.RegularExpressions; +using FSO.Server.Database.DA.DbChanges; +using FSO.Server.Common; +using MySql.Data.MySqlClient; + +namespace FSO.Server.Database.Management +{ + public class DbChangeTool + { + private ISqlContext Context; + + public DbChangeTool(ISqlContext context) + { + this.Context = context; + } + + public List GetChanges() + { + List changes = new List(); + var connection = Context.Connection; + var hasChangesTable = connection.Query("SHOW TABLES LIKE 'fso_db_changes'").FirstOrDefault() != null; + + var scriptsDirectory = Path.Combine(Directory.GetCurrentDirectory(), "DatabaseScripts"); + var manifest = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(scriptsDirectory, "manifest.json"))); + + foreach(var script in manifest.Changes) + { + var scriptData = File.ReadAllText(Path.Combine(scriptsDirectory, script.Script)); + + changes.Add(new DbChangeScript { + ScriptFilename = script.Script, + Idempotent = script.Idempotent, + ScriptID = script.ID, + ScriptData = scriptData, + Status = DbChangeScriptStatus.NOT_INSTALLED, + Hash = hashScriptFile(scriptData) + }); + } + + if (hasChangesTable){ + var changeHistory = connection.Query("SELECT * FROM fso_db_changes"); + foreach(var changeHistoryItem in changeHistory) + { + var match = changes.FirstOrDefault(x => x.ScriptID == changeHistoryItem.id); + if(match == null) + { + continue; + } + + if(match.Hash != changeHistoryItem.hash) + { + match.Status = DbChangeScriptStatus.MODIFIED; + } + else + { + match.Status = DbChangeScriptStatus.INSTALLED; + } + } + } + + return changes; + } + + public void ApplyChange(DbChangeScript change, bool repair) + { + var connection = Context.Connection; + using (var transaction = connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead)) + { + if (!repair) + { + var cmd = transaction.Connection.CreateCommand(); + cmd.CommandText = change.ScriptData; + try + { + cmd.ExecuteNonQuery(); + } + catch (MySqlException e) + { + throw new DbMigrateException(e.ToString()); + } + } + + connection.Execute("INSERT INTO fso_db_changes VALUES (@id, @filename, @date, @hash) ON DUPLICATE KEY UPDATE hash=@hash, date = @date, filename = @filename", new DbChange { + id = change.ScriptID, + date = Epoch.Now, + filename = change.ScriptFilename, + hash = change.Hash + }); + + transaction.Commit(); + } + } + + private string hashScriptFile(string sqlFileData) + { + //People often mess up whitespace in sql files in their IDE. Normalize whitespace before hashing + //to try and avoid changes + sqlFileData = Regex.Replace(sqlFileData, @"\s+", " ").Trim(); + + MD5 md5 = System.Security.Cryptography.MD5.Create(); + byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(sqlFileData); + byte[] hash = md5.ComputeHash(inputBytes); + + // step 2, convert byte array to hex string + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < hash.Length; i++) + { + sb.Append(hash[i].ToString("X2")); + } + return sb.ToString(); + } + } + + public class DbMigrateException : Exception + { + public DbMigrateException(string message) : base(message) + { + } + } + + public class DbChangeScript + { + public DbChangeScriptStatus Status; + public string ScriptID; + public string ScriptFilename; + public string ScriptData; + public string Hash; + public bool Idempotent; + public List Requires; + } + + public enum DbChangeScriptStatus + { + INSTALLED, + MODIFIED, + NOT_INSTALLED, + FORCE_REINSTALL + } + + + + + + public class DbChangeManifest + { + public List Changes; + } + + public class DbChangeManifestScript + { + public string ID; + public string Script; + public bool Idempotent; + } +} diff --git a/server/FSO.Server.Database/Properties/AssemblyInfo.cs b/server/FSO.Server.Database/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..df7a037 --- /dev/null +++ b/server/FSO.Server.Database/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FSO.Server.Database")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FSO.Server.Database")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("430acd60-e798-43f0-ad61-8b5a35df6ab2")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/FSO.Server.Database/app.config b/server/FSO.Server.Database/app.config new file mode 100755 index 0000000..f7e2c59 --- /dev/null +++ b/server/FSO.Server.Database/app.config @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/FSO.Server.Database/dao.xml b/server/FSO.Server.Database/dao.xml new file mode 100755 index 0000000..c04d224 --- /dev/null +++ b/server/FSO.Server.Database/dao.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Database/packages.config b/server/FSO.Server.Database/packages.config new file mode 100755 index 0000000..58803fb --- /dev/null +++ b/server/FSO.Server.Database/packages.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Debug/App.config b/server/FSO.Server.Debug/App.config new file mode 100755 index 0000000..2de6da4 --- /dev/null +++ b/server/FSO.Server.Debug/App.config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/FSO.Server.Debug/FSO.Server.Debug.csproj b/server/FSO.Server.Debug/FSO.Server.Debug.csproj new file mode 100755 index 0000000..265e38e --- /dev/null +++ b/server/FSO.Server.Debug/FSO.Server.Debug.csproj @@ -0,0 +1,189 @@ + + + + + Debug + AnyCPU + {7296CCEC-F459-4071-A9D2-9A07DCC29210} + WinExe + Properties + FSO.Server.Debug + FSO.Server.Debug + v4.5 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + true + + + + False + libs\Be.Windows.Forms.HexBox.dll + + + ..\packages\Common.Logging.3.4.1\lib\net40\Common.Logging.dll + + + ..\packages\Common.Logging.Core.3.4.1\lib\net40\Common.Logging.Core.dll + + + ..\packages\Mina.2.0.11\lib\net40\Mina.NET.dll + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + libs\ScintillaNET.dll + + + + + + + + + + + + + + + + + + + + + Form + + + NetworkDebugger.cs + + + + + UserControl + + + PacketView.cs + + + + + + Form + + + StringDialog.cs + + + NetworkDebugger.cs + + + PacketView.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + StringDialog.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {c051793d-1a9c-4554-9bb8-bafdc01a096a} + FSO.Common.DatabaseService + + + {39b61962-fe43-4b64-8e57-8f793737fffe} + FSO.Server.Common + + + {a08ade32-27e2-44f4-bc52-11a16c56baa8} + FSO.Server.Protocol + + + {c42962a1-8796-4f47-9dcd-79ed5904d8ca} + FSO.Common + + + {c0068df7-f2e8-4399-846d-556bf9a35c00} + FSO.Content + + + {18583453-a970-4ac5-83b1-2d6bfdf94c24} + FSO.Files + + + {9d9558a9-755e-43f9-8bb6-b26f365f5042} + FSO.Vitaboy + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Debug/NetworkDebugger.Designer.cs b/server/FSO.Server.Debug/NetworkDebugger.Designer.cs new file mode 100755 index 0000000..d7e1467 --- /dev/null +++ b/server/FSO.Server.Debug/NetworkDebugger.Designer.cs @@ -0,0 +1,214 @@ +namespace FSO.Server.Debug +{ + partial class NetworkDebugger + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NetworkDebugger)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.menuStash = new System.Windows.Forms.ToolStripMenuItem(); + this.tab = new System.Windows.Forms.TabControl(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.btnInspect = new System.Windows.Forms.ToolStripButton(); + this.btnCreate = new System.Windows.Forms.ToolStripDropDownButton(); + this.btnClear = new System.Windows.Forms.ToolStripButton(); + this.btnStash = new System.Windows.Forms.ToolStripButton(); + this.packetList = new System.Windows.Forms.ListView(); + this.packetIcons = new System.Windows.Forms.ImageList(this.components); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.menuStrip1.SuspendLayout(); + this.toolStrip1.SuspendLayout(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.menuStash}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(778, 24); + this.menuStrip1.TabIndex = 0; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); + this.fileToolStripMenuItem.Text = "File"; + // + // menuStash + // + this.menuStash.Name = "menuStash"; + this.menuStash.Size = new System.Drawing.Size(47, 20); + this.menuStash.Text = "Stash"; + this.menuStash.DropDownOpening += new System.EventHandler(this.menuStash_DropDownOpening); + // + // tab + // + this.tab.Dock = System.Windows.Forms.DockStyle.Fill; + this.tab.Location = new System.Drawing.Point(0, 0); + this.tab.Name = "tab"; + this.tab.SelectedIndex = 0; + this.tab.Size = new System.Drawing.Size(515, 435); + this.tab.TabIndex = 1; + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnInspect, + this.btnCreate, + this.btnClear, + this.btnStash}); + this.toolStrip1.Location = new System.Drawing.Point(0, 24); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(778, 25); + this.toolStrip1.TabIndex = 3; + this.toolStrip1.Text = "toolStrip1"; + // + // btnInspect + // + this.btnInspect.Image = ((System.Drawing.Image)(resources.GetObject("btnInspect.Image"))); + this.btnInspect.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnInspect.Name = "btnInspect"; + this.btnInspect.Size = new System.Drawing.Size(103, 22); + this.btnInspect.Text = "Inspect Packet"; + // + // btnCreate + // + this.btnCreate.Image = global::FSO.Server.Debug.Properties.Resources.blueprint__plus; + this.btnCreate.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnCreate.Name = "btnCreate"; + this.btnCreate.Size = new System.Drawing.Size(108, 22); + this.btnCreate.Text = "Create Packet"; + // + // btnClear + // + this.btnClear.Image = global::FSO.Server.Debug.Properties.Resources.bin; + this.btnClear.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnClear.Name = "btnClear"; + this.btnClear.Size = new System.Drawing.Size(54, 22); + this.btnClear.Text = "Clear"; + this.btnClear.Click += new System.EventHandler(this.btnClear_Click); + // + // btnStash + // + this.btnStash.Enabled = false; + this.btnStash.Image = global::FSO.Server.Debug.Properties.Resources.jar__plus; + this.btnStash.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnStash.Name = "btnStash"; + this.btnStash.Size = new System.Drawing.Size(102, 22); + this.btnStash.Text = "Stash Selected"; + this.btnStash.Click += new System.EventHandler(this.btnStash_Click); + // + // packetList + // + this.packetList.Dock = System.Windows.Forms.DockStyle.Fill; + this.packetList.FullRowSelect = true; + this.packetList.LargeImageList = this.packetIcons; + this.packetList.Location = new System.Drawing.Point(0, 0); + this.packetList.Name = "packetList"; + this.packetList.Size = new System.Drawing.Size(259, 435); + this.packetList.SmallImageList = this.packetIcons; + this.packetList.TabIndex = 0; + this.packetList.UseCompatibleStateImageBehavior = false; + this.packetList.View = System.Windows.Forms.View.List; + this.packetList.DoubleClick += new System.EventHandler(this.packetList_DoubleClick); + this.packetList.ItemSelectionChanged += new System.Windows.Forms.ListViewItemSelectionChangedEventHandler(this.packetList_ItemSelectionChanged); + // + // packetIcons + // + this.packetIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("packetIcons.ImageStream"))); + this.packetIcons.TransparentColor = System.Drawing.Color.Transparent; + this.packetIcons.Images.SetKeyName(0, "navigation-180.png"); + this.packetIcons.Images.SetKeyName(1, "navin.png"); + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(0, 52); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.packetList); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.tab); + this.splitContainer1.Size = new System.Drawing.Size(778, 435); + this.splitContainer1.SplitterDistance = 259; + this.splitContainer1.TabIndex = 4; + // + // NetworkInspector + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(778, 487); + this.Controls.Add(this.toolStrip1); + this.Controls.Add(this.menuStrip1); + this.Controls.Add(this.splitContainer1); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow; + this.MainMenuStrip = this.menuStrip1; + this.Name = "NetworkInspector"; + this.Text = "Network Inspector"; + this.Load += new System.EventHandler(this.NetworkInspector_Load); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.MenuStrip menuStrip1; + private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; + private System.Windows.Forms.TabControl tab; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton btnInspect; + private System.Windows.Forms.ListView packetList; + private System.Windows.Forms.ToolStripMenuItem menuStash; + private System.Windows.Forms.ImageList packetIcons; + private System.Windows.Forms.ToolStripButton btnClear; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.ToolStripButton btnStash; + private System.Windows.Forms.ToolStripDropDownButton btnCreate; + } +} \ No newline at end of file diff --git a/server/FSO.Server.Debug/NetworkDebugger.cs b/server/FSO.Server.Debug/NetworkDebugger.cs new file mode 100755 index 0000000..86b35fb --- /dev/null +++ b/server/FSO.Server.Debug/NetworkDebugger.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; +using System.IO; +using FSO.Server.Common; +using FSO.Server.Protocol.Voltron; +using tso.debug.network; +using FSO.Common.Serialization; +using Ninject; + +namespace FSO.Server.Debug +{ + public partial class NetworkDebugger : Form, IServerDebugger, IPacketLogger + { + private Dictionary Packets = new Dictionary(); + private int PacketSequence = 0; + private NetworkStash _Stash; + private ISerializationContext Context; + + public NetworkDebugger(IKernel kernel) + { + Context = kernel.Get(); + + _Stash = new NetworkStash(Path.Combine(Directory.GetCurrentDirectory(), "debug-network-stash")); + InitializeComponent(); + + var packetTypes = Enum.GetNames(typeof(VoltronPacketType)); + foreach (var packetType in packetTypes) + { + var item = new ToolStripMenuItem(); + item.Text = packetType; + item.Click += new EventHandler(createPacket_Click); + btnCreate.DropDownItems.Add(item); + } + } + + void createPacket_Click(object sender, EventArgs e) + { + var index = btnCreate.DropDownItems.IndexOf((ToolStripItem)sender); + if (index != -1) + { + var enumNames = Enum.GetNames(typeof(VoltronPacketType)); + var packetType = (VoltronPacketType)Enum.Parse(typeof(VoltronPacketType), (string)enumNames.GetValue(index)); + + + OnPacket(new Packet { + Type = PacketType.VOLTRON, + SubType = packetType.GetPacketCode(), + Direction = PacketDirection.OUTPUT, + Data = new byte[0] + }); + } + } + + private void RefreshStashMenu() + { + this.menuStash.DropDownItems.Clear(); + + foreach (var stashItem in _Stash.Items) + { + ToolStripMenuItem item = new ToolStripMenuItem(); + item.Text = stashItem.Name; + item.Click += new EventHandler(stash_item_Click); + this.menuStash.DropDownItems.Add(item); + } + } + + void stash_item_Click(object sender, EventArgs e) + { + var index = menuStash.DropDownItems.IndexOf((ToolStripItem)sender); + if (index != -1) + { + var stash = _Stash.Items[index]; + foreach (var item in stash.Packets) + { + OnPacket(new Packet { + Type = item.Type, + SubType = item.SubType, + Data = item.Data, + Direction = item.Direction + }); + } + } + } + + + + private void NetworkInspector_Load(object sender, EventArgs e) + { + + } + + private delegate void OnPacketDelegate(Packet packet); + + public void OnPacket(Packet packet) + { + try { + this.BeginInvoke(new OnPacketDelegate(_OnPacket), new object[] { packet }); + }catch(Exception ex) + { + } + } + + private void _OnPacket(Packet packet) + { + var dataItem = new RawPacketReference(); + dataItem.Packet = packet; + dataItem.Sequence = PacketSequence; + PacketSequence++; + + var listItem = new ListViewItem(); + if (packet.Direction == PacketDirection.OUTPUT) + { + listItem.ImageIndex = 0; + } + else + { + listItem.ImageIndex = 1; + } + + listItem.Text = dataItem.Sequence + " - " + packet.GetPacketName(); + listItem.Name = Guid.NewGuid().ToString(); + Packets.Add(listItem.Name, dataItem); + + packetList.Items.Add(listItem); + } + + private void btnClear_Click(object sender, EventArgs e) + { + Packets.Clear(); + packetList.Items.Clear(); + } + + private void packetList_DoubleClick(object sender, EventArgs e) + { + foreach (ListViewItem item in packetList.SelectedItems) + { + ViewPacket((RawPacketReference)Packets[item.Name]); + } + } + + private void ViewPacket(RawPacketReference packet) + { + var tabPage = new TabPage(); + tabPage.Text = packet.Sequence + " - " + packet.Packet.GetPacketName(); + PacketView control = new PacketView(packet, tabPage, this, Context); + control.Dock = DockStyle.Fill; + tabPage.Controls.Add(control); + + this.tab.TabPages.Add(tabPage); + this.tab.SelectedTab = tabPage; + } + + public void Stash(params RawPacketReference[] packets) + { + var dialog = new StringDialog("Stash packets", "Your selected packets will be stored with the name below"); + if (dialog.ShowDialog(this) == DialogResult.OK) + { + _Stash.Add(dialog.Result.Value, packets); + } + } + + private void menuStash_DropDownOpening(object sender, EventArgs e) + { + RefreshStashMenu(); + } + + private void btnStash_Click(object sender, EventArgs e) + { + RawPacketReference[] packets = new RawPacketReference[packetList.SelectedItems.Count]; + + for (int i = 0; i < packetList.SelectedItems.Count; i++) + { + var listItem = (ListViewItem)packetList.SelectedItems[i]; + var packet = Packets[listItem.Name]; + + packets[i] = packet; + } + + Stash(packets); + } + + private void packetList_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) + { + btnStash.Enabled = packetList.SelectedItems.Count > 0; + } + + public IPacketLogger GetPacketLogger() + { + return this; + } + + public List SocketServers = new List(); + + public void AddSocketServer(ISocketServer server) + { + SocketServers.Add(server); + } + + public List GetSessions() + { + var result = new List(); + foreach(var server in SocketServers) + { + result.AddRange(server.GetSocketSessions()); + } + return result; + } + } + + +} diff --git a/server/FSO.Server.Debug/NetworkDebugger.resx b/server/FSO.Server.Debug/NetworkDebugger.resx new file mode 100755 index 0000000..99a91d6 --- /dev/null +++ b/server/FSO.Server.Debug/NetworkDebugger.resx @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 132, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFTSURBVDhPYyAVvJ7GkPa4j+HMzRaGNKgQ8QCm+c8jz/+X + 6xjOnColwRBkza+3y/1/d0T7/+E8hjNQafwAl+bdaUS4gCLNQBDGyMi4mmjNf5YzpH1fxHDm01yGM0Cb + z5Cl+f+70P//n/r8/3vf7f+PqzZkaL7r8v/Pdbv/X04agDW/2CxF0M82IKeCNN+dyYCi+eEizv9PlvH+ + B2rGHV0gzR0dHf+bm5vBmq9PZoBrfjCb6f/b1UL/tybgj29boCGbW1pa/iclJYE1n2xlAGt+vZTn/+89 + yv/XRxFOMI5AQw7k5ub+t7AwB2veW8kA17wqlLg4dwcaciEgIOi/o6M3SZqZgJgHiMWAOBGIH4SFpfwH + 0q9r7BiKgbQgEPMBMTcQcwAxGxAzAzEjEIMBCxCLA7EOEBsDcS4QvwbiHCBWB2JFIJYBYpAFAkAMMghk + CNBiBgYAtkz9leWyevkAAAAASUVORK5CYII= + + + + 237, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACc + CQAAAk1TRnQBSQFMAgEBAgEAAVABAAFQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAARADAAEBAQABCAYAAQQYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA + AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 + AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA + AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm + AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM + AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA + ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz + AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ + AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM + AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA + AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA + AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ + AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ + AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA + AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm + ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ + Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz + AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA + AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM + AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM + ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM + Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA + AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM + AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ + AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz + AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm + AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw + AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD/wIADv8CAA7/IgAC/wH0 + AfIBBwG1Aq4BtQEHAfIB9AL/AgAC/wH0AfIBBwEcAm4BHAEHAfIB9AL/JAAB8wHPAq0CzgKtAc8B8wYA + AfMBbwFMBBcBTAFvAfMlAAHzAc8BrQLOAq0CzgGtAc8B8wQAAfMBbwEXAkcCRgJHAUYBbwHzIwAB/wG0 + BK0C8wStAbQB/wIAAf8BdAFMA0YC8wRGAW8B/yIAAfABzwOtAvIBCQWtAfACAAEaAW8ERgEaAvMDRgFM + ARoiAAG1Ac8BrQGnAfAB8QEHBKcCrQG1AgABkwFvBUYBBwLzA0YBkyIAAbQBzwGtA/AB8QLyAvMCrQG0 + AgACbwFGA/AB8QLyAvMCRgFvIgABtAHPAa0B/wHyAvAB8QLyAfMBpwGtAbQCAAJvAUYB/wHyAvAB8QLy + AfMCRgFvIgABtQG0Aq0C/wEJAqcChgGnAa0BtQIAAZMBbwNMAkYBGgLyAkUBTAGTIgAB3QG0Ac8CrQL/ + Ad0DrQLPAd0CAAEaAm8DTAEaAv8CTAJvARoiAAH/AbQB1QPPAv8BrQLPArQB/wIAAf8BdAEWAm8BTAL/ + BG8BdAH/IwAB8wG0AtUBtALPAbQC1QG0AfMEAAHzAW8BFgHjAW8BTAJvAuMBbwHzJQAB8wK0BNUCtAHz + BgAB8wF0AW8EFgFvAXQB8ycAAf8B3QG1ArQBtQHdAf8IAAH/ARoBkwJvAZMBGgH/ZAABQgFNAT4HAAE+ + AwABKAMAAUADAAEQAwABAQEAAQEFAAGAFwAD/wEAAYABAQGAAQEEAAGAAQEBgAEBBAAB4AEHAeABBwQA + AcABAwHAAQMEAAGAAQEBgAEBBAABgAEBAYABAQQAAYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQA + AYABAQGAAQEEAAGAAQEBgAEBBAABgAEBAYABAQQAAcABAwHAAQMEAAHgAQcB4AEHBAAB8AEPAfABDwQA + BP8EAAs= + + + \ No newline at end of file diff --git a/server/FSO.Server.Debug/NetworkStash.cs b/server/FSO.Server.Debug/NetworkStash.cs new file mode 100755 index 0000000..01d21ed --- /dev/null +++ b/server/FSO.Server.Debug/NetworkStash.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using System.IO; +using Newtonsoft.Json.Converters; +using FSO.Server.Common; +using FSO.Common.Utils; +using tso.debug.network; + +namespace FSO.Server.Debug +{ + public class NetworkStash + { + + private static JsonSerializerSettings SETTINGS; + + static NetworkStash() + { + SETTINGS = new JsonSerializerSettings(); + SETTINGS.Formatting = Formatting.Indented; + SETTINGS.Converters.Add(new StringEnumConverter()); + } + + + + private string Dir; + public List Items; + + + public NetworkStash(string dir) + { + this.Dir = dir; + this.Items = new List(); + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + + string[] files = Directory.GetFiles(dir); + foreach (var file in files) + { + if (file.EndsWith(".json")) + { + var parsedItem = JsonConvert.DeserializeObject(File.ReadAllText(file), SETTINGS); + this.Items.Add(parsedItem); + } + } + } + + public void Add(string name, RawPacketReference[] packets) + { + var item = new NetworkStashItem(); + item.Name = name; + item.Packets = new List(); + + foreach (var packet in packets) + { + item.Packets.Add(new NetworkStashItemPacket { + Type = packet.Packet.Type, + SubType = (ushort)packet.Packet.SubType, + Data = packet.Packet.Data, + Direction = packet.Packet.Direction + }); + } + + this.Items.Add(item); + + var jsonData = JsonConvert.SerializeObject(item, SETTINGS); + File.WriteAllText(Path.Combine(Dir, "stash-" + DateTime.Now.Ticks + ".json"), jsonData); + } + } + + public class NetworkStashItem + { + [JsonProperty] + public string Name; + + [JsonProperty] + public List Packets; + } + + public class NetworkStashItemPacket + { + [JsonProperty] + public PacketType Type; + + [JsonProperty] + public uint SubType; + + [JsonProperty] + public PacketDirection Direction; + + [JsonConverter(typeof(Base64JsonConverter))] + public byte[] Data; + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/ByteCountPacketAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/ByteCountPacketAnalyzer.cs new file mode 100755 index 0000000..6688e32 --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/ByteCountPacketAnalyzer.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public class ByteCountPacketAnalyzer : IPacketAnalyzer + { + #region IPacketAnalyzer Members + + public List Analyze(byte[] data) + { + var result = new List(); + + for (var i = 0; i < data.Length; i++) + { + if (i + 4 < data.Length) + { + byte len1 = data[i]; + byte len2 = data[i + 1]; + byte len3 = data[i + 2]; + byte len4 = data[i + 3]; + + long len = len1 << 24 | len2 << 16 | len3 << 8 | len4; + + if (len == data.Length - (i + 4)) + { + result.Add(new PacketAnalyzerResult + { + Offset = i, + Length = 4, + Description = "byte-count(" + len + ")" + }); + } + } + } + + return result; + } + + #endregion + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/ConstantsPacketAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/ConstantsPacketAnalyzer.cs new file mode 100755 index 0000000..ee05e5a --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/ConstantsPacketAnalyzer.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections.Generic; +using FSO.Server.Protocol.Voltron.Model; +using FSO.Server.Protocol.Voltron; +using FSO.Common.DatabaseService.Model; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public class ConstantsPacketAnalyzer : IPacketAnalyzer + { + private static List Constants = new List(); + + static ConstantsPacketAnalyzer() + { + /*var voltronTypes = Enum.GetNames(typeof(VoltronPacketType)); + foreach (var name in voltronTypes) + { + var enumValue = (VoltronPacketType)Enum.Parse(typeof(VoltronPacketType), name); + if (enumValue == VoltronPacketType.Unknown) { continue; } + + Constants.Add(new Constant { + Type = ConstantType.USHORT, + Description = "VoltronPacket." + name, + Value = VoltronPacketTypeUtils.GetPacketCode(enumValue) + }); + }*/ + + var dbRequestTypes = Enum.GetNames(typeof(DBRequestType)); + foreach (var name in dbRequestTypes) + { + var enumValue = (DBRequestType)Enum.Parse(typeof(DBRequestType), name); + if (enumValue == DBRequestType.Unknown) { continue; } + + Constants.Add(new Constant + { + Type = ConstantType.UINT, + Description = "DBRequestType." + name, + Value = DBRequestTypeUtils.GetRequestID(enumValue) + }); + + if (enumValue == DBRequestType.UpdatePreferedLanguageByID) + { + var val = DBRequestTypeUtils.GetRequestID(enumValue); + } + } + + var dbResponseTypes = Enum.GetNames(typeof(DBResponseType)); + foreach (var name in dbResponseTypes) + { + var enumValue = (DBResponseType)Enum.Parse(typeof(DBResponseType), name); + if (enumValue == DBResponseType.Unknown) + { + continue; + } + Constants.Add(new Constant + { + Type = ConstantType.UINT, + Description = "DBResponseType." + name, + Value = DBResponseTypeUtils.GetResponseID(enumValue) + }); + } + + var magicNumberTypes = Enum.GetNames(typeof(MagicNumberEnum)); + foreach (var name in magicNumberTypes) + { + var enumValue = (MagicNumberEnum)Enum.Parse(typeof(MagicNumberEnum), name); + var intVal = MagicNumberEnumUtils.ToInt(enumValue); + var floatVal = MagicNumberEnumUtils.ToFloat(enumValue); + + Constants.Add(new Constant + { + Type = ConstantType.UINT, + Description = "MagicNumberEnum." + name + "( " + intVal + ", " + floatVal + ")", + Value = MagicNumberEnumUtils.ToID(enumValue) + }); + } + + var voltronTypes = Enum.GetNames(typeof(VoltronPacketType)); + foreach (var name in voltronTypes) + { + var enumValue = (VoltronPacketType)Enum.Parse(typeof(VoltronPacketType), name); + if (enumValue == VoltronPacketType.Unknown) + { + continue; + } + + var intVal = VoltronPacketTypeUtils.GetPacketCode(enumValue); + + Constants.Add(new Constant + { + Type = ConstantType.USHORT, + Description = "VoltronPacketType." + name, + Value = intVal + }); + } + + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x09736027, Description = "cTSOTopicUpdateMessage" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x0A2C6585, Description = "cTSODataTransportBuffer" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x496A78BC, Description = "cTSODataDefinitionContainer" }); + + + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x097608AB, Description = "cTSOValueVector < unsigned char>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x097608B3, Description = "cTSOValueVector < signed char>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x097608B6, Description = "cTSOValueVector < unsigned short>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x29739B14, Description = "cTSOTopic" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x2A404946, Description = "cTSOTopicUpdateErrorMessage" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x496A78BC, Description = "cTSODataDefinitionContainer" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x696D1183, Description = "cTSOValue < bool >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x696D1189, Description = "cTSOValue < unsigned long>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x69D3E3DB, Description = "cTSOValue < unsigned __int64 >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x896D1196, Description = "cTSOValue < long >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x896D11A2, Description = "cTSOValueMap >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x896D1688, Description = "cTSOValue >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x89738492, Description = "cTSOValueBVector" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x89738496, Description = "cTSOValueVector" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x8973849A, Description = "cTSOValueVector" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x8973849E, Description = "cTSOValueVector >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x89739A79, Description = "cTSOProperty" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x89D3E3EF, Description = "cTSOValue<__int64>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0x89D3E40E, Description = "cTSOValueMap" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA96E38A0, Description = "cTSOValueMap" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA96E38A8, Description = "cTSOValueMap" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA96E38AC, Description = "cTSOValueMap >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA96E7E5B, Description = "cTSOValue >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA97353EE, Description = "cTSODataService" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA97384A3, Description = "cTSOValueVector >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA975FA6E, Description = "cTSODataServiceClient" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA99AF3A8, Description = "cTSOValueMap >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA99AF3AC, Description = "cTSOValueVector >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA99AF3B7, Description = "cTSOValue >" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA9D3E412, Description = "cTSOValueMap<__int64>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA9D3E428, Description = "cTSOValueVector " }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xA9D3E42D, Description = "cTSOValueVector<__int64>" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xC976087C, Description = "cTSOValue" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xC97757F5, Description = "cTSOValueMap" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE976088A, Description = "cTSOValue" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE9760891, Description = "cTSOValue" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE9760897, Description = "cTSOValue" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE976089F, Description = "cTSOValueMap" }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE97608A2, Description = "cTSOValueMap" }); + + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE97608A5, Description = "cTSOValueMap " }); + Constants.Add(new Constant { Type = ConstantType.UINT, Value = 0xE97608A8, Description = "cTSOValueMap" }); + } + + + #region IPacketAnalyzer Members + public List Analyze(byte[] data) + { + var result = new List(); + + for (var i = 0; i < data.Length; i++) + { + foreach (var constant in GetConstants()) + { + int len = 0; + object value = null; + switch (constant.Type) + { + case ConstantType.UINT: + if (i + 4 >= data.Length) { continue; } + byte len1 = data[i]; + byte len2 = data[i + 1]; + byte len3 = data[i + 2]; + byte len4 = data[i + 3]; + value = (uint)(len1 << 24 | len2 << 16 | len3 << 8 | len4); + len = 4; + break; + case ConstantType.USHORT: + if (i + 2 >= data.Length) { continue; } + byte short1 = data[i]; + byte short2 = data[i + 1]; + value = (ushort)(short1 << 8 | short2); + len = 2; + break; + case ConstantType.ULONG: + if (i + 8 >= data.Length) { continue; } + byte long1 = data[i]; + byte long2 = data[i + 1]; + byte long3 = data[i + 2]; + byte long4 = data[i + 3]; + byte long5 = data[i + 4]; + byte long6 = data[i + 5]; + byte long7 = data[i + 6]; + byte long8 = data[i + 7]; + + value = (ulong)(long1 << 54 | long2 << 48 | long3 << 40 | long4 << 32 | long5 << 24 | long6 << 16 | long7 << 8 | long8); + len = 4; + break; + } + + if (value.ToString() == constant.Value.ToString()) + { + result.Add(new PacketAnalyzerResult { + Offset = i, + Length = len, + Description = constant.Description + }); + } + } + } + return result; + } + #endregion + + public virtual List GetConstants() + { + return Constants; + } + } + + + public class Constant + { + public ConstantType Type; + public object Value; + public string Description; + } + + public enum ConstantType + { + USHORT, + UINT, + ULONG + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/ContentPacketAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/ContentPacketAnalyzer.cs new file mode 100755 index 0000000..a9e0ffd --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/ContentPacketAnalyzer.cs @@ -0,0 +1,58 @@ +using FSO.Content.Framework; +using FSO.Vitaboy; +using System.Collections.Generic; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public class ContentPacketAnalyzer : ConstantsPacketAnalyzer + { + private List Constants = new List(); + + public ContentPacketAnalyzer() + { + var content = Content.Content.Get(); + + /** Avatar Collections **/ + foreach(var collection in content.AvatarCollections.List()) + { + var items = collection.Get(); + var collectionCast = (Far3ProviderEntry)collection; + + foreach(var item in items) + { + Constants.Add(new Constant { + Type = ConstantType.ULONG, + Value = item.PurchasableOutfitId, + Description = collectionCast.FarEntry.Filename + "." + item.Index + }); + + /**Constants.Add(new Constant + { + Type = ConstantType.UINT, + Value = item.FileID, + Description = collectionCast.FarEntry.Filename + "." + item.Index + });**/ + } + } + + + //TSODataDefinition file + var dataDef = content.DataDefinition; + + foreach (var str in dataDef.Strings) + { + Constants.Add(new Constant + { + Type = ConstantType.UINT, + Description = "TSOData_datadefinition(" + str.Value + ")", + Value = str.ID + }); + } + } + + public override List GetConstants() + { + return Constants; + } + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/IPacketAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/IPacketAnalyzer.cs new file mode 100755 index 0000000..d41793c --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/IPacketAnalyzer.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public interface IPacketAnalyzer + { + List Analyze(byte[] data); + } + + public class PacketAnalyzerResult + { + public int Offset; + public int Length; + + public string Description; + + public override string ToString() + { + return Description; + } + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/PascalStringPacketAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/PascalStringPacketAnalyzer.cs new file mode 100755 index 0000000..086aa26 --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/PascalStringPacketAnalyzer.cs @@ -0,0 +1,66 @@ +using System.Collections.Generic; +using System.Text; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public class PascalStringPacketAnalyzer : IPacketAnalyzer + { + #region IPacketAnalyzer Members + + public List Analyze(byte[] data) + { + var result = new List(); + + /** + * We are looking for a uint32 with the msb flipped for length followed by that many chars within a reasonable ascii range + */ + for (var i = 0; i < data.Length; i++) + { + var stringValue = GetString(data, i); + if (stringValue != null) + { + result.Add(new PacketAnalyzerResult { + Offset = i, + Length = stringValue.Length + 4, + Description = "pascal-string(" + stringValue + ")" + }); + } + } + + return result; + } + + private string GetString(byte[] data, int index) + { + if (index + 4 <= data.Length) + { + byte len1 = data[index]; + byte len2 = data[index + 1]; + byte len3 = data[index + 2]; + byte len4 = data[index + 3]; + + //Is msb set? + if ((len1 >> 7) != 1) { return null; } + len1 &= 0x7F; + + long len = len1 << 24 | len2 << 16 | len3 << 8 | len4; + if (len < 0) { return null; } + + if (index + 4 + len <= data.Length) + { + /** Could be! **/ + StringBuilder str = new StringBuilder(); + for (int i = 0; i < len; i++) + { + byte charValue = data[index + 4 + i]; + str.Append((char)charValue); + } + return str.ToString(); + } + } + return null; + } + + #endregion + } +} diff --git a/server/FSO.Server.Debug/PacketAnalyzer/VariableLengthStringAnalyzer.cs b/server/FSO.Server.Debug/PacketAnalyzer/VariableLengthStringAnalyzer.cs new file mode 100755 index 0000000..c4f2a26 --- /dev/null +++ b/server/FSO.Server.Debug/PacketAnalyzer/VariableLengthStringAnalyzer.cs @@ -0,0 +1,97 @@ +using System.Collections.Generic; +using System.Text; + +namespace FSO.Server.Debug.PacketAnalyzer +{ + public class VariableLengthStringAnalyzer : IPacketAnalyzer + { + public List Analyze(byte[] data) + { + var result = new List(); + + /** + * We are looking for a uint32 with the msb flipped for length followed by that many chars within a reasonable ascii range + */ + for (var i = 0; i < data.Length; i++) + { + var stringValue = GetString(data, i); + if (stringValue != null) + { + var offset = 1; + if(stringValue.Length > 128) + { + offset = 2; + } + + result.Add(new PacketAnalyzerResult + { + Offset = i, + Length = stringValue.Length + offset, + Description = "var-string(" + stringValue + ")" + }); + } + } + + return result; + } + + private string GetString(byte[] data, int index) + { + byte lengthByte = 0; + uint length = 0; + int shift = 0; + byte lengthBytes = 0; + + do + { + lengthByte = data[index + lengthBytes]; + length |= (uint)((lengthByte & (uint)0x7F) << shift); + shift += 7; + lengthBytes++; + } while ( + (lengthByte >> 7) == 1 && + index + lengthBytes < data.Length + ); + + if (length > 600 || length == 0) + { + return null; + } + + if((index + lengthBytes + length) <= data.Length) + { + /** Could be! **/ + StringBuilder str = new StringBuilder(); + for (int i = 0; i < length; i++) + { + byte charValue = data[index + lengthBytes + i]; + + + if(charValue == 0x09) + { + //Tab + } + else if(charValue == 0x0A) + { + //Line feed + }else if(charValue == 0x0D) + { + //CR + }else if(charValue >= 0x20 && charValue <= 0x7E) + { + //a-z, special chars, numbers + } + else + { + return null; + } + + str.Append((char)charValue); + } + return str.ToString(); + } + + return null; + } + } +} diff --git a/server/FSO.Server.Debug/PacketView.cs b/server/FSO.Server.Debug/PacketView.cs new file mode 100755 index 0000000..9ebe59f --- /dev/null +++ b/server/FSO.Server.Debug/PacketView.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows.Forms; +using Be.Windows.Forms; +using Mina.Core.Buffer; +using System.IO; +using tso.debug.network; +using FSO.Server.Common; +using FSO.Server.Protocol.Voltron; +using FSO.Server.Debug.PacketAnalyzer; +using FSO.Server.Protocol.Aries; +using FSO.Server.Protocol.Voltron.Packets; +using FSO.Common.Serialization; + +namespace FSO.Server.Debug +{ + public partial class PacketView : UserControl + { + private RawPacketReference Packet; + private TabPage Tab; + private DynamicByteProvider BytesProvider; + private NetworkDebugger Inspector; + + private object ParsedPacket; + private ISerializationContext Context; + + public PacketView(RawPacketReference packet, TabPage tab, NetworkDebugger inspector, ISerializationContext context) + { + this.Tab = tab; + this.Packet = packet; + this.Inspector = inspector; + this.Context = context; + + InitializeComponent(); + + BytesProvider = new DynamicByteProvider(packet.Packet.Data); + + hex.ByteProvider = BytesProvider; + hex.StringViewVisible = true; + + splitContainer1.Panel2Collapsed = true; + + + + } + + private void PacketView_Load(object sender, EventArgs e) + { + } + + private void btnClose_Click(object sender, EventArgs e) + { + ((TabControl)this.Tab.Parent).TabPages.Remove(Tab); + } + + private void btnStash_Click(object sender, EventArgs e) + { + var toStash = new RawPacketReference + { + Packet = new Packet + { + Data = GetBytes(), + Direction = this.Packet.Packet.Direction, + Type = this.Packet.Packet.Type, + SubType = this.Packet.Packet.SubType + }, + Sequence = this.Packet.Sequence + }; + this.Inspector.Stash(toStash); + } + + private void btnTools_Click(object sender, EventArgs e) + { + Analyze(); + splitContainer1.Panel2Collapsed = !splitContainer1.Panel2Collapsed; + } + + + private void ParsePacket() + { + /** Can we parse it? **/ + try + { + var packet = Packet.Packet; + if(packet.Type == PacketType.VOLTRON) + { + var voltronClazz = VoltronPackets.GetByPacketCode((ushort)packet.SubType); + if(voltronClazz != null) + { + IVoltronPacket parsed = (IVoltronPacket)Activator.CreateInstance(voltronClazz); + //TODO: VoltronContext + parsed.Deserialize(IoBuffer.Wrap(GetBytes()), Context); + + this.ParsedPacket = parsed; + this.parsedInspetor.SelectedObject = ParsedPacket; + } + }else if(packet.Type == PacketType.ARIES) + { + var ariesClazz = AriesPackets.GetByPacketCode(packet.SubType); + if(ariesClazz != null) + { + IAriesPacket parsed = (IAriesPacket)Activator.CreateInstance(ariesClazz); + parsed.Deserialize(IoBuffer.Wrap(GetBytes()), Context); + this.ParsedPacket = parsed; + this.parsedInspetor.SelectedObject = ParsedPacket; + } + } + } + catch (Exception ex) + { + } + } + + private void Analyze() + { + analyzeResults.Items.Clear(); + var analyzers = new IPacketAnalyzer[]{ + new PascalStringPacketAnalyzer(), + new ByteCountPacketAnalyzer(), + new ConstantsPacketAnalyzer(), + new VariableLengthStringAnalyzer(), + new ContentPacketAnalyzer() + }; + + var data = GetBytes(); + + foreach (var analyzer in analyzers) + { + var results = analyzer.Analyze(data); + if (results != null) + { + foreach (var result in results) + { + analyzeResults.Items.Add(result); + } + } + } + } + + + private List AllSessions = new List(); + + private void menuSend_DropDownOpening(object sender, EventArgs e) + { + /** Get the list of sessions **/ + menuSend.DropDownItems.Clear(); + AllSessions.Clear(); + + foreach (var session in Inspector.GetSessions()) + { + var label = session.ToString(); + + var menuItem = new ToolStripMenuItem(); + menuItem.Text = label; + menuItem.Click += new EventHandler(sendSession_Click); + + menuSend.DropDownItems.Add(menuItem); + + AllSessions.Add(session); + } + } + + void sendSession_Click(object sender, EventArgs e) + { + var index = menuSend.DropDownItems.IndexOf((ToolStripItem)sender); + if (index != -1) + { + var session = AllSessions[index]; + + switch (Packet.Packet.Type) + { + case PacketType.VOLTRON: + var packet = new VariableVoltronPacket((ushort)Packet.Packet.SubType, GetBytes()); + session.Write(packet); + break; + } + + } + } + + + + private byte[] GetBytes() + { + BytesProvider.ApplyChanges(); + byte[] allBytes = new byte[BytesProvider.Bytes.Count]; + + for (int i = 0; i < allBytes.Length; i++) + { + allBytes[i] = BytesProvider.Bytes[i]; + } + + return allBytes; + } + + private void analyzeResults_SelectedIndexChanged(object sender, EventArgs e) + { + if (analyzeResults.SelectedItem != null) + { + PacketAnalyzerResult item = (PacketAnalyzerResult)analyzeResults.SelectedItem; + hex.Select(item.Offset, item.Length); + } + } + + private void btnParse_Click(object sender, EventArgs e) + { + ParsePacket(); + } + + private void btnImportBytes_Click(object sender, EventArgs e) + { + var result = importBrowser.ShowDialog(this); + if (result == DialogResult.OK) + { + var bytes = File.ReadAllBytes(importBrowser.FileName); + BytesProvider.InsertBytes(BytesProvider.Length, bytes); + } + } + + private void btnExportByteArray_Click(object sender, EventArgs e) + { + var bytes = GetBytes(); + + var str = new StringBuilder(); + str.Append("new byte[]{"); + + for (var i = 0; i < bytes.Length; i++) + { + if (i > 0) + { + str.Append(", "); + } + str.Append("0x" + (bytes[i].ToString("X2"))); + } + + str.Append("}"); + + Clipboard.SetText(str.ToString()); + } + } +} diff --git a/server/FSO.Server.Debug/PacketView.designer.cs b/server/FSO.Server.Debug/PacketView.designer.cs new file mode 100755 index 0000000..63a335c --- /dev/null +++ b/server/FSO.Server.Debug/PacketView.designer.cs @@ -0,0 +1,372 @@ +namespace FSO.Server.Debug +{ + partial class PacketView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PacketView)); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.btnClose = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.btnStash = new System.Windows.Forms.ToolStripButton(); + this.menuSend = new System.Windows.Forms.ToolStripDropDownButton(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.btnParse = new System.Windows.Forms.ToolStripButton(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.toolStrip2 = new System.Windows.Forms.ToolStrip(); + this.btnTools = new System.Windows.Forms.ToolStripButton(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.btnWriteUint32 = new System.Windows.Forms.ToolStripButton(); + this.btnWriteint32 = new System.Windows.Forms.ToolStripButton(); + this.btnWriteUint16 = new System.Windows.Forms.ToolStripButton(); + this.btnWriteint16 = new System.Windows.Forms.ToolStripButton(); + this.btnWritePascalString = new System.Windows.Forms.ToolStripButton(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.hex = new Be.Windows.Forms.HexBox(); + this.analyzeResults = new System.Windows.Forms.ListBox(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.parsedInspetor = new System.Windows.Forms.PropertyGrid(); + this.btnImportBytes = new System.Windows.Forms.ToolStripButton(); + this.importBrowser = new System.Windows.Forms.OpenFileDialog(); + this.toolStripButton1 = new System.Windows.Forms.ToolStripDropDownButton(); + this.btnExportByteArray = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStrip1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.toolStrip2.SuspendLayout(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // toolStrip1 + // + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnClose, + this.toolStripSeparator1, + this.btnStash, + this.menuSend, + this.toolStripSeparator3, + this.btnParse}); + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(628, 25); + this.toolStrip1.TabIndex = 0; + this.toolStrip1.Text = "toolStrip1"; + // + // btnClose + // + this.btnClose.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnClose.Image = global::FSO.Server.Debug.Properties.Resources.cross_button; + this.btnClose.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnClose.Name = "btnClose"; + this.btnClose.Size = new System.Drawing.Size(23, 22); + this.btnClose.Text = "Close"; + this.btnClose.Click += new System.EventHandler(this.btnClose_Click); + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25); + // + // btnStash + // + this.btnStash.Image = global::FSO.Server.Debug.Properties.Resources.jar__plus; + this.btnStash.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnStash.Name = "btnStash"; + this.btnStash.Size = new System.Drawing.Size(55, 22); + this.btnStash.Text = "Stash"; + this.btnStash.Click += new System.EventHandler(this.btnStash_Click); + // + // menuSend + // + this.menuSend.Image = ((System.Drawing.Image)(resources.GetObject("menuSend.Image"))); + this.menuSend.ImageTransparentColor = System.Drawing.Color.Magenta; + this.menuSend.Name = "menuSend"; + this.menuSend.Size = new System.Drawing.Size(62, 22); + this.menuSend.Text = "Send"; + this.menuSend.DropDownOpening += new System.EventHandler(this.menuSend_DropDownOpening); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(6, 25); + // + // btnParse + // + this.btnParse.Image = ((System.Drawing.Image)(resources.GetObject("btnParse.Image"))); + this.btnParse.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnParse.Name = "btnParse"; + this.btnParse.Size = new System.Drawing.Size(93, 22); + this.btnParse.Text = "Parse Packet"; + this.btnParse.Click += new System.EventHandler(this.btnParse_Click); + // + // tabControl1 + // + this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Location = new System.Drawing.Point(3, 28); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(622, 360); + this.tabControl1.TabIndex = 2; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.toolStrip2); + this.tabPage1.Controls.Add(this.splitContainer1); + this.tabPage1.Location = new System.Drawing.Point(4, 22); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(614, 334); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Hex"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // toolStrip2 + // + this.toolStrip2.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnTools, + this.toolStripSeparator2, + this.btnWriteUint32, + this.btnWriteint32, + this.btnWriteUint16, + this.btnWriteint16, + this.btnWritePascalString, + this.btnImportBytes, + this.toolStripButton1}); + this.toolStrip2.Location = new System.Drawing.Point(3, 3); + this.toolStrip2.Name = "toolStrip2"; + this.toolStrip2.Size = new System.Drawing.Size(608, 25); + this.toolStrip2.TabIndex = 5; + this.toolStrip2.Text = "toolStrip2"; + // + // btnTools + // + this.btnTools.Image = ((System.Drawing.Image)(resources.GetObject("btnTools.Image"))); + this.btnTools.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnTools.Name = "btnTools"; + this.btnTools.Size = new System.Drawing.Size(68, 22); + this.btnTools.Text = "Analyse"; + this.btnTools.Click += new System.EventHandler(this.btnTools_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(6, 25); + // + // btnWriteUint32 + // + this.btnWriteUint32.Image = ((System.Drawing.Image)(resources.GetObject("btnWriteUint32.Image"))); + this.btnWriteUint32.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnWriteUint32.Name = "btnWriteUint32"; + this.btnWriteUint32.Size = new System.Drawing.Size(61, 22); + this.btnWriteUint32.Text = "UInt32"; + // + // btnWriteint32 + // + this.btnWriteint32.Image = ((System.Drawing.Image)(resources.GetObject("btnWriteint32.Image"))); + this.btnWriteint32.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnWriteint32.Name = "btnWriteint32"; + this.btnWriteint32.Size = new System.Drawing.Size(53, 22); + this.btnWriteint32.Text = "Int32"; + // + // btnWriteUint16 + // + this.btnWriteUint16.Image = ((System.Drawing.Image)(resources.GetObject("btnWriteUint16.Image"))); + this.btnWriteUint16.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnWriteUint16.Name = "btnWriteUint16"; + this.btnWriteUint16.Size = new System.Drawing.Size(61, 22); + this.btnWriteUint16.Text = "UInt16"; + // + // btnWriteint16 + // + this.btnWriteint16.Image = ((System.Drawing.Image)(resources.GetObject("btnWriteint16.Image"))); + this.btnWriteint16.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnWriteint16.Name = "btnWriteint16"; + this.btnWriteint16.Size = new System.Drawing.Size(53, 22); + this.btnWriteint16.Text = "Int16"; + // + // btnWritePascalString + // + this.btnWritePascalString.Image = ((System.Drawing.Image)(resources.GetObject("btnWritePascalString.Image"))); + this.btnWritePascalString.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnWritePascalString.Name = "btnWritePascalString"; + this.btnWritePascalString.Size = new System.Drawing.Size(94, 22); + this.btnWritePascalString.Text = "Pascal String"; + // + // splitContainer1 + // + this.splitContainer1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.splitContainer1.Location = new System.Drawing.Point(0, 31); + this.splitContainer1.Name = "splitContainer1"; + this.splitContainer1.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.hex); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.BackColor = System.Drawing.Color.Gainsboro; + this.splitContainer1.Panel2.Controls.Add(this.analyzeResults); + this.splitContainer1.Size = new System.Drawing.Size(614, 307); + this.splitContainer1.SplitterDistance = 150; + this.splitContainer1.TabIndex = 4; + // + // hex + // + this.hex.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.hex.Dock = System.Windows.Forms.DockStyle.Fill; + this.hex.Font = new System.Drawing.Font("Courier New", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.hex.InfoForeColor = System.Drawing.Color.Empty; + this.hex.LineInfoVisible = true; + this.hex.Location = new System.Drawing.Point(0, 0); + this.hex.Name = "hex"; + this.hex.ShadowSelectionColor = System.Drawing.Color.FromArgb(((int)(((byte)(100)))), ((int)(((byte)(60)))), ((int)(((byte)(188)))), ((int)(((byte)(255))))); + this.hex.Size = new System.Drawing.Size(614, 150); + this.hex.StringViewVisible = true; + this.hex.TabIndex = 2; + this.hex.VScrollBarVisible = true; + // + // analyzeResults + // + this.analyzeResults.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.analyzeResults.FormattingEnabled = true; + this.analyzeResults.Location = new System.Drawing.Point(304, 16); + this.analyzeResults.Name = "analyzeResults"; + this.analyzeResults.Size = new System.Drawing.Size(304, 121); + this.analyzeResults.TabIndex = 0; + this.analyzeResults.SelectedIndexChanged += new System.EventHandler(this.analyzeResults_SelectedIndexChanged); + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.parsedInspetor); + this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Size = new System.Drawing.Size(614, 334); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Parsed Packet"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // parsedInspetor + // + this.parsedInspetor.Location = new System.Drawing.Point(3, 3); + this.parsedInspetor.Name = "parsedInspetor"; + this.parsedInspetor.Size = new System.Drawing.Size(608, 328); + this.parsedInspetor.TabIndex = 0; + // + // btnImportBytes + // + this.btnImportBytes.Image = ((System.Drawing.Image)(resources.GetObject("btnImportBytes.Image"))); + this.btnImportBytes.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnImportBytes.Name = "btnImportBytes"; + this.btnImportBytes.Size = new System.Drawing.Size(84, 22); + this.btnImportBytes.Text = "Import File"; + this.btnImportBytes.Click += new System.EventHandler(this.btnImportBytes_Click); + // + // toolStripButton1 + // + this.toolStripButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.btnExportByteArray}); + this.toolStripButton1.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image"))); + this.toolStripButton1.ImageTransparentColor = System.Drawing.Color.Magenta; + this.toolStripButton1.Name = "toolStripButton1"; + this.toolStripButton1.Size = new System.Drawing.Size(69, 22); + this.toolStripButton1.Text = "Export"; + // + // btnExportByteArray + // + this.btnExportByteArray.Name = "btnExportByteArray"; + this.btnExportByteArray.Size = new System.Drawing.Size(207, 22); + this.btnExportByteArray.Text = "To clipboard as C# byte[]"; + this.btnExportByteArray.Click += new System.EventHandler(this.btnExportByteArray_Click); + // + // PacketView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.toolStrip1); + this.Name = "PacketView"; + this.Size = new System.Drawing.Size(628, 391); + this.Load += new System.EventHandler(this.PacketView_Load); + this.toolStrip1.ResumeLayout(false); + this.toolStrip1.PerformLayout(); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage1.PerformLayout(); + this.toolStrip2.ResumeLayout(false); + this.toolStrip2.PerformLayout(); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + this.splitContainer1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton btnClose; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private Be.Windows.Forms.HexBox hex; + private System.Windows.Forms.ToolStripButton btnStash; + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.ToolStrip toolStrip2; + private System.Windows.Forms.ToolStripButton btnTools; + private System.Windows.Forms.ToolStripDropDownButton menuSend; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; + private System.Windows.Forms.ToolStripButton btnWriteint32; + private System.Windows.Forms.ToolStripButton btnWriteUint32; + private System.Windows.Forms.ToolStripButton btnWriteUint16; + private System.Windows.Forms.ToolStripButton btnWriteint16; + private System.Windows.Forms.ToolStripButton btnWritePascalString; + private System.Windows.Forms.ListBox analyzeResults; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.PropertyGrid parsedInspetor; + private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; + private System.Windows.Forms.ToolStripButton btnParse; + private System.Windows.Forms.ToolStripButton btnImportBytes; + private System.Windows.Forms.OpenFileDialog importBrowser; + private System.Windows.Forms.ToolStripDropDownButton toolStripButton1; + private System.Windows.Forms.ToolStripMenuItem btnExportByteArray; + } +} diff --git a/server/FSO.Server.Debug/PacketView.resx b/server/FSO.Server.Debug/PacketView.resx new file mode 100755 index 0000000..33826c9 --- /dev/null +++ b/server/FSO.Server.Debug/PacketView.resx @@ -0,0 +1,277 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAKGSURBVDhPhZBtSFNhFMeftTAqDT8kkkJ9CMrELBUzM3tR + MBpRrBVBKJIJVhCRWWliKpo1rYzMpcyX1HJWohSmlJGO0MrNzFpjIfNlU1llZo4MauPfc64XHJb1hx/3 + cM7v3Oe5l/2RTIO79JJ1n1Q5opLkjzwiqKYezURrjqS98JaeN6iD1f2Gc1rbhNow4WgZnXJUDU5NyO4O + G2hGjmjPyrE2d+kJbUV844A1u9WCZ2M/cVFrQ3nPGPQ/gC7OydZRKznkilszmRenORCUpzWdabGgsOsL + 6vq+I715EE8/A6qXNjz8CGiGfmFl6hMTueLaTCRyVeXOou7J7cVvsLfGhP23TYit+4BTTRYoinUoeAsc + brAiIrd9klxxzSXRF7SyEpMjUtWH4GuvEX7zHcL5y2SVA0h87ET0DRMCcjsQmK11kCtuuWRb1vOQnA5n + gLIXa5R6rL3ag0COf24nNuQbEFpgRGSpDWHKbie54pZLonKqAtPa7YGXexF6/T02FRuxWWVERJEBUSX9 + iCjohaIJ2FExZCdX3HJJzJWD3gkac4x6ELJyC+TVVv4fhgX2lPUj9t4oTusAv5RmM7nilkt2l3kwRfmd + oCydLbF+HEcavuL4g2mS7o8ho20ciltGm4Q7gvvX+MmXsbj6Wr/0TnN8zYg9teWbk4ivttrXZXeYJXwm + OHNkPseXefhuZFuSk9mhRg2LOqsToJp6Hj7h3FnBcaOF2ZnHWcKhE3zY6oU+/JknMF0TNPPk0GH/Sa1X + Kcvw1AtQ/Y8s5YRxkjglnDaOnu1aoJd/SgBBtdBj7BWnjpPC2crx4gjfQ1enK67irOeEsKOLClnmYr0A + 1dSbxp+znMM/hbn9Bi6RVNbCkBvIAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEfSURBVDhP1ZK9SgNBFIVnwSaNgjGitrYhghISBDWii13a + kDTp1NfwiRI1/iFEbVTEVJpWLETxKdbveu/gJplgZeGBj3vmsHPPFOv+SutRFLWgLV4jt8G5A6f4ikZh + TctlZh6K+GPLTpgFKOMvmGMlHx+mfMfmmUYui780H5R8fJTy8mS55FvFd83/iFBa6+Bb5bkl/DnTty7B + Kv6aOShCaW3oyVXkIkjrpkZui/MV3OC3Nfpvinn+LdzjdzQKaDFuJSu1p+EfZYaLd8xlWMP3vtO0mgcf + SbnRTVjwWqw9JxZ7yYIH8znoqw1ozAtyLHg0Pwsvan+Rte6Cby1BDO8QVAQTkIFJa90HURXe4BP2YApG + NLAAsjAHC0PMAwuc+wKYtDjrv8PKOgAAAABJRU5ErkJggg== + + + + 227, 17 + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHBSURBVDhPxdNPS9twHMfxX4jsIXjwWew5ePM2URlFaWXi + 0KEtaCpSpRFMW9s4DfaPzGS2moJVwUroOsusrNgJWXWMFvQkO+lWHIMi4sr46DcHYYMNdQd/8D4kfF7h + dwl7+JPvbni+4+CD94kse+fg5V9HSfwsx+8UGbIsZ+dfXn5+DXFqGG6/+1bRlgxZ9qaLVy4OFjA0OQR9 + U0e9XkepXIKsytDWNIQWQpCi0m/RlgxZZnTykXMzBqfoRHw9jsxOBqffTqGndRx/OUZ4KYzKYQW+qA+i + IlrRlgxZtmHj52sf5tDv6YexbaD6vWp9yPxkIp1Lo7BXgHlgIrochUf2WNGWDFm2/pRXfxRm0CP0YOv9 + FtSUCvmVjEAsgNHgKCaUCYwERiD4hJtoS4YsW+ng42f5EOwuO8bkMQiSgP3yPlJGCsWPReR380isJZDd + zkLRFMyqs9aWDFmmt3J6NeeH7YXNupp32gun1wmX6MLA+ID17s9oS4YsW3zCpb5mJ9Hd14b23va/tmqs + olarQUtq1pYMWTbXwmWqbyWcGOI/qyQGb6JnMmTZs8dcRGrmdu8TWfodHl3XeF3THSND9n8OY1cLIuRK + tChIkwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI6SURBVDhPrY9RSFNhFMe/jRkK18l228xF2e5wCmZBRhFW + w1aTio0chhWGUNDTHnsNeiuhh156qcwecq5J8yGNyvQWW2bEEnNrFSO23T0Mttdd9nI5nXP9nCThU3/4 + weGc/+/uG/v/CYsO9twWYlFbmEXFxDo4045u2yYi+htftMkH46eUwI8r1Yu/b2hDCM0H4v1KA96ow9tb + Min6hRln8mx6VA3+ug6B76Pg+XRBh+bBn9fAl7qqCrF9Sepyi+ex6GiYbJN9qRF1YOUS+L4Ow7EP52Aj + NNOObme+DavUJYfbmCfWUNfbPsX7ZQhOfAzo9M6f5jro88a+/3MQOt4cUsjhNuZhy5RnabB6ZHEAeuZO + 6rhjR6FcLkOhUICd4x1gfeTSsU90gmv6cJUcbmMetCQ8SwGt++VxqNVqkM/nIZ1OQyaTgWw2C7lcDorF + IpRKJbA8lWB3dL9GDrcx9/ED8fOaNNMLqVQK1tbW/ilXKhWwhCVojXVp5HAbc695yr3QV7XOusASkdZ5 + JtVlmuv7WQmEqLNKDrcxd80hMdKu2N67wbKIJWJO2nw2zvU9YpqwK+RwGzPW5DCMNcvW+U7VuoyvWMbi + O2nz2TjrO8T8ul2lLjnc5rnV5DfeEZJm2alaV/Ejqyi84tCMmBf2qtShLre2JLjDb7jZKJvGRUWQ91Qt + K06NoJl2dKMOb/8VE9KKdDMH8zKv4Ta7bJhmI8aEDs20oxtjPcgu7tRjRATEjtB/2w76Ieqiw9gfhDpi + 1Mewf+0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI8SURBVDhPrY9PaJJxGMd/So4NnEPf6ZpRy1f2J9bqYBSx + SpbVRqFsEllgDOrSwWPXoFsNOnTpUq11aM6suUNbMNpmgpIRFqbOFh7U14Og1/fFizw9z7vfHI3YqS98 + 4OF5vp/Xn+z/JyhY2VtzgIXNQRYW4tvgTDu67ZuQ4G5f7I2eTFyUPFt+2Ve817yBeH755RPxMUmHN+rw + 9p7MC279ki11LT+teH/fBc/mNDi/TKrQPLV1ByY2byv6yNEUdbnF81Kw6uZ7oxNZvzL+4yZc+e6Ds7Gr + sBOaaUe3yz99CnXJ4TbmlSlwbG1Ucn27DucTHhXHp0tcB3Xe2Y999UL/qkMih9uY510LzuSUfHpjHEZW + LqgMRM5ArVaDcrkM3bP9YHphV7HMDYJ98ZRMDrcxz7rizuRkc/jDOWg0GlAqlSCXy0E+n4dCoQDFYhEq + lQpUq1UwvhbhUPh4kxxuY57iBxLuprjkgGw2C5lM5p9yvV4HY1CEnshQkxxuY550Lgytj8qmZTsYQ+I2 + b8SWTHNrvyyC4b1NJofbmMeGgBDqk8yfB8C4gSViRdx9Ns6tPdI2Z5HI4TZmpsOqmemMdq8PKqYkviKJ + xTVx99k4qzvEsNqnUJccbvM86HBrH+lThphNMaXxI2kUPnJoRgzRIwp1qMutPfG2uTX326O6WUHSxw7L + xrStSdBMO7pRh7f/ygGkBxlmVuZiLs1Ddkvzjvm1cRWaaUc3xkaQg9xpRYvoEQtC/20/6Ieoiw5jfwAq + DGMd1erLWwAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI6SURBVDhPrY9BaJJhGMdfZcYG6tAvXTNq+cnmYK2gRRGr + ZFkJI61JtaLFoA5dPHYNutWgQ5cu1VqH5syVO7RFsaVGhouwWuqsEFI/D4Jevw8v8vQ83945GrFTf/jB + w/P8f5+v7P8nKNjYc0uAhS1BFhYSa+BMO7ptmZDgbX3ZGdufOCH5flyRL/6+0biA0Lzvw5Ckwxt1eHtT + pgWvfs6eGl4dV/y/roNvdRxcyXMqNI/8vAae7FVFH9mToi63eB4LNt10Z8yTGVM8Xy/B6S+jcOT9MKyH + ZtrR7dT3UYW65HAb88Qc6F0clNyfz8Oxjz6VgcWTXAd1Xt8PffJD99sDEjncxjxsn3ElR+RDUQ/0LxxX + 6Ykchmq1CqVSCbZPdoP5kUPFOuUEx4uDMjncxjxoT7iSZxt9r45CvV6HYrEI2WwWcrkc5PN5KBQKUC6X + oVKpgOmpCDvDexvkcBtzHz+QONMQ5wYgk8lAOp3+p1yr1cAUFKEj0tsgh9uYe4YZ57tB2TzvAFNIXOOZ + 2JRpbu7nRTDM2mVyuI25awwIoS7JEu8BUxRLxIK48Wycm3tEN2WVyOE2ZqLNppkwxIQlp2JexlcsY3FJ + 3Hg2zuoOMb7pUqhLDrd5brV5tXf0KWPcrphX8CMrKLzm0IwYo7sV6lCXW5vi3+bV3GyNtUwKkj6+SzZ9 + szcImmlHN+rw9l9pQTqQPmZjbubW3GaXNbNsTJtQoZl2dGOsH9nBnWa0iB6xIvTftoJ+iLroMPYHz9di + 9dziY6IAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI6SURBVDhPrY9RSFNhFMe/jRkK18l228xF2e5wCmZBRhFW + w1aTio0chhWGUNDTHnsNeiuhh156qcwecq5J8yGNyvQWW2bEEnNrFSO23T0Mttdd9nI5nXP9nCThU3/4 + weGc/+/uG/v/CYsO9twWYlFbmEXFxDo4045u2yYi+htftMkH46eUwI8r1Yu/b2hDCM0H4v1KA96ow9tb + Min6hRln8mx6VA3+ug6B76Pg+XRBh+bBn9fAl7qqCrF9Sepyi+ex6GiYbJN9qRF1YOUS+L4Ow7EP52Aj + NNOObme+DavUJYfbmCfWUNfbPsX7ZQhOfAzo9M6f5jro88a+/3MQOt4cUsjhNuZhy5RnabB6ZHEAeuZO + 6rhjR6FcLkOhUICd4x1gfeTSsU90gmv6cJUcbmMetCQ8SwGt++VxqNVqkM/nIZ1OQyaTgWw2C7lcDorF + IpRKJbA8lWB3dL9GDrcx9/ED8fOaNNMLqVQK1tbW/ilXKhWwhCVojXVp5HAbc695yr3QV7XOusASkdZ5 + JtVlmuv7WQmEqLNKDrcxd80hMdKu2N67wbKIJWJO2nw2zvU9YpqwK+RwGzPW5DCMNcvW+U7VuoyvWMbi + O2nz2TjrO8T8ul2lLjnc5rnV5DfeEZJm2alaV/Ejqyi84tCMmBf2qtShLre2JLjDb7jZKJvGRUWQ91Qt + K06NoJl2dKMOb/8VE9KKdDMH8zKv4Ta7bJhmI8aEDs20oxtjPcgu7tRjRATEjtB/2w76Ieqiw9gfhDpi + 1Mewf+0AAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAI6SURBVDhPrY9RaFJhFMc/xcUGdw696ZpRyytzg7WCFkWs + kmW5GCjNBmuwGBS9+dhr0FsNeuill2qth+ackXtoi1pLqyktwsVSs8JAvT4I+urFl8vpnLtvjkbsqT/8 + 4HDO/3f9ZP8/QdHG5i0BFrYEWViMb4Iz7ei2a0Kit/lFR+zo6jnZ92O8Nvr7hnoZofnI6qDchDfq8PaO + zIpeYcGevJieVPy/roPv+yS4Pl3SoHnk5zXwpK8qQuRQkrrc4nks2ppmO2Ke9IQy9PUKeNbH4NSHYdgK + zbSj24VvYwp1yeE25ok50LM8ILu/jMKZhE+j/+15roM2b+0HP/uh680xmRxuYx62zbkSI7UT0SHoWzqr + 4YychEqlAsViEfZOd4H5kUPDOtMNjvDxGjncxjxoi7sSXrX35Wmo1+tQKBQgk8lANpuFXC4H+XweSqUS + lMtlMD2VYH/4sEoOtzH38QMfh1VpoR/S6TSkUql/ytVqFUxBCdojPSo53Mbca51zvhuomRcdYApJmzyT + GjLNjf2iBMK8vUYOtzF3jQEx1Clb3jvBFMUSsSRtPxvnxh4xzFhlcriNmWqx6aZaY6blbsW8hq9Yw+KK + tP1snLUdYnzdqVCXHG7z3Grx6u8ISWPUrpg38CMbKLzi0IwYVw4q1KEut3bEv8eru9kcM0yLshA7UDOt + 21WCZtrRjTq8/VcMSDvSy2zMzdy622xc95xN6OMaNNOOboz1Ifu404geERArQv9tN+iHqIsOY38ATfti + vc3anMAAAAAASUVORK5CYII= + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAF2SURBVDhPYxgawH7uixggPgOioULEA5sZj2NsZj45M/n+ + //8gGsSHSqECs0l3Z5pPuosiCeKbT753pv/2v/+NZ3//77v19z+Ij64ODIx6rp8BYcOuq2BJEA3id1// + 87/iyHc47rjy+z9IHKwJGWi3nD/TefX3fxCt03yuH0S3Xvz5v2DPZzhuOvcTIt96HtMFqlVHz5Qf/gJU + 9OM/iN1w5sf/zK0f4Lj6+DewuFrNcexhIF+850zx/k//0za9+19z4tv/hLWv/ocufvDfe9b1/0kbHv4H + ySuW7MeuGQTEs7aeKdz76X/8+tf/3RY++G8x48Z/s+nX/weve/wfJCeRsw23ZhAQTFxzJmLru//aC5/8 + V5v/CIydN778DxIXTFjdD1WGG/BELT2jteHTf7Hl71GwzqZP/0Fy3BGL8buAPWjuGbkdv/+LbP71XxiI + hYBYYNOv//xALLbl13+QPGvwXNyGMPvNnMnkO+MMPgxSA1U+aAADAwA7TQnn8HZE9QAAAABJRU5ErkJg + gg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFoSURBVDhPYxh8wH7ey5n2c1+cwYuBaqDKMYHN7GcxNjOf + nJl8////7uv//nddQ8V9t/79B8lDlWMH5pPuxphPvnem58bv/8X7v6Lg2pPf/4PkoEpxA8Oe6/1GPdfP + NJ//8T998zs4Ltr36T9IHKoMO9BpOhuj3XL+TOXRD/99Z1797zHlwn/XiWfBOGLJrf8gOahSTKBSeSRG + teromdydT/+7TDgDx6kbH4DpoHlX/4PkocpRgVzhnhj54j1nknc8/2819QocR214/B8kHrbm4X/3BbfA + bKgWBBDL3BIjnrX1TPCut//V5z+CY8/Nr/+DxMUzt/aDaLu1L8B8qDYEEExcc8Zx37f/Iis/wrHpjq// + QeLCiatjQGpANIgPwmBNyIA3elkMT9TSM5r7/v5n2fjnv/Kev/9BfJA4VAkYgPhAjD0hcQTPjWEPmntG + avf//yAaxIdKEQ+YfGfEAPEZEA0VGtSAgQEAqhMIKUAk180AAAAASUVORK5CYII= + + + + 332, 17 + + \ No newline at end of file diff --git a/server/FSO.Server.Debug/Program.cs b/server/FSO.Server.Debug/Program.cs new file mode 100755 index 0000000..6b6cfe9 --- /dev/null +++ b/server/FSO.Server.Debug/Program.cs @@ -0,0 +1,19 @@ +using System; +using System.Windows.Forms; + +namespace FSO.Server.Debug +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + //Application.Run(new NetworkDebugger()); + } + } +} diff --git a/server/FSO.Server.Debug/Properties/AssemblyInfo.cs b/server/FSO.Server.Debug/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..911c9fb --- /dev/null +++ b/server/FSO.Server.Debug/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FSO.Server.Debug")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FSO.Server.Debug")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("7296ccec-f459-4071-a9d2-9a07dcc29210")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/FSO.Server.Debug/Properties/Resources.Designer.cs b/server/FSO.Server.Debug/Properties/Resources.Designer.cs new file mode 100755 index 0000000..701fb04 --- /dev/null +++ b/server/FSO.Server.Debug/Properties/Resources.Designer.cs @@ -0,0 +1,163 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FSO.Server.Debug.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("FSO.Server.Debug.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap bin { + get { + object obj = ResourceManager.GetObject("bin", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap blueprint__plus { + get { + object obj = ResourceManager.GetObject("blueprint--plus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap box_add { + get { + object obj = ResourceManager.GetObject("box-add", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap cross_button { + get { + object obj = ResourceManager.GetObject("cross-button", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap filter { + get { + object obj = ResourceManager.GetObject("filter", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap icondsel { + get { + object obj = ResourceManager.GetObject("icondsel", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap iconsel { + get { + object obj = ResourceManager.GetObject("iconsel", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap jar__plus { + get { + object obj = ResourceManager.GetObject("jar--plus", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap search { + get { + object obj = ResourceManager.GetObject("search", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap users { + get { + object obj = ResourceManager.GetObject("users", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/server/FSO.Server.Debug/Properties/Resources.resx b/server/FSO.Server.Debug/Properties/Resources.resx new file mode 100755 index 0000000..68eb60e --- /dev/null +++ b/server/FSO.Server.Debug/Properties/Resources.resx @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\iconsel.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\cross-button.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\users.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\Icondsel.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\filter.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\blueprint--plus.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\search.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\box-add.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\bin.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\jar--plus.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + diff --git a/server/FSO.Server.Debug/Properties/Settings.Designer.cs b/server/FSO.Server.Debug/Properties/Settings.Designer.cs new file mode 100755 index 0000000..a2c393b --- /dev/null +++ b/server/FSO.Server.Debug/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace FSO.Server.Debug.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/server/FSO.Server.Debug/Properties/Settings.settings b/server/FSO.Server.Debug/Properties/Settings.settings new file mode 100755 index 0000000..3964565 --- /dev/null +++ b/server/FSO.Server.Debug/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/FSO.Server.Debug/RawPacketReference.cs b/server/FSO.Server.Debug/RawPacketReference.cs new file mode 100755 index 0000000..214c168 --- /dev/null +++ b/server/FSO.Server.Debug/RawPacketReference.cs @@ -0,0 +1,28 @@ +using FSO.Server.Common; +using FSO.Server.Protocol.Voltron; +using FSO.Server.Protocol.Aries; + +namespace tso.debug.network +{ + public class RawPacketReference + { + public Packet Packet; + public int Sequence; + } + + + public static class PacketExtensions + { + public static string GetPacketName(this Packet packet) + { + switch (packet.Type) + { + case PacketType.VOLTRON: + return VoltronPacketTypeUtils.FromPacketCode((ushort)packet.SubType).ToString(); + case PacketType.ARIES: + return AriesPacketTypeUtils.FromPacketCode(packet.SubType).ToString(); + } + return packet.Type.ToString() + " (" + packet.SubType + ")"; + } + } +} diff --git a/server/FSO.Server.Debug/Resources/Icondsel.png b/server/FSO.Server.Debug/Resources/Icondsel.png new file mode 100755 index 0000000..3997fd6 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/Icondsel.png differ diff --git a/server/FSO.Server.Debug/Resources/actionSel.bmp b/server/FSO.Server.Debug/Resources/actionSel.bmp new file mode 100755 index 0000000..55516c7 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/actionSel.bmp differ diff --git a/server/FSO.Server.Debug/Resources/bin.png b/server/FSO.Server.Debug/Resources/bin.png new file mode 100755 index 0000000..01d304a Binary files /dev/null and b/server/FSO.Server.Debug/Resources/bin.png differ diff --git a/server/FSO.Server.Debug/Resources/blueprint--plus.png b/server/FSO.Server.Debug/Resources/blueprint--plus.png new file mode 100755 index 0000000..ff8f207 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/blueprint--plus.png differ diff --git a/server/FSO.Server.Debug/Resources/box-add.png b/server/FSO.Server.Debug/Resources/box-add.png new file mode 100755 index 0000000..72b103a Binary files /dev/null and b/server/FSO.Server.Debug/Resources/box-add.png differ diff --git a/server/FSO.Server.Debug/Resources/cross-button.png b/server/FSO.Server.Debug/Resources/cross-button.png new file mode 100755 index 0000000..933272b Binary files /dev/null and b/server/FSO.Server.Debug/Resources/cross-button.png differ diff --git a/server/FSO.Server.Debug/Resources/filter.png b/server/FSO.Server.Debug/Resources/filter.png new file mode 100755 index 0000000..f052f79 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/filter.png differ diff --git a/server/FSO.Server.Debug/Resources/iconsel.png b/server/FSO.Server.Debug/Resources/iconsel.png new file mode 100755 index 0000000..cd9f6dc Binary files /dev/null and b/server/FSO.Server.Debug/Resources/iconsel.png differ diff --git a/server/FSO.Server.Debug/Resources/jar--plus.png b/server/FSO.Server.Debug/Resources/jar--plus.png new file mode 100755 index 0000000..c9d3c39 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/jar--plus.png differ diff --git a/server/FSO.Server.Debug/Resources/search.png b/server/FSO.Server.Debug/Resources/search.png new file mode 100755 index 0000000..cc26666 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/search.png differ diff --git a/server/FSO.Server.Debug/Resources/users.png b/server/FSO.Server.Debug/Resources/users.png new file mode 100755 index 0000000..36d60e9 Binary files /dev/null and b/server/FSO.Server.Debug/Resources/users.png differ diff --git a/server/FSO.Server.Debug/StringDialog.cs b/server/FSO.Server.Debug/StringDialog.cs new file mode 100755 index 0000000..85ea37e --- /dev/null +++ b/server/FSO.Server.Debug/StringDialog.cs @@ -0,0 +1,52 @@ +using System; +using System.Windows.Forms; + +namespace tso.debug.network +{ + public partial class StringDialog : Form + { + public StringDialogResult Result; + + public StringDialog(string title, string description) + { + this.Text = title; + InitializeComponent(); + this.description.Text = description; + } + + private void StringModal_Load(object sender, EventArgs e) + { + } + + private void txtValue_Enter(object sender, EventArgs e) + { + btnOk.PerformClick(); + } + + private void txtValue_TextChanged(object sender, EventArgs e) + { + this.btnOk.Enabled = txtValue.Text.Length > 0; + } + + private void StringDialog_Deactivate(object sender, EventArgs e) + { + + } + + private void btnOk_Click(object sender, EventArgs e) + { + SetResult(); + } + + private void SetResult() + { + Result = new StringDialogResult { Value = txtValue.Text }; + } + } + + public class StringDialogResult + { + public string Value; + } + +} diff --git a/server/FSO.Server.Debug/StringDialog.designer.cs b/server/FSO.Server.Debug/StringDialog.designer.cs new file mode 100755 index 0000000..8e89ee5 --- /dev/null +++ b/server/FSO.Server.Debug/StringDialog.designer.cs @@ -0,0 +1,103 @@ +namespace tso.debug.network +{ + partial class StringDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.description = new System.Windows.Forms.Label(); + this.btnCancel = new System.Windows.Forms.Button(); + this.btnOk = new System.Windows.Forms.Button(); + this.txtValue = new System.Windows.Forms.TextBox(); + this.SuspendLayout(); + // + // description + // + this.description.AutoSize = true; + this.description.Location = new System.Drawing.Point(12, 9); + this.description.Name = "description"; + this.description.Size = new System.Drawing.Size(35, 13); + this.description.TabIndex = 0; + this.description.Text = "label1"; + // + // btnCancel + // + this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.btnCancel.Location = new System.Drawing.Point(299, 62); + this.btnCancel.Name = "btnCancel"; + this.btnCancel.Size = new System.Drawing.Size(75, 23); + this.btnCancel.TabIndex = 1; + this.btnCancel.Text = "Cancel"; + this.btnCancel.UseVisualStyleBackColor = true; + // + // btnOk + // + this.btnOk.DialogResult = System.Windows.Forms.DialogResult.OK; + this.btnOk.Enabled = false; + this.btnOk.Location = new System.Drawing.Point(218, 62); + this.btnOk.Name = "btnOk"; + this.btnOk.Size = new System.Drawing.Size(75, 23); + this.btnOk.TabIndex = 2; + this.btnOk.Text = "Ok"; + this.btnOk.UseVisualStyleBackColor = true; + this.btnOk.Click += new System.EventHandler(this.btnOk_Click); + // + // txtValue + // + this.txtValue.Location = new System.Drawing.Point(15, 36); + this.txtValue.Name = "txtValue"; + this.txtValue.Size = new System.Drawing.Size(359, 20); + this.txtValue.TabIndex = 3; + this.txtValue.TextChanged += new System.EventHandler(this.txtValue_TextChanged); + this.txtValue.Enter += new System.EventHandler(this.txtValue_Enter); + // + // StringDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(386, 96); + this.Controls.Add(this.txtValue); + this.Controls.Add(this.btnOk); + this.Controls.Add(this.btnCancel); + this.Controls.Add(this.description); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; + this.Name = "StringDialog"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Deactivate += new System.EventHandler(this.StringDialog_Deactivate); + this.Load += new System.EventHandler(this.StringModal_Load); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label description; + private System.Windows.Forms.Button btnCancel; + private System.Windows.Forms.Button btnOk; + private System.Windows.Forms.TextBox txtValue; + } +} \ No newline at end of file diff --git a/server/FSO.Server.Debug/StringDialog.resx b/server/FSO.Server.Debug/StringDialog.resx new file mode 100755 index 0000000..19dc0dd --- /dev/null +++ b/server/FSO.Server.Debug/StringDialog.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/server/FSO.Server.Debug/libs/Be.Windows.Forms.HexBox.dll b/server/FSO.Server.Debug/libs/Be.Windows.Forms.HexBox.dll new file mode 100755 index 0000000..318d8b8 Binary files /dev/null and b/server/FSO.Server.Debug/libs/Be.Windows.Forms.HexBox.dll differ diff --git a/server/FSO.Server.Debug/packages.config b/server/FSO.Server.Debug/packages.config new file mode 100755 index 0000000..87286c7 --- /dev/null +++ b/server/FSO.Server.Debug/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Domain/Domain/Shards.cs b/server/FSO.Server.Domain/Domain/Shards.cs new file mode 100755 index 0000000..802f409 --- /dev/null +++ b/server/FSO.Server.Domain/Domain/Shards.cs @@ -0,0 +1,87 @@ +using FSO.Common.Domain.Shards; +using FSO.Server.Database.DA; +using FSO.Server.Protocol.CitySelector; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace FSO.Server.Domain +{ + public class Shards : IShardsDomain + { + private List _Shards = new List(); + private IDAFactory _DbFactory; + private DateTime _LastPoll; + + public Shards(IDAFactory factory) + { + _DbFactory = factory; + Poll(); + } + + public List All + { + get{ + return _Shards; + } + } + + public int? CurrentShard + { + get + { + throw new Exception("CurrentShard not avaliable in server domain"); + } + } + + public void AutoUpdate() + { + Task.Delay(60000).ContinueWith(x => + { + try{ + Poll(); + }catch(Exception ex){ + } + AutoUpdate(); + }); + } + + public void Update() + { + + } + + private void Poll() + { + _LastPoll = DateTime.UtcNow; + + using (var db = _DbFactory.Get()) + { + _Shards = db.Shards.All().Select(x => new ShardStatusItem() + { + Id = x.shard_id, + Name = x.name, + Map = x.map, + Rank = x.rank, + Status = (Server.Protocol.CitySelector.ShardStatus)(byte)x.status, + PublicHost = x.public_host, + InternalHost = x.internal_host, + VersionName = x.version_name, + VersionNumber = x.version_number, + UpdateID = x.update_id + }).ToList(); + } + } + + public ShardStatusItem GetById(int id) + { + return _Shards.FirstOrDefault(x => x.Id == id); + } + + public ShardStatusItem GetByName(string name) + { + return _Shards.FirstOrDefault(x => x.Name == name); + } + } +} diff --git a/server/FSO.Server.Domain/FSO.Server.Domain.csproj b/server/FSO.Server.Domain/FSO.Server.Domain.csproj new file mode 100755 index 0000000..b3c885f --- /dev/null +++ b/server/FSO.Server.Domain/FSO.Server.Domain.csproj @@ -0,0 +1,95 @@ + + + + + Debug + AnyCPU + {A1D9ABA0-0105-436D-8F8C-2418DB768080} + Library + Properties + FSO.Server.Domain + FSO.Server.Domain + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + + + + + + + + + + + + + + + + {9848faf5-444a-48cc-a26a-8115d8c4fb52} + FSO.Common.Domain + + + {39b61962-fe43-4b64-8e57-8f793737fffe} + FSO.Server.Common + + + {430acd60-e798-43f0-ad61-8b5a35df6ab2} + FSO.Server.Database + + + {a08ade32-27e2-44f4-bc52-11a16c56baa8} + FSO.Server.Protocol + + + {c42962a1-8796-4f47-9dcd-79ed5904d8ca} + FSO.Common + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Domain/IGluonHostPool.cs b/server/FSO.Server.Domain/IGluonHostPool.cs new file mode 100755 index 0000000..be4c6df --- /dev/null +++ b/server/FSO.Server.Domain/IGluonHostPool.cs @@ -0,0 +1,30 @@ +using FSO.Server.Database.DA.Hosts; +using FSO.Server.Framework.Gluon; +using FSO.Server.Protocol.Gluon.Packets; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace FSO.Server.Domain +{ + public interface IGluonHostPool + { + string PoolHash { get; } + + IGluonHost Get(string callSign); + IGluonHost GetByShardId(int shard_id); + IEnumerable GetByRole(DbHostRole role); + IEnumerable GetAll(); + + void Start(); + void Stop(); + } + + public interface IGluonHost : IGluonSession + { + DbHostRole Role { get; } + bool Connected { get; } + DateTime BootTime { get; } + Task Call(IN input) where IN : IGluonCall; + } +} diff --git a/server/FSO.Server.Domain/Properties/AssemblyInfo.cs b/server/FSO.Server.Domain/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..f8ff490 --- /dev/null +++ b/server/FSO.Server.Domain/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FSO.Server.Domain")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FSO.Server.Domain")] +[assembly: AssemblyCopyright("Copyright © 2017")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a1d9aba0-0105-436d-8f8c-2418db768080")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/FSO.Server.Domain/app.config b/server/FSO.Server.Domain/app.config new file mode 100755 index 0000000..51e422b --- /dev/null +++ b/server/FSO.Server.Domain/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Domain/packages.config b/server/FSO.Server.Domain/packages.config new file mode 100755 index 0000000..cb9a27f --- /dev/null +++ b/server/FSO.Server.Domain/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/server/FSO.Server.Protocol/Aries/AriesPacketType.cs b/server/FSO.Server.Protocol/Aries/AriesPacketType.cs new file mode 100755 index 0000000..e527a7e --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesPacketType.cs @@ -0,0 +1,77 @@ +using System; + +namespace FSO.Server.Protocol.Aries +{ + public enum AriesPacketType + { + Voltron, + Electron, + Gluon, + + RequestClientSession, + RequestClientSessionResponse, + RequestChallenge, + RequestChallengeResponse, + AnswerChallenge, + AnswerAccepted, + + Unknown + } + + public static class AriesPacketTypeUtils + { + public static AriesPacketType FromPacketCode(uint code) + { + switch (code) + { + case 0: + return AriesPacketType.Voltron; + case 1000: + return AriesPacketType.Electron; + case 1001: + return AriesPacketType.Gluon; + case 1002: + return AriesPacketType.RequestChallenge; + case 1003: + return AriesPacketType.RequestChallengeResponse; + case 1004: + return AriesPacketType.AnswerChallenge; + case 1005: + return AriesPacketType.AnswerAccepted; + case 22: + return AriesPacketType.RequestClientSession; + case 21: + return AriesPacketType.RequestClientSessionResponse; + default: + return AriesPacketType.Unknown; + } + } + + public static uint GetPacketCode(this AriesPacketType type) + { + switch (type) + { + case AriesPacketType.Voltron: + return 0; + case AriesPacketType.Electron: + return 1000; + case AriesPacketType.Gluon: + return 1001; + case AriesPacketType.RequestChallenge: + return 1002; + case AriesPacketType.RequestChallengeResponse: + return 1003; + case AriesPacketType.AnswerChallenge: + return 1004; + case AriesPacketType.AnswerAccepted: + return 1005; + case AriesPacketType.RequestClientSession: + return 22; + case AriesPacketType.RequestClientSessionResponse: + return 21; + default: + throw new Exception("Unknown aries packet type " + type.ToString()); + } + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/AriesPackets.cs b/server/FSO.Server.Protocol/Aries/AriesPackets.cs new file mode 100755 index 0000000..cf1882d --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesPackets.cs @@ -0,0 +1,41 @@ +using FSO.Server.Protocol.Aries.Packets; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Protocol.Aries +{ + public class AriesPackets + { + public static Dictionary ARIES_PACKET_BY_TYPEID; + public static Type[] ARIES_PACKETS = new Type[] { + typeof(RequestClientSession), + typeof(RequestClientSessionResponse), + typeof(RequestChallenge), + typeof(RequestChallengeResponse), + typeof(AnswerChallenge), + typeof(AnswerAccepted) + }; + + static AriesPackets() + { + ARIES_PACKET_BY_TYPEID = new Dictionary(); + foreach (Type packetType in ARIES_PACKETS) + { + IAriesPacket packet = (IAriesPacket)Activator.CreateInstance(packetType); + ARIES_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType); + } + } + + public static Type GetByPacketCode(uint code) + { + if (ARIES_PACKET_BY_TYPEID.ContainsKey(code)) + { + return ARIES_PACKET_BY_TYPEID[code]; + } + else + { + return null; + } + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/AriesProtocol.cs b/server/FSO.Server.Protocol/Aries/AriesProtocol.cs new file mode 100755 index 0000000..36f243a --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesProtocol.cs @@ -0,0 +1,38 @@ +using Mina.Filter.Codec; +using Ninject; +using Mina.Core.Session; + +namespace FSO.Server.Protocol.Aries +{ + public class AriesProtocol : IProtocolCodecFactory + { + private IKernel Kernel; + + public AriesProtocol(IKernel kernel) + { + this.Kernel = kernel; + } + + private IProtocolDecoder _Decoder; + + public IProtocolDecoder GetDecoder(IoSession session) + { + if (_Decoder == null) + { + _Decoder = Kernel.Get(); + } + return _Decoder; + } + + private IProtocolEncoder _Encoder; + + public IProtocolEncoder GetEncoder(IoSession session) + { + if(_Encoder == null) + { + _Encoder = Kernel.Get(); + } + return _Encoder; + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/AriesProtocolDecoder.cs b/server/FSO.Server.Protocol/Aries/AriesProtocolDecoder.cs new file mode 100755 index 0000000..35ef057 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesProtocolDecoder.cs @@ -0,0 +1,111 @@ +using Mina.Filter.Codec; +using System; +using Mina.Core.Buffer; +using Mina.Core.Session; +using FSO.Server.Protocol.Voltron; +using FSO.Server.Protocol.Electron; +using FSO.Common.Serialization; +using FSO.Server.Protocol.Utils; +using FSO.Server.Protocol.Gluon; + +namespace FSO.Server.Protocol.Aries +{ + public class AriesProtocolDecoder : CustomCumulativeProtocolDecoder + { + //private static Logger LOG = LogManager.GetCurrentClassLogger(); + private ISerializationContext Context; + + public AriesProtocolDecoder(ISerializationContext context) + { + this.Context = context; + } + + protected override bool DoDecode(IoSession session, IoBuffer buffer, IProtocolDecoderOutput output) + { + if(buffer.Remaining < 12){ + return false; + } + + /** + * We expect aries, voltron or electron packets + */ + var startPosition = buffer.Position; + + buffer.Order = ByteOrder.LittleEndian; + uint packetType = buffer.GetUInt32(); + uint timestamp = buffer.GetUInt32(); + uint payloadSize = buffer.GetUInt32(); + + if (buffer.Remaining < payloadSize) + { + /** Not all here yet **/ + buffer.Position = startPosition; + return false; + } + + //LOG.Info("[ARIES] " + packetType + " (" + payloadSize + ")"); + + if(packetType == AriesPacketType.Voltron.GetPacketCode()) + { + DecodeVoltronStylePackets(buffer, ref payloadSize, output, VoltronPackets.GetByPacketCode); + } + else if (packetType == AriesPacketType.Electron.GetPacketCode()) + { + DecodeVoltronStylePackets(buffer, ref payloadSize, output, ElectronPackets.GetByPacketCode); + }else if(packetType == AriesPacketType.Gluon.GetPacketCode()) + { + DecodeVoltronStylePackets(buffer, ref payloadSize, output, GluonPackets.GetByPacketCode); + } + else + { + //Aries + var packetClass = AriesPackets.GetByPacketCode(packetType); + if (packetClass != null) + { + byte[] data = new byte[(int)payloadSize]; + buffer.Get(data, 0, (int)payloadSize); + + IAriesPacket packet = (IAriesPacket)Activator.CreateInstance(packetClass); + var io = IoBuffer.Wrap(data); + io.Order = ByteOrder.LittleEndian; + packet.Deserialize(io, Context); + output.Write(packet); + + payloadSize = 0; + } + else + { + buffer.Skip((int)payloadSize); + payloadSize = 0; + } + } + + return true; + } + + + private void DecodeVoltronStylePackets(IoBuffer buffer, ref uint payloadSize, IProtocolDecoderOutput output, Func typeResolver) + { + while (payloadSize > 0) + { + /** Voltron packet **/ + buffer.Order = ByteOrder.BigEndian; + ushort type = buffer.GetUInt16(); + uint innerPayloadSize = buffer.GetUInt32() - 6; + + byte[] data = new byte[(int)innerPayloadSize]; + buffer.Get(data, 0, (int)innerPayloadSize); + + var packetClass = typeResolver(type); + if (packetClass != null) + { + IoBufferDeserializable packet = (IoBufferDeserializable)Activator.CreateInstance(packetClass); + packet.Deserialize(IoBuffer.Wrap(data), Context); + output.Write(packet); + } + + payloadSize -= innerPayloadSize + 6; + } + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/AriesProtocolEncoder.cs b/server/FSO.Server.Protocol/Aries/AriesProtocolEncoder.cs new file mode 100755 index 0000000..6b98e24 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesProtocolEncoder.cs @@ -0,0 +1,166 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Electron; +using FSO.Server.Protocol.Gluon; +using FSO.Server.Protocol.Voltron; +using Mina.Core.Buffer; +using Mina.Core.Session; +using Mina.Filter.Codec; +using System; + +namespace FSO.Server.Protocol.Aries +{ + public class AriesProtocolEncoder : IProtocolEncoder + { + //private static Logger LOG = LogManager.GetCurrentClassLogger(); + private ISerializationContext Context; + + public AriesProtocolEncoder(ISerializationContext context) + { + this.Context = context; + } + + public void Dispose(IoSession session) + { + } + + public void Encode(IoSession session, object message, IProtocolEncoderOutput output) + { + if (message is IVoltronPacket) + { + EncodeVoltron(session, message, output); + } + else if (message is IElectronPacket) + { + EncodeElectron(session, message, output); + }else if(message is IGluonPacket) + { + EncodeGluon(session, message, output); + } + else if (message is IAriesPacket) + { + EncodeAries(session, message, output); + } + else if (message.GetType().IsArray) + { + object[] arr = (object[])message; + bool allVoltron = true; + + for (var i = 0; i < arr.Length; i++) + { + if (!(arr[i] is IVoltronPacket)) + { + allVoltron = false; + break; + } + } + + //TODO: Chunk these into fewer packets + for (var i = 0; i < arr.Length; i++) + { + Encode(session, arr[i], output); + } + } + } + + private void EncodeAries(IoSession session, object message, IProtocolEncoderOutput output) + { + IAriesPacket ariesPacket = (IAriesPacket)message; + AriesPacketType ariesPacketType = ariesPacket.GetPacketType(); + + var payload = IoBuffer.Allocate(128); + payload.Order = ByteOrder.LittleEndian; + payload.AutoExpand = true; + ariesPacket.Serialize(payload, Context); + payload.Flip(); + + int payloadSize = payload.Remaining; + IoBuffer headers = IoBuffer.Allocate(12); + headers.Order = ByteOrder.LittleEndian; + + /** + * Aries header + * uint32 type + * uint32 timestamp + * uint32 payloadSize + */ + uint timestamp = (uint)TimeSpan.FromTicks(DateTime.Now.Ticks - session.CreationTime.Ticks).TotalMilliseconds; + headers.PutUInt32(ariesPacketType.GetPacketCode()); + headers.PutUInt32(timestamp); + headers.PutUInt32((uint)payloadSize); + + if (payloadSize > 0) + { + headers.AutoExpand = true; + headers.Put(payload); + } + + headers.Flip(); + output.Write(headers); + //output.Flush(); + } + + private void EncodeVoltron(IoSession session, object message, IProtocolEncoderOutput output) + { + IVoltronPacket voltronPacket = (IVoltronPacket)message; + VoltronPacketType voltronPacketType = voltronPacket.GetPacketType(); + EncodeVoltronStylePackets(session, output, AriesPacketType.Voltron, voltronPacketType.GetPacketCode(), voltronPacket); + } + + private void EncodeElectron(IoSession session, object message, IProtocolEncoderOutput output) + { + IElectronPacket packet = (IElectronPacket)message; + ElectronPacketType packetType = packet.GetPacketType(); + EncodeVoltronStylePackets(session, output, AriesPacketType.Electron, packetType.GetPacketCode(), packet); + } + + private void EncodeGluon(IoSession session, object message, IProtocolEncoderOutput output) + { + IGluonPacket packet = (IGluonPacket)message; + GluonPacketType packetType = packet.GetPacketType(); + EncodeVoltronStylePackets(session, output, AriesPacketType.Gluon, packetType.GetPacketCode(), packet); + } + + private void EncodeVoltronStylePackets(IoSession session, IProtocolEncoderOutput output, AriesPacketType ariesType, ushort packetType, IoBufferSerializable message) + { + var payload = IoBuffer.Allocate(512); + payload.Order = ByteOrder.BigEndian; + payload.AutoExpand = true; + message.Serialize(payload, Context); + payload.Flip(); + + int payloadSize = payload.Remaining; + IoBuffer headers = IoBuffer.Allocate(18); + headers.Order = ByteOrder.LittleEndian; + + /** + * Aries header + * uint32 type + * uint32 timestamp + * uint32 payloadSize + */ + uint timestamp = (uint)TimeSpan.FromTicks(DateTime.Now.Ticks - session.CreationTime.Ticks).TotalMilliseconds; + headers.PutUInt32(ariesType.GetPacketCode()); + headers.PutUInt32(timestamp); + headers.PutUInt32((uint)payloadSize + 6); + + /** + * Voltron header + * uint16 type + * uint32 payloadSize + */ + headers.Order = ByteOrder.BigEndian; + headers.PutUInt16(packetType); + headers.PutUInt32((uint)payloadSize + 6); + + if (payloadSize > 0) + { + headers.AutoExpand = true; + headers.Put(payload); + } + + headers.Flip(); + output.Write(headers); + //output.Flush(); + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/AriesProtocolLogger.cs b/server/FSO.Server.Protocol/Aries/AriesProtocolLogger.cs new file mode 100755 index 0000000..a0562ea --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/AriesProtocolLogger.cs @@ -0,0 +1,160 @@ +using Mina.Core.Session; +using Mina.Core.Buffer; +using Mina.Core.Filterchain; +using FSO.Server.Common; +using Mina.Core.Write; +using FSO.Server.Protocol.Voltron; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Aries +{ + public class AriesProtocolLogger : IoFilterAdapter + { + //private static Logger LOG = LogManager.GetCurrentClassLogger(); + + private IPacketLogger PacketLogger; + private ISerializationContext Context; + + public AriesProtocolLogger(IPacketLogger packetLogger, ISerializationContext context) + { + this.PacketLogger = packetLogger; + this.Context = context; + } + + public override void MessageSent(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest) + { + IVoltronPacket voltronPacket = writeRequest.OriginalRequest.Message as IVoltronPacket; + if (voltronPacket != null) + { + var voltronBuffer = IoBuffer.Allocate(512); + voltronBuffer.Order = ByteOrder.BigEndian; + voltronBuffer.AutoExpand = true; + voltronPacket.Serialize(voltronBuffer, Context); + voltronBuffer.Flip(); + + var byteArray = new byte[voltronBuffer.Remaining]; + voltronBuffer.Get(byteArray, 0, voltronBuffer.Remaining); + + PacketLogger.OnPacket(new Packet + { + Data = byteArray, + Type = PacketType.VOLTRON, + SubType = voltronPacket.GetPacketType().GetPacketCode(), + Direction = PacketDirection.OUTPUT + }); + nextFilter.MessageSent(session, writeRequest); + return; + } + + IAriesPacket ariesPacket = writeRequest.OriginalRequest.Message as IAriesPacket; + if(ariesPacket != null) + { + IoBuffer ariesBuffer = IoBuffer.Allocate(128); + ariesBuffer.AutoExpand = true; + ariesBuffer.Order = ByteOrder.LittleEndian; + ariesPacket.Serialize(ariesBuffer, Context); + ariesBuffer.Flip(); + + var byteArray = new byte[ariesBuffer.Remaining]; + ariesBuffer.Get(byteArray, 0, ariesBuffer.Remaining); + + PacketLogger.OnPacket(new Packet + { + Data = byteArray, + Type = PacketType.ARIES, + SubType = ariesPacket.GetPacketType().GetPacketCode(), + Direction = PacketDirection.OUTPUT + }); + nextFilter.MessageSent(session, writeRequest); + return; + } + + IoBuffer buffer = writeRequest.Message as IoBuffer; + if (buffer == null) + { + nextFilter.MessageSent(session, writeRequest); + return; + } + + TryParseAriesFrame(buffer, PacketDirection.OUTPUT); + nextFilter.MessageSent(session, writeRequest); + } + + public override void MessageReceived(INextFilter nextFilter, IoSession session, object message) + { + IoBuffer buffer = message as IoBuffer; + if (buffer == null) + { + nextFilter.MessageReceived(session, message); + return; + } + + TryParseAriesFrame(buffer, PacketDirection.INPUT); + + nextFilter.MessageReceived(session, message); + } + + private void TryParseAriesFrame(IoBuffer buffer, PacketDirection direction) + { + buffer.Rewind(); + + if(buffer.Remaining < 12) + { + return; + } + + buffer.Order = ByteOrder.LittleEndian; + uint packetType = buffer.GetUInt32(); + uint timestamp = buffer.GetUInt32(); + uint payloadSize = buffer.GetUInt32(); + + if (buffer.Remaining < payloadSize) + { + buffer.Skip(-12); + return; + } + + while (payloadSize > 0) + { + if (packetType == 0) + { + /** Voltron packet **/ + buffer.Order = ByteOrder.BigEndian; + ushort voltronType = buffer.GetUInt16(); + uint voltronPayloadSize = buffer.GetUInt32() - 6; + + byte[] data = new byte[(int)voltronPayloadSize]; + buffer.Get(data, 0, (int)voltronPayloadSize); + + PacketLogger.OnPacket(new Packet + { + Data = data, + Type = PacketType.VOLTRON, + SubType = voltronType, + Direction = direction + }); + + payloadSize -= voltronPayloadSize + 6; + } + else + { + byte[] data = new byte[(int)payloadSize]; + buffer.Get(data, 0, (int)payloadSize); + + PacketLogger.OnPacket(new Packet + { + Data = data, + Type = PacketType.ARIES, + SubType = packetType, + Direction = direction + }); + + payloadSize = 0; + } + } + + + buffer.Rewind(); + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/IAriesPacket.cs b/server/FSO.Server.Protocol/Aries/IAriesPacket.cs new file mode 100755 index 0000000..2096890 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/IAriesPacket.cs @@ -0,0 +1,14 @@ +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Aries +{ + public interface IAriesPacket : IoBufferSerializable, IoBufferDeserializable + { + /** + * Get packet type + * + * @return + */ + AriesPacketType GetPacketType(); + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/AnswerAccepted.cs b/server/FSO.Server.Protocol/Aries/Packets/AnswerAccepted.cs new file mode 100755 index 0000000..7520489 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/AnswerAccepted.cs @@ -0,0 +1,21 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class AnswerAccepted : IAriesPacket + { + public void Deserialize(IoBuffer input, ISerializationContext context) + { + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.AnswerAccepted; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/AnswerChallenge.cs b/server/FSO.Server.Protocol/Aries/Packets/AnswerChallenge.cs new file mode 100755 index 0000000..6c0f710 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/AnswerChallenge.cs @@ -0,0 +1,25 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class AnswerChallenge : IAriesPacket + { + public string Answer; + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + Answer = input.GetPascalVLCString(); + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.AnswerChallenge; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutPascalVLCString(Answer); + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/RequestChallenge.cs b/server/FSO.Server.Protocol/Aries/Packets/RequestChallenge.cs new file mode 100755 index 0000000..235986d --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/RequestChallenge.cs @@ -0,0 +1,31 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class RequestChallenge : IAriesPacket + { + public string CallSign; + public string PublicHost; + public string InternalHost; + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + CallSign = input.GetPascalString(); + PublicHost = input.GetPascalString(); + InternalHost = input.GetPascalString(); + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.RequestChallenge; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutPascalString(CallSign); + output.PutPascalString(PublicHost); + output.PutPascalString(InternalHost); + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/RequestChallengeResponse.cs b/server/FSO.Server.Protocol/Aries/Packets/RequestChallengeResponse.cs new file mode 100755 index 0000000..20276f0 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/RequestChallengeResponse.cs @@ -0,0 +1,25 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class RequestChallengeResponse : IAriesPacket + { + public string Challenge; + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + Challenge = input.GetPascalVLCString(); + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.RequestChallengeResponse; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutPascalVLCString(Challenge); + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/RequestClientSession.cs b/server/FSO.Server.Protocol/Aries/Packets/RequestClientSession.cs new file mode 100755 index 0000000..468543d --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/RequestClientSession.cs @@ -0,0 +1,21 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class RequestClientSession : IAriesPacket + { + public void Deserialize(IoBuffer input, ISerializationContext context) + { + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.RequestClientSession; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + } + } +} diff --git a/server/FSO.Server.Protocol/Aries/Packets/RequestClientSessionResponse.cs b/server/FSO.Server.Protocol/Aries/Packets/RequestClientSessionResponse.cs new file mode 100755 index 0000000..989f8e4 --- /dev/null +++ b/server/FSO.Server.Protocol/Aries/Packets/RequestClientSessionResponse.cs @@ -0,0 +1,50 @@ +using System.Text; +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Aries.Packets +{ + public class RequestClientSessionResponse : IAriesPacket + { + public string User { get; set; } + public string AriesVersion { get; set; } + public string Email { get; set; } + public string Authserv { get; set; } + public ushort Product { get; set; } + public byte Unknown { get; set; } = 39; + public string ServiceIdent { get; set; } + public ushort Unknown2 { get; set; } = 4; //1 if re-establishing + public string Password { get; set; } + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + this.User = input.GetString(112, Encoding.ASCII); + this.AriesVersion = input.GetString(80, Encoding.ASCII); + this.Email = input.GetString(40, Encoding.ASCII); + this.Authserv = input.GetString(84, Encoding.ASCII); + this.Product = input.GetUInt16(); + this.Unknown = input.Get(); + this.ServiceIdent = input.GetString(3, Encoding.ASCII); + this.Unknown2 = input.GetUInt16(); + this.Password = input.GetString(32, Encoding.ASCII); + } + + public AriesPacketType GetPacketType() + { + return AriesPacketType.RequestClientSessionResponse; + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutString(this.User, 112, Encoding.ASCII); + output.PutString(this.AriesVersion, 80, Encoding.ASCII); + output.PutString(this.Email, 40, Encoding.ASCII); + output.PutString(this.Authserv, 84, Encoding.ASCII); + output.PutUInt16(this.Product); + output.Put(this.Unknown); + output.PutString(this.ServiceIdent, 3, Encoding.ASCII); + output.PutUInt16(this.Unknown2); + output.PutString(this.Password, 32, Encoding.ASCII); + } + } +} diff --git a/server/FSO.Server.Protocol/Authorization/AuthRequest.cs b/server/FSO.Server.Protocol/Authorization/AuthRequest.cs new file mode 100755 index 0000000..5de8797 --- /dev/null +++ b/server/FSO.Server.Protocol/Authorization/AuthRequest.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Protocol.Authorization +{ + public class AuthRequest + { + public string Username; + public string Password; + public string ServiceID; + public string Version; + public string ClientID; + } +} diff --git a/server/FSO.Server.Protocol/Authorization/AuthResult.cs b/server/FSO.Server.Protocol/Authorization/AuthResult.cs new file mode 100755 index 0000000..d4e283d --- /dev/null +++ b/server/FSO.Server.Protocol/Authorization/AuthResult.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Protocol.Authorization +{ + public class AuthResult + { + public bool Valid; + public string Ticket; + public string ReasonCode; + public string ReasonText; + public string ReasonURL; + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/AvatarAppearanceType.cs b/server/FSO.Server.Protocol/CitySelector/AvatarAppearanceType.cs new file mode 100755 index 0000000..1a78345 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/AvatarAppearanceType.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Protocol.CitySelector +{ + public enum AvatarAppearanceType + { + Light = 0, + Medium = 1, + Dark = 2 + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/AvatarData.cs b/server/FSO.Server.Protocol/CitySelector/AvatarData.cs new file mode 100755 index 0000000..558f397 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/AvatarData.cs @@ -0,0 +1,96 @@ +using FSO.Common.Utils; +using System; + +namespace FSO.Server.Protocol.CitySelector +{ + public class AvatarData : IXMLEntity + { + public uint ID; + public string Name; + public string ShardName; + + + + /** Non standard **/ + + /** Appearance **/ + public AvatarAppearanceType AppearanceType { get; set; } + public ulong HeadOutfitID { get; set; } + public ulong BodyOutfitID { get; set; } + public string Description { get; set; } + + /** Lot **/ + public uint? LotId { get; set; } + public uint? LotLocation { get; set; } + public string LotName { get; set; } + + #region IXMLPrinter Members + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var result = doc.CreateElement("Avatar-Data"); + result.AppendTextNode("AvatarID", ID.ToString()); + result.AppendTextNode("Name", Name); + result.AppendTextNode("Shard-Name", ShardName); + + //NEW: Appearance info + result.AppendTextNode("Head", HeadOutfitID.ToString()); + result.AppendTextNode("Body", BodyOutfitID.ToString()); + result.AppendTextNode("Appearance", AppearanceType.ToString()); + + if (LotId.HasValue && LotLocation.HasValue && LotName != null){ + result.AppendTextNode("LotId", LotId.Value.ToString()); + result.AppendTextNode("LotName", LotName); + result.AppendTextNode("LotLocation", LotLocation.Value.ToString()); + } + + result.AppendTextNode("Description", Description); + + return result; + } + + public void Parse(System.Xml.XmlElement element) + { + this.ID = uint.Parse(element.ReadTextNode("AvatarID")); + this.Name = element.ReadTextNode("Name"); + this.ShardName = element.ReadTextNode("Shard-Name"); + + var headString = element.ReadTextNode("Head"); + if (headString != null) + { + this.HeadOutfitID = ulong.Parse(headString); + } + + var bodyString = element.ReadTextNode("Body"); + if (bodyString != null) + { + this.BodyOutfitID = ulong.Parse(bodyString); + } + + var apprString = element.ReadTextNode("Appearance"); + if (apprString != null) + { + this.AppearanceType = (AvatarAppearanceType)Enum.Parse(typeof(AvatarAppearanceType), apprString); + } + + var lotId = element.ReadTextNode("LotId"); + if(lotId != null) + { + this.LotId = uint.Parse(lotId); + } + + var lotLocation = element.ReadTextNode("LotLocation"); + if (lotLocation != null) + { + this.LotLocation = uint.Parse(lotLocation); + } + + LotName = element.ReadTextNode("LotName"); + + var descString = element.ReadTextNode("Description"); + this.Description = descString ?? ""; + } + + #endregion + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/AvatarGender.cs b/server/FSO.Server.Protocol/CitySelector/AvatarGender.cs new file mode 100755 index 0000000..68d2d56 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/AvatarGender.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.CitySelector +{ + public enum AvatarGender + { + Male = 1, + Female = 2 + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/InitialConnectServletRequest.cs b/server/FSO.Server.Protocol/CitySelector/InitialConnectServletRequest.cs new file mode 100755 index 0000000..de328cb --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/InitialConnectServletRequest.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.CitySelector +{ + public class InitialConnectServletRequest + { + public string Ticket; + public string Version; + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/InitialConnectServletResult.cs b/server/FSO.Server.Protocol/CitySelector/InitialConnectServletResult.cs new file mode 100755 index 0000000..bf98711 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/InitialConnectServletResult.cs @@ -0,0 +1,50 @@ +using FSO.Common.Utils; +using System; + +namespace FSO.Server.Protocol.CitySelector +{ + public class InitialConnectServletResult : IXMLEntity + { + public InitialConnectServletResultType Status; + public XMLErrorMessage Error; + public UserAuthorized UserAuthorized; + + + + #region IXMLEntity Members + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + throw new NotImplementedException(); + } + + public void Parse(System.Xml.XmlElement element) + { + switch (element.Name) + { + case "Error-Message": + Status = InitialConnectServletResultType.Error; + Error = new XMLErrorMessage(); + Error.Parse(element); + break; + case "User-Authorized": + Status = InitialConnectServletResultType.Authorized; + UserAuthorized = new UserAuthorized(); + UserAuthorized.Parse(element); + break; + case "Patch-Result": + Status = InitialConnectServletResultType.Patch; + break; + } + } + + #endregion + } + + public enum InitialConnectServletResultType + { + Authorized, + Patch, + Error + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletRequest.cs b/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletRequest.cs new file mode 100755 index 0000000..3036e63 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletRequest.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.CitySelector +{ + public class ShardSelectorServletRequest + { + public string ShardName; + public string AvatarID; + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletResponse.cs b/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletResponse.cs new file mode 100755 index 0000000..129b439 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/ShardSelectorServletResponse.cs @@ -0,0 +1,45 @@ +using FSO.Common.Utils; + +namespace FSO.Server.Protocol.CitySelector +{ + public class ShardSelectorServletResponse : IXMLEntity + { + public string Address; + public string Ticket; + public string ConnectionID; + public uint PlayerID; + public string AvatarID; + + public bool PreAlpha = false; + + #region IXMLPrinter Members + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var result = doc.CreateElement("Shard-Selection"); + result.AppendTextNode("Connection-Address", Address); + result.AppendTextNode("Authorization-Ticket", Ticket); + result.AppendTextNode("PlayerID", PlayerID.ToString()); + + if (PreAlpha == false) + { + result.AppendTextNode("ConnectionID", ConnectionID); + result.AppendTextNode("EntitlementLevel", ""); + } + result.AppendTextNode("AvatarID", AvatarID); //freeso now uses this + + return result; + } + + public void Parse(System.Xml.XmlElement element) + { + this.Address = element.ReadTextNode("Connection-Address"); + this.Ticket = element.ReadTextNode("Authorization-Ticket"); + this.PlayerID = uint.Parse(element.ReadTextNode("PlayerID")); + + this.AvatarID = element.ReadTextNode("AvatarID"); + } + + #endregion + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/ShardStatus.cs b/server/FSO.Server.Protocol/CitySelector/ShardStatus.cs new file mode 100755 index 0000000..4e510f3 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/ShardStatus.cs @@ -0,0 +1,12 @@ +namespace FSO.Server.Protocol.CitySelector +{ + public enum ShardStatus + { + Up, + Down, + Busy, + Full, + Closed, + Frontier + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/ShardStatusItem.cs b/server/FSO.Server.Protocol/CitySelector/ShardStatusItem.cs new file mode 100755 index 0000000..80994e4 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/ShardStatusItem.cs @@ -0,0 +1,44 @@ +using System; +using FSO.Common.Utils; + +namespace FSO.Server.Protocol.CitySelector +{ + public class ShardStatusItem : IXMLEntity + { + public string Name; + public int Rank; + public string Map; + public ShardStatus Status; + public int Id; + public string PublicHost; + public string InternalHost; + public string VersionName; + public string VersionNumber; + public int? UpdateID; + + public ShardStatusItem() + { + } + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var result = doc.CreateElement("Shard-Status"); + result.AppendTextNode("Location", "public"); + result.AppendTextNode("Name", Name); + result.AppendTextNode("Rank", Rank.ToString()); + result.AppendTextNode("Map", Map); + result.AppendTextNode("Status", Status.ToString()); + result.AppendTextNode("Id", Id.ToString()); + return result; + } + + public void Parse(System.Xml.XmlElement element) + { + this.Name = element.ReadTextNode("Name"); + this.Rank = int.Parse(element.ReadTextNode("Rank")); + this.Map = element.ReadTextNode("Map"); + this.Status = (ShardStatus)Enum.Parse(typeof(ShardStatus), element.ReadTextNode("Status")); + this.Id = int.Parse(element.ReadTextNode("Id")); + } + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/UserAuthorized.cs b/server/FSO.Server.Protocol/CitySelector/UserAuthorized.cs new file mode 100755 index 0000000..b1e9557 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/UserAuthorized.cs @@ -0,0 +1,30 @@ +using FSO.Common.Utils; + +namespace FSO.Server.Protocol.CitySelector +{ + public class UserAuthorized : IXMLEntity + { + public string FSOVersion; + public string FSOBranch; + public string FSOUpdateUrl; + public string FSOCDNUrl; + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var element = doc.CreateElement("User-Authorized"); + element.AppendTextNode("FSO-Version", FSOVersion); + element.AppendTextNode("FSO-Branch", FSOBranch); + element.AppendTextNode("FSO-UpdateUrl", FSOUpdateUrl); + element.AppendTextNode("FSO-CDNUrl", FSOCDNUrl); + return element; + } + + public void Parse(System.Xml.XmlElement element) + { + this.FSOVersion = element.ReadTextNode("FSO-Version"); + this.FSOBranch = element.ReadTextNode("FSO-Branch"); + this.FSOUpdateUrl = element.ReadTextNode("FSO-UpdateUrl"); + this.FSOCDNUrl = element.ReadTextNode("FSO-CDNUrl"); + } + } +} diff --git a/server/FSO.Server.Protocol/CitySelector/XMLErrorMessage.cs b/server/FSO.Server.Protocol/CitySelector/XMLErrorMessage.cs new file mode 100755 index 0000000..d35de60 --- /dev/null +++ b/server/FSO.Server.Protocol/CitySelector/XMLErrorMessage.cs @@ -0,0 +1,38 @@ +using FSO.Common.Utils; +using System; + +namespace FSO.Server.Protocol.CitySelector +{ + public class XMLErrorMessage : IXMLEntity + { + public String Code; + public String Message; + + public XMLErrorMessage(){ + } + + public XMLErrorMessage(String code, String message) + { + this.Code = code; + this.Message = message; + } + + #region IXMLPrinter Members + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var element = doc.CreateElement("Error-Message"); + element.AppendTextNode("Error-Number", Code); + element.AppendTextNode("Error", Message); + return element; + } + + public void Parse(System.Xml.XmlElement element) + { + this.Code = element.ReadTextNode("Error-Number"); + this.Message = element.ReadTextNode("Error"); + } + + #endregion + } +} diff --git a/server/FSO.Server.Protocol/Electron/AbstractElectronPacket.cs b/server/FSO.Server.Protocol/Electron/AbstractElectronPacket.cs new file mode 100755 index 0000000..5d59a1d --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/AbstractElectronPacket.cs @@ -0,0 +1,19 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Electron +{ + public abstract class AbstractElectronPacket : IElectronPacket + { + public static IoBuffer Allocate(int size) + { + IoBuffer buffer = IoBuffer.Allocate(size); + buffer.Order = ByteOrder.BigEndian; + return buffer; + } + + public abstract ElectronPacketType GetPacketType(); + public abstract void Deserialize(IoBuffer input, ISerializationContext context); + public abstract void Serialize(IoBuffer output, ISerializationContext context); + } +} diff --git a/server/FSO.Server.Protocol/Electron/ElectronPacketType.cs b/server/FSO.Server.Protocol/Electron/ElectronPacketType.cs new file mode 100755 index 0000000..f374ebb --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/ElectronPacketType.cs @@ -0,0 +1,51 @@ +using System; + +namespace FSO.Server.Protocol.Electron +{ + public enum ElectronPacketType : ushort + { + CreateASimResponse = 1, + PurchaseLotRequest, + PurchaseLotResponse, + InstantMessage, + FindLotRequest, + FindLotResponse, + FSOVMTickBroadcast, + FSOVMDirectToClient, + FSOVMCommand, + FindAvatarRequest, + FindAvatarResponse, + ChangeRoommateRequest, + KeepAlive, + ChangeRoommateResponse, + ModerationRequest, + FSOVMProtocolMessage, + AvatarRetireRequest, + MailRequest, + MailResponse, + NhoodRequest, + NhoodResponse, + NhoodCandidateList, + BulletinRequest, + BulletinResponse, + GlobalTuningUpdate, + Unknown = 0xFFFF + } + + public static class ElectronPacketTypeUtils + { + public static ElectronPacketType FromPacketCode(ushort code) + { + var result = (ElectronPacketType)code; + if (Enum.IsDefined(typeof(ElectronPacketType), result)) + return result; + else + return ElectronPacketType.Unknown; + } + + public static ushort GetPacketCode(this ElectronPacketType type) + { + return (ushort)type; + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/ElectronPackets.cs b/server/FSO.Server.Protocol/Electron/ElectronPackets.cs new file mode 100755 index 0000000..688e179 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/ElectronPackets.cs @@ -0,0 +1,60 @@ +using FSO.Server.Protocol.Electron.Packets; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Protocol.Electron +{ + public class ElectronPackets + { + public static Dictionary ELECTRON_PACKET_BY_TYPEID; + public static Type[] ELECTRON_PACKETS = new Type[] { + typeof(CreateASimResponse), + typeof(PurchaseLotRequest), + typeof(PurchaseLotResponse), + typeof(InstantMessage), + typeof(FindLotRequest), + typeof(FindLotResponse), + typeof(FSOVMTickBroadcast), + typeof(FSOVMDirectToClient), + typeof(FSOVMCommand), + typeof(FindAvatarRequest), + typeof(FindAvatarResponse), + typeof(ChangeRoommateRequest), + typeof(KeepAlive), + typeof(ChangeRoommateResponse), + typeof(ModerationRequest), + typeof(FSOVMProtocolMessage), + typeof(AvatarRetireRequest), + typeof(MailRequest), + typeof(MailResponse), + typeof(NhoodRequest), + typeof(NhoodResponse), + typeof(NhoodCandidateList), + typeof(BulletinRequest), + typeof(BulletinResponse), + typeof(GlobalTuningUpdate) + }; + + static ElectronPackets() + { + ELECTRON_PACKET_BY_TYPEID = new Dictionary(); + foreach (Type packetType in ELECTRON_PACKETS) + { + IElectronPacket packet = (IElectronPacket)Activator.CreateInstance(packetType); + ELECTRON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType); + } + } + + public static Type GetByPacketCode(ushort code) + { + if (ELECTRON_PACKET_BY_TYPEID.ContainsKey(code)) + { + return ELECTRON_PACKET_BY_TYPEID[code]; + } + else + { + return null; + } + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/IElectronPacket.cs b/server/FSO.Server.Protocol/Electron/IElectronPacket.cs new file mode 100755 index 0000000..8bde1df --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/IElectronPacket.cs @@ -0,0 +1,9 @@ +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Electron +{ + public interface IElectronPacket : IoBufferDeserializable, IoBufferSerializable + { + ElectronPacketType GetPacketType(); + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateResponseStatus.cs b/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateResponseStatus.cs new file mode 100755 index 0000000..a9a59d4 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateResponseStatus.cs @@ -0,0 +1,33 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public enum ChangeRoommateResponseStatus : byte + { + INVITE_SUCCESS = 0, + + //invite codes + ROOMIE_ELSEWHERE = 1, + TOO_MANY_ROOMMATES = 2, + OTHER_INVITE_PENDING = 3, + + //shared + YOU_ARE_NOT_OWNER = 4, //everything but move out + + //kick or move out + YOU_ARE_NOT_ROOMMATE = 5, + LOT_MUST_BE_CLOSED = 6, //move out of lot with 1 roommate + + //invite response + LOT_DOESNT_EXIST = 7, + NO_INVITE_PENDING = 8, + + ACCEPT_SUCCESS = 9, + DECLINE_SUCCESS = 10, + KICK_SUCCESS = 11, + SELFKICK_SUCCESS = 12, + + ROOMMATE_LEFT = 13, + GOT_KICKED = 14, + + UNKNOWN = 255 + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateType.cs b/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateType.cs new file mode 100755 index 0000000..7c0c010 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/ChangeRoommateType.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public enum ChangeRoommateType : byte + { + INVITE = 0, + KICK = 1, + ACCEPT = 2, + DECLINE = 3, + POLL = 4 + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/FindAvatarResponseStatus.cs b/server/FSO.Server.Protocol/Electron/Model/FindAvatarResponseStatus.cs new file mode 100755 index 0000000..d54b492 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/FindAvatarResponseStatus.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public enum FindAvatarResponseStatus + { + FOUND, + IGNORING_THEM, + IGNORING_YOU, + NOT_ON_LOT, + PRIVACY_ENABLED, + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/FindLotResponseStatus.cs b/server/FSO.Server.Protocol/Electron/Model/FindLotResponseStatus.cs new file mode 100755 index 0000000..3b48984 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/FindLotResponseStatus.cs @@ -0,0 +1,14 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public enum FindLotResponseStatus + { + FOUND, + NO_SUCH_LOT, + NOT_OPEN, + NOT_PERMITTED_TO_OPEN, + CLAIM_FAILED, + NO_CAPACITY, + NO_ADMIT, + UNKNOWN_ERROR + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/IActionRequest.cs b/server/FSO.Server.Protocol/Electron/Model/IActionRequest.cs new file mode 100755 index 0000000..6700b16 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/IActionRequest.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public interface IActionRequest + { + object OType { get; } + bool NeedsValidation { get; } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/IActionResponse.cs b/server/FSO.Server.Protocol/Electron/Model/IActionResponse.cs new file mode 100755 index 0000000..eef67f4 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/IActionResponse.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public interface IActionResponse + { + bool Success { get; } + object OCode { get; } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Model/ModerationRequestType.cs b/server/FSO.Server.Protocol/Electron/Model/ModerationRequestType.cs new file mode 100755 index 0000000..da7f1b5 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Model/ModerationRequestType.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Protocol.Electron.Model +{ + public enum ModerationRequestType + { + IPBAN_USER, + BAN_USER, + KICK_USER + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/AvatarRetireRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/AvatarRetireRequest.cs new file mode 100755 index 0000000..f2f5324 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/AvatarRetireRequest.cs @@ -0,0 +1,23 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class AvatarRetireRequest : AbstractElectronPacket + { + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.AvatarRetireRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(0); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/BulletinRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/BulletinRequest.cs new file mode 100755 index 0000000..0c3f239 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/BulletinRequest.cs @@ -0,0 +1,69 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Electron.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class BulletinRequest : AbstractElectronPacket, IActionRequest + { + public BulletinRequestType Type; + public uint TargetNHood; //the bulletin board to use + + //post message + public string Title = ""; + public string Message = ""; + public uint LotID; //0 if empty - optionally reference a lot in this bulletin post + + //post message, delete message, promote message + public uint Value; //bulletin type if post, bulletin ID otherwise. + + public object OType => Type; + public bool NeedsValidation => false; //the CAN POST items are one off requests, rather than a state machine. + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + TargetNHood = input.GetUInt32(); + + if (Type == BulletinRequestType.POST_MESSAGE || Type == BulletinRequestType.POST_SYSTEM_MESSAGE) + { + Title = input.GetPascalString(); + Message = input.GetPascalString(); + LotID = input.GetUInt32(); + } + Value = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.BulletinRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutUInt32(TargetNHood); + + if (Type == BulletinRequestType.POST_MESSAGE || Type == BulletinRequestType.POST_SYSTEM_MESSAGE) + { + output.PutPascalString(Title); + output.PutPascalString(Message); + output.PutUInt32(LotID); + } + output.PutUInt32(Value); + } + } + + public enum BulletinRequestType : byte + { + GET_MESSAGES = 0, + POST_MESSAGE, + PROMOTE_MESSAGE, //mayor/admin only. + CAN_POST_MESSAGE, + CAN_POST_SYSTEM_MESSAGE, + + //admin + POST_SYSTEM_MESSAGE, + DELETE_MESSAGE, + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/BulletinResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/BulletinResponse.cs new file mode 100755 index 0000000..bdda29e --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/BulletinResponse.cs @@ -0,0 +1,90 @@ +using FSO.Common.Serialization; +using FSO.Files.Formats.tsodata; +using FSO.Server.Protocol.Electron.Model; +using Mina.Core.Buffer; +using System.IO; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class BulletinResponse : AbstractElectronPacket, IActionResponse + { + public BulletinResponseType Type; + public BulletinItem[] Messages = new BulletinItem[0]; + public string Message; + public uint BanEndDate; + + public bool Success => Type == BulletinResponseType.SUCCESS || Type == BulletinResponseType.SEND_SUCCESS || Type == BulletinResponseType.MESSAGES; + public object OCode => Type; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + var numMessages = input.GetInt32(); + Messages = new BulletinItem[numMessages]; + for (int j = 0; j < numMessages; j++) + { + var length = input.GetInt32(); + var dat = new byte[length]; + for (int i = 0; i < length; i++) + { + dat[i] = input.Get(); + } + + using (var str = new MemoryStream(dat)) + { + Messages[j] = new BulletinItem(str); + } + } + Message = input.GetPascalVLCString(); + BanEndDate = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.BulletinResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutInt32(Messages.Length); + foreach (var msg in Messages) + { + byte[] dat; + using (var str = new MemoryStream()) + { + msg.Save(str); + dat = str.ToArray(); + } + output.PutInt32(dat.Length); + foreach (var b in dat) + output.Put(b); + } + output.PutPascalVLCString(Message); + output.PutUInt32(BanEndDate); + } + } + + public enum BulletinResponseType + { + MESSAGES, + SEND_SUCCESS, //returns message you sent, with dbid + SUCCESS, + SEND_FAIL_NON_RESIDENT, + SEND_FAIL_BAD_PERMISSION, + SEND_FAIL_INVALID_LOT, + SEND_FAIL_INVALID_MESSAGE, + SEND_FAIL_INVALID_TITLE, + SEND_FAIL_GAMEPLAY_BAN, + SEND_FAIL_TOO_FREQUENT, + SEND_FAIL_JUST_MOVED, + FAIL_MESSAGE_DOESNT_EXIST, + FAIL_NOT_MAYOR, + FAIL_CANT_DELETE, + FAIL_ALREADY_PROMOTED, + FAIL_BAD_PERMISSION, + + CANCEL = 0xFE, + FAIL_UNKNOWN = 0xFF + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateRequest.cs new file mode 100755 index 0000000..e397506 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateRequest.cs @@ -0,0 +1,32 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Electron.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class ChangeRoommateRequest : AbstractElectronPacket + { + public ChangeRoommateType Type; + public uint AvatarId; + public uint LotLocation; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + AvatarId = input.GetUInt32(); + LotLocation = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.ChangeRoommateRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutUInt32(AvatarId); + output.PutUInt32(LotLocation); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateResponse.cs new file mode 100755 index 0000000..387067f --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/ChangeRoommateResponse.cs @@ -0,0 +1,29 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Electron.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class ChangeRoommateResponse : AbstractElectronPacket + { + public ChangeRoommateResponseStatus Type; + public uint Extra; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + Extra = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.ChangeRoommateResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutUInt32(Extra); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/CreateASimResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/CreateASimResponse.cs new file mode 100755 index 0000000..de91a95 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/CreateASimResponse.cs @@ -0,0 +1,47 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class CreateASimResponse : AbstractElectronPacket + { + public CreateASimStatus Status { get; set; } + public CreateASimFailureReason Reason { get; set; } = CreateASimFailureReason.NONE; + public uint NewAvatarId { get; set; } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.CreateASimResponse; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Status = input.GetEnum(); + Reason = input.GetEnum(); + NewAvatarId = input.GetUInt32(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Status); + output.PutEnum(Reason); + output.PutUInt32(NewAvatarId); + } + } + + public enum CreateASimStatus + { + SUCCESS = 0x01, + FAILED = 0x02 + } + + public enum CreateASimFailureReason + { + NONE = 0x00, + NAME_TAKEN = 0x01, + NAME_VALIDATION_ERROR = 0x02, + DESC_VALIDATION_ERROR = 0x03, + BODY_VALIDATION_ERROR = 0x04, + HEAD_VALIDATION_ERROR = 0x05 + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FSOVMCommand.cs b/server/FSO.Server.Protocol/Electron/Packets/FSOVMCommand.cs new file mode 100755 index 0000000..2b051f9 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FSOVMCommand.cs @@ -0,0 +1,28 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FSOVMCommand : AbstractElectronPacket + { + public byte[] Data; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable. + Data = new byte[dataLen]; + input.Get(Data, 0, dataLen); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FSOVMCommand; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutInt32(Data.Length); + output.Put(Data, 0, Data.Length); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FSOVMDirectToClient.cs b/server/FSO.Server.Protocol/Electron/Packets/FSOVMDirectToClient.cs new file mode 100755 index 0000000..f10861b --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FSOVMDirectToClient.cs @@ -0,0 +1,28 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FSOVMDirectToClient : AbstractElectronPacket + { + public byte[] Data; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable. + Data = new byte[dataLen]; + input.Get(Data, 0, dataLen); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FSOVMDirectToClient; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutInt32(Data.Length); + output.Put(Data, 0, Data.Length); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FSOVMProtocolMessage.cs b/server/FSO.Server.Protocol/Electron/Packets/FSOVMProtocolMessage.cs new file mode 100755 index 0000000..ca8ad13 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FSOVMProtocolMessage.cs @@ -0,0 +1,43 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FSOVMProtocolMessage : AbstractElectronPacket + { + public bool UseCst; + public string Title; + public string Message; + + public FSOVMProtocolMessage() + { + + } + + public FSOVMProtocolMessage(bool cst, string title, string body) + { + UseCst = cst; + Title = title; + Message = body; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + UseCst = input.GetBool(); + Title = input.GetPascalVLCString(); + Message = input.GetPascalVLCString(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FSOVMProtocolMessage; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutBool(UseCst); + output.PutPascalVLCString(Title); + output.PutPascalVLCString(Message); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FSOVMTickBroadcast.cs b/server/FSO.Server.Protocol/Electron/Packets/FSOVMTickBroadcast.cs new file mode 100755 index 0000000..bdab5da --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FSOVMTickBroadcast.cs @@ -0,0 +1,28 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FSOVMTickBroadcast : AbstractElectronPacket + { + public byte[] Data; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + var dataLen = input.GetInt32(); //TODO: limits? 4MB is probably reasonable. + Data = new byte[dataLen]; + input.Get(Data, 0, dataLen); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FSOVMTickBroadcast; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutInt32(Data.Length); + output.Put(Data, 0, Data.Length); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FindAvatarRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/FindAvatarRequest.cs new file mode 100755 index 0000000..9981f03 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FindAvatarRequest.cs @@ -0,0 +1,25 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FindAvatarRequest : AbstractElectronPacket + { + public uint AvatarId; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + AvatarId = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FindAvatarRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(AvatarId); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FindAvatarResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/FindAvatarResponse.cs new file mode 100755 index 0000000..47ba79c --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FindAvatarResponse.cs @@ -0,0 +1,32 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Electron.Model; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FindAvatarResponse : AbstractElectronPacket + { + public uint AvatarId; + public FindAvatarResponseStatus Status; + public uint LotId; //0 if status is not FOUND. + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + AvatarId = input.GetUInt32(); + Status = input.GetEnum(); + LotId = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FindAvatarResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(AvatarId); + output.PutEnum(Status); + output.PutUInt32(LotId); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FindLotRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/FindLotRequest.cs new file mode 100755 index 0000000..50aedc9 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FindLotRequest.cs @@ -0,0 +1,28 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FindLotRequest : AbstractElectronPacket + { + public uint LotId; + public bool OpenIfClosed; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + LotId = input.GetUInt32(); + OpenIfClosed = input.GetBool(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FindLotRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(LotId); + output.PutBool(OpenIfClosed); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/FindLotResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/FindLotResponse.cs new file mode 100755 index 0000000..badb221 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/FindLotResponse.cs @@ -0,0 +1,38 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Electron.Model; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class FindLotResponse : AbstractElectronPacket + { + public FindLotResponseStatus Status; + public uint LotId; + public string LotServerTicket; + public string Address; + public string User; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Status = input.GetEnum(); + LotId = input.GetUInt32(); + LotServerTicket = input.GetPascalVLCString(); + Address = input.GetPascalVLCString(); + User = input.GetPascalVLCString(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.FindLotResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Status); + output.PutUInt32(LotId); + output.PutPascalVLCString(LotServerTicket); + output.PutPascalVLCString(Address); + output.PutPascalVLCString(User); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/GlobalTuningUpdate.cs b/server/FSO.Server.Protocol/Electron/Packets/GlobalTuningUpdate.cs new file mode 100755 index 0000000..490442d --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/GlobalTuningUpdate.cs @@ -0,0 +1,54 @@ +using FSO.Common.Model; +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using System; +using System.IO; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class GlobalTuningUpdate : AbstractElectronPacket + { + public DynamicTuning Tuning; + public byte[] ObjectUpgrades; + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + + var dataLen = input.GetInt32(); + if (dataLen > 4000000 || dataLen > input.Remaining) throw new Exception("Tuning too long"); + var data = new byte[dataLen]; + input.Get(data, 0, dataLen); + using (var mem = new MemoryStream(data)) + { + using (var reader = new BinaryReader(mem)) + { + Tuning = new DynamicTuning(reader); + } + } + var upgLen = input.GetInt32(); + if (upgLen > 10000000 || upgLen > input.Remaining) throw new Exception("Upgrades too long"); + ObjectUpgrades = new byte[upgLen]; + input.Get(ObjectUpgrades, 0, upgLen); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.GlobalTuningUpdate; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + using (var mem = new MemoryStream()) + { + using (var writer = new BinaryWriter(mem)) + { + Tuning.SerializeInto(writer); + var result = mem.ToArray(); + output.PutInt32(result.Length); + output.Put(result, 0, result.Length); + } + } + output.PutInt32(ObjectUpgrades.Length); + output.Put(ObjectUpgrades, 0, ObjectUpgrades.Length); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/InstantMessage.cs b/server/FSO.Server.Protocol/Electron/Packets/InstantMessage.cs new file mode 100755 index 0000000..9b5fe8c --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/InstantMessage.cs @@ -0,0 +1,63 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Common.Enum; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class InstantMessage : AbstractElectronPacket + { + public UserReferenceType FromType; + public uint From; + public uint To; + public InstantMessageType Type; + public string Message; + public string AckID; + public InstantMessageFailureReason Reason = InstantMessageFailureReason.NONE; + public uint Color; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + FromType = input.GetEnum(); + From = input.GetUInt32(); + To = input.GetUInt32(); + Type = input.GetEnum(); + Message = input.GetPascalVLCString(); + AckID = input.GetPascalVLCString(); + Reason = input.GetEnum(); + Color = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.InstantMessage; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(FromType); + output.PutUInt32(From); + output.PutUInt32(To); + output.PutEnum(Type); + output.PutPascalVLCString(Message); + output.PutPascalVLCString(AckID); + output.PutEnum(Reason); + output.PutUInt32(Color); + } + } + + public enum InstantMessageType + { + MESSAGE, + SUCCESS_ACK, + FAILURE_ACK + } + + public enum InstantMessageFailureReason + { + NONE, + THEY_ARE_OFFLINE, + THEY_ARE_IGNORING_YOU, + YOU_ARE_IGNORING_THEM, + MESSAGE_QUEUE_FULL + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/KeepAlive.cs b/server/FSO.Server.Protocol/Electron/Packets/KeepAlive.cs new file mode 100755 index 0000000..cb8fce0 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/KeepAlive.cs @@ -0,0 +1,23 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class KeepAlive : AbstractElectronPacket + { + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.KeepAlive; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/MailRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/MailRequest.cs new file mode 100755 index 0000000..35faa94 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/MailRequest.cs @@ -0,0 +1,70 @@ +using FSO.Common.Serialization; +using FSO.Files.Formats.tsodata; +using Mina.Core.Buffer; +using System.IO; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class MailRequest : AbstractElectronPacket + { + public MailRequestType Type; + public long TimestampID; + public MessageItem Item; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + if (Type == MailRequestType.SEND) { + var length = input.GetInt32(); + var dat = new byte[length]; + for (int i=0; i(); + var numMessages = input.GetInt32(); + Messages = new MessageItem[numMessages]; + for (int j = 0; j < numMessages; j++) + { + var length = input.GetInt32(); + var dat = new byte[length]; + for (int i = 0; i < length; i++) + { + dat[i] = input.Get(); + } + + using (var str = new MemoryStream(dat)) + { + Messages[j] = new MessageItem(str); + } + } + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.MailResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutInt32(Messages.Length); + foreach (var msg in Messages) + { + byte[] dat; + using (var str = new MemoryStream()) + { + msg.Save(str); + dat = str.ToArray(); + } + output.PutInt32(dat.Length); + foreach (var b in dat) + output.Put(b); + } + } + } + + public enum MailResponseType + { + POLL_RESPONSE, + NEW_MAIL, + SEND_IGNORING_YOU, + SEND_IGNORING_THEM, + SEND_THROTTLED, + SEND_THROTTLED_DAILY, + SEND_FAILED, + SEND_SUCCESS //returns the message you sent, with its db id + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/ModerationRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/ModerationRequest.cs new file mode 100755 index 0000000..6a49e13 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/ModerationRequest.cs @@ -0,0 +1,29 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Electron.Model; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class ModerationRequest : AbstractElectronPacket + { + public ModerationRequestType Type; + public uint EntityId; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + EntityId = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.ModerationRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutUInt32(EntityId); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/NhoodCandidateList.cs b/server/FSO.Server.Protocol/Electron/Packets/NhoodCandidateList.cs new file mode 100755 index 0000000..a51e01b --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/NhoodCandidateList.cs @@ -0,0 +1,76 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using System.Collections.Generic; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class NhoodCandidateList : AbstractElectronPacket + { + public bool NominationMode; + public List Candidates; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + NominationMode = input.GetBool(); + int candCount = input.GetInt32(); + + Candidates = new List(); + for (int i=0; i Type; + public bool NeedsValidation => + Type == NhoodRequestType.CAN_NOMINATE || Type == NhoodRequestType.CAN_RATE + || Type == NhoodRequestType.CAN_RUN || Type == NhoodRequestType.CAN_VOTE || Type == NhoodRequestType.CAN_FREE_VOTE; + + public string Message = ""; //bulletin, rate + public uint Value; //rate (stars), nomination_run (accept if >0) + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + TargetAvatar = input.GetUInt32(); + TargetNHood = input.GetUInt32(); + + Message = input.GetPascalString(); + Value = input.GetUInt32(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.NhoodRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutUInt32(TargetAvatar); + output.PutUInt32(TargetNHood); + + output.PutPascalString(Message); + output.PutUInt32(Value); + } + } + + public enum NhoodRequestType : byte + { + VOTE = 0, + CAN_VOTE, + NOMINATE, + CAN_NOMINATE, + + RATE, + CAN_RATE, + NOMINATION_RUN, + CAN_RUN, + + CAN_FREE_VOTE, + FREE_VOTE, + + //moderator commands + DELETE_RATE, + FORCE_MAYOR, + REMOVE_CANDIDATE, + ADD_CANDIDATE, + TEST_ELECTION, //nhood id, avatar id = state (over/nomination/election), value = end date in x days + PRETEND_DATE, //run the daily nhood task as if it's (value) date. (Epoch value) + NHOOD_GAMEPLAY_BAN + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/NhoodResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/NhoodResponse.cs new file mode 100755 index 0000000..2e10f1c --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/NhoodResponse.cs @@ -0,0 +1,81 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Electron.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class NhoodResponse : AbstractElectronPacket, IActionResponse + { + public NhoodResponseCode Code; + public uint BanEndDate; + public string Message = ""; + + public bool Success => Code == NhoodResponseCode.SUCCESS; + public object OCode => Code; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Code = input.GetEnum(); + BanEndDate = input.GetUInt32(); + Message = input.GetPascalVLCString(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.NhoodResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Code); + output.PutUInt32(BanEndDate); + output.PutPascalVLCString(Message); + } + } + + public enum NhoodResponseCode : byte + { + SUCCESS = 0x00, + + //nominate/vote + NOT_IN_NHOOD = 0x01, + ELECTION_OVER = 0x02, + CANDIDATE_NOT_IN_NHOOD = 0x03, + CANDIDATE_NOT_NOMINATED = 0x04, + ALREADY_VOTED = 0x05, + ALREADY_VOTED_SAME_IP = 0x06, + BAD_STATE = 0x07, + + //rate + NOT_YOUR_MAYOR = 0x08, + INVALID_RATING = 0x09, + CANT_RATE_AVATAR = 0x0A, + + //accept or decline a nomination + NOBODY_NOMINATED_YOU_IDIOT = 0x0B, + ALREADY_RUNNING = 0x0C, + BAD_COMMENT = 0x0D, + + //moderator actions + NOT_MODERATOR = 0x0E, + INVALID_AVATAR = 0x0F, + INVALID_NHOOD = 0x10, + + //shared + NHOOD_GAMEPLAY_BAN = 0x11, + CANDIDATE_MOVED_RECENTLY = 0x12, + YOU_MOVED_RECENTLY = 0x13, + CANDIDATE_NHOOD_GAMEPLAY_BAN = 0x14, + MISSING_ENTITY = 0x15, //missing someone + + //free vote + NHOOD_NO_ELECTION = 0x16, + ALREADY_ENROLLED_FOR_FREE_VOTE = 0x17, + FREE_VOTE_ALREADY_ELIGIBLE = 0x18, + FREE_VOTE_MOVE_DATE = 0x19, + FREE_VOTE_ELECTION_OVER = 0x1A, + + CANCEL = 0xFE, + UNKNOWN_ERROR = 0xFF + }; +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotRequest.cs b/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotRequest.cs new file mode 100755 index 0000000..7b000a4 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotRequest.cs @@ -0,0 +1,37 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class PurchaseLotRequest : AbstractElectronPacket + { + public ushort LotLocation_X; + public ushort LotLocation_Y; + public string Name; + public bool StartFresh; + public bool MayorMode; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + LotLocation_X = input.GetUInt16(); + LotLocation_Y = input.GetUInt16(); + Name = input.GetPascalString(); + StartFresh = input.GetBool(); + MayorMode = input.GetBool(); + } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.PurchaseLotRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt16(LotLocation_X); + output.PutUInt16(LotLocation_Y); + output.PutPascalString(Name); + output.PutBool(StartFresh); + output.PutBool(MayorMode); + } + } +} diff --git a/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotResponse.cs b/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotResponse.cs new file mode 100755 index 0000000..4dcb778 --- /dev/null +++ b/server/FSO.Server.Protocol/Electron/Packets/PurchaseLotResponse.cs @@ -0,0 +1,60 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Electron.Packets +{ + public class PurchaseLotResponse : AbstractElectronPacket + { + public PurchaseLotStatus Status { get; set; } + public PurchaseLotFailureReason Reason { get; set; } = PurchaseLotFailureReason.NONE; + public uint NewLotId { get; set; } + public int NewFunds { get; set; } + + public override ElectronPacketType GetPacketType() + { + return ElectronPacketType.PurchaseLotResponse; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Status = input.GetEnum(); + Reason = input.GetEnum(); + NewLotId = input.GetUInt32(); + NewFunds = input.GetInt32(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Status); + output.PutEnum(Reason); + output.PutUInt32(NewLotId); + output.PutInt32(NewFunds); + } + } + + public enum PurchaseLotStatus + { + SUCCESS = 0x01, + FAILED = 0x02 + } + + public enum PurchaseLotFailureReason + { + NONE = 0x00, + NAME_TAKEN = 0x01, + NAME_VALIDATION_ERROR = 0x02, + INSUFFICIENT_FUNDS = 0x03, + LOT_TAKEN = 0x04, + LOT_NOT_PURCHASABLE = 0x05, + IN_LOT_CANT_EVICT = 0x06, + NOT_OFFLINE_FOR_MOVE = 0x07, + LOCATION_TAKEN = 0x08, + NHOOD_RESERVED = 0x09, + + TH_NOT_MAYOR = 0x80, + TH_INCORRECT_NHOOD = 0x81, + + + UNKNOWN = 0xFF + } +} diff --git a/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj b/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj new file mode 100755 index 0000000..58fefe5 --- /dev/null +++ b/server/FSO.Server.Protocol/FSO.Server.Protocol.csproj @@ -0,0 +1,229 @@ + + + + + Debug + AnyCPU + {A08ADE32-27E2-44F4-BC52-11A16C56BAA8} + Library + Properties + FSO.Server.Protocol + FSO.Server.Protocol + v4.5 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + true + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Common.Logging.3.4.1\lib\net40\Common.Logging.dll + + + ..\packages\Common.Logging.Core.3.4.1\lib\net40\Common.Logging.Core.dll + + + ..\packages\Mina.2.0.11\lib\net40\Mina.NET.dll + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + ..\packages\NLog.4.5.7\lib\net45\NLog.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {39b61962-fe43-4b64-8e57-8f793737fffe} + FSO.Server.Common + + + {c42962a1-8796-4f47-9dcd-79ed5904d8ca} + FSO.Common + + + {18583453-a970-4ac5-83b1-2d6bfdf94c24} + FSO.Files + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Protocol/Gluon/AbstractElectronPacket.cs b/server/FSO.Server.Protocol/Gluon/AbstractElectronPacket.cs new file mode 100755 index 0000000..d6db4b6 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/AbstractElectronPacket.cs @@ -0,0 +1,36 @@ +using System; +using Mina.Core.Buffer; +using FSO.Common.Serialization; +using FSO.Server.Protocol.Gluon.Packets; + +namespace FSO.Server.Protocol.Gluon +{ + public abstract class AbstractGluonPacket : IGluonPacket + { + public static IoBuffer Allocate(int size) + { + IoBuffer buffer = IoBuffer.Allocate(size); + buffer.Order = ByteOrder.BigEndian; + return buffer; + } + + public abstract GluonPacketType GetPacketType(); + public abstract void Deserialize(IoBuffer input, ISerializationContext context); + public abstract void Serialize(IoBuffer output, ISerializationContext context); + } + + public abstract class AbstractGluonCallPacket : AbstractGluonPacket, IGluonCall + { + public Guid CallId { get; set; } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutPascalString(CallId.ToString()); + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + CallId = Guid.Parse(input.GetPascalString()); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/GluonPacketType.cs b/server/FSO.Server.Protocol/Gluon/GluonPacketType.cs new file mode 100755 index 0000000..5117454 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/GluonPacketType.cs @@ -0,0 +1,107 @@ +namespace FSO.Server.Protocol.Gluon +{ + public enum GluonPacketType + { + AdvertiseCapacity, + TransferClaim, + TransferClaimResponse, + RequestLotClientTermination, + ShardShutdownRequest, + ShardShutdownCompleteResponse, + + HealthPing, + HealthPingResponse, + RequestTask, + RequestTaskResponse, + + NotifyLotRoommateChange, + MatchmakerNotify, + CityNotify, + + TuningChanged, + CitySendMail, + + Unknown + } + + public static class GluonPacketTypeUtils + { + public static GluonPacketType FromPacketCode(ushort code) + { + switch (code) + { + case 0x0001: + return GluonPacketType.AdvertiseCapacity; + case 0x0002: + return GluonPacketType.TransferClaim; + case 0x0003: + return GluonPacketType.TransferClaimResponse; + case 0x0004: + return GluonPacketType.RequestLotClientTermination; + case 0x0005: + return GluonPacketType.ShardShutdownRequest; + case 0x0006: + return GluonPacketType.ShardShutdownCompleteResponse; + case 0x0007: + return GluonPacketType.HealthPing; + case 0x0008: + return GluonPacketType.HealthPingResponse; + case 0x0009: + return GluonPacketType.RequestTask; + case 0x0010: + return GluonPacketType.RequestTaskResponse; + case 0x0011: + return GluonPacketType.NotifyLotRoommateChange; + case 0x0012: + return GluonPacketType.MatchmakerNotify; + case 0x0013: + return GluonPacketType.CityNotify; + case 0x0014: + return GluonPacketType.TuningChanged; + case 0x0015: + return GluonPacketType.CitySendMail; + default: + return GluonPacketType.Unknown; + } + } + + public static ushort GetPacketCode(this GluonPacketType type) + { + switch (type) + { + case GluonPacketType.AdvertiseCapacity: + return 0x0001; + case GluonPacketType.TransferClaim: + return 0x0002; + case GluonPacketType.TransferClaimResponse: + return 0x0003; + case GluonPacketType.RequestLotClientTermination: + return 0x0004; + case GluonPacketType.ShardShutdownRequest: + return 0x0005; + case GluonPacketType.ShardShutdownCompleteResponse: + return 0x0006; + case GluonPacketType.HealthPing: + return 0x0007; + case GluonPacketType.HealthPingResponse: + return 0x0008; + case GluonPacketType.RequestTask: + return 0x0009; + case GluonPacketType.RequestTaskResponse: + return 0x0010; + case GluonPacketType.NotifyLotRoommateChange: + return 0x0011; + case GluonPacketType.MatchmakerNotify: + return 0x0012; + case GluonPacketType.CityNotify: + return 0x0013; + case GluonPacketType.TuningChanged: + return 0x0014; + case GluonPacketType.CitySendMail: + return 0x0015; + } + + return 0xFFFF; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/GluonPackets.cs b/server/FSO.Server.Protocol/Gluon/GluonPackets.cs new file mode 100755 index 0000000..c7a0c0b --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/GluonPackets.cs @@ -0,0 +1,50 @@ +using FSO.Server.Protocol.Gluon.Packets; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Protocol.Gluon +{ + public class GluonPackets + { + public static Dictionary GLUON_PACKET_BY_TYPEID; + public static Type[] ELECTRON_PACKETS = new Type[] { + typeof(AdvertiseCapacity), + typeof(TransferClaim), + typeof(TransferClaimResponse), + typeof(RequestLotClientTermination), + typeof(ShardShutdownRequest), + typeof(ShardShutdownCompleteResponse), + typeof(HealthPing), + typeof(HealthPingResponse), + typeof(RequestTask), + typeof(RequestTaskResponse), + typeof(NotifyLotRoommateChange), + typeof(MatchmakerNotify), + typeof(CityNotify), + typeof(TuningChanged), + typeof(SendCityMail) + }; + + static GluonPackets() + { + GLUON_PACKET_BY_TYPEID = new Dictionary(); + foreach (Type packetType in ELECTRON_PACKETS) + { + IGluonPacket packet = (IGluonPacket)Activator.CreateInstance(packetType); + GLUON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType); + } + } + + public static Type GetByPacketCode(ushort code) + { + if (GLUON_PACKET_BY_TYPEID.ContainsKey(code)) + { + return GLUON_PACKET_BY_TYPEID[code]; + } + else + { + return null; + } + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/IGluonPacket.cs b/server/FSO.Server.Protocol/Gluon/IGluonPacket.cs new file mode 100755 index 0000000..eb4f72b --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/IGluonPacket.cs @@ -0,0 +1,9 @@ +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Gluon +{ + public interface IGluonPacket : IoBufferDeserializable, IoBufferSerializable + { + GluonPacketType GetPacketType(); + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Model/ChangeType.cs b/server/FSO.Server.Protocol/Gluon/Model/ChangeType.cs new file mode 100755 index 0000000..ce1516e --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Model/ChangeType.cs @@ -0,0 +1,11 @@ +namespace FSO.Server.Protocol.Gluon.Model +{ + public enum ChangeType + { + REMOVE_ROOMMATE, + ADD_ROOMMATE, + BECOME_OWNER, + BECOME_OWNER_WITH_OBJECTS, + ROOMIE_INHERIT_OBJECTS_ONLY + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Model/ClaimAction.cs b/server/FSO.Server.Protocol/Gluon/Model/ClaimAction.cs new file mode 100755 index 0000000..3c39bc5 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Model/ClaimAction.cs @@ -0,0 +1,10 @@ +namespace FSO.Server.Protocol.Gluon.Model +{ + public enum ClaimAction + { + DEFAULT, + + LOT_HOST, + LOT_CLEANUP + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Model/ClaimType.cs b/server/FSO.Server.Protocol/Gluon/Model/ClaimType.cs new file mode 100755 index 0000000..f6404f3 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Model/ClaimType.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Gluon.Model +{ + public enum ClaimType + { + LOT, + AVATAR + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/AdvertiseCapacity.cs b/server/FSO.Server.Protocol/Gluon/Packets/AdvertiseCapacity.cs new file mode 100755 index 0000000..b9b45c8 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/AdvertiseCapacity.cs @@ -0,0 +1,37 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class AdvertiseCapacity : AbstractGluonPacket + { + public short MaxLots; + public short CurrentLots; + public byte CpuPercentAvg; + public long RamUsed; + public long RamAvaliable; + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.AdvertiseCapacity; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + MaxLots = input.GetInt16(); + CurrentLots = input.GetInt16(); + CpuPercentAvg = input.Get(); + RamUsed = input.GetInt64(); + RamAvaliable = input.GetInt64(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutInt16(MaxLots); + output.PutInt16(CurrentLots); + output.Put(CpuPercentAvg); + output.PutInt64(RamUsed); + output.PutInt64(RamAvaliable); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/CityNotify.cs b/server/FSO.Server.Protocol/Gluon/Packets/CityNotify.cs new file mode 100755 index 0000000..af6e1b1 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/CityNotify.cs @@ -0,0 +1,45 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +// Task -> City notifications. + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class CityNotify : AbstractGluonPacket + { + public CityNotifyType Mode; + public uint Value; + public string Message = ""; + + public CityNotify() { } + + public CityNotify(CityNotifyType mode) + { + Mode = mode; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Mode = input.GetEnum(); + Value = input.GetUInt32(); + Message = input.GetPascalVLCString(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.CityNotify; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Mode); + output.PutUInt32(Value); + output.PutPascalVLCString(Message); + } + } + + public enum CityNotifyType : byte + { + NhoodUpdate = 1 + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/HealthPing.cs b/server/FSO.Server.Protocol/Gluon/Packets/HealthPing.cs new file mode 100755 index 0000000..702c274 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/HealthPing.cs @@ -0,0 +1,23 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class HealthPing : AbstractGluonCallPacket + { + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.HealthPing; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/HealthPingResponse.cs b/server/FSO.Server.Protocol/Gluon/Packets/HealthPingResponse.cs new file mode 100755 index 0000000..ae87825 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/HealthPingResponse.cs @@ -0,0 +1,27 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class HealthPingResponse : AbstractGluonCallPacket + { + public string PoolHash { get; set; } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + PoolHash = input.GetPascalString(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + output.PutPascalString(PoolHash); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.HealthPingResponse; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/IGluonCall.cs b/server/FSO.Server.Protocol/Gluon/Packets/IGluonCall.cs new file mode 100755 index 0000000..09ef619 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/IGluonCall.cs @@ -0,0 +1,9 @@ +using System; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public interface IGluonCall + { + Guid CallId { get; set; } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/MatchmakerNotify.cs b/server/FSO.Server.Protocol/Gluon/Packets/MatchmakerNotify.cs new file mode 100755 index 0000000..60b2563 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/MatchmakerNotify.cs @@ -0,0 +1,40 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + /// + /// Lot -> City server messages used to notify the matchmaker about some change to lot state. + /// (currently only when an avatar leaves a lot. this frees up a space for the matchmaker to shove someone else in) + /// + public class MatchmakerNotify : AbstractGluonPacket + { + public MatchmakerNotifyType Mode; + public uint LotID; + public uint AvatarID; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Mode = input.GetEnum(); + LotID = input.GetUInt32(); + AvatarID = input.GetUInt32(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.MatchmakerNotify; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Mode); + output.PutUInt32(LotID); + output.PutUInt32(AvatarID); + } + } + + public enum MatchmakerNotifyType : byte + { + RemoveAvatar = 1 + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/NotifyLotRoommateChange.cs b/server/FSO.Server.Protocol/Gluon/Packets/NotifyLotRoommateChange.cs new file mode 100755 index 0000000..5628120 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/NotifyLotRoommateChange.cs @@ -0,0 +1,39 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Gluon.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + /// + /// A signal sent from the city server to notify a lot that an avatar's roommate status on that lot has changed. + /// May wish to change this to be more generic for further avatar related changes in future. + /// + public class NotifyLotRoommateChange : AbstractGluonPacket + { + public uint AvatarId; + public uint ReplaceId; + public int LotId; + public ChangeType Change; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + AvatarId = input.GetUInt32(); + ReplaceId = input.GetUInt32(); + LotId = input.GetInt32(); + Change = input.GetEnum(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.NotifyLotRoommateChange; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(AvatarId); + output.PutUInt32(ReplaceId); + output.PutInt32(LotId); + output.PutEnum(Change); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/RequestLotClientTermination.cs b/server/FSO.Server.Protocol/Gluon/Packets/RequestLotClientTermination.cs new file mode 100755 index 0000000..703ff07 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/RequestLotClientTermination.cs @@ -0,0 +1,31 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class RequestLotClientTermination : AbstractGluonPacket + { + public uint AvatarId; + public int LotId; + public string FromOwner; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + AvatarId = input.GetUInt32(); + LotId = input.GetInt32(); + FromOwner = input.GetPascalString(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.RequestLotClientTermination; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(AvatarId); + output.PutInt32(LotId); + output.PutPascalString(FromOwner); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/RequestTask.cs b/server/FSO.Server.Protocol/Gluon/Packets/RequestTask.cs new file mode 100755 index 0000000..4e381b9 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/RequestTask.cs @@ -0,0 +1,34 @@ +using System.Text; +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class RequestTask : AbstractGluonCallPacket + { + public string TaskType { get; set; } + public string ParameterJson { get; set; } + public int ShardId { get; set; } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + TaskType = input.GetPascalString(); + ShardId = input.GetInt32(); + ParameterJson = input.GetString(Encoding.UTF8); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + output.PutPascalString(TaskType); + output.PutInt32(ShardId); + output.PutString(ParameterJson, Encoding.UTF8); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.RequestTask; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/RequestTaskResponse.cs b/server/FSO.Server.Protocol/Gluon/Packets/RequestTaskResponse.cs new file mode 100755 index 0000000..2f32ce8 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/RequestTaskResponse.cs @@ -0,0 +1,27 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class RequestTaskResponse : AbstractGluonCallPacket + { + public int TaskId; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + TaskId = input.GetInt32(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + output.PutInt32(TaskId); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.RequestTaskResponse; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/SendCityMail.cs b/server/FSO.Server.Protocol/Gluon/Packets/SendCityMail.cs new file mode 100755 index 0000000..0ea0cb0 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/SendCityMail.cs @@ -0,0 +1,58 @@ +using FSO.Common.Serialization; +using FSO.Files.Formats.tsodata; +using Mina.Core.Buffer; +using System.Collections.Generic; +using System.IO; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class SendCityMail : AbstractGluonCallPacket + { + public List Items { get; set; } + + public SendCityMail() { } + + public SendCityMail(List items) { + Items = items; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + var itemCount = input.GetInt32(); + var dataSize = input.GetInt32(); + var data = input.GetSlice(dataSize).GetBytes(); + using (var mem = new MemoryStream(data)) { + Items = new List(); + for (int i = 0; i < itemCount; i++) + { + var message = new MessageItem(); + message.Read(mem); + Items.Add(message); + } + } + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + byte[] data = null; + using (var mem = new MemoryStream()) + { + foreach (var item in Items) + { + item.Save(mem); + } + data = mem.ToArray(); + } + output.PutInt32(Items.Count); + output.PutInt32(data.Length); + output.Put(data); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.CitySendMail; + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownCompleteResponse.cs b/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownCompleteResponse.cs new file mode 100755 index 0000000..bce02d0 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownCompleteResponse.cs @@ -0,0 +1,25 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class ShardShutdownCompleteResponse : AbstractGluonPacket + { + public uint ShardId; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + ShardId = input.GetUInt32(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.ShardShutdownCompleteResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(ShardId); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownRequest.cs b/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownRequest.cs new file mode 100755 index 0000000..93cdf48 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/ShardShutdownRequest.cs @@ -0,0 +1,29 @@ +using FSO.Common.Serialization; +using FSO.Server.Common; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class ShardShutdownRequest : AbstractGluonPacket + { + public uint ShardId; + public ShutdownType Type; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + ShardId = input.GetUInt32(); + Type = input.GetEnum(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.ShardShutdownRequest; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(ShardId); + output.PutEnum(Type); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/TransferClaim.cs b/server/FSO.Server.Protocol/Gluon/Packets/TransferClaim.cs new file mode 100755 index 0000000..f4537e5 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/TransferClaim.cs @@ -0,0 +1,41 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Gluon.Model; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class TransferClaim : AbstractGluonPacket + { + public ClaimType Type; + public ClaimAction Action; + public int EntityId; + public uint ClaimId; + public uint SpecialId; //job lot info + public string FromOwner; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Type = input.GetEnum(); + Action = input.GetEnum(); + EntityId = input.GetInt32(); + ClaimId = input.GetUInt32(); + SpecialId = input.GetUInt32(); + FromOwner = input.GetPascalString(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.TransferClaim; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Type); + output.PutEnum(Action); + output.PutInt32(EntityId); + output.PutUInt32(ClaimId); + output.PutUInt32(SpecialId); + output.PutPascalString(FromOwner); + } + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/TransferClaimResponse.cs b/server/FSO.Server.Protocol/Gluon/Packets/TransferClaimResponse.cs new file mode 100755 index 0000000..8f19fa5 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/TransferClaimResponse.cs @@ -0,0 +1,45 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Gluon.Model; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class TransferClaimResponse : AbstractGluonPacket + { + public TransferClaimResponseStatus Status; + public ClaimType Type; + public int EntityId; + public uint ClaimId; + public string NewOwner; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Status = input.GetEnum(); + Type = input.GetEnum(); + EntityId = input.GetInt32(); + ClaimId = input.GetUInt32(); + NewOwner = input.GetPascalString(); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.TransferClaimResponse; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutEnum(Status); + output.PutEnum(Type); + output.PutInt32(EntityId); + output.PutUInt32(ClaimId); + output.PutPascalString(NewOwner); + } + } + + public enum TransferClaimResponseStatus + { + ACCEPTED, + REJECTED, + CLAIM_NOT_FOUND + } +} diff --git a/server/FSO.Server.Protocol/Gluon/Packets/TuningChanged.cs b/server/FSO.Server.Protocol/Gluon/Packets/TuningChanged.cs new file mode 100755 index 0000000..a9e41e4 --- /dev/null +++ b/server/FSO.Server.Protocol/Gluon/Packets/TuningChanged.cs @@ -0,0 +1,27 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Gluon.Packets +{ + public class TuningChanged : AbstractGluonCallPacket + { + public bool UpdateInstantly; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + base.Deserialize(input, context); + UpdateInstantly = input.GetBool(); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + base.Serialize(output, context); + output.PutBool(UpdateInstantly); + } + + public override GluonPacketType GetPacketType() + { + return GluonPacketType.TuningChanged; + } + } +} diff --git a/server/FSO.Server.Protocol/Properties/AssemblyInfo.cs b/server/FSO.Server.Protocol/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..421cbaf --- /dev/null +++ b/server/FSO.Server.Protocol/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("FSO.Server.Protocol")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("FSO.Server.Protocol")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a08ade32-27e2-44f4-bc52-11a16c56baa8")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/FSO.Server.Protocol/Utils/ChallengeResponse.cs b/server/FSO.Server.Protocol/Utils/ChallengeResponse.cs new file mode 100755 index 0000000..0e45940 --- /dev/null +++ b/server/FSO.Server.Protocol/Utils/ChallengeResponse.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.Security.Cryptography; +using System.Text; + +namespace FSO.Server.Protocol.Utils +{ + public class ChallengeResponse + { + private static int _salt_byte_length = 320; + private static int _nonce_byte_length = 32; + private static RNGCryptoServiceProvider _random_crypt_prov = new RNGCryptoServiceProvider(); + private static Random _random_gen = new Random(); + private static int _min_iteration_count = 4000; + private static int _max_iteration_count = 5000; + private const int _sha_output_length = 20; + + private static byte[] ComputeHMACHash(byte[] data, string secret) + { + using (var _hmac_sha_1 = new HMACSHA1(data, true)) + { + byte[] _hash_bytes = _hmac_sha_1.ComputeHash(Encoding.UTF8.GetBytes(secret)); + return _hash_bytes; + } + } + + public static string AnswerChallenge(string challenge, string secret) + { + var components = new Dictionary(); + var parts = challenge.Split(','); + foreach(var part in parts){ + var subParts = part.Split(new char[] { '=' }, 2); + components.Add(subParts[0], subParts[1]); + } + + var iterations = int.Parse(components["i"]); + var salt = components["s"]; + var salted = Hi(secret, Convert.FromBase64String(salt), iterations); + + return Convert.ToBase64String(ComputeHMACHash(salted, secret)); + } + + public static string GetChallenge() + { + var numIterations = GetRandomInteger(); + return "i=" + numIterations + ",s=" + Convert.ToBase64String(GetRandomByteArray(_nonce_byte_length)); + } + + private static byte[] Hi(string password, byte[] salt, int iteration_count) + { + Rfc2898DeriveBytes _pdb = new Rfc2898DeriveBytes(password, salt, iteration_count); + return _pdb.GetBytes(_sha_output_length); + } + + private static int GetRandomInteger() + { + if (_random_gen == null) + _random_gen = new Random(); + + int _random_int = _random_gen.Next(_min_iteration_count, _max_iteration_count); + + if (_random_int < 0) + _random_int *= -1; + + return _random_int; + } + + private static byte[] GetRandomByteArray(int byte_array_length) + { + byte[] _random_byte_array = new byte[byte_array_length]; + + _random_crypt_prov.GetBytes(_random_byte_array); + + return _random_byte_array; + } + } +} diff --git a/server/FSO.Server.Protocol/Utils/CustomCumulativeProtocolDecoder.cs b/server/FSO.Server.Protocol/Utils/CustomCumulativeProtocolDecoder.cs new file mode 100755 index 0000000..109f20e --- /dev/null +++ b/server/FSO.Server.Protocol/Utils/CustomCumulativeProtocolDecoder.cs @@ -0,0 +1,160 @@ +using System; +using Mina.Core.Buffer; +using Mina.Core.Session; +using Mina.Filter.Codec; + +namespace FSO.Server.Protocol.Utils +{ + /// + /// A that cumulates the content of received buffers to a + /// cumulative buffer to help users implement decoders. + /// + public abstract class CustomCumulativeProtocolDecoder : ProtocolDecoderAdapter + { + private readonly AttributeKey BUFFER = new AttributeKey(typeof(CustomCumulativeProtocolDecoder), "buffer"); + + /// + /// + protected CustomCumulativeProtocolDecoder() + { } + + /// + public override void Decode(IoSession session, IoBuffer input, IProtocolDecoderOutput output) + { + if (!session.TransportMetadata.HasFragmentation) + { + while (input.HasRemaining) + { + if (!DoDecode(session, input, output)) + break; + } + + return; + } + + Boolean usingSessionBuffer = true; + IoBuffer buf = session.GetAttribute(BUFFER); + + // If we have a session buffer, append data to that; otherwise + // use the buffer read from the network directly. + if (buf == null) + { + buf = input; + usingSessionBuffer = false; + } + else + { + Boolean appended = false; + // Make sure that the buffer is auto-expanded. + if (buf.AutoExpand) + { + try + { + buf.Put(input); + appended = true; + } + catch (InvalidOperationException) + { + // A user called derivation method (e.g. slice()), + // which disables auto-expansion of the parent buffer. + } + catch (OverflowException) + { + // A user disabled auto-expansion. + } + } + + if (appended) + { + buf.Flip(); + } + else + { + // Reallocate the buffer if append operation failed due to + // derivation or disabled auto-expansion. + buf.Flip(); + + IoBuffer newBuf = IoBuffer.Allocate(buf.Remaining + input.Remaining); + newBuf.AutoExpand = true; + newBuf.Order = buf.Order; + newBuf.Put(buf); + newBuf.Put(input); + newBuf.Flip(); + buf = newBuf; + + // Update the session attribute. + session.SetAttribute(BUFFER, buf); + } + } + + while (true) + { + Int32 oldPos = buf.Position; + Boolean decoded = DoDecode(session, buf, output); + if (decoded) + { + if (buf.Position == oldPos) + throw new InvalidOperationException("DoDecode() can't return true when buffer is not consumed."); + if (!buf.HasRemaining) + break; + } + else + { + break; + } + } + + // if there is any data left that cannot be decoded, we store + // it in a buffer in the session and next time this decoder is + // invoked the session buffer gets appended to + if (buf.HasRemaining) + { + if (usingSessionBuffer && buf.AutoExpand) + { + buf.Compact(); + } + else + { + StoreRemainingInSession(buf, session); + } + } + else + { + if (usingSessionBuffer) + { + RemoveSessionBuffer(session); + } + } + } + + /// + /// Implement this method to consume the specified cumulative buffer and decode its content into message(s). + /// + /// + /// + /// + /// + /// true if and only if there's more to decode in the buffer + /// and you want to have DoDecode method invoked again. + /// Return false if remaining data is not enough to decode, + /// then this method will be invoked again when more data is cumulated. + /// + protected abstract Boolean DoDecode(IoSession session, IoBuffer input, IProtocolDecoderOutput output); + + private void RemoveSessionBuffer(IoSession session) + { + session.RemoveAttribute(BUFFER); + } + + private void StoreRemainingInSession(IoBuffer buf, IoSession session) + { + IoBuffer remainingBuf = IoBuffer.Allocate(buf.Capacity); + remainingBuf.AutoExpand = true; + + remainingBuf.Order = buf.Order; + remainingBuf.Put(buf); + + session.SetAttribute(BUFFER, remainingBuf); + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Protocol/Utils/SslClientFilter.cs b/server/FSO.Server.Protocol/Utils/SslClientFilter.cs new file mode 100755 index 0000000..aabe2be --- /dev/null +++ b/server/FSO.Server.Protocol/Utils/SslClientFilter.cs @@ -0,0 +1,618 @@ +using System; +using System.Collections.Concurrent; +using System.IO; +using System.Net.Security; +using System.Security.Authentication; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using Common.Logging; +using Mina.Core.Buffer; +using Mina.Core.Filterchain; +using Mina.Core.Future; +using Mina.Core.Session; +using Mina.Core.Write; + +namespace FSO.Server.Protocol.Utils +{ + public class CustomSslFilter : IoFilterAdapter + { + static readonly ILog log = LogManager.GetLogger(typeof(CustomSslFilter)); + + private static readonly AttributeKey NEXT_FILTER = new AttributeKey(typeof(CustomSslFilter), "nextFilter"); + private static readonly AttributeKey SSL_HANDLER = new AttributeKey(typeof(CustomSslFilter), "handler"); + + X509Certificate _serverCertificate = null; + SslProtocols _sslProtocol = SslProtocols.Default; + + public CustomSslFilter(String certFile) + : this(X509Certificate.CreateFromCertFile(certFile)) + { } + + public CustomSslFilter(X509Certificate cert) + { + _serverCertificate = cert; + } + + public SslProtocols SslProtocol + { + get { return _sslProtocol; } + set { _sslProtocol = value; } + } + + public X509Certificate Certificate + { + get { return _serverCertificate; } + } + + /// + /// Returns true if and only if the specified session is + /// encrypted/decrypted over SSL/TLS currently. + /// + public Boolean IsSslStarted(IoSession session) + { + SslHandler handler = session.GetAttribute(SSL_HANDLER); + return handler != null && handler.Authenticated; + } + + /// + public override void OnPreAdd(IoFilterChain parent, String name, INextFilter nextFilter) + { + if (parent.Contains()) + throw new InvalidOperationException("Only one SSL filter is permitted in a chain."); + + IoSession session = parent.Session; + session.SetAttribute(NEXT_FILTER, nextFilter); + // Create a SSL handler and start handshake. + SslHandler handler = new SslHandler(this, session); + session.SetAttribute(SSL_HANDLER, handler); + } + + /// + public override void OnPostAdd(IoFilterChain parent, String name, INextFilter nextFilter) + { + SslHandler handler = GetSslSessionHandler(parent.Session); + handler.Handshake(nextFilter); + } + + /// + public override void OnPreRemove(IoFilterChain parent, String name, INextFilter nextFilter) + { + IoSession session = parent.Session; + session.RemoveAttribute(NEXT_FILTER); + session.RemoveAttribute(SSL_HANDLER); + } + + /// + public override void SessionClosed(INextFilter nextFilter, IoSession session) + { + SslHandler handler = GetSslSessionHandler(session); + try + { + // release resources + handler.Destroy(); + } + finally + { + // notify closed session + base.SessionClosed(nextFilter, session); + } + } + + /// + public override void MessageReceived(INextFilter nextFilter, IoSession session, Object message) + { + IoBuffer buf = (IoBuffer)message; + SslHandler handler = GetSslSessionHandler(session); + // forward read encrypted data to SSL handler + handler.MessageReceived(nextFilter, buf); + } + + /// + public override void MessageSent(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest) + { + EncryptedWriteRequest encryptedWriteRequest = writeRequest as EncryptedWriteRequest; + if (encryptedWriteRequest == null) + { + // ignore extra buffers used for handshaking + } + else + { + base.MessageSent(nextFilter, session, encryptedWriteRequest.InnerRequest); + } + } + + /// + public override void ExceptionCaught(INextFilter nextFilter, IoSession session, Exception cause) + { + base.ExceptionCaught(nextFilter, session, cause); + } + + /// + public override void FilterWrite(INextFilter nextFilter, IoSession session, IWriteRequest writeRequest) + { + SslHandler handler = GetSslSessionHandler(session); + handler.ScheduleFilterWrite(nextFilter, writeRequest); + } + + /// + public override void FilterClose(INextFilter nextFilter, IoSession session) + { + SslHandler handler = session.GetAttribute(SSL_HANDLER); + if (handler == null) + { + // The connection might already have closed, or + // SSL might have not started yet. + base.FilterClose(nextFilter, session); + return; + } + + IWriteFuture future = null; + try + { + future = InitiateClosure(handler, nextFilter, session); + future.Complete += (s, e) => base.FilterClose(nextFilter, session); + } + finally + { + if (future == null) + base.FilterClose(nextFilter, session); + } + } + + private IWriteFuture InitiateClosure(SslHandler handler, INextFilter nextFilter, IoSession session) + { + IWriteFuture future = DefaultWriteFuture.NewWrittenFuture(session); + handler.Destroy(); + return future; + } + + private SslHandler GetSslSessionHandler(IoSession session) + { + SslHandler handler = session.GetAttribute(SSL_HANDLER); + + if (handler == null) + throw new InvalidOperationException(); + + if (handler.SslFilter != this) + throw new ArgumentException("Not managed by this filter."); + + return handler; + } + + public static void DisplaySecurityLevel(SslStream stream) + { + log.DebugFormat("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength); + log.DebugFormat("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength); + log.DebugFormat("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength); + log.DebugFormat("Protocol: {0}", stream.SslProtocol); + } + + public static void DisplaySecurityServices(SslStream stream) + { + log.DebugFormat("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer); + log.DebugFormat("IsSigned: {0}", stream.IsSigned); + log.DebugFormat("Is Encrypted: {0}", stream.IsEncrypted); + } + + public static void DisplayStreamProperties(SslStream stream) + { + log.DebugFormat("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite); + log.DebugFormat("Can timeout: {0}", stream.CanTimeout); + } + + public static void DisplayCertificateInformation(SslStream stream) + { + log.DebugFormat("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus); + + X509Certificate localCertificate = stream.LocalCertificate; + if (stream.LocalCertificate != null) + { + log.DebugFormat("Local cert was issued to {0} and is valid from {1} until {2}.", + localCertificate.Subject, + localCertificate.GetEffectiveDateString(), + localCertificate.GetExpirationDateString()); + } + else + { + log.DebugFormat("Local certificate is null."); + } + // Display the properties of the client's certificate. + X509Certificate remoteCertificate = stream.RemoteCertificate; + if (stream.RemoteCertificate != null) + { + log.DebugFormat("Remote cert was issued to {0} and is valid from {1} until {2}.", + remoteCertificate.Subject, + remoteCertificate.GetEffectiveDateString(), + remoteCertificate.GetExpirationDateString()); + } + else + { + log.DebugFormat("Remote certificate is null."); + } + } + + internal class EncryptedWriteRequest : WriteRequestWrapper + { + private readonly IoBuffer _encryptedMessage; + + public EncryptedWriteRequest(IWriteRequest writeRequest, IoBuffer encryptedMessage) + : base(writeRequest) + { + _encryptedMessage = encryptedMessage; + } + + public override Object Message + { + get { return _encryptedMessage; } + } + } + } + + class SslHandler : IDisposable + { + static readonly ILog log = LogManager.GetLogger(typeof(CustomSslFilter)); + + private readonly CustomSslFilter _sslFilter; + private readonly IoSession _session; + private readonly IoSessionStream _sessionStream; + private readonly SslStream _sslStream; + private volatile Boolean _authenticated; + private readonly ConcurrentQueue _preHandshakeEventQueue = new ConcurrentQueue(); + private INextFilter _currentNextFilter; + private IWriteRequest _currentWriteRequest; + + public SslHandler(CustomSslFilter sslFilter, IoSession session) + { + _sslFilter = sslFilter; + _session = session; + _sessionStream = new IoSessionStream(this); + _sslStream = new SslStream(_sessionStream, false); + } + + public CustomSslFilter SslFilter + { + get { return _sslFilter; } + } + + public Boolean Authenticated + { + get { return _authenticated; } + private set + { + _authenticated = value; + if (value) + FlushPreHandshakeEvents(); + } + } + + public void Dispose() + { + _sessionStream.Dispose(); + _sslStream.Dispose(); + } + + public void Handshake(INextFilter nextFilter) + { + //lock (_sessionStream) + //{ + _currentNextFilter = nextFilter; + _sslStream.BeginAuthenticateAsClient("auth.east.ea.com", null, _sslFilter.SslProtocol, false, AuthenticateCallback, null); + //} + } + + private void AuthenticateCallback(IAsyncResult ar) + { + try + { + _sslStream.EndAuthenticateAsClient(ar); + } + catch (AuthenticationException e) + { + _sslFilter.ExceptionCaught(_currentNextFilter, _session, e); + return; + } + catch (IOException e) + { + _sslFilter.ExceptionCaught(_currentNextFilter, _session, e); + return; + } + + Authenticated = true; + + if (log.IsDebugEnabled) + { + // Display the properties and settings for the authenticated stream. + CustomSslFilter.DisplaySecurityLevel(_sslStream); + CustomSslFilter.DisplaySecurityServices(_sslStream); + CustomSslFilter.DisplayCertificateInformation(_sslStream); + CustomSslFilter.DisplayStreamProperties(_sslStream); + } + } + + public void ScheduleFilterWrite(INextFilter nextFilter, IWriteRequest writeRequest) + { + + if (!_authenticated) + { + if (_session.Connected) + { + // Handshake not complete yet. + _preHandshakeEventQueue.Enqueue(new IoFilterEvent(nextFilter, IoEventType.Write, _session, writeRequest)); + } + return; + } + + IoBuffer buf = (IoBuffer)writeRequest.Message; + if (buf.Remaining == 0) { return; } + + //lock (_sessionStream) + //{ + ArraySegment array = buf.GetRemaining(); + _currentNextFilter = nextFilter; + _currentWriteRequest = writeRequest; + // SSL encrypt + _sslStream.Write(array.Array, array.Offset, array.Count); + _sslStream.Flush(); + //} + } + + public void MessageReceived(INextFilter nextFilter, IoBuffer buf) + { + //lock (_sessionStream) + //{ + _currentNextFilter = nextFilter; + _sessionStream.Write(buf); + if (_authenticated) + { + IoBuffer readBuffer = ReadBuffer(); + nextFilter.MessageReceived(_session, readBuffer); + } + //} + } + + public void Destroy() + { + _sslStream.Close(); + IoFilterEvent scheduledWrite; + while (_preHandshakeEventQueue.TryDequeue(out scheduledWrite)) + { } + } + + private void FlushPreHandshakeEvents() + { + lock (_sessionStream) + { + IoFilterEvent scheduledWrite; + while (_preHandshakeEventQueue.TryDequeue(out scheduledWrite)) + { + _sslFilter.FilterWrite(scheduledWrite.NextFilter, scheduledWrite.Session, (IWriteRequest)scheduledWrite.Parameter); + } + } + } + + private void WriteBuffer(IoBuffer buf) + { + IWriteRequest writeRequest; + if (_authenticated) + writeRequest = new CustomSslFilter.EncryptedWriteRequest(_currentWriteRequest, buf); + else + writeRequest = new DefaultWriteRequest(buf); + _currentNextFilter.FilterWrite(_session, writeRequest); + } + + private IoBuffer ReadBuffer() + { + IoBuffer buf = IoBuffer.Allocate(_sessionStream.Remaining); + + while (true) + { + ArraySegment array = buf.GetRemaining(); + Int32 bytesRead = _sslStream.Read(array.Array, array.Offset, array.Count); + if (bytesRead <= 0) + break; + buf.Position += bytesRead; + + if (_sessionStream.Remaining == 0) + break; + else + { + // We have to grow the target buffer, it's too small. + buf.Capacity += _sessionStream.Remaining; + buf.Limit = buf.Capacity; + } + } + + buf.Flip(); + return buf; + } + + class IoSessionStream : System.IO.Stream + { + readonly Object _syncRoot = new Byte[0]; + readonly SslHandler _sslHandler; + readonly IoBuffer _buf; + volatile Boolean _closed; + volatile Boolean _released; + IOException _exception; + + public IoSessionStream(SslHandler sslHandler) + { + _sslHandler = sslHandler; + _buf = IoBuffer.Allocate(16); + _buf.AutoExpand = true; + _buf.Limit = 0; + } + + public override Int32 ReadByte() + { + lock (_syncRoot) + { + if (!WaitForData()) + return 0; + return _buf.Get() & 0xff; + } + } + + public override Int32 Read(Byte[] buffer, Int32 offset, Int32 count) + { + lock (_syncRoot) + { + if (!WaitForData()) + return 0; + + Int32 readBytes = Math.Min(count, _buf.Remaining); + _buf.Get(buffer, offset, readBytes); + return readBytes; + } + } + + public override void Close() + { + base.Close(); + + if (_closed) + return; + + lock (_syncRoot) + { + _closed = true; + ReleaseBuffer(); + Monitor.PulseAll(_syncRoot); + } + } + + public override void Write(Byte[] buffer, Int32 offset, Int32 count) + { + _sslHandler.WriteBuffer(IoBuffer.Wrap((Byte[])buffer.Clone(), offset, count)); + } + + public override void WriteByte(Byte value) + { + IoBuffer buf = IoBuffer.Allocate(1); + buf.Put(value); + buf.Flip(); + _sslHandler.WriteBuffer(buf); + } + + public override void Flush() + { } + + public void Write(IoBuffer buf) + { + if (_closed) + return; + + lock (_syncRoot) + { + if (_buf.HasRemaining) + { + _buf.Compact().Put(buf).Flip(); + } + else + { + _buf.Clear().Put(buf).Flip(); + Monitor.PulseAll(_syncRoot); + } + } + } + + private Boolean WaitForData() + { + if (_released) + return false; + + lock (_syncRoot) + { + while (!_released && _buf.Remaining == 0 && _exception == null) + { + try + { + Monitor.Wait(_syncRoot); + } + catch (ThreadInterruptedException e) + { + throw new IOException("Interrupted while waiting for more data", e); + } + } + } + + if (_exception != null) + { + ReleaseBuffer(); + throw _exception; + } + + if (_closed && _buf.Remaining == 0) + { + ReleaseBuffer(); + return false; + } + + return true; + } + + private void ReleaseBuffer() + { + if (_released) + return; + _released = true; + } + + public IOException Exception + { + set + { + if (_exception == null) + { + lock (_syncRoot) + { + _exception = value; + Monitor.PulseAll(_syncRoot); + } + } + } + } + + public Int32 Remaining + { + get { return _buf.Remaining; } + } + + public override Boolean CanRead + { + get { return true; } + } + + public override Boolean CanSeek + { + get { return false; } + } + + public override Boolean CanWrite + { + get { return true; } + } + + public override Int64 Length + { + get { throw new NotSupportedException(); } + } + + public override Int64 Position + { + get { throw new NotSupportedException(); } + set { throw new NotSupportedException(); } + } + + public override Int64 Seek(Int64 offset, SeekOrigin origin) + { + throw new NotSupportedException(); + } + + public override void SetLength(Int64 value) + { + throw new NotSupportedException(); + } + } + } +} \ No newline at end of file diff --git a/server/FSO.Server.Protocol/Voltron/AbstractVoltronPacket.cs b/server/FSO.Server.Protocol/Voltron/AbstractVoltronPacket.cs new file mode 100755 index 0000000..1598acf --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/AbstractVoltronPacket.cs @@ -0,0 +1,33 @@ +using FSO.Common.Serialization; +using FSO.Server.Protocol.Voltron.Model; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Voltron +{ + public abstract class AbstractVoltronPacket : IVoltronPacket + { + public static Sender GetSender(IoBuffer buffer) + { + var ariesID = buffer.GetPascalString(); + var masterID = buffer.GetPascalString(); + return new Sender { AriesID = ariesID, MasterAccountID = masterID }; + } + + public static void PutSender(IoBuffer buffer, Sender sender) + { + buffer.PutPascalString(sender.AriesID); + buffer.PutPascalString(sender.MasterAccountID); + } + + public static IoBuffer Allocate(int size) + { + IoBuffer buffer = IoBuffer.Allocate(size); + buffer.Order = ByteOrder.BigEndian; + return buffer; + } + + public abstract VoltronPacketType GetPacketType(); + public abstract void Serialize(IoBuffer output, ISerializationContext context); + public abstract void Deserialize(IoBuffer input, ISerializationContext context); + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/Avatar.cs b/server/FSO.Server.Protocol/Voltron/DataService/Avatar.cs new file mode 100755 index 0000000..9c3bab6 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/Avatar.cs @@ -0,0 +1,20 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class Avatar + { + public bool Avatar_IsFounder { get; set; } + public string Avatar_Name { get; set; } + public string Avatar_Description { get; set; } + public bool Avatar_IsParentalControlLocked { get; set; } + + /*public bool Avatar_IsOnline { get; set; } + public uint Avatar_LotGridXY { get; set; } + public uint Avatar_Age { get; set; } + public ushort Avatar_SkillsLockPoints { get; set; } + + public AvatarAppearance Avatar_Appearance { get; set; } + public AvatarSkills Avatar_Skills { get; set; } + + public List Avatar_BookmarksVec { get; set; }*/ + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/AvatarAppearance.cs b/server/FSO.Server.Protocol/Voltron/DataService/AvatarAppearance.cs new file mode 100755 index 0000000..f18ab83 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/AvatarAppearance.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class AvatarAppearance + { + public ulong AvatarAppearance_BodyOutfitID { get; set; } + public byte AvatarAppearance_SkinTone { get; set; } + public ulong AvatarAppearance_HeadOutfitID { get; set; } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/AvatarSkills.cs b/server/FSO.Server.Protocol/Voltron/DataService/AvatarSkills.cs new file mode 100755 index 0000000..2546752 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/AvatarSkills.cs @@ -0,0 +1,18 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class AvatarSkills + { + public ushort AvatarSkills_Logic { get; set; } + public ushort AvatarSkills_LockLv_Logic { get; set; } + public ushort AvatarSkills_Body { get; set; } + public ushort AvatarSkills_LockLv_Body { get; set; } + public ushort AvatarSkills_LockLv_Mechanical { get; set; } + public ushort AvatarSkills_LockLv_Creativity { get; set; } + public ushort AvatarSkills_LockLv_Cooking { get; set; } + public ushort AvatarSkills_Cooking { get; set; } + public ushort AvatarSkills_Charisma { get; set; } + public ushort AvatarSkills_LockLv_Charisma { get; set; } + public ushort AvatarSkills_Mechanical { get; set; } + public ushort AvatarSkills_Creativity { get; set; } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/Bookmark.cs b/server/FSO.Server.Protocol/Voltron/DataService/Bookmark.cs new file mode 100755 index 0000000..5e573a4 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/Bookmark.cs @@ -0,0 +1,13 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class Bookmark + { + public uint Bookmark_TargetID { get; set; } + public BookmarkType Bookmark_Type { get; set; } + } + + public enum BookmarkType : byte + { + BOOKMARK = 0x01 + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/Location.cs b/server/FSO.Server.Protocol/Voltron/DataService/Location.cs new file mode 100755 index 0000000..98ad552 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/Location.cs @@ -0,0 +1,6 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class Location + { + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/Lot.cs b/server/FSO.Server.Protocol/Voltron/DataService/Lot.cs new file mode 100755 index 0000000..942cdba --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/Lot.cs @@ -0,0 +1,7 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class Lot + { + + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/cITSOProperty.cs b/server/FSO.Server.Protocol/Voltron/DataService/cITSOProperty.cs new file mode 100755 index 0000000..7d676b9 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/cITSOProperty.cs @@ -0,0 +1,41 @@ +using System.Collections.Generic; +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class cITSOProperty : IoBufferSerializable + { + public uint StructType; + public List StructFields; + + /**cTSOValue > body: +* dword Body clsid (iid=896E3E90 or "GZIID_cITSOProperty"; clsid should be 0x89739A79 for cTSOProperty) +* dword Body + * dword Struct type (e.g. 0x3B0430BF for AvatarAppearance) + * dword Field count + * Fields - for each field: + * dword Field name (e.g. 0x1D530275 for AvatarAppearance_BodyOutfitID) + * dword cTSOValue clsid + * cTSOValue body**/ + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(0x89739A79); + output.PutUInt32(StructType); + output.PutUInt32((uint)StructFields.Count); + + foreach(var item in StructFields){ + output.PutUInt32(item.ID); + output.PutUInt32(item.Value.Type); + output.PutSerializable(item.Value.Value, context); + } + } + } + + public class cITSOField + { + public uint ID; + public cTSOValue Value; + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/cTSOSerializer.cs b/server/FSO.Server.Protocol/Voltron/DataService/cTSOSerializer.cs new file mode 100755 index 0000000..a1f07e4 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/cTSOSerializer.cs @@ -0,0 +1,398 @@ +using FSO.Common.Serialization; +using FSO.Files.Formats.tsodata; +using Mina.Core.Buffer; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace FSO.Server.Protocol.Voltron.DataService +{ + /// + /// TODO: Rewrite this to have much tighter performance + /// + public class cTSOSerializer + { + + //private static Logger LOG = LogManager.GetCurrentClassLogger(); + + public static cTSOSerializer INSTANCE = null; + public static cTSOSerializer Get(){ + return INSTANCE; + } + + + public const uint cTSOValue_bool = 0x696D1183; + public const uint cTSOValue_uint8 = 0xC976087C; + public const uint cTSOValue_uint16 = 0xE9760891; + public const uint cTSOValue_uint32 = 0x696D1189; + public const uint cTSOValue_uint64 = 0x69D3E3DB; + public const uint cTSOValue_sint8 = 0xE976088A; + public const uint cTSOValue_sint16 = 0xE9760897; + public const uint cTSOValue_sint32 = 0x896D1196; + public const uint cTSOValue_sint64 = 0x89D3E3EF; + public const uint cTSOValue_string = 0x896D1688; + public const uint cTSOValue_property = 0xA96E7E5B; + + private TSODataDefinition Format; + private Dictionary ClassesById = new Dictionary(); + private Dictionary IdByClass = new Dictionary(); + + private Dictionary cNetMessageParametersById = new Dictionary(); + + + public cTSOSerializer(TSODataDefinition data){ + INSTANCE = this; + + this.Format = data; + + //Scan for classes with decorations + var assembly = Assembly.GetAssembly(typeof(cTSOSerializer)); + + foreach (Type type in assembly.GetTypes()) + { + System.Attribute[] attributes = System.Attribute.GetCustomAttributes(type); + + foreach (Attribute attribute in attributes) + { + if (attribute is clsid){ + ClassesById.Add(((clsid)attribute).Value, type); + IdByClass.Add(type, ((clsid)attribute).Value); + }else if(attribute is cTSONetMessageParameter) + { + var param = (cTSONetMessageParameter)attribute; + object paramValue = param.Value; + + /*if(paramValue is DBRequestType){ + paramValue = ((DBRequestType)paramValue).GetRequestID(); + }else if(paramValue is DBResponseType) + { + paramValue = ((DBResponseType)paramValue).GetResponseID(); + }*/ + cNetMessageParametersById.Add((uint)paramValue, type); + } + } + } + } + + + public object Deserialize(uint clsid, IoBuffer buffer) + { + if (cNetMessageParametersById.ContainsKey(clsid)) + { + var instance = (IoBufferDeserializable)Activator.CreateInstance(cNetMessageParametersById[clsid]); + //instance.Deserialize(buffer); + return instance; + } + else if (ClassesById.ContainsKey(clsid)) + { + var instance = (IoBufferDeserializable)Activator.CreateInstance(ClassesById[clsid]); + //instance.Deserialize(buffer); + return instance; + } + else if(clsid == cTSOValue_string) + { + return buffer.GetPascalVLCString(); + } + return null; + } + + public object Serialize(object obj) + { + if(obj is IoBufferSerializable) + { + return (IoBufferSerializable)obj; + } + return GetValue(obj).Value; + } + + public cTSOValue GetValue(object obj){ + var type = obj.GetType(); + if (IdByClass.ContainsKey(type)) + { + uint clsid = IdByClass[type]; + return new cTSOValue() { Type = clsid, Value = obj }; + } + + throw new Exception("Unknown class " + type); + } + + public DerivedStruct GetDerivedStruct(uint id) + { + return Format.DerivedStructs.FirstOrDefault(x => x.ID == id); + } + + public DerivedStruct GetDerivedStruct(string name) + { + return Format.DerivedStructs.FirstOrDefault(x => x.Name == name); + } + + /*public List SerializeDerivedUpdate(uint avatarId, string derivedTypeName, uint structId, object instance) + { + var type = GetDerivedStruct(derivedTypeName); + + var fields = SerializeDerived(derivedTypeName, structId, instance); + var result = new List(); + + foreach(var update in fields){ + result.Add(new DataServiceWrapperPDU() { + SendingAvatarID = avatarId, + RequestTypeID = 0x3998426C, + Body = update + }); + } + + return result; + }*/ + + /* + public List SerializeDerived(string derivedTypeName, uint structId, object instance) + { + return SerializeDerived(GetDerivedStruct(derivedTypeName).ID, structId, instance); + } + + public List SerializeDerived(uint derivedType, uint structId, object instance){ + var result = new List(); + var type = Format.DerivedStructs.First(x => x.ID == derivedType); + var parent = Format.Structs.First(x => x.ID == type.Parent); + + foreach(var field in parent.Fields){ + var mask = type.FieldMasks.FirstOrDefault(x => x.ID == field.ID); + var action = DerivedStructFieldMaskType.KEEP; + if (mask != null){ + action = mask.Type; + } + + if(action == DerivedStructFieldMaskType.REMOVE){ + continue; + } + + object value = GetFieldValue(instance, field.Name); + if (value == null) { continue; } + + try { + var serialized = SerializeField(field, value); + serialized.StructType = parent.ID; + serialized.StructId = structId; + result.Add(serialized); + }catch(Exception ex) + { + LOG.Error(ex); + } + } + + return result; + }*/ + + private object GetFieldValue(object obj, string fieldName) + { + var objectField = obj.GetType().GetProperty(fieldName); + if (objectField == null) { return null; } + + var value = objectField.GetValue(obj); + + return value; + } + + /*private cTSOTopicUpdateMessage SerializeField(StructField field, object value){ + cTSOTopicUpdateMessage result = new cTSOTopicUpdateMessage(); + result.StructField = field.ID; + + if(field.Classification == StructFieldClassification.List) + { + IoBuffer resultBytes = AbstractVoltronPacket.Allocate(4); + resultBytes.AutoExpand = true; + var serializedValues = new List(); + System.Collections.ICollection list = (System.Collections.ICollection)value; + + foreach (var item in list){ + serializedValues.Add(SerializeValue(field.TypeID, item)); + } + + var itemType = serializedValues.First().Type; + var vectorType = GetVectorClsId(itemType); + + resultBytes.PutUInt32((uint)serializedValues.Count); + + foreach (var serializedValue in serializedValues){ + //resultBytes.PutSerializable(serializedValue.Value); + } + + resultBytes.Flip(); + + /*result.cTSOValue = new cTSOValue { + Type = 0xA97384A3,//field.TypeID, + Value = resultBytes + }; + + }else if(field.Classification == StructFieldClassification.SingleField) + { + var serializedValue = SerializeValue(field.TypeID, value); + //result.cTSOValue = serializedValue; + } + + return result; + }*/ + + private uint GetVectorClsId(uint clsid) + { + switch (clsid) + { + //cTSOValue < unsigned long> + case 0x696D1189: + //cTSOValueVector < unsigned long> + return 0x89738496; + //cTSOValue < long > + case 0x896D1196: + //cTSOValueVector < long > + return 0x8973849A; + //cTSOValue < unsigned short> + case 0xE9760891: + //cTSOValueVector < unsigned short> + return 0x097608B3; + //cTSOValue < short > + case 0xE9760897: + //cTSOValueVector < short > + return 0x097608B6; + //cTSOValue > + case 0xA96E7E5B: + //cTSOValueVector > + return 0xA97384A3; + //cTSOValue > + default: + throw new Exception("Cannot map clsid to vector clsid, " + clsid); + } + } + + private cTSOValue SerializeValue(uint type, object value) + { + var result = new cTSOValue(); + IoBuffer buffer = null; + + switch (type) + { + case 0x48BC841E: + if (!(value is sbyte) && !(value is Enum)) + { + return null; + } + result.Type = cTSOValue_sint8; + result.Value = new sbyte[] { Convert.ToSByte(value) }; + break; + + case 0x74336731: + if (!(value is ushort)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(2); + buffer.PutUInt16((ushort)value); + buffer.Flip(); + + result.Type = cTSOValue_uint16; + result.Value = buffer; + break; + + case 0xF192ECA6: + if (!(value is short)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(2); + buffer.PutInt16((short)value); + buffer.Flip(); + + result.Type = cTSOValue_sint16; + result.Value = buffer; + break; + + case 0xE0463A2F: + if (!(value is uint)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(4); + buffer.PutUInt32((uint)value); + buffer.Flip(); + + result.Type = cTSOValue_uint32; + result.Value = buffer; + break; + + case 0xA0587098: + if (!(value is int)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(4); + buffer.PutInt32((int)value); + buffer.Flip(); + + result.Type = cTSOValue_sint32; + result.Value = buffer; + break; + + case 0x385070C9: + if (!(value is ulong)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(8); + buffer.PutUInt64((ulong)value); + buffer.Flip(); + + result.Type = cTSOValue_uint64; + result.Value = buffer; + break; + + case 0x90D315F7: + if (!(value is long)) + { + return null; + } + + buffer = AbstractVoltronPacket.Allocate(8); + buffer.PutInt64((long)value); + buffer.Flip(); + + result.Type = cTSOValue_sint64; + result.Value = buffer; + break; + + default: + //It may be a struct + var _struct = Format.Structs.FirstOrDefault(x => x.ID == type); + if (_struct != null) + { + var body = new cITSOProperty(); + body.StructType = _struct.ID; + body.StructFields = new List(); + + foreach(var field in _struct.Fields){ + object fieldValue = GetFieldValue(value, field.Name); + if (fieldValue == null) { continue; } + + body.StructFields.Add(new cITSOField { + ID = field.ID, + Value = SerializeValue(field.TypeID, fieldValue) + }); + } + + result.Type = cTSOValue_property; + result.Value = body; + return result; + } + + return null; + + } + + return result; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/cTSOValue.cs b/server/FSO.Server.Protocol/Voltron/DataService/cTSOValue.cs new file mode 100755 index 0000000..2c9279d --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/cTSOValue.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + public class cTSOValue + { + public uint Type { get; set; } + public object Value { get; set; } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/DataService/clsid.cs b/server/FSO.Server.Protocol/Voltron/DataService/clsid.cs new file mode 100755 index 0000000..0104df6 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/DataService/clsid.cs @@ -0,0 +1,12 @@ +namespace FSO.Server.Protocol.Voltron.DataService +{ + [System.AttributeUsage(System.AttributeTargets.Class)] + public class clsid : System.Attribute + { + public uint Value; + + public clsid(uint value) { + this.Value = value; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/IVoltronPacket.cs b/server/FSO.Server.Protocol/Voltron/IVoltronPacket.cs new file mode 100755 index 0000000..871fe41 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/IVoltronPacket.cs @@ -0,0 +1,14 @@ +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron +{ + public interface IVoltronPacket : IoBufferDeserializable, IoBufferSerializable + { + /** + * Get packet type + * + * @return + */ + VoltronPacketType GetPacketType(); + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Model/Gender.cs b/server/FSO.Server.Protocol/Voltron/Model/Gender.cs new file mode 100755 index 0000000..ec369de --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Model/Gender.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Voltron.Model +{ + public enum Gender + { + MALE, + FEMALE + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Model/MagicNumberEnum.cs b/server/FSO.Server.Protocol/Voltron/Model/MagicNumberEnum.cs new file mode 100755 index 0000000..5d8012b --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Model/MagicNumberEnum.cs @@ -0,0 +1,338 @@ +namespace FSO.Server.Protocol.Voltron.Model +{ + public enum MagicNumberEnum + { + VAL_E4E9B25D, + VAL_A46E47DC, + VAL_B5D630DD, + VAL_211D969E, + VAL_D042E9D6, + VAL_3998426C, + VAL_75FFC299, + VAL_87102FBA, + VAL_486B3F7E, + VAL_14656565, + VAL_0C0CB1E6, + VAL_227BED60, + VAL_77A46FE8, + VAL_9062B390, + VAL_13639511, + VAL_94016F9F, + VAL_B2C6ED04, + VAL_67281FA4, + VAL_404D4CB1, + VAL_0350C667, + VAL_C5521020, + VAL_8D7F9BF2, + VAL_55D2AE37, + VAL_74AF57D1, + VAL_D3B216CA, + VAL_4BD42E0C, + VAL_DFAEA619, + VAL_E3FC98F9, + VAL_1C364C5D, + VAL_196546F1, + VAL_9702D009, + VAL_DC07F91F, + VAL_AF3D3F6D + } + + public static class MagicNumberEnumUtils + { + public static int ToInt(this MagicNumberEnum value) + { + switch (value) + { + case MagicNumberEnum.VAL_E4E9B25D: + return 0; + case MagicNumberEnum.VAL_A46E47DC: + return 0; + case MagicNumberEnum.VAL_B5D630DD: + return 4; + case MagicNumberEnum.VAL_211D969E: + return 0; + case MagicNumberEnum.VAL_D042E9D6: + return 0; + case MagicNumberEnum.VAL_3998426C: + return 0; + case MagicNumberEnum.VAL_75FFC299: + return 0; + case MagicNumberEnum.VAL_87102FBA: + return 0; + case MagicNumberEnum.VAL_486B3F7E: + return 2; + case MagicNumberEnum.VAL_14656565: + return 20; + case MagicNumberEnum.VAL_0C0CB1E6: + return 0; + case MagicNumberEnum.VAL_227BED60: + return 2; + case MagicNumberEnum.VAL_77A46FE8: + return 0; + case MagicNumberEnum.VAL_9062B390: + return 100; + case MagicNumberEnum.VAL_13639511: + return 0; + case MagicNumberEnum.VAL_94016F9F: + return 10; + case MagicNumberEnum.VAL_B2C6ED04: + return 0; + case MagicNumberEnum.VAL_67281FA4: + return 20; + case MagicNumberEnum.VAL_404D4CB1: + return 0; + case MagicNumberEnum.VAL_0350C667: + return 30; + case MagicNumberEnum.VAL_C5521020: + return 10; + case MagicNumberEnum.VAL_8D7F9BF2: + return 3; + case MagicNumberEnum.VAL_55D2AE37: + return 10; + case MagicNumberEnum.VAL_74AF57D1: + return 100; + case MagicNumberEnum.VAL_D3B216CA: + return 64; + case MagicNumberEnum.VAL_4BD42E0C: + return 64; + case MagicNumberEnum.VAL_DFAEA619: + return 30; + case MagicNumberEnum.VAL_E3FC98F9: + return 60; + case MagicNumberEnum.VAL_1C364C5D: + return 30; + case MagicNumberEnum.VAL_196546F1: + return 2; + case MagicNumberEnum.VAL_9702D009: + return 60; + case MagicNumberEnum.VAL_DC07F91F: + return 0; + case MagicNumberEnum.VAL_AF3D3F6D: + return 60; + } + return 0; + } + + public static float ToFloat(this MagicNumberEnum value) + { + switch (value) + { + case MagicNumberEnum.VAL_E4E9B25D: + return 0.2f; + case MagicNumberEnum.VAL_A46E47DC: + return 0.2f; + case MagicNumberEnum.VAL_B5D630DD: + return 4.0f; + case MagicNumberEnum.VAL_211D969E: + return 0.1f; + case MagicNumberEnum.VAL_D042E9D6: + return 0.5f; + case MagicNumberEnum.VAL_3998426C: + return 0.5f; + case MagicNumberEnum.VAL_75FFC299: + return 0.5f; + case MagicNumberEnum.VAL_87102FBA: + return 0.5f; + case MagicNumberEnum.VAL_486B3F7E: + return 1.0f; + case MagicNumberEnum.VAL_14656565: + return 10.0f; + case MagicNumberEnum.VAL_0C0CB1E6: + return 0.5f; + case MagicNumberEnum.VAL_227BED60: + return 4.0f; + case MagicNumberEnum.VAL_77A46FE8: + return 0.5f; + case MagicNumberEnum.VAL_9062B390: + return 100.0f; + case MagicNumberEnum.VAL_13639511: + return 0.5f; + case MagicNumberEnum.VAL_94016F9F: + return 2.0f; + case MagicNumberEnum.VAL_B2C6ED04: + return 0.5f; + case MagicNumberEnum.VAL_67281FA4: + return 10.0f; + case MagicNumberEnum.VAL_404D4CB1: + return 0.5f; + case MagicNumberEnum.VAL_0350C667: + return 2.0f; + case MagicNumberEnum.VAL_C5521020: + return 2.0f; + case MagicNumberEnum.VAL_8D7F9BF2: + return 3.0f; + case MagicNumberEnum.VAL_55D2AE37: + return 1.0f; + case MagicNumberEnum.VAL_74AF57D1: + return 2.0f; + case MagicNumberEnum.VAL_D3B216CA: + return 64.0f; + case MagicNumberEnum.VAL_4BD42E0C: + return 64.0f; + case MagicNumberEnum.VAL_DFAEA619: + return 30.0f; + case MagicNumberEnum.VAL_E3FC98F9: + return 60.0f; + case MagicNumberEnum.VAL_1C364C5D: + return 6.0f; + case MagicNumberEnum.VAL_196546F1: + return 0.5f; + case MagicNumberEnum.VAL_9702D009: + return 60.0f; + case MagicNumberEnum.VAL_DC07F91F: + return 0.5f; + case MagicNumberEnum.VAL_AF3D3F6D: + return 60.0f; + } + return 0.0f; + } + + public static uint ToID(this MagicNumberEnum value) + { + switch (value) + { + case MagicNumberEnum.VAL_E4E9B25D: + return 0xE4E9B25D; + case MagicNumberEnum.VAL_A46E47DC: + return 0xA46E47DC; + case MagicNumberEnum.VAL_B5D630DD: + return 0xB5D630DD; + case MagicNumberEnum.VAL_211D969E: + return 0x211D969E; + case MagicNumberEnum.VAL_D042E9D6: + return 0xD042E9D6; + case MagicNumberEnum.VAL_3998426C: + return 0x3998426C; + case MagicNumberEnum.VAL_75FFC299: + return 0x75FFC299; + case MagicNumberEnum.VAL_87102FBA: + return 0x87102FBA; + case MagicNumberEnum.VAL_486B3F7E: + return 0x486B3F7E; + case MagicNumberEnum.VAL_14656565: + return 0x14656565; + case MagicNumberEnum.VAL_0C0CB1E6: + return 0x0C0CB1E6; + case MagicNumberEnum.VAL_227BED60: + return 0x227BED60; + case MagicNumberEnum.VAL_77A46FE8: + return 0x77A46FE8; + case MagicNumberEnum.VAL_9062B390: + return 0x9062B390; + case MagicNumberEnum.VAL_13639511: + return 0x13639511; + case MagicNumberEnum.VAL_94016F9F: + return 0x94016F9F; + case MagicNumberEnum.VAL_B2C6ED04: + return 0xB2C6ED04; + case MagicNumberEnum.VAL_67281FA4: + return 0x67281FA4; + case MagicNumberEnum.VAL_404D4CB1: + return 0x404D4CB1; + case MagicNumberEnum.VAL_0350C667: + return 0x0350C667; + case MagicNumberEnum.VAL_C5521020: + return 0xC5521020; + case MagicNumberEnum.VAL_8D7F9BF2: + return 0x8D7F9BF2; + case MagicNumberEnum.VAL_55D2AE37: + return 0x55D2AE37; + case MagicNumberEnum.VAL_74AF57D1: + return 0x74AF57D1; + case MagicNumberEnum.VAL_D3B216CA: + return 0xD3B216CA; + case MagicNumberEnum.VAL_4BD42E0C: + return 0x4BD42E0C; + case MagicNumberEnum.VAL_DFAEA619: + return 0xDFAEA619; + case MagicNumberEnum.VAL_E3FC98F9: + return 0xE3FC98F9; + case MagicNumberEnum.VAL_1C364C5D: + return 0x1C364C5D; + case MagicNumberEnum.VAL_196546F1: + return 0x196546F1; + case MagicNumberEnum.VAL_9702D009: + return 0x9702D009; + case MagicNumberEnum.VAL_DC07F91F: + return 0xDC07F91F; + case MagicNumberEnum.VAL_AF3D3F6D: + return 0xAF3D3F6D; + } + return 0; + } + + public static MagicNumberEnum FromID(uint id) + { + switch (id) + { + case 0xE4E9B25D: + return MagicNumberEnum.VAL_E4E9B25D; + case 0xA46E47DC: + return MagicNumberEnum.VAL_A46E47DC; + case 0xB5D630DD: + return MagicNumberEnum.VAL_B5D630DD; + case 0x211D969E: + return MagicNumberEnum.VAL_211D969E; + case 0xD042E9D6: + return MagicNumberEnum.VAL_D042E9D6; + case 0x3998426C: + return MagicNumberEnum.VAL_3998426C; + case 0x75FFC299: + return MagicNumberEnum.VAL_75FFC299; + case 0x87102FBA: + return MagicNumberEnum.VAL_87102FBA; + case 0x486B3F7E: + return MagicNumberEnum.VAL_486B3F7E; + case 0x14656565: + return MagicNumberEnum.VAL_14656565; + case 0x0C0CB1E6: + return MagicNumberEnum.VAL_0C0CB1E6; + case 0x227BED60: + return MagicNumberEnum.VAL_227BED60; + case 0x77A46FE8: + return MagicNumberEnum.VAL_77A46FE8; + case 0x9062B390: + return MagicNumberEnum.VAL_9062B390; + case 0x13639511: + return MagicNumberEnum.VAL_13639511; + case 0x94016F9F: + return MagicNumberEnum.VAL_94016F9F; + case 0xB2C6ED04: + return MagicNumberEnum.VAL_B2C6ED04; + case 0x67281FA4: + return MagicNumberEnum.VAL_67281FA4; + case 0x404D4CB1: + return MagicNumberEnum.VAL_404D4CB1; + case 0x0350C667: + return MagicNumberEnum.VAL_0350C667; + case 0xC5521020: + return MagicNumberEnum.VAL_C5521020; + case 0x8D7F9BF2: + return MagicNumberEnum.VAL_8D7F9BF2; + case 0x55D2AE37: + return MagicNumberEnum.VAL_55D2AE37; + case 0x74AF57D1: + return MagicNumberEnum.VAL_74AF57D1; + case 0xD3B216CA: + return MagicNumberEnum.VAL_D3B216CA; + case 0x4BD42E0C: + return MagicNumberEnum.VAL_4BD42E0C; + case 0xDFAEA619: + return MagicNumberEnum.VAL_DFAEA619; + case 0xE3FC98F9: + return MagicNumberEnum.VAL_E3FC98F9; + case 0x1C364C5D: + return MagicNumberEnum.VAL_1C364C5D; + case 0x196546F1: + return MagicNumberEnum.VAL_196546F1; + case 0x9702D009: + return MagicNumberEnum.VAL_9702D009; + case 0xDC07F91F: + return MagicNumberEnum.VAL_DC07F91F; + case 0xAF3D3F6D: + return MagicNumberEnum.VAL_AF3D3F6D; + } + return default(MagicNumberEnum); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Model/RPCRequest.cs b/server/FSO.Server.Protocol/Voltron/Model/RPCRequest.cs new file mode 100755 index 0000000..bdab59f --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Model/RPCRequest.cs @@ -0,0 +1,61 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using System; + +namespace FSO.Server.Protocol.Voltron.Model +{ + /// + /// DBRequestWrapperPDU + /// + public class RPCRequest + { + public object[] Parameters { get; set; } + + + public RPCRequest(IoBuffer buffer) + { + var bodyType = buffer.GetUInt32(); + + switch (bodyType) + { + case 0x125194E5: + ParseFormat1(buffer); + break; + default: + throw new Exception("Unknown RPC request type"); + } + } + + private void ParseFormat1(IoBuffer buffer) + { + var unknown = buffer.GetUInt32(); + var sendingAvatarId = buffer.GetUInt32(); + var flags = (byte)buffer.Get(); + var messageId = buffer.GetUInt32(); + + if ((((flags) >> 1) & 0x01) == 0x01) + { + var unknown2 = buffer.GetUInt32(); + } + + if ((((flags) >> 2) & 0x01) == 0x01) + { + var parameter = new byte[4]; + buffer.Get(parameter, 0, 4); + } + + if ((((flags) >> 3) & 0x01) == 0x01) + { + var unknown3 = buffer.GetUInt32(); + } + + if ((((flags) >> 5) & 0x01) == 0x01) + { + var requestResponseID = buffer.GetUInt32(); + + /** Variable bytes **/ + + } + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Model/Sender.cs b/server/FSO.Server.Protocol/Voltron/Model/Sender.cs new file mode 100755 index 0000000..bb3b009 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Model/Sender.cs @@ -0,0 +1,8 @@ +namespace FSO.Server.Protocol.Voltron.Model +{ + public class Sender + { + public string AriesID; + public string MasterAccountID; + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Model/SkinTone.cs b/server/FSO.Server.Protocol/Voltron/Model/SkinTone.cs new file mode 100755 index 0000000..b51fc89 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Model/SkinTone.cs @@ -0,0 +1,9 @@ +namespace FSO.Server.Protocol.Voltron.Model +{ + public enum SkinTone + { + LIGHT, + MEDIUM, + DARK + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/AnnouncementMsgPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/AnnouncementMsgPDU.cs new file mode 100755 index 0000000..ef2d11f --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/AnnouncementMsgPDU.cs @@ -0,0 +1,40 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class AnnouncementMsgPDU : AbstractVoltronPacket + { + public string SenderID = "??ARIES_OPERATIONS"; + public string SenderAccount = ""; + public byte Badge; + public byte IsAlertable; + public string Subject = ""; + public string Message = ""; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.SenderID = input.GetPascalString(); + this.SenderAccount = input.GetPascalString(); + this.Badge = input.Get(); + this.IsAlertable = input.Get(); + this.Subject = input.GetPascalString(); + this.Message = input.GetPascalString(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.AnnouncementMsgPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutPascalString(SenderID); + output.PutPascalString(SenderAccount); + output.Put(Badge); + output.Put(IsAlertable); + output.PutPascalString(Subject); + output.PutPascalString(Message); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/ChatMsgPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/ChatMsgPDU.cs new file mode 100755 index 0000000..8e6f82e --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/ChatMsgPDU.cs @@ -0,0 +1,38 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; +using FSO.Server.Protocol.Voltron.Model; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class ChatMsgPDU : AbstractVoltronPacket + { + public bool EchoRequested; + public Sender Sender; + public byte Badge; + public byte Alertable; + public string Message; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + EchoRequested = input.Get() == 0x01; + Sender = GetSender(input); + Badge = input.Get(); + Alertable = input.Get(); + Message = input.GetPascalString(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.ChatMsgPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.Put(EchoRequested ? (byte)1 : (byte)0); + PutSender(output, Sender); + output.Put(Badge); + output.Put(Alertable); + output.PutPascalString(Message); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/ClientByePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/ClientByePDU.cs new file mode 100755 index 0000000..ce0a139 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/ClientByePDU.cs @@ -0,0 +1,36 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class ClientByePDU : AbstractVoltronPacket + { + public uint ReasonCode; + public string ReasonText; + public byte RequestTicket; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.ReasonCode = input.GetUInt32(); + this.ReasonText = input.GetPascalString(); + this.RequestTicket = input.Get(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.ClientByePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + var text = ReasonText; + if(text == null){ + text = ""; + } + + output.PutUInt32(ReasonCode); + output.PutPascalString(text); + output.Put(RequestTicket); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/ClientOnlinePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/ClientOnlinePDU.cs new file mode 100755 index 0000000..1c9586b --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/ClientOnlinePDU.cs @@ -0,0 +1,57 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class ClientOnlinePDU : AbstractVoltronPacket + { + public ushort MajorVersion { get; set; } + public ushort MinorVersion { get; set; } + public ushort PointVersion { get; set; } + public ushort ArtVersion { get; set; } + + public ulong Timestamp { get; set; } + public byte NumberOfAttempts { get; set; } + + public byte LastExitCode { get; set; } + public byte LastFailureType { get; set; } + public byte FailureCount { get; set; } + public byte IsRunning { get; set; } + public byte IsReLogging { get; set; } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.ClientOnlinePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt16(MajorVersion); + output.PutUInt16(MinorVersion); + output.PutUInt16(PointVersion); + output.PutUInt16(ArtVersion); + output.PutUInt64(this.Timestamp); + output.Put(NumberOfAttempts); + output.Put(LastExitCode); + output.Put(LastFailureType); + output.Put(FailureCount); + output.Put(IsRunning); + output.Put(IsReLogging); + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.MajorVersion = input.GetUInt16(); + this.MinorVersion = input.GetUInt16(); + this.PointVersion = input.GetUInt16(); + this.ArtVersion = input.GetUInt16(); + this.Timestamp = input.GetUInt64(); + this.NumberOfAttempts = input.Get(); + this.LastExitCode = input.Get(); + this.LastFailureType = input.Get(); + this.FailureCount = input.Get(); + this.IsRunning = input.Get(); + this.IsReLogging = input.Get(); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/DBRequestWrapperPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/DBRequestWrapperPDU.cs new file mode 100755 index 0000000..ea51da1 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/DBRequestWrapperPDU.cs @@ -0,0 +1,56 @@ +using Mina.Core.Buffer; +using FSO.Server.Protocol.Voltron.Model; +using System.ComponentModel; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class DBRequestWrapperPDU : AbstractVoltronPacket + { + public uint SendingAvatarID { get; set; } + public Sender Sender { get; set; } + public byte Badge { get; set; } + public byte IsAlertable { get; set; } + + public object BodyType { get; set; } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public object Body { get; set; } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + SendingAvatarID = input.GetUInt32(); + Sender = GetSender(input); + Badge = input.Get(); + IsAlertable = input.Get(); + + var bodySize = input.GetUInt32(); + var bodyType = input.GetUInt32(); + + var bodyBytes = new byte[bodySize-4]; + input.Get(bodyBytes, 0, (int)bodySize-4); + var bodyBuffer = IoBuffer.Wrap(bodyBytes); + + this.Body = context.ModelSerializer.Deserialize(bodyType, bodyBuffer, context); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(SendingAvatarID); + PutSender(output, Sender); + output.Put(Badge); + output.Put(IsAlertable); + + if (Body != null) + { + var bodyBytes = context.ModelSerializer.SerializeBuffer(Body, context, true); + output.PutUInt32((uint)bodyBytes.Remaining); + output.Put(bodyBytes); + } + } + + public override VoltronPacketType GetPacketType(){ + return VoltronPacketType.DBRequestWrapperPDU; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/DataServiceWrapperPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/DataServiceWrapperPDU.cs new file mode 100755 index 0000000..453492f --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/DataServiceWrapperPDU.cs @@ -0,0 +1,53 @@ +using Mina.Core.Buffer; +using System.ComponentModel; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class DataServiceWrapperPDU : AbstractVoltronPacket + { + public uint SendingAvatarID { get; set; } + public uint RequestTypeID { get; set; } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public object Body { get; set; } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.DataServiceWrapperPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(SendingAvatarID); + output.PutUInt32(RequestTypeID); + + if(Body != null){ + var bodyBytes = context.ModelSerializer.SerializeBuffer(Body, context, true); + output.PutUInt32((uint)bodyBytes.Remaining); + output.Put(bodyBytes); + } + + //output.PutUInt32(RequestTypeID); + //output.PutUInt32(0); + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.SendingAvatarID = input.GetUInt32(); + this.RequestTypeID = input.GetUInt32(); + + var bodySize = input.GetUInt32(); + var bodyBytes = new byte[bodySize]; + input.Get(bodyBytes, 0, (int)bodySize); + this.Body = bodyBytes; + var bodyBuffer = IoBuffer.Wrap(bodyBytes); + var bodyType = bodyBuffer.GetUInt32(); + + this.Body = context.ModelSerializer.Deserialize(bodyType, bodyBuffer, context); + } + + } + + +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerPDU.cs new file mode 100755 index 0000000..7b2fe1b --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerPDU.cs @@ -0,0 +1,29 @@ +using Mina.Core.Buffer; +using FSO.Server.Protocol.Voltron.Model; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class FindPlayerPDU : AbstractVoltronPacket + { + public Sender Sender; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.Sender = GetSender(input); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.FindPlayerPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + //var result = Allocate(8); + //result.AutoExpand = true; + PutSender(output, Sender); + //return result; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerResponsePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerResponsePDU.cs new file mode 100755 index 0000000..f01b2fc --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/FindPlayerResponsePDU.cs @@ -0,0 +1,95 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class FindPlayerResponsePDU : AbstractVoltronPacket + { + public uint StatusCode; + public string ReasonText; + + public int AvatarID; + public int RoomID; + public int StageID; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + StatusCode = input.GetUInt32(); + ReasonText = input.GetPascalString(); + + //Room Info + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.FindPlayerResponsePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + //var result = Allocate(8); + //result.AutoExpand = true; + + output.PutUInt32(StatusCode); + output.PutPascalString(ReasonText); + + + //Room Info + output.PutPascalString("A 16318812"); + output.PutPascalString("1"); + output.Put((byte)0); + + //Owner + output.PutPascalString("A 65538"); + output.PutPascalString("1"); + + //Stage id + output.PutPascalString("A 16318812"); + output.PutPascalString("1"); + + //Currnet ocupancy + output.PutUInt32(10); + + //Max occupancy + output.PutUInt32(50); + + //pswd required + output.Put((byte)0); + + //room type + output.Put((byte)1); + + //Group + output.PutPascalString("1"); + + //Admin list + output.PutUInt16(0); + + //m_EnabledFlag + output.Put(0); + + //m_AdmitList + output.PutUInt16(0); + + //m_EnabledFlag + output.Put(0); + + //m_DenyList + output.PutUInt16(0); + + //m_EnabledFlag + output.Put(0); + + output.PutUInt32(0); + output.PutUInt32(0); + output.PutUInt32(0); + + //player info + output.PutPascalString("A "+AvatarID.ToString()); + output.PutPascalString(""); + output.Put(0); + output.Put(0); + //return result; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/HostOnlinePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/HostOnlinePDU.cs new file mode 100755 index 0000000..9baad5f --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/HostOnlinePDU.cs @@ -0,0 +1,33 @@ +using FSO.Common.Serialization; +using Mina.Core.Buffer; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class HostOnlinePDU : AbstractVoltronPacket + { + public ushort HostReservedWords; + public ushort HostVersion; + public ushort ClientBufSize = 4096; + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.HostOnlinePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + //IoBuffer result = Allocate(6); + output.PutUInt16(HostReservedWords); + output.PutUInt16(HostVersion); + output.PutUInt16(ClientBufSize); + //return result; + } + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + HostReservedWords = input.GetUInt16(); + HostVersion = input.GetUInt16(); + ClientBufSize = input.GetUInt16(); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/OccupantArrivedPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/OccupantArrivedPDU.cs new file mode 100755 index 0000000..6c7c830 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/OccupantArrivedPDU.cs @@ -0,0 +1,32 @@ +using Mina.Core.Buffer; +using FSO.Server.Protocol.Voltron.Model; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class OccupantArrivedPDU : AbstractVoltronPacket + { + public Sender Sender; + public byte Badge; + public bool IsAlertable; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + Sender = GetSender(input); + Badge = input.Get(); + IsAlertable = input.Get() == 0x1; + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.OccupantArrivedPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + PutSender(output, Sender); + output.Put(Badge); + output.Put((IsAlertable ? (byte)0x01 : (byte)0x00)); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/RSGZWrapperPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/RSGZWrapperPDU.cs new file mode 100755 index 0000000..24f2042 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/RSGZWrapperPDU.cs @@ -0,0 +1,76 @@ +using Mina.Core.Buffer; +using FSO.Server.Protocol.Voltron.Model; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class RSGZWrapperPDU : AbstractVoltronPacket + { + public string Name { get; set; } + public string Description { get; set; } + public Gender Gender { get; set; } + public SkinTone SkinTone { get; set; } + public uint HeadOutfitId { get; set; } + public uint BodyOutfitId { get; set; } + + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + //ignoring the dbwrapper junk + //byte 17 and 18 change without changing settings, perhaps a message id? + input.Skip(37); + this.Name = input.GetPascalVLCString(); + this.Description = input.GetPascalVLCString(); + this.Gender = input.Get() == 0x1 ? Gender.FEMALE : Gender.MALE; + + var skin = input.Get(); + switch (skin) { + default: + case 0x00: + SkinTone = SkinTone.LIGHT; + break; + case 0x01: + SkinTone = SkinTone.MEDIUM; + break; + case 0x02: + SkinTone = SkinTone.DARK; + break; + } + + this.HeadOutfitId = input.GetUInt32(); + input.Skip(4); //Unknown + this.BodyOutfitId = input.GetUInt32(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.RSGZWrapperPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.Skip(37); + + output.PutPascalVLCString(Name); + output.PutPascalVLCString(Description); + output.Put(Gender == Gender.FEMALE ? (byte)0x01 : (byte)0x00); + + switch (SkinTone) + { + case SkinTone.LIGHT: + output.Put(0x00); + break; + case SkinTone.MEDIUM: + output.Put(0x01); + break; + case SkinTone.DARK: + output.Put(0x02); + break; + } + + output.PutUInt32(HeadOutfitId); + output.Skip(4);//Unknown + output.PutUInt32(BodyOutfitId); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/ServerByePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/ServerByePDU.cs new file mode 100755 index 0000000..f07f86d --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/ServerByePDU.cs @@ -0,0 +1,36 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class ServerByePDU : AbstractVoltronPacket + { + public uint ReasonCode; + public string ReasonText; + public string Ticket; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.ReasonCode = input.GetUInt32(); + this.ReasonText = input.GetPascalString(); + this.Ticket = input.GetPascalString(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.ServerByePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + var text = ReasonText; + if(text == null){ + text = ""; + } + + output.PutUInt32(ReasonCode); + output.PutPascalString(text); + output.PutPascalString(Ticket); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListPDU.cs new file mode 100755 index 0000000..a1db865 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListPDU.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class SetIgnoreListPDU : AbstractVoltronPacket + { + public List PlayerIds; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + var length = input.GetUInt16(); + PlayerIds = new List(); + + for(var i=0; i < length; i++) + { + PlayerIds.Add(input.GetUInt32()); + } + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + var len = 0; + if(PlayerIds != null) + { + len = PlayerIds.Count; + } + + output.PutUInt16((ushort)len); + + for(int i=0; i < len; i++) + { + output.PutUInt32(PlayerIds[i]); + } + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.SetIgnoreListPDU; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListResponsePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListResponsePDU.cs new file mode 100755 index 0000000..4ab73a7 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/SetIgnoreListResponsePDU.cs @@ -0,0 +1,33 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class SetIgnoreListResponsePDU : AbstractVoltronPacket + { + public uint StatusCode; + public string ReasonText; + public uint MaxNumberOfIgnored; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.StatusCode = input.GetUInt32(); + this.ReasonText = input.GetPascalString(); + this.MaxNumberOfIgnored = input.GetUInt32(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.SetIgnoreListResponsePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + //var result = Allocate(8 + 4 + ReasonText.Length); + output.PutUInt32(StatusCode); + output.PutPascalString(this.ReasonText); + output.PutUInt32(MaxNumberOfIgnored); + //return result; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/SetInvinciblePDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/SetInvinciblePDU.cs new file mode 100755 index 0000000..7575c42 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/SetInvinciblePDU.cs @@ -0,0 +1,25 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class SetInvinciblePDU : AbstractVoltronPacket + { + public uint Action; + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + this.Action = input.GetUInt32(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.SetInvinciblePDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(Action); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/TransmitCreateAvatarNotificationPDU.cs b/server/FSO.Server.Protocol/Voltron/Packets/TransmitCreateAvatarNotificationPDU.cs new file mode 100755 index 0000000..f2fd3a1 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/TransmitCreateAvatarNotificationPDU.cs @@ -0,0 +1,23 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class TransmitCreateAvatarNotificationPDU : AbstractVoltronPacket + { + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketType.TransmitCreateAvatarNotificationPDU; + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.Put(10); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/Packets/VariableVoltronPacket.cs b/server/FSO.Server.Protocol/Voltron/Packets/VariableVoltronPacket.cs new file mode 100755 index 0000000..e235aef --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/Packets/VariableVoltronPacket.cs @@ -0,0 +1,34 @@ +using System; +using Mina.Core.Buffer; +using FSO.Common.Serialization; + +namespace FSO.Server.Protocol.Voltron.Packets +{ + public class VariableVoltronPacket : AbstractVoltronPacket + { + public ushort Type; + public byte[] Bytes; + + public VariableVoltronPacket(ushort type, byte[] bytes) + { + this.Type = type; + this.Bytes = bytes; + } + + + public override void Deserialize(IoBuffer input, ISerializationContext context) + { + throw new NotImplementedException(); + } + + public override VoltronPacketType GetPacketType() + { + return VoltronPacketTypeUtils.FromPacketCode(Type); + } + + public override void Serialize(IoBuffer output, ISerializationContext context) + { + output.Put(Bytes, 0, Bytes.Length); + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/VoltronPacketType.cs b/server/FSO.Server.Protocol/Voltron/VoltronPacketType.cs new file mode 100755 index 0000000..f686b05 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/VoltronPacketType.cs @@ -0,0 +1,776 @@ +namespace FSO.Server.Protocol.Voltron +{ + public enum VoltronPacketType + { + AlertHandledPDU, + AlertMsgPDU, + AlertMsgResponsePDU, + AnnouncementMsgResponsePDU, + AnnouncementMsgPDU, + ClientByePDU, + ServerByePDU, + ChatMsgFailedPDU, + ChatMsgPDU, + ClientOnlinePDU, + CreateAndJoinRoomFailedPDU, + CreateAndJoinRoomPDU, + CreateRoomPDU, + CreateRoomResponsePDU, + DestroyRoomPDU, + DestroyRoomResponsePDU, + DetachFromRoomFailedPDU, + DetachFromRoomPDU, + EjectOccupantPDU, + EjectOccupantResponsePDU, + ErrorPDU, + ExitRoomFailedPDU, + ExitRoomPDU, + FindPlayerPDU, + FindPlayerResponsePDU, + FlashMsgResponsePDU, + FlashMsgPDU, + HandleAlertPDU, + HostOfflinePDU, + HostOnlinePDU, + InvitationMsgResponsePDU, + InvitationMsgPDU, + JoinPlayerFailedPDU, + JoinPlayerPDU, + JoinRoomFailedPDU, + JoinRoomPDU, + ListOccupantsPDU, + ListOccupantsResponsePDU, + ListRoomsPDU, + ListRoomsResponsePDU, + LogEventPDU, + LogEventResponsePDU, + MessageLostPDU, + OccupantArrivedPDU, + OccupantDepartedPDU, + ReadProfilePDU, + ReadProfileResponsePDU, + ReleaseProfilePDU, + ReleaseProfileResponsePDU, + SetAcceptAlertsPDU, + SetAcceptAlertsResponsePDU, + SetIgnoreListPDU, + SetIgnoreListResponsePDU, + SetInvinciblePDU, + SetInvincibleResponsePDU, + SetInvisiblePDU, + SetInvisibleResponsePDU, + SetRoomNamePDU, + SetRoomNameResponsePDU, + UpdateOccupantsPDU, + UpdatePlayerPDU, + UpdateProfilePDU, + UpdateRoomPDU, + YankPlayerFailedPDU, + YankPlayerPDU, + SetAcceptFlashesPDU, + SetAcceptFlashesResponsePDU, + SplitBufferPDU, + ActionRoomNamePDU, + ActionRoomNameResponsePDU, + NotifyRoomActionedPDU, + ModifyProfilePDU, + ModifyProfileResponsePDU, + ListBBSFoldersPDU, + ListBBSFoldersResponsePDU, + GetBBSMessageListPDU, + GetBBSMessageListResponsePDU, + PostBBSMessagePDU, + PostBBSReplyPDU, + PostBBSMessageResponsePDU, + GetMPSMessagesPDU, + GetMPSMessagesResponsePDU, + DeleteMPSMessagePDU, + DeleteMPSMessageResponsePDU, + BBSMessageDataPDU, + UpdateRoomAdminListPDU, + GetRoomAdminListPDU, + GetRoomAdminListResponsePDU, + GroupInfoRequestPDU, + GroupInfoResponsePDU, + GroupAdminRequestPDU, + GroupAdminResponsePDU, + GroupMembershipRequestPDU, + GroupMembershipResponsePDU, + FlashGroupPDU, + FlashGroupResponsePDU, + UpdateGroupMemberPDU, + UpdateGroupMemberResponsePDU, + UpdateGroupAdminPDU, + UpdateGroupAdminResponsePDU, + ListGroupsPDU, + ListGroupsResponsePDU, + ListJoinedGroupsPDU, + ListJoinedGroupsResponsePDU, + GpsChatPDU, + GpsChatResponsePDU, + PetitionStatusUpdatePDU, + LogGPSPetitionPDU, + LogGPSPetitionResponsePDU, + List20RoomsPDU, + List20RoomsResponsePDU, + UpdateIgnoreListPDU, + ResetWatchdogPDU, + ResetWatchdogResponsePDU, + BroadcastDataBlobPDU, + TransmitDataBlobPDU, + DBRequestWrapperPDU, + TransmitCreateAvatarNotificationPDU, + BC_PlayerLoginEventPDU, + BC_PlayerLogoutEventPDU, + RoomserverUserlistPDU, + LotEntryRequestPDU, + ClientConfigPDU, + KickoutRoommatePDU, + GenericFlashPDU, + GenericFlashRequestPDU, + GenericFlashResponsePDU, + TransmitGenericGDMPDU, + EjectAvatarPDU, + TestPDU, + HouseSimConstraintsPDU, + HouseSimConstraintsResponsePDU, + LoadHouseResponsePDU, + ComponentVersionRequestPDU, + ComponentVersionResponsePDU, + InviteRoommatePDU, + RoommateInvitationAnswerPDU, + RoommateGDMPDU, + HSB_ShutdownSimulatorPDU, + RoommateGDMResponsePDU, + RSGZWrapperPDU, + AvatarHasNewLotIDPDU, + CheatPDU, + DataServiceWrapperPDU, + CsrEjectAvatarPDU, + CsrEjectAvatarResponsePDU, + cTSONetMessagePDU, + LogCsrActionPDU, + LogAvatarActionPDU, + + Unknown + } + + public static class VoltronPacketTypeUtils + { + public static VoltronPacketType FromPacketCode(ushort code) + { + switch (code) + { + case 0x0001: + return VoltronPacketType.AlertHandledPDU; + case 0x0002: + return VoltronPacketType.AlertMsgPDU; + case 0x0003: + return VoltronPacketType.AlertMsgResponsePDU; + case 0x0004: + return VoltronPacketType.AnnouncementMsgResponsePDU; + case 0x0005: + return VoltronPacketType.AnnouncementMsgPDU; + case 0x0006: + return VoltronPacketType.ClientByePDU; + case 0x0007: + return VoltronPacketType.ServerByePDU; + case 0x0008: + return VoltronPacketType.ChatMsgFailedPDU; + case 0x0009: + return VoltronPacketType.ChatMsgPDU; + case 0x000a: + return VoltronPacketType.ClientOnlinePDU; + case 0x000b: + return VoltronPacketType.CreateAndJoinRoomFailedPDU; + case 0x000c: + return VoltronPacketType.CreateAndJoinRoomPDU; + case 0x000d: + return VoltronPacketType.CreateRoomPDU; + case 0x000e: + return VoltronPacketType.CreateRoomResponsePDU; + case 0x000f: + return VoltronPacketType.DestroyRoomPDU; + case 0x0010: + return VoltronPacketType.DestroyRoomResponsePDU; + case 0x0011: + return VoltronPacketType.DetachFromRoomFailedPDU; + case 0x0012: + return VoltronPacketType.DetachFromRoomPDU; + case 0x0013: + return VoltronPacketType.EjectOccupantPDU; + case 0x0014: + return VoltronPacketType.EjectOccupantResponsePDU; + case 0x0015: + return VoltronPacketType.ErrorPDU; + case 0x0016: + return VoltronPacketType.ExitRoomFailedPDU; + case 0x0017: + return VoltronPacketType.ExitRoomPDU; + case 0x0018: + return VoltronPacketType.FindPlayerPDU; + case 0x0019: + return VoltronPacketType.FindPlayerResponsePDU; + case 0x001a: + return VoltronPacketType.FlashMsgResponsePDU; + case 0x001b: + return VoltronPacketType.FlashMsgPDU; + case 0x001c: + return VoltronPacketType.HandleAlertPDU; + case 0x001d: + return VoltronPacketType.HostOfflinePDU; + case 0x001e: + return VoltronPacketType.HostOnlinePDU; + case 0x001f: + return VoltronPacketType.InvitationMsgResponsePDU; + case 0x0020: + return VoltronPacketType.InvitationMsgPDU; + case 0x0021: + return VoltronPacketType.JoinPlayerFailedPDU; + case 0x0022: + return VoltronPacketType.JoinPlayerPDU; + case 0x0023: + return VoltronPacketType.JoinRoomFailedPDU; + case 0x0024: + return VoltronPacketType.JoinRoomPDU; + case 0x0025: + return VoltronPacketType.ListOccupantsPDU; + case 0x0026: + return VoltronPacketType.ListOccupantsResponsePDU; + case 0x0027: + return VoltronPacketType.ListRoomsPDU; + case 0x0028: + return VoltronPacketType.ListRoomsResponsePDU; + case 0x0029: + return VoltronPacketType.LogEventPDU; + case 0x002a: + return VoltronPacketType.LogEventResponsePDU; + case 0x002b: + return VoltronPacketType.MessageLostPDU; + case 0x002c: + return VoltronPacketType.OccupantArrivedPDU; + case 0x002d: + return VoltronPacketType.OccupantDepartedPDU; + case 0x002e: + return VoltronPacketType.ReadProfilePDU; + case 0x002f: + return VoltronPacketType.ReadProfileResponsePDU; + case 0x0030: + return VoltronPacketType.ReleaseProfilePDU; + case 0x0031: + return VoltronPacketType.ReleaseProfileResponsePDU; + case 0x0032: + return VoltronPacketType.SetAcceptAlertsPDU; + case 0x0033: + return VoltronPacketType.SetAcceptAlertsResponsePDU; + case 0x0034: + return VoltronPacketType.SetIgnoreListPDU; + case 0x0035: + return VoltronPacketType.SetIgnoreListResponsePDU; + case 0x0036: + return VoltronPacketType.SetInvinciblePDU; + case 0x0037: + return VoltronPacketType.SetInvincibleResponsePDU; + case 0x0038: + return VoltronPacketType.SetInvisiblePDU; + case 0x0039: + return VoltronPacketType.SetInvisibleResponsePDU; + case 0x003a: + return VoltronPacketType.SetRoomNamePDU; + case 0x003b: + return VoltronPacketType.SetRoomNameResponsePDU; + case 0x003c: + return VoltronPacketType.UpdateOccupantsPDU; + case 0x003d: + return VoltronPacketType.UpdatePlayerPDU; + case 0x003e: + return VoltronPacketType.UpdateProfilePDU; + case 0x003f: + return VoltronPacketType.UpdateRoomPDU; + case 0x0040: + return VoltronPacketType.YankPlayerFailedPDU; + case 0x0041: + return VoltronPacketType.YankPlayerPDU; + case 0x0042: + return VoltronPacketType.SetAcceptFlashesPDU; + case 0x0043: + return VoltronPacketType.SetAcceptFlashesResponsePDU; + case 0x0044: + return VoltronPacketType.SplitBufferPDU; + case 0x0045: + return VoltronPacketType.ActionRoomNamePDU; + case 0x0046: + return VoltronPacketType.ActionRoomNameResponsePDU; + case 0x0047: + return VoltronPacketType.NotifyRoomActionedPDU; + case 0x0048: + return VoltronPacketType.ModifyProfilePDU; + case 0x0049: + return VoltronPacketType.ModifyProfileResponsePDU; + case 0x004a: + return VoltronPacketType.ListBBSFoldersPDU; + case 0x004b: + return VoltronPacketType.ListBBSFoldersResponsePDU; + case 0x004c: + return VoltronPacketType.GetBBSMessageListPDU; + case 0x004d: + return VoltronPacketType.GetBBSMessageListResponsePDU; + case 0x004e: + return VoltronPacketType.PostBBSMessagePDU; + case 0x004f: + return VoltronPacketType.PostBBSReplyPDU; + case 0x0050: + return VoltronPacketType.PostBBSMessageResponsePDU; + case 0x0051: + return VoltronPacketType.GetMPSMessagesPDU; + case 0x0052: + return VoltronPacketType.GetMPSMessagesResponsePDU; + case 0x0053: + return VoltronPacketType.DeleteMPSMessagePDU; + case 0x0054: + return VoltronPacketType.DeleteMPSMessageResponsePDU; + case 0x0055: + return VoltronPacketType.BBSMessageDataPDU; + case 0x0056: + return VoltronPacketType.UpdateRoomAdminListPDU; + case 0x0057: + return VoltronPacketType.GetRoomAdminListPDU; + case 0x0058: + return VoltronPacketType.GetRoomAdminListResponsePDU; + case 0x0059: + return VoltronPacketType.GroupInfoRequestPDU; + case 0x005a: + return VoltronPacketType.GroupInfoResponsePDU; + case 0x005b: + return VoltronPacketType.GroupAdminRequestPDU; + case 0x005c: + return VoltronPacketType.GroupAdminResponsePDU; + case 0x005d: + return VoltronPacketType.GroupMembershipRequestPDU; + case 0x005e: + return VoltronPacketType.GroupMembershipResponsePDU; + case 0x005f: + return VoltronPacketType.FlashGroupPDU; + case 0x0060: + return VoltronPacketType.FlashGroupResponsePDU; + case 0x0061: + return VoltronPacketType.UpdateGroupMemberPDU; + case 0x0062: + return VoltronPacketType.UpdateGroupMemberResponsePDU; + case 0x0063: + return VoltronPacketType.UpdateGroupAdminPDU; + case 0x0064: + return VoltronPacketType.UpdateGroupAdminResponsePDU; + case 0x0065: + return VoltronPacketType.ListGroupsPDU; + case 0x0066: + return VoltronPacketType.ListGroupsResponsePDU; + case 0x0067: + return VoltronPacketType.ListJoinedGroupsPDU; + case 0x0068: + return VoltronPacketType.ListJoinedGroupsResponsePDU; + case 0x0069: + return VoltronPacketType.GpsChatPDU; + case 0x006a: + return VoltronPacketType.GpsChatResponsePDU; + case 0x006b: + return VoltronPacketType.PetitionStatusUpdatePDU; + case 0x006c: + return VoltronPacketType.LogGPSPetitionPDU; + case 0x006d: + return VoltronPacketType.LogGPSPetitionResponsePDU; + case 0x006e: + return VoltronPacketType.List20RoomsPDU; + case 0x006f: + return VoltronPacketType.List20RoomsResponsePDU; + case 0x0070: + return VoltronPacketType.UpdateIgnoreListPDU; + case 0x0071: + return VoltronPacketType.ResetWatchdogPDU; + case 0x0072: + return VoltronPacketType.ResetWatchdogResponsePDU; + case 0x2710: + return VoltronPacketType.BroadcastDataBlobPDU; + case 0x2711: + return VoltronPacketType.TransmitDataBlobPDU; + case 0x2712: + return VoltronPacketType.DBRequestWrapperPDU; + case 0x2713: + return VoltronPacketType.TransmitCreateAvatarNotificationPDU; + case 0x2715: + return VoltronPacketType.BC_PlayerLoginEventPDU; + case 0x2716: + return VoltronPacketType.BC_PlayerLogoutEventPDU; + case 0x2718: + return VoltronPacketType.RoomserverUserlistPDU; + case 0x2719: + return VoltronPacketType.LotEntryRequestPDU; + case 0x271a: + return VoltronPacketType.ClientConfigPDU; + case 0x271c: + return VoltronPacketType.KickoutRoommatePDU; + case 0x271d: + return VoltronPacketType.GenericFlashPDU; + case 0x271e: + return VoltronPacketType.GenericFlashRequestPDU; + case 0x271f: + return VoltronPacketType.GenericFlashResponsePDU; + case 0x2722: + return VoltronPacketType.TransmitGenericGDMPDU; + case 0x2723: + return VoltronPacketType.EjectAvatarPDU; + case 0x2724: + return VoltronPacketType.TestPDU; + case 0x2725: + return VoltronPacketType.HouseSimConstraintsPDU; + case 0x2726: + return VoltronPacketType.HouseSimConstraintsResponsePDU; + case 0x2728: + return VoltronPacketType.LoadHouseResponsePDU; + case 0x2729: + return VoltronPacketType.ComponentVersionRequestPDU; + case 0x272a: + return VoltronPacketType.ComponentVersionResponsePDU; + case 0x272b: + return VoltronPacketType.InviteRoommatePDU; + case 0x272c: + return VoltronPacketType.RoommateInvitationAnswerPDU; + case 0x272d: + return VoltronPacketType.RoommateGDMPDU; + case 0x272e: + return VoltronPacketType.HSB_ShutdownSimulatorPDU; + case 0x272f: + return VoltronPacketType.RoommateGDMResponsePDU; + case 0x2730: + return VoltronPacketType.RSGZWrapperPDU; + case 0x2731: + return VoltronPacketType.AvatarHasNewLotIDPDU; + case 0x2733: + return VoltronPacketType.CheatPDU; + case 0x2734: + return VoltronPacketType.DataServiceWrapperPDU; + case 0x2735: + return VoltronPacketType.CsrEjectAvatarPDU; + case 0x2736: + return VoltronPacketType.CsrEjectAvatarResponsePDU; + case 0x2737: + return VoltronPacketType.cTSONetMessagePDU; + case 0x2738: + return VoltronPacketType.LogCsrActionPDU; + case 0x2739: + return VoltronPacketType.LogAvatarActionPDU; + case 0xffff: + return VoltronPacketType.Unknown; + } + return VoltronPacketType.Unknown; + } + + public static ushort GetPacketCode(this VoltronPacketType type) + { + switch (type) + { + case VoltronPacketType.AlertHandledPDU: + return 0x0001; + case VoltronPacketType.AlertMsgPDU: + return 0x0002; + case VoltronPacketType.AlertMsgResponsePDU: + return 0x0003; + case VoltronPacketType.AnnouncementMsgResponsePDU: + return 0x0004; + case VoltronPacketType.AnnouncementMsgPDU: + return 0x0005; + case VoltronPacketType.ClientByePDU: + return 0x0006; + case VoltronPacketType.ServerByePDU: + return 0x0007; + case VoltronPacketType.ChatMsgFailedPDU: + return 0x0008; + case VoltronPacketType.ChatMsgPDU: + return 0x0009; + case VoltronPacketType.ClientOnlinePDU: + return 0x000a; + case VoltronPacketType.CreateAndJoinRoomFailedPDU: + return 0x000b; + case VoltronPacketType.CreateAndJoinRoomPDU: + return 0x000c; + case VoltronPacketType.CreateRoomPDU: + return 0x000d; + case VoltronPacketType.CreateRoomResponsePDU: + return 0x000e; + case VoltronPacketType.DestroyRoomPDU: + return 0x000f; + case VoltronPacketType.DestroyRoomResponsePDU: + return 0x0010; + case VoltronPacketType.DetachFromRoomFailedPDU: + return 0x0011; + case VoltronPacketType.DetachFromRoomPDU: + return 0x0012; + case VoltronPacketType.EjectOccupantPDU: + return 0x0013; + case VoltronPacketType.EjectOccupantResponsePDU: + return 0x0014; + case VoltronPacketType.ErrorPDU: + return 0x0015; + case VoltronPacketType.ExitRoomFailedPDU: + return 0x0016; + case VoltronPacketType.ExitRoomPDU: + return 0x0017; + case VoltronPacketType.FindPlayerPDU: + return 0x0018; + case VoltronPacketType.FindPlayerResponsePDU: + return 0x0019; + case VoltronPacketType.FlashMsgResponsePDU: + return 0x001a; + case VoltronPacketType.FlashMsgPDU: + return 0x001b; + case VoltronPacketType.HandleAlertPDU: + return 0x001c; + case VoltronPacketType.HostOfflinePDU: + return 0x001d; + case VoltronPacketType.HostOnlinePDU: + return 0x001e; + case VoltronPacketType.InvitationMsgResponsePDU: + return 0x001f; + case VoltronPacketType.InvitationMsgPDU: + return 0x0020; + case VoltronPacketType.JoinPlayerFailedPDU: + return 0x0021; + case VoltronPacketType.JoinPlayerPDU: + return 0x0022; + case VoltronPacketType.JoinRoomFailedPDU: + return 0x0023; + case VoltronPacketType.JoinRoomPDU: + return 0x0024; + case VoltronPacketType.ListOccupantsPDU: + return 0x0025; + case VoltronPacketType.ListOccupantsResponsePDU: + return 0x0026; + case VoltronPacketType.ListRoomsPDU: + return 0x0027; + case VoltronPacketType.ListRoomsResponsePDU: + return 0x0028; + case VoltronPacketType.LogEventPDU: + return 0x0029; + case VoltronPacketType.LogEventResponsePDU: + return 0x002a; + case VoltronPacketType.MessageLostPDU: + return 0x002b; + case VoltronPacketType.OccupantArrivedPDU: + return 0x002c; + case VoltronPacketType.OccupantDepartedPDU: + return 0x002d; + case VoltronPacketType.ReadProfilePDU: + return 0x002e; + case VoltronPacketType.ReadProfileResponsePDU: + return 0x002f; + case VoltronPacketType.ReleaseProfilePDU: + return 0x0030; + case VoltronPacketType.ReleaseProfileResponsePDU: + return 0x0031; + case VoltronPacketType.SetAcceptAlertsPDU: + return 0x0032; + case VoltronPacketType.SetAcceptAlertsResponsePDU: + return 0x0033; + case VoltronPacketType.SetIgnoreListPDU: + return 0x0034; + case VoltronPacketType.SetIgnoreListResponsePDU: + return 0x0035; + case VoltronPacketType.SetInvinciblePDU: + return 0x0036; + case VoltronPacketType.SetInvincibleResponsePDU: + return 0x0037; + case VoltronPacketType.SetInvisiblePDU: + return 0x0038; + case VoltronPacketType.SetInvisibleResponsePDU: + return 0x0039; + case VoltronPacketType.SetRoomNamePDU: + return 0x003a; + case VoltronPacketType.SetRoomNameResponsePDU: + return 0x003b; + case VoltronPacketType.UpdateOccupantsPDU: + return 0x003c; + case VoltronPacketType.UpdatePlayerPDU: + return 0x003d; + case VoltronPacketType.UpdateProfilePDU: + return 0x003e; + case VoltronPacketType.UpdateRoomPDU: + return 0x003f; + case VoltronPacketType.YankPlayerFailedPDU: + return 0x0040; + case VoltronPacketType.YankPlayerPDU: + return 0x0041; + case VoltronPacketType.SetAcceptFlashesPDU: + return 0x0042; + case VoltronPacketType.SetAcceptFlashesResponsePDU: + return 0x0043; + case VoltronPacketType.SplitBufferPDU: + return 0x0044; + case VoltronPacketType.ActionRoomNamePDU: + return 0x0045; + case VoltronPacketType.ActionRoomNameResponsePDU: + return 0x0046; + case VoltronPacketType.NotifyRoomActionedPDU: + return 0x0047; + case VoltronPacketType.ModifyProfilePDU: + return 0x0048; + case VoltronPacketType.ModifyProfileResponsePDU: + return 0x0049; + case VoltronPacketType.ListBBSFoldersPDU: + return 0x004a; + case VoltronPacketType.ListBBSFoldersResponsePDU: + return 0x004b; + case VoltronPacketType.GetBBSMessageListPDU: + return 0x004c; + case VoltronPacketType.GetBBSMessageListResponsePDU: + return 0x004d; + case VoltronPacketType.PostBBSMessagePDU: + return 0x004e; + case VoltronPacketType.PostBBSReplyPDU: + return 0x004f; + case VoltronPacketType.PostBBSMessageResponsePDU: + return 0x0050; + case VoltronPacketType.GetMPSMessagesPDU: + return 0x0051; + case VoltronPacketType.GetMPSMessagesResponsePDU: + return 0x0052; + case VoltronPacketType.DeleteMPSMessagePDU: + return 0x0053; + case VoltronPacketType.DeleteMPSMessageResponsePDU: + return 0x0054; + case VoltronPacketType.BBSMessageDataPDU: + return 0x0055; + case VoltronPacketType.UpdateRoomAdminListPDU: + return 0x0056; + case VoltronPacketType.GetRoomAdminListPDU: + return 0x0057; + case VoltronPacketType.GetRoomAdminListResponsePDU: + return 0x0058; + case VoltronPacketType.GroupInfoRequestPDU: + return 0x0059; + case VoltronPacketType.GroupInfoResponsePDU: + return 0x005a; + case VoltronPacketType.GroupAdminRequestPDU: + return 0x005b; + case VoltronPacketType.GroupAdminResponsePDU: + return 0x005c; + case VoltronPacketType.GroupMembershipRequestPDU: + return 0x005d; + case VoltronPacketType.GroupMembershipResponsePDU: + return 0x005e; + case VoltronPacketType.FlashGroupPDU: + return 0x005f; + case VoltronPacketType.FlashGroupResponsePDU: + return 0x0060; + case VoltronPacketType.UpdateGroupMemberPDU: + return 0x0061; + case VoltronPacketType.UpdateGroupMemberResponsePDU: + return 0x0062; + case VoltronPacketType.UpdateGroupAdminPDU: + return 0x0063; + case VoltronPacketType.UpdateGroupAdminResponsePDU: + return 0x0064; + case VoltronPacketType.ListGroupsPDU: + return 0x0065; + case VoltronPacketType.ListGroupsResponsePDU: + return 0x0066; + case VoltronPacketType.ListJoinedGroupsPDU: + return 0x0067; + case VoltronPacketType.ListJoinedGroupsResponsePDU: + return 0x0068; + case VoltronPacketType.GpsChatPDU: + return 0x0069; + case VoltronPacketType.GpsChatResponsePDU: + return 0x006a; + case VoltronPacketType.PetitionStatusUpdatePDU: + return 0x006b; + case VoltronPacketType.LogGPSPetitionPDU: + return 0x006c; + case VoltronPacketType.LogGPSPetitionResponsePDU: + return 0x006d; + case VoltronPacketType.List20RoomsPDU: + return 0x006e; + case VoltronPacketType.List20RoomsResponsePDU: + return 0x006f; + case VoltronPacketType.UpdateIgnoreListPDU: + return 0x0070; + case VoltronPacketType.ResetWatchdogPDU: + return 0x0071; + case VoltronPacketType.ResetWatchdogResponsePDU: + return 0x0072; + case VoltronPacketType.BroadcastDataBlobPDU: + return 0x2710; + case VoltronPacketType.TransmitDataBlobPDU: + return 0x2711; + case VoltronPacketType.DBRequestWrapperPDU: + return 0x2712; + case VoltronPacketType.TransmitCreateAvatarNotificationPDU: + return 0x2713; + case VoltronPacketType.BC_PlayerLoginEventPDU: + return 0x2715; + case VoltronPacketType.BC_PlayerLogoutEventPDU: + return 0x2716; + case VoltronPacketType.RoomserverUserlistPDU: + return 0x2718; + case VoltronPacketType.LotEntryRequestPDU: + return 0x2719; + case VoltronPacketType.ClientConfigPDU: + return 0x271a; + case VoltronPacketType.KickoutRoommatePDU: + return 0x271c; + case VoltronPacketType.GenericFlashPDU: + return 0x271d; + case VoltronPacketType.GenericFlashRequestPDU: + return 0x271e; + case VoltronPacketType.GenericFlashResponsePDU: + return 0x271f; + case VoltronPacketType.TransmitGenericGDMPDU: + return 0x2722; + case VoltronPacketType.EjectAvatarPDU: + return 0x2723; + case VoltronPacketType.TestPDU: + return 0x2724; + case VoltronPacketType.HouseSimConstraintsPDU: + return 0x2725; + case VoltronPacketType.HouseSimConstraintsResponsePDU: + return 0x2726; + case VoltronPacketType.LoadHouseResponsePDU: + return 0x2728; + case VoltronPacketType.ComponentVersionRequestPDU: + return 0x2729; + case VoltronPacketType.ComponentVersionResponsePDU: + return 0x272a; + case VoltronPacketType.InviteRoommatePDU: + return 0x272b; + case VoltronPacketType.RoommateInvitationAnswerPDU: + return 0x272c; + case VoltronPacketType.RoommateGDMPDU: + return 0x272d; + case VoltronPacketType.HSB_ShutdownSimulatorPDU: + return 0x272e; + case VoltronPacketType.RoommateGDMResponsePDU: + return 0x272f; + case VoltronPacketType.RSGZWrapperPDU: + return 0x2730; + case VoltronPacketType.AvatarHasNewLotIDPDU: + return 0x2731; + case VoltronPacketType.CheatPDU: + return 0x2733; + case VoltronPacketType.DataServiceWrapperPDU: + return 0x2734; + case VoltronPacketType.CsrEjectAvatarPDU: + return 0x2735; + case VoltronPacketType.CsrEjectAvatarResponsePDU: + return 0x2736; + case VoltronPacketType.cTSONetMessagePDU: + return 0x2737; + case VoltronPacketType.LogCsrActionPDU: + return 0x2738; + case VoltronPacketType.LogAvatarActionPDU: + return 0x2739; + case VoltronPacketType.Unknown: + return 0xffff; + } + return 0; + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/VoltronPackets.cs b/server/FSO.Server.Protocol/Voltron/VoltronPackets.cs new file mode 100755 index 0000000..c489fd8 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/VoltronPackets.cs @@ -0,0 +1,50 @@ +using FSO.Server.Protocol.Voltron.Packets; +using System; +using System.Collections.Generic; + +namespace FSO.Server.Protocol.Voltron +{ + public class VoltronPackets + { + public static Dictionary VOLTRON_PACKET_BY_TYPEID; + public static Type[] VOLTRON_PACKETS = new Type[] { + typeof(ClientOnlinePDU), + typeof(HostOnlinePDU), + typeof(SetIgnoreListPDU), + typeof(SetIgnoreListResponsePDU), + typeof(SetInvinciblePDU), + typeof(RSGZWrapperPDU), + typeof(TransmitCreateAvatarNotificationPDU), + typeof(DataServiceWrapperPDU), + typeof(DBRequestWrapperPDU), + typeof(OccupantArrivedPDU), + typeof(ClientByePDU), + typeof(ServerByePDU), + typeof(FindPlayerPDU), + typeof(FindPlayerResponsePDU), + typeof(ChatMsgPDU), + typeof(AnnouncementMsgPDU) + }; + + static VoltronPackets() + { + VOLTRON_PACKET_BY_TYPEID = new Dictionary(); + foreach (Type packetType in VOLTRON_PACKETS) + { + IVoltronPacket packet = (IVoltronPacket)Activator.CreateInstance(packetType); + VOLTRON_PACKET_BY_TYPEID.Add(packet.GetPacketType().GetPacketCode(), packetType); + } + } + + public static Type GetByPacketCode(ushort code) + { + if (VOLTRON_PACKET_BY_TYPEID.ContainsKey(code)) + { + return VOLTRON_PACKET_BY_TYPEID[code]; + } + else { + return null; + } + } + } +} diff --git a/server/FSO.Server.Protocol/Voltron/cTSONetMessageParameter.cs b/server/FSO.Server.Protocol/Voltron/cTSONetMessageParameter.cs new file mode 100755 index 0000000..56eead3 --- /dev/null +++ b/server/FSO.Server.Protocol/Voltron/cTSONetMessageParameter.cs @@ -0,0 +1,15 @@ +using System; + +namespace FSO.Server.Protocol.Voltron +{ + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class cTSONetMessageParameter : Attribute + { + public object Value; + + public cTSONetMessageParameter(object value) + { + this.Value = value; + } + } +} diff --git a/server/FSO.Server.Protocol/app.config b/server/FSO.Server.Protocol/app.config new file mode 100755 index 0000000..51e422b --- /dev/null +++ b/server/FSO.Server.Protocol/app.config @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/server/FSO.Server.Protocol/packages.config b/server/FSO.Server.Protocol/packages.config new file mode 100755 index 0000000..9477ab4 --- /dev/null +++ b/server/FSO.Server.Protocol/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/server/README.md b/server/README.md new file mode 100644 index 0000000..f1cae9f --- /dev/null +++ b/server/README.md @@ -0,0 +1,12 @@ +# API Server + +zTSO utilizes the FreeSO API architecture for its backend, albeit not entirely compatible due to differences in simulation management. + +### Versioning Scheme + +Instead of using FreeSO's versioning scheme, zTSO adopts a versioning pattern that adheres to SemVer guidelines with some modifications: + +- FreeSO version ``beta/update-88b`` becomes ``beta/update-0.88.101`` in zTSO. +- Prefixed letters in FreeSO version are replaced with a three-digit incremental patch number in zTSO, akin to .NET's SDK versions. + +This versioning strategy aims to ensure that zTSO servers remain distinct from FreeSO-compatible servers while maintaining familiarity for existing users and server operators. \ No newline at end of file diff --git a/server/ZTSO.Server.sln b/server/ZTSO.Server.sln new file mode 100644 index 0000000..7d2b6ba --- /dev/null +++ b/server/ZTSO.Server.sln @@ -0,0 +1,30 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "server", "server", "{DE9F1DBC-27C5-4BC3-8516-6071FFE86B92}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FSO.Server.Api.Core", "FSO.Server.Api.Core\FSO.Server.Api.Core.csproj", "{02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {02B79DD0-1D96-4C2C-9E5D-E21B8DDBC9E4} = {DE9F1DBC-27C5-4BC3-8516-6071FFE86B92} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A6208BB0-8CE4-44ED-9E24-BA84CEEFF636} + EndGlobalSection +EndGlobal diff --git a/server/tso.common/Audio/MP3Player.cs b/server/tso.common/Audio/MP3Player.cs new file mode 100755 index 0000000..ab23700 --- /dev/null +++ b/server/tso.common/Audio/MP3Player.cs @@ -0,0 +1,288 @@ +using Mp3Sharp; +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework.Audio; +using System.Threading; +using System.Threading.Tasks; + +namespace FSO.Common.Audio +{ + public class MP3Player : ISFXInstanceLike + { + public static bool NewMode = true; + + private Mp3Stream Stream; + public DynamicSoundEffectInstance Inst; + private int LastChunkSize = 1; //don't die immediately.. + private Thread DecoderThread; + + private List NextBuffers = new List(); + private List NextSizes = new List(); + private int Requests; + private AutoResetEvent DecodeNext; + private AutoResetEvent BufferDone; + private bool EndOfStream; + private bool Active = true; + private Thread MainThread; //keep track of this, terminate when it closes. + + private SoundState _State = SoundState.Stopped; + private bool Disposed = false; + + private float _Volume = 1f; + private float _Pan; + + private object ControlLock = new object(); + private string Path; + public int SendExtra = 2; + + private static byte[] Blank = new byte[65536]; + + public MP3Player(string path) + { + Path = path; + // //let's get started... + + DecodeNext = new AutoResetEvent(true); + BufferDone = new AutoResetEvent(false); + MainThread = Thread.CurrentThread; + + Task.Run((Action)Start); + } + + public void Start() + { + Stream = new Mp3Stream(Path); + Stream.DecodeFrames(1); + var freq = Stream.Frequency; + lock (ControlLock) + { + if (Disposed) return; + Inst = new DynamicSoundEffectInstance(freq, AudioChannels.Stereo); + Inst.IsLooped = false; + Inst.BufferNeeded += SubmitBufferAsync; + if (_State == SoundState.Playing) Inst.Play(); + else if (_State == SoundState.Paused) + { + Inst.Play(); + Inst.Pause(); + } + Inst.Volume = _Volume; + Inst.Pan = _Pan; + Requests = 2; + } + + //SubmitBuffer(null, null); + //SubmitBuffer(null, null); + + DecoderThread = new Thread(() => + { + try + { + while (Active && MainThread.IsAlive) + { + DecodeNext.WaitOne(128); + bool go; + lock (this) go = Requests > 0; + while (go) + { + var buf = new byte[262144];// 524288]; + var read = Stream.Read(buf, 0, buf.Length); + lock (this) + { + Requests--; + NextBuffers.Add(buf); + NextSizes.Add(read); + if (read == 0) + { + EndOfStream = true; + BufferDone.Set(); + return; + } + BufferDone.Set(); + } + lock (this) go = Requests > 0; + } + } + } + catch (Exception e) { } + }); + DecoderThread.Start(); + DecodeNext.Set(); + } + + public void Play() + { + lock (ControlLock) + { + _State = SoundState.Playing; + Inst?.Play(); + } + } + + public void Stop() + { + lock (ControlLock) + { + _State = SoundState.Stopped; + Inst?.Stop(); + } + } + + public void Pause() + { + lock (ControlLock) + { + _State = SoundState.Paused; + Inst?.Pause(); + } + } + + public void Resume() + { + lock (ControlLock) + { + _State = SoundState.Playing; + Inst?.Resume(); + } + } + + public void Dispose() + { + lock (ControlLock) + { + Disposed = true; + Inst?.Dispose(); + Stream?.Dispose(); + + Active = false; + DecodeNext.Set(); //end the mp3 thread immediately + + EndOfStream = true; + } + } + + public bool IsEnded() + { + return EndOfStream && Inst.PendingBufferCount == 0; + } + + public float Volume + { + get + { + lock (ControlLock) + { + if (Inst != null) return Inst.Volume; + else return _Volume; + } + } + set + { + lock (ControlLock) + { + _Volume = value; + if (Inst != null) Inst.Volume = value; + } + } + } + + public float Pan + { + get + { + lock (ControlLock) + { + if (Inst != null) return Inst.Pan; + else return _Pan; + } + } + set + { + lock (ControlLock) + { + _Pan = value; + if (Inst != null) Inst.Pan = value; + } + } + } + + public SoundState State + { + get + { + lock (ControlLock) + { + if (Inst != null) return Inst.State; + else return _State; + } + } + } + + public bool IsLooped { get; set; } + + private void SubmitBuffer(object sender, EventArgs e) + { + byte[] buffer = new byte[524288]; + lock (this) + { + var read = Stream.Read(buffer, 0, buffer.Length); + LastChunkSize = read; + if (read == 0) + { + return; + } + Inst.SubmitBuffer(buffer, 0, read); + } + } + + private void SubmitBufferAsync(object sender, EventArgs e) + { + while (true) + { + if (EndOfStream) return; + var gotData = false; + lock (this) + { + if (NextBuffers.Count > 0) + { + if (NextSizes[0] > 0) Inst.SubmitBuffer(NextBuffers[0], 0, NextSizes[0]); + gotData = true; + NextBuffers.RemoveAt(0); + NextSizes.RemoveAt(0); + Requests++; + DecodeNext.Set(); + if (SendExtra > 0) + { + SendExtra--; + continue; + } + return; + } + + if (EndOfStream) return; + } + if (!gotData) + { + Inst.SubmitBuffer(Blank, 0, Blank.Length); + Requests++; + DecodeNext.Set(); + return; + //if (NewMode) BufferDone.WaitOne(128); + } + } + } + } + + public interface ISFXInstanceLike + { + float Volume { get; set; } + float Pan { get; set; } + SoundState State { get; } + bool IsLooped { get; set; } + void Play(); + void Stop(); + void Pause(); + void Resume(); + void Dispose(); + } +} diff --git a/server/tso.common/ClientEpoch.cs b/server/tso.common/ClientEpoch.cs new file mode 100755 index 0000000..0ac5313 --- /dev/null +++ b/server/tso.common/ClientEpoch.cs @@ -0,0 +1,50 @@ +using System; + +namespace FSO.Common +{ + /// + /// TODO: apply a time delta to sync with server time. right now we assume client time is correct. + /// + public class ClientEpoch + { + public static uint Now + { + get + { + uint epoch = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; + return epoch; + } + } + + public static uint FromDate(DateTime time) + { + return (uint)(time.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds; + } + + public static DateTime ToDate(uint time) + { + var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + return epoch.AddSeconds(time); + } + + public static string HMSRemaining(uint date) + { + TimeSpan span = (ToDate(date) - ToDate(ClientEpoch.Now)); + + return String.Format("{0} hours, {1} minutes and {2} seconds", (int)span.TotalHours, span.Minutes, span.Seconds); + } + + public static string DHMRemaining(uint date) + { + if (date == uint.MaxValue) return "Permanent"; + TimeSpan span = (ToDate(date) - ToDate(ClientEpoch.Now)); + + return String.Format("{0} days, {1} hours and {2} minutes", (int)span.TotalDays, span.Hours, span.Minutes); + } + + public static uint Default + { + get { return 0; } + } + } +} diff --git a/server/tso.common/Content/ContentID.cs b/server/tso.common/Content/ContentID.cs new file mode 100755 index 0000000..3870e83 --- /dev/null +++ b/server/tso.common/Content/ContentID.cs @@ -0,0 +1,43 @@ +namespace FSO.Common.Content +{ + /// + /// Represents the ID of a content resource. + /// Consists of two parts: TypeID (uint) and FileID (uint). + /// + public class ContentID + { + public uint TypeID; + public uint FileID; + public string FileName; + private long v; + + + /// + /// Creates a new ContentID instance. + /// + /// The TypeID of the content resource. + /// The FileID of the content resource. + public ContentID(uint typeID, uint fileID) + { + this.TypeID = typeID; + this.FileID = fileID; + } + + public ContentID(string name) + { + this.FileName = name; + } + + public ContentID(long v) + { + this.TypeID = (uint)v; + this.FileID = (uint)(v >> 32); + } + + public ulong Shift() + { + var fileIDLong = ((ulong)FileID) << 32; + return fileIDLong | TypeID; + } + } +} diff --git a/server/tso.common/Content/IContent.cs b/server/tso.common/Content/IContent.cs new file mode 100755 index 0000000..8a71627 --- /dev/null +++ b/server/tso.common/Content/IContent.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace TSO.Common.content +{ + public interface IContent + { + } +} diff --git a/server/tso.common/Content/IContentProvider.cs b/server/tso.common/Content/IContentProvider.cs new file mode 100755 index 0000000..606c542 --- /dev/null +++ b/server/tso.common/Content/IContentProvider.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace FSO.Common.Content +{ + public interface IContentProvider + { + T Get(ulong id); + T Get(string name); + T Get(uint type, uint fileID); + T Get(ContentID id); + List> List(); + } +} diff --git a/server/tso.common/Content/IContentReference.cs b/server/tso.common/Content/IContentReference.cs new file mode 100755 index 0000000..5d2e0e2 --- /dev/null +++ b/server/tso.common/Content/IContentReference.cs @@ -0,0 +1,13 @@ +namespace FSO.Common.Content +{ + public interface IContentReference : IContentReference + { + T Get(); + } + + public interface IContentReference + { + object GetGeneric(); + object GetThrowawayGeneric(); + } +} diff --git a/server/tso.common/Content/SDL2.dll b/server/tso.common/Content/SDL2.dll new file mode 100755 index 0000000..f514eba Binary files /dev/null and b/server/tso.common/Content/SDL2.dll differ diff --git a/server/tso.common/Enum/LotCategory.cs b/server/tso.common/Enum/LotCategory.cs new file mode 100755 index 0000000..998aa12 --- /dev/null +++ b/server/tso.common/Enum/LotCategory.cs @@ -0,0 +1,20 @@ +namespace FSO.Common.Enum +{ + public enum LotCategory + { + none = 0, + money = 1, + offbeat = 2, + romance = 3, + services = 4, + shopping = 5, + skills = 6, + welcome = 7, + games = 8, + entertainment = 9, + residence = 10, + community = 11, //cannot be set by users + + recent = 255 //for filter searches + } +} diff --git a/server/tso.common/Enum/Top100Category.cs b/server/tso.common/Enum/Top100Category.cs new file mode 100755 index 0000000..a7a24be --- /dev/null +++ b/server/tso.common/Enum/Top100Category.cs @@ -0,0 +1,114 @@ +using System; + +namespace FSO.Common.Enum +{ + public enum Top100Category + { + lot_money = 1, + lot_offbeat = 2, + lot_romance = 3, + lot_services = 4, + lot_shopping = 5, + lot_skills = 6, + lot_welcome = 7, + lot_games = 8, + lot_entertainment = 9, + lot_residence = 10, + + avatar_most_famous = 11, + avatar_best_karma = 12, + avatar_friendliest = 13, + avatar_most_infamous = 14, + avatar_meanest = 15 + } + + public static class Top100CategoryUtils + { + public static bool IsAvatarCategory(this Top100Category category) + { + return !category.IsLotCategory(); + } + + public static bool IsLotCategory(this Top100Category category) + { + switch (category) + { + case Top100Category.lot_money: + case Top100Category.lot_offbeat: + case Top100Category.lot_romance: + case Top100Category.lot_services: + case Top100Category.lot_shopping: + case Top100Category.lot_skills: + case Top100Category.lot_welcome: + case Top100Category.lot_games: + case Top100Category.lot_entertainment: + case Top100Category.lot_residence: + return true; + default: + return false; + } + } + + public static Top100Category FromLotCategory(LotCategory category) + { + switch (category) + { + case LotCategory.money: + return Top100Category.lot_money; + case LotCategory.offbeat: + return Top100Category.lot_offbeat; + case LotCategory.romance: + return Top100Category.lot_romance; + case LotCategory.services: + return Top100Category.lot_services; + case LotCategory.shopping: + return Top100Category.lot_shopping; + case LotCategory.skills: + return Top100Category.lot_skills; + case LotCategory.welcome: + return Top100Category.lot_welcome; + case LotCategory.games: + return Top100Category.lot_games; + case LotCategory.entertainment: + return Top100Category.lot_entertainment; + case LotCategory.residence: + return Top100Category.lot_residence; + } + throw new Exception("Unknown lot category"); + } + + public static LotCategory ToLotCategory(this Top100Category category) + { + switch (category) + { + case Top100Category.lot_money: + return LotCategory.money; + case Top100Category.lot_offbeat: + return LotCategory.offbeat; + case Top100Category.lot_romance: + return LotCategory.romance; + case Top100Category.lot_services: + return LotCategory.services; + case Top100Category.lot_shopping: + return LotCategory.shopping; + case Top100Category.lot_skills: + return LotCategory.skills; + case Top100Category.lot_welcome: + return LotCategory.welcome; + case Top100Category.lot_games: + return LotCategory.games; + case Top100Category.lot_entertainment: + return LotCategory.entertainment; + case Top100Category.lot_residence: + return LotCategory.residence; + } + return LotCategory.none; + } + } + + public enum Top100CategoryType + { + AVATAR = 1, + LOT = 2 + } +} diff --git a/server/tso.common/Enum/UserReferenceType.cs b/server/tso.common/Enum/UserReferenceType.cs new file mode 100755 index 0000000..58f976d --- /dev/null +++ b/server/tso.common/Enum/UserReferenceType.cs @@ -0,0 +1,11 @@ +namespace FSO.Common.Enum +{ + public enum UserReferenceType + { + EA = 1, + MAXIS = 2, + MOMI = 3, + TSO = 4, + AVATAR = 5 + } +} diff --git a/server/tso.common/FSO.Common.csproj b/server/tso.common/FSO.Common.csproj new file mode 100755 index 0000000..a3e11f0 --- /dev/null +++ b/server/tso.common/FSO.Common.csproj @@ -0,0 +1,307 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {C42962A1-8796-4F47-9DCD-79ED5904D8CA} + Library + Properties + FSO.Common + FSO.Common + v4.5 + 512 + + + + + 3.5 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + true + false + true + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + true + + + + ..\packages\Common.Logging.3.4.1\lib\net40\Common.Logging.dll + + + ..\packages\Common.Logging.Core.3.4.1\lib\net40\Common.Logging.Core.dll + + + + + true + bin\x86\Debug\ + DEBUG;TRACE + true + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\ServerRelease\ + TRACE + true + pdbonly + AnyCPU + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\ServerRelease\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + ..\packages\Mina.2.0.11\lib\net40\Mina.NET.dll + + + ..\packages\MonoGame.Framework.Portable.3.6.0.1625\lib\portable-net45+win8+wpa81\MonoGame.Framework.dll + False + + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\Portable.Ninject.3.3.1\lib\net40-client\Ninject.dll + + + ..\packages\NLog.4.5.7\lib\net45\NLog.dll + + + + ..\packages\System.Collections.Immutable.1.5.0\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {834cab58-648d-47cc-ac6f-d01c08c809a4} + Mp3Sharp + + + + + + Always + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 3.1 + true + + + + + + + + + + \ No newline at end of file diff --git a/server/tso.common/FSOEnvironment.cs b/server/tso.common/FSOEnvironment.cs new file mode 100755 index 0000000..abe4e6f --- /dev/null +++ b/server/tso.common/FSOEnvironment.cs @@ -0,0 +1,38 @@ +using System.Threading; + +namespace FSO.Common +{ + public static class FSOEnvironment + { + public static Thread GameThread; + + public static string ContentDir = "Content/"; + public static string UserDir = "Content/"; + public static string GFXContentDir = "Content/OGL"; + public static bool DirectX = false; + public static bool Linux = false; + public static bool UseMRT = true; + /// + /// True if system does not support gl_FragDepth (eg. iOS). Uses alternate pipeline that abuses stencil buffer. + /// + public static bool SoftwareDepth = false; + public static int GLVer = 3; + public static float UIZoomFactor = 1f; + public static float DPIScaleFactor = 1; + public static bool SoftwareKeyboard = false; + public static bool NoSound = false; + public static int RefreshRate = 60; + + /// + /// True if 3D features are enabled (like smooth rotation + zoom). Loads some content with mipmaps and other things. + /// Used to mean "3d camera" as well, though that has been moved to configuration and world state. + /// + public static bool Enable3D; + public static bool EnableNPOTMip = true; + public static bool TexCompress = true; + public static bool TexCompressSupport = true; + public static bool MSAASupport = true; + + public static string Args = ""; + } +} diff --git a/server/tso.common/IniConfig.cs b/server/tso.common/IniConfig.cs new file mode 100755 index 0000000..a760288 --- /dev/null +++ b/server/tso.common/IniConfig.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; + +namespace FSO.Common +{ + public abstract class IniConfig + { + private string ActivePath; + + public abstract Dictionary DefaultValues + { + get; set; + } + + private void SetValue(string key, string value) + { + var prop = this.GetType().GetProperty(key); + if (prop != null) + { + try + { + if (prop.PropertyType != typeof(string)) + prop.SetValue(this, Convert.ChangeType(value, prop.PropertyType, CultureInfo.InvariantCulture)); + else prop.SetValue(this, value); + } + catch (Exception) { } + } + } + + public IniConfig(string path) + { + ActivePath = path; + Load(); + } + + public void Load() + { + //assume default values for all unset properties + foreach (var pair in DefaultValues) + { + SetValue(pair.Key, pair.Value); + } + + if (!File.Exists(ActivePath)) + { + Save(); + } else + { + var lines = File.ReadAllLines(ActivePath); + foreach (var line in lines) + { + var clean = line.Trim(); + if (clean.Length == 0 || clean[0] == '#' || clean[0] == '[') continue; + var split = clean.IndexOf('='); + if (split == -1) continue; //? + var prop = clean.Substring(0, split).Trim(); + var value = clean.Substring(split+1).Trim(); + + SetValue(prop, value); + } + } + } + + public void Save() + { + try + { + using (var stream = new StreamWriter(File.Open(ActivePath, FileMode.Create, FileAccess.Write))) + { + stream.WriteLine("# FreeSO Settings File. Properties are self explanatory."); + var props = this.GetType().GetProperties(); + foreach (var prop in props) + { + if (prop.Name == "Default" || prop.Name == "DefaultValues") continue; + stream.WriteLine(prop.Name + "=" + Convert.ToString(prop.GetValue(this), CultureInfo.InvariantCulture)); + } + } + } + catch (Exception) { } + } + } +} diff --git a/server/tso.common/MeshSimplify/MSRef.cs b/server/tso.common/MeshSimplify/MSRef.cs new file mode 100755 index 0000000..c36ee0e --- /dev/null +++ b/server/tso.common/MeshSimplify/MSRef.cs @@ -0,0 +1,7 @@ +namespace FSO.Common.MeshSimplify +{ + public struct MSRef + { + public int tid, tvertex; + } +} diff --git a/server/tso.common/MeshSimplify/MSTriangle.cs b/server/tso.common/MeshSimplify/MSTriangle.cs new file mode 100755 index 0000000..354a3e5 --- /dev/null +++ b/server/tso.common/MeshSimplify/MSTriangle.cs @@ -0,0 +1,12 @@ +using Microsoft.Xna.Framework; + +namespace FSO.Common.MeshSimplify +{ + public class MSTriangle + { + public int[] v = new int[3]; + public double[] err = new double[4]; + public bool deleted, dirty; + public Vector3 n; + } +} diff --git a/server/tso.common/MeshSimplify/MSVertex.cs b/server/tso.common/MeshSimplify/MSVertex.cs new file mode 100755 index 0000000..1c80658 --- /dev/null +++ b/server/tso.common/MeshSimplify/MSVertex.cs @@ -0,0 +1,13 @@ +using Microsoft.Xna.Framework; + +namespace FSO.Common.MeshSimplify +{ + public class MSVertex + { + public Vector3 p; + public Vector2 t; //texcoord + public int tstart, tcount; + public SymmetricMatrix q; + public bool border; + } +} diff --git a/server/tso.common/MeshSimplify/Simplify.cs b/server/tso.common/MeshSimplify/Simplify.cs new file mode 100755 index 0000000..051774b --- /dev/null +++ b/server/tso.common/MeshSimplify/Simplify.cs @@ -0,0 +1,403 @@ +/* + * ==== Fast Quadratic Mesh Simplification ==== + * Ported and extended from https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification/ + * + * Typically used for simplifying meshes the 3D reconstruction generates. + * + */ + +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; + +namespace FSO.Common.MeshSimplify +{ + public class Simplify + { + public List triangles = new List(); + public List vertices = new List(); + public List refs = new List(); + + public void simplify_mesh(int target_count, double agressiveness = 7, int iterations = 100) + { + //for (int i=0; i(); + var deleted1 = new List(); + int triangle_count = triangles.Count; + + for (int iteration=0; iteration threshold) continue; + if (t.deleted) continue; + if (t.dirty) continue; + + for (int j = 0; j < 3; j++) + { + if (t.err[j] < threshold) + { + int i0 = t.v[j]; var v0 = vertices[i0]; + int i1 = t.v[(j + 1) % 3]; var v1 = vertices[i1]; + + // Border check + if (v0.border != v1.border) continue; + + // Compute vertex to collapse to + Vector3 p = Vector3.Zero; + calculate_error(i0, i1, ref p); + + deleted0.Clear(); // normals temporarily + for (int n = 0; n < v0.tcount; n++) deleted0.Add(0); + deleted1.Clear(); // normals temporarily + for (int n = 0; n < v1.tcount; n++) deleted1.Add(0); + + // dont remove if flipped + if (flipped(p, i0, i1, v0, v1, deleted0)) continue; + if (flipped(p, i1, i0, v1, v0, deleted1)) continue; + + // not flipped, so remove edge + + var vec = v1.p - v0.p; + var vec2 = p - v0.p; + vec2 /= vec.Length(); + vec /= vec.Length(); + var lp = Vector3.Dot(vec, vec2); + v0.p = p; + v0.t = Vector2.Lerp(v0.t, v1.t, lp); + v0.q = v1.q + v0.q; + int tstart = refs.Count; + + update_triangles(i0, v0, deleted0, ref deleted_triangles); + update_triangles(i0, v1, deleted1, ref deleted_triangles); + + int tcount = refs.Count - tstart; + + if (tcount <= v0.tcount) + { + // save ram + for (int tc=0; tc deleted) + { + int bordercount = 0; + for (int k=0; k 0.999) return true; + Vector3 n; + n = Vector3.Cross(d1, d2); + n.Normalize(); + deleted[k] = 0; + if (Vector3.Dot(n, t.n) < 0.2) return true; + } + return false; + } + + // Update triangle connections and edge error after a edge is collapsed + + void update_triangles(int i0, MSVertex v, List deleted, ref int deleted_triangles) + { + Vector3 p = Vector3.Zero; + for (int k = 0; k < v.tcount; k++) + { + var r = refs[v.tstart + k]; + var t = triangles[r.tid]; + if (t.deleted) continue; + if (k < deleted.Count && deleted[k] > 0) + { + t.deleted = true; + deleted_triangles++; + continue; + } + t.v[r.tvertex] = i0; + t.dirty = true; + t.err[0] = calculate_error(t.v[0], t.v[1], ref p); + t.err[1] = calculate_error(t.v[1], t.v[2], ref p); + t.err[2] = calculate_error(t.v[2], t.v[0], ref p); + t.err[3] = Math.Min(t.err[0], Math.Min(t.err[1], t.err[2])); + refs.Add(r); + } + } + + // compact triangles, compute edge error and build reference list + + void update_mesh(int iteration) + { + if (iteration > 0) // compact triangles + { + int dst = 0; + for (int i = 0; i vcount = new List(); + List vids = new List(); + + for (int i = 0; i < vertices.Count; i++) + vertices[i].border = false; + + for (int i = 0; i < vertices.Count; i++) + { + var v = vertices[i]; + vcount.Clear(); + vids.Clear(); + for (int j = 0; j < v.tcount; j++) + { + int k = refs[v.tstart + j].tid; + var t = triangles[k]; + for (k = 0; k < 3; k++) + { + int ofs = 0, id = t.v[k]; + while (ofs < vcount.Count) + { + if (vids[ofs] == id) break; + ofs++; + } + if (ofs == vcount.Count) + { + vcount.Add(1); + vids.Add(id); + } + else + vcount[ofs]++; + } + } + for (int j = 0; j < vcount.Count; j++) + { + if (vcount[j] == 1) + vertices[vids[j]].border = true; + } + } + } + } + + // Finally compact mesh before exiting + + void compact_mesh() + { + int dst = 0; + for (int i = 0; i < vertices.Count; i++) + { + vertices[i].tcount = 0; + } + for (int i = 0; i < triangles.Count; i++) + { + if (!triangles[i].deleted) + { + var t = triangles[i]; + triangles[dst++] = t; + for (int j = 0; j < 3; j++) vertices[t.v[j]].tcount = 1; + } + } + triangles.RemoveRange(dst, triangles.Count - dst); + dst = 0; + for (int i = 0; i < vertices.Count; i++) + { + if (vertices[i].tcount > 0) + { + vertices[i].tstart = dst; + vertices[dst].p = vertices[i].p; + vertices[dst].t = vertices[i].t; + dst++; + } + } + for (int i = 0; i < triangles.Count; i++) + { + var t = triangles[i]; + for (int j = 0; j < 3; j++) t.v[j] = vertices[t.v[j]].tstart; + } + vertices.RemoveRange(dst, vertices.Count - dst); + } + + // Error between vertex and Quadric + + double vertex_error(SymmetricMatrix q, double x, double y, double z) + { + return q[0] * x * x + 2 * q[1] * x * y + 2 * q[2] * x * z + 2 * q[3] * x + q[4] * y * y + + 2 * q[5] * y * z + 2 * q[6] * y + q[7] * z * z + 2 * q[8] * z + q[9]; + } + + // Error for one edge + + double calculate_error(int id_v1, int id_v2, ref Vector3 p_result) + { + // compute interpolated vertex + + SymmetricMatrix q = vertices[id_v1].q + vertices[id_v2].q; + bool border = vertices[id_v1].border && vertices[id_v2].border; + double error = 0; + double det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7); + + if (det != 0 && !border) + { + // q_delta is invertible + p_result.X = (float)(-1 / det * (q.det(1, 2, 3, 4, 5, 6, 5, 7, 8))); // vx = A41/det(q_delta) + p_result.Y = (float)(1 / det * (q.det(0, 2, 3, 1, 5, 6, 2, 7, 8))); // vy = A42/det(q_delta) + p_result.Z = (float)(-1 / det * (q.det(0, 1, 3, 1, 4, 6, 2, 5, 8))); // vz = A43/det(q_delta) + error = vertex_error(q, p_result.X, p_result.Y, p_result.Z); + } + else + { + // det = 0 -> try to find best result + Vector3 p1 = vertices[id_v1].p; + Vector3 p2 = vertices[id_v2].p; + Vector3 p3 = (p1 + p2) / 2; + double error1 = vertex_error(q, p1.X, p1.Y, p1.Z); + double error2 = vertex_error(q, p2.X, p2.Y, p2.Z); + double error3 = vertex_error(q, p3.X, p3.Y, p3.Z); + error = Math.Min(error1, Math.Min(error2, error3)); + if (error1 == error) p_result = p1; + if (error2 == error) p_result = p2; + if (error3 == error) p_result = p3; + } + return error; + } + + } +} diff --git a/server/tso.common/MeshSimplify/SymmetricMatrix.cs b/server/tso.common/MeshSimplify/SymmetricMatrix.cs new file mode 100755 index 0000000..23b0be3 --- /dev/null +++ b/server/tso.common/MeshSimplify/SymmetricMatrix.cs @@ -0,0 +1,56 @@ +namespace FSO.Common.MeshSimplify +{ + public class SymmetricMatrix + { + public SymmetricMatrix(double c) { + for (int i=0; i<10; i++) m[i] = c; + } + + + public SymmetricMatrix(double m11, double m12, double m13, double m14, + double m22, double m23, double m24, + double m33, double m34, + double m44) + { + m[0] = m11; m[1] = m12; m[2] = m13; m[3] = m14; + m[4] = m22; m[5] = m23; m[6] = m24; + m[7] = m33; m[8] = m34; + m[9] = m44; + } + + // Make plane + + public SymmetricMatrix(double a, double b, double c, double d) + { + m[0] = a * a; m[1] = a * b; m[2] = a * c; m[3] = a * d; + m[4] = b * b; m[5] = b * c; m[6] = b * d; + m[7] = c * c; m[8] = c * d; + m[9] = d * d; + } + + public double this[int c] { + get { return m[c]; } + set { m[c] = value; } + } + + public double[] m = new double[10]; + + //determinant + public double det(int a11, int a12, int a13, + int a21, int a22, int a23, + int a31, int a32, int a33) + { + double det = m[a11] * m[a22] * m[a33] + m[a13] * m[a21] * m[a32] + m[a12] * m[a23] * m[a31] + - m[a13] * m[a22] * m[a31] - m[a11] * m[a23] * m[a32] - m[a12] * m[a21] * m[a33]; + return det; + } + + public static SymmetricMatrix operator +(SymmetricMatrix m, SymmetricMatrix n) + { + return new SymmetricMatrix(m[0] + n[0], m[1] + n[1], m[2] + n[2], m[3] + n[3], + m[4] + n[4], m[5] + n[5], m[6] + n[6], + m[7] + n[7], m[8] + n[8], + m[9] + n[9]); + } + } +} diff --git a/server/tso.common/Model/DynTuningEntry.cs b/server/tso.common/Model/DynTuningEntry.cs new file mode 100755 index 0000000..2a5b2ca --- /dev/null +++ b/server/tso.common/Model/DynTuningEntry.cs @@ -0,0 +1,10 @@ +namespace FSO.Common.Model +{ + public class DynTuningEntry + { + public string tuning_type { get; set; } + public int tuning_table { get; set; } + public int tuning_index { get; set; } + public float value { get; set; } + } +} diff --git a/server/tso.common/Model/DynamicTuning.cs b/server/tso.common/Model/DynamicTuning.cs new file mode 100755 index 0000000..b835fb3 --- /dev/null +++ b/server/tso.common/Model/DynamicTuning.cs @@ -0,0 +1,148 @@ +using System.Collections.Generic; +using System.IO; + +namespace FSO.Common.Model +{ + public class DynamicTuning + { + //global tuning: + // city - + // 0: terrain + // 0: forceSnow (0/1/null) + public static DynamicTuning Global; + + //string type/iff, int table, int index. + public Dictionary>> Tuning = new Dictionary>>(); + public const int CURRENT_VERSION = 0; + public int Version = CURRENT_VERSION; + + public void SerializeInto(BinaryWriter writer) + { + writer.Write(CURRENT_VERSION); + writer.Write(Tuning.Count); + foreach (var type in Tuning) + { + writer.Write(type.Key); + writer.Write(type.Value.Count); + foreach (var table in type.Value) + { + writer.Write(table.Key); + writer.Write(table.Value.Count); + foreach (var value in table.Value) + { + writer.Write(value.Key); + writer.Write(value.Value); + } + } + } + } + + public DynamicTuning(IEnumerable entries) + { + foreach (var entry in entries) + { + AddTuning(entry); + } + } + + public void AddTuning(DynTuningEntry entry) + { + Dictionary> tables; + if (!Tuning.TryGetValue(entry.tuning_type, out tables)) + { + tables = new Dictionary>(); + Tuning[entry.tuning_type] = tables; + } + Dictionary data; + if (!tables.TryGetValue(entry.tuning_table, out data)) + { + data = new Dictionary(); + tables[entry.tuning_table] = data; + } + data[entry.tuning_index] = entry.value; + } + + public DynamicTuning(DynamicTuning old) + { + foreach (var type in Tuning) + { + var newType = new Dictionary>(); + foreach (var table in type.Value) + { + var newTable = new Dictionary(); + foreach (var value in table.Value) + { + newTable[value.Key] = value.Value; + } + newType[table.Key] = newTable; + } + Tuning[type.Key] = newType; + } + } + + public DynamicTuning(BinaryReader reader) + { + Version = reader.ReadInt32(); + var count = reader.ReadInt32(); + for (int i=0; i>(); + for (int j = 0; j < count2; j++) + { + var key2 = reader.ReadInt32(); + var count3 = reader.ReadInt32(); + var newTable = new Dictionary(); + for (int k=0; k GetTable(string type, int table) + { + Dictionary> tables; + if (Tuning.TryGetValue(type, out tables)) + { + Dictionary data; + if (tables.TryGetValue(table, out data)) + { + return data; + } + } + return null; + } + + public Dictionary> GetTables(string type) + { + Dictionary> tables; + if (Tuning.TryGetValue(type, out tables)) + { + return tables; + } + return null; + } + + public float? GetTuning(string type, int table, int index) + { + Dictionary> tables; + if (Tuning.TryGetValue(type, out tables)) + { + Dictionary data; + if (tables.TryGetValue(table, out data)) + { + float result; + if (data.TryGetValue(index, out result)) + return result; + } + } + return null; + } + } +} diff --git a/server/tso.common/Model/IntersectRectSet.cs b/server/tso.common/Model/IntersectRectSet.cs new file mode 100755 index 0000000..f57414b --- /dev/null +++ b/server/tso.common/Model/IntersectRectSet.cs @@ -0,0 +1,115 @@ +using Microsoft.Xna.Framework; + +namespace FSO.Common.Model +{ + /// + /// A k-d Tree for looking up rectangle intersections + /// TODO: balancing? could make performance gains more stable at the cost of some of the worst case. + /// + public class IntersectRectTree + { + public IntersectRectNode Root; + + public void Add(Rectangle rect) + { + if (Root == null) + { + Root = new IntersectRectNode + { + Dimension = IntersectRectDimension.Left, + Rect = rect + }; + } else + { + Root.AddAsChild(rect); + } + } + + public bool SearchForIntersect(Rectangle rect) + { + if (Root == null) return false; + else + { + return Root.SearchForIntersect(rect); + } + } + } + + public class IntersectRectNode + { + public IntersectRectNode LeftChild; + public IntersectRectNode RightChild; + public IntersectRectDimension Dimension; + public Rectangle Rect; + + public void AddAsChild(Rectangle rect) + { + bool rightSide = false; + switch (Dimension) + { + case IntersectRectDimension.Top: + rightSide = rect.Top > Rect.Top; break; + case IntersectRectDimension.Left: + rightSide = rect.Left > Rect.Left; break; + case IntersectRectDimension.Bottom: + rightSide = rect.Bottom > Rect.Bottom; break; + case IntersectRectDimension.Right: + rightSide = rect.Right > Rect.Right; break; + } + if (rightSide) + { + if (RightChild != null) RightChild.AddAsChild(rect); + else + { + RightChild = new IntersectRectNode + { + Dimension = (IntersectRectDimension)(((int)Dimension + 1) % 4), + Rect = rect + }; + } + } + else + { + if (LeftChild != null) LeftChild.AddAsChild(rect); + else + { + LeftChild = new IntersectRectNode + { + Dimension = (IntersectRectDimension)(((int)Dimension + 1) % 4), + Rect = rect + }; + } + } + } + + public bool SearchForIntersect(Rectangle rect) + { + if (rect.Intersects(Rect)) return true; + //search in child nodes. + int dontSearch = 0; + switch (Dimension) + { + case IntersectRectDimension.Top: + dontSearch = (rect.Bottom < Rect.Top)?2:0; break; //if true, do not have to search right (where top greater) + case IntersectRectDimension.Left: + dontSearch = (rect.Right < Rect.Left)?2:0; break; //if true, do not have to search right (where left greater) + case IntersectRectDimension.Bottom: + dontSearch = (rect.Top > Rect.Bottom)?1:0; break; //if true, do not have to search left (where bottom less) + case IntersectRectDimension.Right: + dontSearch = (rect.Left > Rect.Right)?1:0; break; //if true, do not have to search left (where right less) + } + + //may need to search both :'( won't happen often with our small rectangles over large space though. + return ((dontSearch != 1 && LeftChild != null && LeftChild.SearchForIntersect(rect)) + || (dontSearch != 2 && RightChild != null && RightChild.SearchForIntersect(rect))); + } + } + + public enum IntersectRectDimension : byte + { + Top, + Left, + Bottom, + Right + } +} diff --git a/server/tso.common/Properties/AssemblyInfo.cs b/server/tso.common/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..ba49bd8 --- /dev/null +++ b/server/tso.common/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("TSO.Common")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("TSO.Common")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f1dd298b-4150-4948-8cb2-dbba73e35dac")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/server/tso.common/Rendering/CachableTexture2D.cs b/server/tso.common/Rendering/CachableTexture2D.cs new file mode 100755 index 0000000..4e5441d --- /dev/null +++ b/server/tso.common/Rendering/CachableTexture2D.cs @@ -0,0 +1,88 @@ +using FSO.Common.Utils; +using Microsoft.Xna.Framework.Graphics; +using System; + +namespace FSO.Common.Rendering +{ + public class CachableTexture2D : Texture2D, ITimedCachable + { + /// + /// Creates a new texture of the given size + /// + /// + /// + /// + public CachableTexture2D(GraphicsDevice graphicsDevice, int width, int height) + : base(graphicsDevice, width, height) + { + } + /// + /// Creates a new texture of a given size with a surface format and optional mipmaps + /// + /// + /// + /// + /// + /// + public CachableTexture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format) + : base(graphicsDevice, width, height, mipmap, format) + { + } + /// + /// Creates a new texture array of a given size with a surface format and optional mipmaps. + /// Throws ArgumentException if the current GraphicsDevice can't work with texture arrays + /// + /// + /// + /// + /// + /// + /// + public CachableTexture2D(GraphicsDevice graphicsDevice, int width, int height, bool mipmap, SurfaceFormat format, int arraySize) + : base(graphicsDevice, width, height, mipmap, format, arraySize) + { + + } + + private bool WasReferenced = true; + public bool BeingDisposed = false; + private bool Resurrect = true; + public object Parent; //set if you want a parent object to be tied to this object (don't kill parent til we die) + ~CachableTexture2D() { + if (!IsDisposed && !BeingDisposed) + { + //if we are disposed, there's no need to do anything. + if (WasReferenced) + { + TimedReferenceController.KeepAlive(this, KeepAliveType.DEREFERENCED); + WasReferenced = false; + GC.ReRegisterForFinalize(this); + Resurrect = true; + } + else + { + BeingDisposed = true; + GameThread.NextUpdate(x => this.Dispose()); + GC.ReRegisterForFinalize(this); + Resurrect = true; //one more final + } + } + else { Resurrect = false; } + } + + public void Rereferenced(bool saved) + { + WasReferenced = saved; + } + + protected override void Dispose(bool disposing) + { + if (disposing) base.Dispose(disposing); + else if (Resurrect) + { + //in finalizer + GC.ReRegisterForFinalize(this); + } + } + } +} diff --git a/server/tso.common/Rendering/Emoji/EmojiCache.cs b/server/tso.common/Rendering/Emoji/EmojiCache.cs new file mode 100755 index 0000000..8e4a301 --- /dev/null +++ b/server/tso.common/Rendering/Emoji/EmojiCache.cs @@ -0,0 +1,103 @@ +using FSO.Common.Utils; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; + +namespace FSO.Common.Rendering.Emoji +{ + public class EmojiCache + { + public string Source = "https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/72x72/"; + public int DefaultRes = 24; + public int Width = 32; + + public int NextIndex = 0; + public List Emojis = new List(); + public Dictionary EmojiToIndex = new Dictionary(); + public RenderTarget2D EmojiTex; + public SpriteBatch EmojiBatch; + public HashSet IncompleteSpaces = new HashSet(); + public HashSet ErrorSpaces = new HashSet(); + private GraphicsDevice GD; + private bool needClear = true; + + public EmojiCache(GraphicsDevice gd) + { + GD = gd; + EmojiBatch = new SpriteBatch(gd); + + EmojiTex = new RenderTarget2D(gd, Width * DefaultRes, Width * DefaultRes, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents); + ServicePointManager.Expect100Continue = true; + ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11; + } + + public void ExpandIfNeeded() + { + //todo + } + + public Rectangle GetEmoji(string emojiID) { + + int index; + if (EmojiToIndex.TryGetValue(emojiID, out index)) + { + return RectForIndex(index); + } else + { + index = NextIndex++; + ExpandIfNeeded(); + lock (IncompleteSpaces) IncompleteSpaces.Add(index); + var client = new WebClient(); + client.DownloadDataCompleted += (object sender, DownloadDataCompletedEventArgs e) => + { + if (e.Cancelled || e.Error != null || e.Result == null) + { + lock (ErrorSpaces) ErrorSpaces.Add(index); + } else + { + GameThread.NextUpdate(x => + { + try + { + using (var mem = new MemoryStream(e.Result)) + { + var tex = Texture2D.FromStream(GD, mem); + + var decimated = TextureUtils.Decimate(tex, GD, 72 / DefaultRes, true); + //blit this into our emoji buffer + GD.SetRenderTarget(EmojiTex); + if (needClear) + { + GD.Clear(Color.TransparentBlack); + needClear = false; + } + EmojiBatch.Begin(blendState: BlendState.NonPremultiplied, sortMode: SpriteSortMode.Immediate); + EmojiBatch.Draw(decimated, RectForIndex(index), Color.White); + EmojiBatch.End(); + GD.SetRenderTarget(null); + } + } + catch (Exception) + { + lock (ErrorSpaces) ErrorSpaces.Add(index); + } + }); + } + lock (IncompleteSpaces) IncompleteSpaces.Remove(index); + }; + client.DownloadDataAsync(new Uri((emojiID[0] == '!')?(emojiID.Substring(1)):(Source + emojiID + ".png"))); + Emojis.Add(emojiID); + EmojiToIndex[emojiID] = index; + return RectForIndex(index); + } + } + + private Rectangle RectForIndex(int index) + { + return new Rectangle((index % Width) * DefaultRes, (index / Width) * DefaultRes, DefaultRes, DefaultRes); + } + } +} diff --git a/server/tso.common/Rendering/Emoji/EmojiDictionary.cs b/server/tso.common/Rendering/Emoji/EmojiDictionary.cs new file mode 100755 index 0000000..8524750 --- /dev/null +++ b/server/tso.common/Rendering/Emoji/EmojiDictionary.cs @@ -0,0 +1,95 @@ +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace FSO.Common.Rendering.Emoji +{ + public class EmojiDictionary + { + public Dictionary NameToEmojis = new Dictionary(); + public Dictionary> KeywordToCandidates = new Dictionary>(); + public Dictionary> CandidatesToKeywords = new Dictionary>(); + + public EmojiDictionary() + { + JObject emojis; + using (var emojiDict = new StreamReader( + new FileStream(Path.Combine(FSOEnvironment.ContentDir, "UI/emojis.json"), FileMode.Open, FileAccess.Read, FileShare.Read))) + { + emojis = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(emojiDict.ReadToEnd()); + } + + foreach (var token in emojis) + { + var charValue = token.Value.Value("char"); + var twemojiID = ToCodePoint(charValue); + NameToEmojis[token.Key] = twemojiID; + var keys = token.Value.Value("keywords"); + foreach (var key in keys) + AddKeyword(key.Value(), token.Key); + } + + using (var emojiDict = new StreamReader( + new FileStream(Path.Combine(FSOEnvironment.ContentDir, "UI/customemojis.json"), FileMode.Open, FileAccess.Read, FileShare.Read))) + { + emojis = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(emojiDict.ReadToEnd()); + } + + foreach (var token in emojis) + { + NameToEmojis[token.Key] = "!" + token.Value.Value("url"); + var keys = token.Value.Value("keywords"); + foreach (var key in keys) + AddKeyword(key.Value(), token.Key); + } + } + + public void AddKeyword(string keyword, string candidate) + { + List cand; + if (!KeywordToCandidates.TryGetValue(keyword, out cand)) + { + cand = new List(); + KeywordToCandidates[keyword] = cand; + } + cand.Add(candidate); + + if (!CandidatesToKeywords.TryGetValue(candidate, out cand)) + { + cand = new List(); + CandidatesToKeywords[candidate] = cand; + } + cand.Add(keyword); + } + + public string ToCodePoint(string str) + { + var cs = str.ToCharArray(); + var i = 0; + var c = 0; + var p = 0; + var r = new List(); + var zeroWidth = str.Any(x => x == '\x200D'); + while (i < cs.Length) + { + c = cs[i++]; + if (c == 0xfe0f && !zeroWidth) continue; //"as image", just ignore this + if (p > 0) + { + r.Add((0x10000 + ((p - 0xD800) << 10) + (c - 0xDC00)).ToString("x")); + p = 0; + } + else if (0xD800 <= c && c <= 0xDBFF) + { + p = c; + } + else + { + r.Add(c.ToString("x")); + } + } + return string.Join("-", r); + } + } +} diff --git a/server/tso.common/Rendering/Emoji/EmojiProvider.cs b/server/tso.common/Rendering/Emoji/EmojiProvider.cs new file mode 100755 index 0000000..cf892b4 --- /dev/null +++ b/server/tso.common/Rendering/Emoji/EmojiProvider.cs @@ -0,0 +1,232 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; +using System.Collections.Generic; +using System.Text; + +namespace FSO.Common.Rendering.Emoji +{ + public class EmojiProvider + { + public EmojiDictionary Dict; + public EmojiCache Cache; + public Random DictRand = new Random(); + + public Dictionary TranslateShortcuts = new Dictionary() + { + { "i", "eye" }, + { "you", "point_right" }, + { "your", "point_right" }, + { "you're", "point_right" }, + { "me", "relieved: :point_left" }, + { "i'm", "relieved: :point_left" }, + { "us", "couple" }, + { "we", "couple" }, + { "our", "couple" }, + { "what", "woman_shrugging" }, + { "be", "b" }, + { "to", "two" }, + { "and", "symbols" }, + { "that", "point_up" }, + { "for", "four" }, + { "not", "exclamation" }, + { "this", "point_up" }, + { "but", "exclamation" }, + { "his", "man" }, + { "her", "woman" }, + { "him", "man" }, + { "he", "man" }, + { "she", "woman" }, + { "from", "postbox" }, + { "they", "family_man_woman_girl_boy" }, + { "them", "family_man_woman_girl_boy" }, + { "or", "thinking" }, + { "an", "a" }, + { "will", "thinking" }, + { "my", "relieved: :point_left" }, + { "all", "rainbow_flag" }, + { "would", "tree" }, + { "so", "woman_shrugging" }, + { "out", "outbox_tray" }, + { "if", "thinking" }, + { "about", "arrows_counterclockwise" }, + { "who", "thinking: :family_man_woman_girl_boy" }, + { "get", "gift" }, + { "which", "woman_shrugging" }, + { "go", "door" }, + { "when", "watch" }, + { "make", "toolbox" }, + { "know", "brain" }, + { "take", "takeout_box" }, + { "into", "arrow_heading_down" }, + { "year", "calendar" }, + { "because", "woman_shrugging" }, + { "hmm", "thinking" }, + { "yo", "wave" }, + { "hey", "wave" }, + { "sup", "wave" }, + }; + + public EmojiProvider(GraphicsDevice gd) + { + Dict = new EmojiDictionary(); + Cache = new EmojiCache(gd); + } + + public string EmojiFromName(string name) + { + string result; + if (Dict.NameToEmojis.TryGetValue(name, out result)) + return result; + return null; + } + + private string StripPunctuation(string word, out string punctuation) + { + for (int i=word.Length-1; i>=0; i--) + { + if (!char.IsPunctuation(word[i])) + { + punctuation = word.Substring(i + 1); + return word.Substring(0, i + 1); + } + } + punctuation = ""; + return word; + } + + public string SearchForWordHit(string word) + { + string direct; + if (TranslateShortcuts.TryGetValue(word, out direct)) + { + return ":" + direct + ":"; + } + + if (Dict.NameToEmojis.TryGetValue(word, out direct)) + { + return ":" + word + ":"; + } + + List options; + if (Dict.KeywordToCandidates.TryGetValue(word, out options)) + { + return ":" + options[DictRand.Next(options.Count)] + ":"; + } + return null; + } + + public string TranslateWordToEmoji(string word) + { + string punctuation; + var lower = StripPunctuation(word.ToLowerInvariant(), out punctuation); + string result; + result = SearchForWordHit(lower); + if (result != null) return result + ' ' + punctuation; + if (lower.EndsWith("s")) + { + result = SearchForWordHit(lower.Substring(0, lower.Length-1)); + if (result != null) return result + ' ' + punctuation; + } + if (lower.EndsWith("ing")) + { + result = SearchForWordHit(lower.Substring(0, lower.Length - 3)); + if (result != null) return result + ' ' + punctuation; + } + return word.Substring(0, lower.Length) + punctuation; + } + + public Tuple GetEmoji(string id) + { + var rect = Cache.GetEmoji(id); + return new Tuple(Cache.EmojiTex, rect); + } + + public string EmojiToBB(string input) + { + //search through the string for emojis to turn to BBcode + int index = 0; + int lastColon = -1; + var result = new StringBuilder(); + while (true) + { + var nColon = input.IndexOf(':', index); + if (nColon == -1) break; + if (lastColon == -1) result.Append(input.Substring(index, nColon - index)); //add up to the colon + else + { + //is the string between the two colons an emoji? + var emoji = EmojiFromName(input.Substring(lastColon + 1, nColon - (lastColon + 1))); + if (emoji == null) + { + result.Append(":"+input.Substring(index, nColon - index)); //add up to the colon (include the last colon we skipped) + } else + { + result.Append("[emoji=" + emoji + "] "); + lastColon = -1; + index = nColon + 1; + continue; + } + } + index = nColon + 1; + lastColon = nColon; + } + result.Append(((lastColon == -1) ? "" : ":") + input.Substring(index)); + return result.ToString(); + } + + public string EmojiTranslate(string input) + { + //search for replacement candidates for each word in input + var words = input.Split(' '); + + for (int i=0; i 2 && word.StartsWith(":") && word.EndsWith(":")) + { + //is this already an emoji? if so, skip it + var existing = EmojiFromName(word.Substring(1, word.Length-2)); + if (existing == null) continue; + } + words[i] = TranslateWordToEmoji(word); + } + return String.Join(" ", words); + } + + public string EmojiOnly(string input, int mode) + { + if (mode == 2) return EmojiTranslate(input); + //search through the string for emojis to keep + int index = 0; + int lastColon = -1; + var result = new StringBuilder(); + while (true) + { + var nColon = input.IndexOf(':', index); + if (nColon == -1) break; + else + { + //is the string between the two colons an emoji? + var name = input.Substring(lastColon + 1, nColon - (lastColon + 1)); + var emoji = EmojiFromName(name); + if (emoji == null) + { + } + else + { + result.Append(":" + name + ": "); + lastColon = -1; + index = nColon + 1; + continue; + } + } + index = nColon + 1; + lastColon = nColon; + } + //result.Append(((lastColon == -1) ? "" : ":")); + return result.ToString(); + } + } +} diff --git a/server/tso.common/Rendering/Framework/3DAbstract.cs b/server/tso.common/Rendering/Framework/3DAbstract.cs new file mode 100755 index 0000000..eb92d5d --- /dev/null +++ b/server/tso.common/Rendering/Framework/3DAbstract.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; +using FSO.Common.Rendering.Framework.Camera; +using FSO.Common.Rendering.Framework.Model; + +namespace FSO.Common.Rendering.Framework +{ + /// + /// Base class for scenes with 3D elements. + /// + public abstract class _3DAbstract : IDisposable + { + public ICamera Camera; + public string ID; + public bool Visible = true; + public abstract List<_3DComponent> GetElements(); + public abstract void Add(_3DComponent item); + public abstract void Update(UpdateState Time); + public abstract void Draw(GraphicsDevice device); + + protected _3DLayer Parent; + private EventHandler ResetEvent; + + public virtual void PreDraw(GraphicsDevice device) + { + } + + public virtual void Initialize(_3DLayer layer) + { + Parent = layer; + } + + /// + /// Creates a new _3DAbstract instance. + /// + /// A GraphicsDevice instance. + public _3DAbstract(GraphicsDevice Device) + { + m_Device = Device; + ResetEvent = new EventHandler(m_Device_DeviceReset); + m_Device.DeviceReset += ResetEvent; + } + + /// + /// Called when m_Device is reset. + /// + private void m_Device_DeviceReset(object sender, EventArgs e) + { + DeviceReset(m_Device); + } + + protected GraphicsDevice m_Device; + + public abstract void DeviceReset(GraphicsDevice Device); + public static bool IsInvalidated; + + + + + + public object Controller { get; internal set; } + + public void SetController(object controller) + { + this.Controller = controller; + } + + public T FindController() + { + if(Controller is T) + { + return (T)Controller; + } + return default(T); + } + + public virtual void Dispose() + { + if (m_Device != null) m_Device.DeviceReset -= ResetEvent; + } + } +} diff --git a/server/tso.common/Rendering/Framework/3DComponent.cs b/server/tso.common/Rendering/Framework/3DComponent.cs new file mode 100755 index 0000000..323ebe4 --- /dev/null +++ b/server/tso.common/Rendering/Framework/3DComponent.cs @@ -0,0 +1,161 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using FSO.Common.Rendering.Framework.Model; + +namespace FSO.Common.Rendering.Framework +{ + public abstract class _3DComponent + { + public _3DScene Scene; + + public _3DComponent() + { + } + + private Vector3 m_Position = Vector3.Zero; + private Vector3 m_Scale = Vector3.One; + private float m_RotateX = 0.0f; + private float m_RotateY = 0.0f; + private float m_RotateZ = 0.0f; + + /// + /// Gets or the GraphicsDevice instance for this component. + /// + public GraphicsDevice Device + { + get + { + return Scene.Parent.Device; + } + } + + /// + /// The X component of this 3DComponent's rotation. + /// + public float RotationX + { + get { return m_RotateX; } + set + { + m_RotateX = value; + m_WorldDirty = true; + } + } + + /// + /// The Y component of this 3DComponent's rotation. + /// + public float RotationY + { + get { return m_RotateY; } + set + { + m_RotateY = value; + m_WorldDirty = true; + } + } + + /// + /// The Z component of this 3DComponent's rotation. + /// + public float RotationZ + { + get { return m_RotateZ; } + set + { + m_RotateZ = value; + m_WorldDirty = true; + } + } + + /// + /// This 3DComponent's position. + /// + public Vector3 Position + { + get { return m_Position; } + set + { + m_Position = value; + m_WorldDirty = true; + } + } + + /// + /// This 3DComponent's scale. + /// + public Vector3 Scale + { + get { return m_Scale; } + set + { + m_Scale = value; + m_WorldDirty = true; + } + } + + private Matrix m_World = Matrix.Identity; + private bool m_WorldDirty = false; + public Matrix World + { + get + { + if (m_WorldDirty) + { + m_World = Matrix.CreateRotationX(m_RotateX) * Matrix.CreateRotationY(m_RotateY) * Matrix.CreateRotationZ(m_RotateZ) * Matrix.CreateScale(m_Scale) * Matrix.CreateTranslation(m_Position); + m_WorldDirty = false; + } + return m_World; + } + } + + private string m_StringID; + public string ID + { + get { return m_StringID; } + set { m_StringID = value; } + } + + public virtual void Initialize() + { + } + + public abstract void Update(UpdateState state); + public abstract void Draw(GraphicsDevice device); + /// + /// GraphicsDevice was reset. + /// + public abstract void DeviceReset(GraphicsDevice Device); + + public override string ToString() + { + if (m_StringID != null) + { + return m_StringID; + } + return base.ToString(); + } + + /// + /// This 3DComponent's camera's view. + /// + protected Matrix View + { + get + { + return Scene.Camera.View; + } + } + + /// + /// This 3DComponent's camera's projection. + /// + protected Matrix Projection + { + get + { + return Scene.Camera.Projection; + } + } + } +} diff --git a/server/tso.common/Rendering/Framework/3DLayer.cs b/server/tso.common/Rendering/Framework/3DLayer.cs new file mode 100755 index 0000000..1abbdcc --- /dev/null +++ b/server/tso.common/Rendering/Framework/3DLayer.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering.Framework +{ + public class _3DLayer : IGraphicsLayer + { + public GraphicsDevice Device; + public List<_3DAbstract> Scenes = new List<_3DAbstract>(); + public List<_3DAbstract> External = new List<_3DAbstract>(); + + #region IGraphicsLayer Members + + public void Update(FSO.Common.Rendering.Framework.Model.UpdateState state) + { + foreach (var scene in Scenes) + { + scene.Update(state); + } + foreach (var scene in External) + { + scene.Update(state); + } + } + + public void PreDraw(Microsoft.Xna.Framework.Graphics.GraphicsDevice device) + { + foreach (var scene in Scenes) + { + if (scene.Visible) scene.PreDraw(device); + } + } + + public void Draw(Microsoft.Xna.Framework.Graphics.GraphicsDevice device) + { + foreach (var scene in Scenes) + { + if (scene.Visible) scene.Draw(device); + } + } + + public void Initialize(Microsoft.Xna.Framework.Graphics.GraphicsDevice device) + { + this.Device = device; + foreach (var scene in Scenes) + { + scene.Initialize(this); + } + foreach (var scene in External) + { + scene.Initialize(this); + } + } + + public void Add(_3DAbstract scene) + { + Scenes.Add(scene); + if (this.Device != null) + { + scene.Initialize(this); + } + } + + public void Remove(_3DAbstract scene) + { + Scenes.Remove(scene); + } + + public void Clear() + { + foreach (var scene in Scenes) + { + if (scene is IDisposable) ((IDisposable)scene).Dispose(); + } + Scenes.Clear(); + } + + /// + /// Adds a scene to the draw stack. The system will not call + /// Draw on the scene but it will be initialized and given updates + /// + /// + public void AddExternal(_3DAbstract scene){ + External.Add(scene); + if (this.Device != null) + { + scene.Initialize(this); + } + } + + public void RemoveExternal(_3DAbstract scene) + { + External.Remove(scene); + } + + #endregion + } +} diff --git a/server/tso.common/Rendering/Framework/3DScene.cs b/server/tso.common/Rendering/Framework/3DScene.cs new file mode 100755 index 0000000..31a37db --- /dev/null +++ b/server/tso.common/Rendering/Framework/3DScene.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using FSO.Common.Rendering.Framework.Camera; +using Microsoft.Xna.Framework.Graphics; +using FSO.Common.Rendering.Framework.Model; + +namespace FSO.Common.Rendering.Framework +{ + /// + /// A scene capable of rendering 3D elements. + /// + public class _3DScene : _3DAbstract + { + private List<_3DComponent> m_Elements = new List<_3DComponent>(); + + public new _3DLayer Parent; + + /// + /// Creates a new _3DScene instance. + /// + /// A GraphicsDevice instance used for rendering. + /// A camera inheriting from ICamera used for rendering. + public _3DScene(GraphicsDevice Device, ICamera camera) : base(Device) + { + this.Camera = camera; + } + + /// + /// Creates a new _3DScene instance. + /// + /// A GraphicsDevice instance used for rendering. + public _3DScene(GraphicsDevice Device) : base(Device) + { + } + + /// + /// Graphics device was reset (happens when scene is updated or minimized.) + /// + void m_Device_DeviceReset(object sender, EventArgs e) + { + throw new NotImplementedException(); + } + + /// + /// Returns the _3DComponents that make up this scene. + /// + /// A List of _3DComponent instances. + public override List<_3DComponent> GetElements() + { + return m_Elements; + } + + public override void Initialize(_3DLayer layer) + { + this.Parent = layer; + + foreach (var element in m_Elements) + { + element.Initialize(); + } + } + + public override void Update(UpdateState state) + { + for (int i = 0; i < m_Elements.Count; i++) + { + m_Elements[i].Update(state); + } + } + + /// + /// Removes a 3D element from this 3DScene. + /// + /// The _3DComponent instance to remove. + public void Remove(_3DComponent item) + { + m_Elements.Remove(item); + } + + /// + /// Adds a 3D element to this 3DScene. + /// + /// The _3DComponent instance to add. + public override void Add(_3DComponent item) + { + m_Elements.Add(item); + item.Scene = this; + if (this.Parent != null) + { + item.Initialize(); + } + } + + public override void PreDraw(GraphicsDevice device){ + } + + public override void Draw(GraphicsDevice device) + { + for (int i = 0; i < m_Elements.Count; i++) + { + m_Elements[i].Draw(device); + } + } + + public override string ToString() + { + if (ID != null) + { + return ID; + } + + return base.ToString(); + } + + /// + /// GraphicsDevice was reset. + /// + /// The GraphicsDevice instance. + public override void DeviceReset(GraphicsDevice Device) + { + for (int i = 0; i < m_Elements.Count; i++) + m_Elements[i].DeviceReset(Device); + } + } +} diff --git a/server/tso.common/Rendering/Framework/3DTargetScene.cs b/server/tso.common/Rendering/Framework/3DTargetScene.cs new file mode 100755 index 0000000..90cda62 --- /dev/null +++ b/server/tso.common/Rendering/Framework/3DTargetScene.cs @@ -0,0 +1,44 @@ +using FSO.Common.Rendering.Framework.Camera; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering.Framework +{ + public class _3DTargetScene : _3DScene + { + public RenderTarget2D Target; + private GraphicsDevice Device; + private int Multisample = 0; + public Color ClearColor = Color.Transparent; + public _3DTargetScene(GraphicsDevice device, ICamera camera, Point size, int multisample) : this(device, size, multisample) { Camera = camera; } + public _3DTargetScene(GraphicsDevice device, Point size, int multisample) : base(device) + { + Device = device; + Multisample = multisample; + SetSize(size); + } + + public void SetSize(Point size) + { + if (Target != null) Target.Dispose(); + Target = new RenderTarget2D(Device, size.X, size.Y, false, SurfaceFormat.Color, DepthFormat.Depth24Stencil8, Multisample, RenderTargetUsage.PreserveContents); + } + + public override void Draw(GraphicsDevice device) + { + var oldTargets = device.GetRenderTargets(); + device.SetRenderTarget(Target); + device.Clear(ClearColor); + device.DepthStencilState = DepthStencilState.Default; + Camera.ProjectionDirty(); + base.Draw(device); + device.SetRenderTargets(oldTargets); + } + + public override void Dispose() + { + base.Dispose(); + Target.Dispose(); + } + } +} diff --git a/server/tso.common/Rendering/Framework/Camera/BasicCamera.cs b/server/tso.common/Rendering/Framework/Camera/BasicCamera.cs new file mode 100755 index 0000000..901b5c4 --- /dev/null +++ b/server/tso.common/Rendering/Framework/Camera/BasicCamera.cs @@ -0,0 +1,273 @@ +using System; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System.ComponentModel; + +namespace FSO.Common.Rendering.Framework.Camera +{ + /// + /// A basic camera for the game. + /// + [DisplayName("BasicCamera")] + public class BasicCamera : ICamera + { + public float NearPlane { get; set; } + public float FarPlane { get; set; } + + public float AspectRatioMultiplier { get; set; } + + protected Vector3 m_Position; + protected Vector3 m_Target; + protected Vector3 m_Up; + protected GraphicsDevice m_Device; + + /// + /// Creates a new BasicCamera instance. Assumes projection is full screen! + /// + /// A GraphicsDevice instance used for rendering. + /// Camera's initial position. + /// Camera's initial target. + /// Camera's initial up vector. + public BasicCamera(GraphicsDevice device, Vector3 Position, Vector3 Target, Vector3 Up) + { + m_Device = device; + AspectRatioMultiplier = 1.0f; + NearPlane = 1.0f; + FarPlane = 800.0f; + + m_Position = Position; + m_Target = Target; + m_Up = Up; + + m_ViewDirty = true; + + /** + * Assume the projection is full screen, center origin + */ + ProjectionOrigin = new Vector2( + m_Device.Viewport.Width / 2.0f, + m_Device.Viewport.Height / 2.0f + ); + } + + protected Vector2 m_ProjectionOrigin = Vector2.Zero; + + /// + /// Gets or sets this BasicCamera's projection origin. + /// + public Vector2 ProjectionOrigin + { + get + { + return m_ProjectionOrigin; + } + set + { + m_ProjectionOrigin = value; + m_ProjectionDirty = true; + } + } + + protected Matrix m_Projection; + protected bool m_ProjectionDirty; + + public void ProjectionDirty() + { + m_ProjectionDirty = true; + } + + /// + /// Gets this camera's projection. + /// + [Browsable(false)] + public Matrix Projection + { + get + { + if (m_ProjectionDirty) + { + CalculateProjection(); + m_ProjectionDirty = false; + } + return m_Projection; + } + } + + private float _FOV = (float)Math.PI / 4f; + public float FOV + { + get + { + return _FOV; + } + set + { + _FOV = value; + ProjectionDirty(); + } + } + + protected virtual void CalculateProjection() + { + var device = m_Device; + var aspect = device.Viewport.AspectRatio * AspectRatioMultiplier; + + var ratioX = m_ProjectionOrigin.X / device.Viewport.Width; + var ratioY = m_ProjectionOrigin.Y / device.Viewport.Height; + + var projectionX = 0.0f - (1.0f * ratioX); + var projectionY = (1.0f * ratioY); + + m_Projection = Matrix.CreatePerspectiveFieldOfView(FOV, aspect, NearPlane, FarPlane); + + /*m_Projection = Matrix.CreatePerspectiveOffCenter( + projectionX, projectionX + 1.0f, + ((projectionY-1.0f) / aspect), (projectionY) / aspect, + NearPlane, FarPlane + );*/ + + m_Projection = Matrix.CreateScale(Zoom, Zoom, 1.0f) * m_Projection; + } + + protected virtual void CalculateView() + { + var translate = Matrix.CreateTranslation(m_Translation); + var position = Vector3.Transform(m_Position, translate); + var target = Vector3.Transform(m_Target, translate); + + m_View = Matrix.CreateLookAt(position, target, m_Up); + } + + protected bool m_ViewDirty = false; + protected Matrix m_View = Matrix.Identity; + [Browsable(false)] + public Matrix View + { + get + { + if (m_ViewDirty) + { + m_ViewDirty = false; + CalculateView(); + } + return m_View; + } + } + + + protected float m_Zoom = 1.0f; + + /// + /// Gets or sets this BasicCamera's zoom level. + /// + public float Zoom + { + get { return m_Zoom; } + set + { + m_Zoom = value; + m_ViewDirty = true; + m_ProjectionDirty = true; + } + } + + protected Vector3 m_Translation; + + /// + /// Gets or sets this BasicCamera's translation. + /// + public Vector3 Translation + { + get + { + return m_Translation; + } + set + { + m_Translation = value; + m_ViewDirty = true; + } + } + + /// + /// Gets or sets this BasicCamera's position. + /// + public Vector3 Position + { + get + { + return m_Position; + } + set + { + m_Position = value; + m_ViewDirty = true; + } + } + + /// + /// Gets or sets this BasicCamera's target. + /// + public Vector3 Target + { + get + { + return m_Target; + } + set + { + m_Target = value; + m_ViewDirty = true; + } + } + + /// + /// Gets or sets this BasicCamera's up vector. + /// + public Vector3 Up + { + get + { + return m_Up; + } + set + { + m_Up = value; + m_ViewDirty = true; + } + } + + public bool DrawCamera = false; + + public void Draw(GraphicsDevice device) + { + /* + device.RasterizerState.PointSize = 30.0f; + device.VertexDeclaration = new VertexDeclaration(device, VertexPositionColor.VertexElements); + + var effect = new BasicEffect(device); + + effect.World = Matrix.Identity; + effect.View = View; + effect.Projection = Projection; + effect.VertexColorEnabled = true; + + foreach (var pass in effect.Techniques[0].Passes) + { + pass.Apply(); + + var vertex = new VertexPositionColor(Position, Color.Green); + var vertexList = new VertexPositionColor[1] { vertex }; + device.DrawUserPrimitives(PrimitiveType.PointList, vertexList, 0, 1); + + vertex.Color = Color.Red; + vertex.Position = Target; + device.DrawUserPrimitives(PrimitiveType.PointList, vertexList, 0, 1); + + } + * XNA4 no longer has support for point primitives. + */ + } + + } +} diff --git a/server/tso.common/Rendering/Framework/Camera/ICamera.cs b/server/tso.common/Rendering/Framework/Camera/ICamera.cs new file mode 100755 index 0000000..3cc532b --- /dev/null +++ b/server/tso.common/Rendering/Framework/Camera/ICamera.cs @@ -0,0 +1,24 @@ +using Microsoft.Xna.Framework; + +namespace FSO.Common.Rendering.Framework.Camera +{ + public interface ICamera + { + Matrix View { get; } + Matrix Projection { get; } + + Vector3 Position { get; set; } + Vector3 Target { get; set; } + Vector3 Up { get; set; } + Vector3 Translation { get; set; } + + Vector2 ProjectionOrigin { get; set; } + float NearPlane { get; set; } + float FarPlane { get; set; } + float Zoom { get; set; } + float AspectRatioMultiplier { get; set; } + + void ProjectionDirty(); + + } +} diff --git a/server/tso.common/Rendering/Framework/Camera/ManualCamera.cs b/server/tso.common/Rendering/Framework/Camera/ManualCamera.cs new file mode 100755 index 0000000..bff5e01 --- /dev/null +++ b/server/tso.common/Rendering/Framework/Camera/ManualCamera.cs @@ -0,0 +1,35 @@ +namespace FSO.Common.Rendering.Framework.Camera +{ + public class ManualCamera : ICamera + { + #region ICamera Members + + public Microsoft.Xna.Framework.Matrix View { get; set; } + + public Microsoft.Xna.Framework.Matrix Projection { get; set; } + + public Microsoft.Xna.Framework.Vector3 Position { get; set; } + + public Microsoft.Xna.Framework.Vector3 Target { get; set; } + + public Microsoft.Xna.Framework.Vector3 Up { get; set; } + + public Microsoft.Xna.Framework.Vector3 Translation { get; set; } + + public Microsoft.Xna.Framework.Vector2 ProjectionOrigin { get; set; } + + public float NearPlane { get; set; } + + public float FarPlane { get; set; } + + public float Zoom { get; set; } + + public float AspectRatioMultiplier { get; set; } + + public void ProjectionDirty() + { + } + + #endregion + } +} diff --git a/server/tso.common/Rendering/Framework/Camera/OrthographicCamera.cs b/server/tso.common/Rendering/Framework/Camera/OrthographicCamera.cs new file mode 100755 index 0000000..10729fc --- /dev/null +++ b/server/tso.common/Rendering/Framework/Camera/OrthographicCamera.cs @@ -0,0 +1,37 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering.Framework.Camera +{ + /// + /// Orthographic camera for the game. Used for rendering lots. + /// + public class OrthographicCamera : BasicCamera + { + public OrthographicCamera(GraphicsDevice device, Vector3 Position, Vector3 Target, Vector3 Up) + : base(device, Position, Target, Up) + { + } + + protected override void CalculateProjection() + { + var device = m_Device; + var aspect = device.Viewport.AspectRatio * AspectRatioMultiplier; + + var ratioX = m_ProjectionOrigin.X / device.Viewport.Width; + var ratioY = m_ProjectionOrigin.Y / device.Viewport.Height; + + var projectionX = 0.0f - (1.0f * ratioX); + var projectionY = (1.0f * ratioY); + + m_Projection = Matrix.CreateOrthographicOffCenter( + projectionX, projectionX + 1.0f, + ((projectionY - 1.0f) / aspect), (projectionY) / aspect, + NearPlane, FarPlane + ); + + var zoom = 1 / m_Zoom; + m_Projection = m_Projection * Matrix.CreateScale(zoom); + } + } +} diff --git a/server/tso.common/Rendering/Framework/CursorManager.cs b/server/tso.common/Rendering/Framework/CursorManager.cs new file mode 100755 index 0000000..ab08476 --- /dev/null +++ b/server/tso.common/Rendering/Framework/CursorManager.cs @@ -0,0 +1,137 @@ +using System.Collections.Generic; +using System.IO; +using Microsoft.Xna.Framework.Input; +using Microsoft.Xna.Framework.Graphics; +using FSO.Common.Utils; + +namespace FSO.Common.Rendering.Framework +{ + public enum CursorType + { + Normal, + ArrowUp, + ArrowUpLeft, + ArrowUpRight, + ArrowDown, + ArrowDownLeft, + ArrowDownRight, + ArrowLeft, + ArrowRight, + LiveNothing, + LiveObjectUnavail, + LivePerson, + IBeam, + + SimsRotate, + SimsRotateNE, + SimsRotateSE, + SimsRotateSW, + SimsRotateNW, + + SimsMove, + SimsPlace, + + Hourglass, + + LiveObjectAvail, + LiveObject1Star, + LiveObject2Star, + LiveObject3Star, + LiveObject4Star, + LiveObject5Star, + LiveObjectSpecial, + } + + /// + /// Manages cursors in the game. + /// + public class CursorManager + { + public static CursorManager INSTANCE; + + private Dictionary m_CursorMap; + private GraphicsDevice GD; + public CursorType CurrentCursor { get; internal set;} = CursorType.Normal; + + public CursorManager(GraphicsDevice gd) + { + INSTANCE = this; + m_CursorMap = new Dictionary(); + this.GD = gd; + } + + public void SetCursor(CursorType type) + { + if (m_CursorMap.ContainsKey(type)) + { + CurrentCursor = type; + Mouse.SetCursor(m_CursorMap[type]); + } + } + + public Dictionary GenMap() + { + return new Dictionary< CursorType, string> (){ + //{CursorType.Normal, "arrow.cur"}, + { CursorType.ArrowUp, "up.cur"}, + { CursorType.ArrowUpLeft, "upleft.cur"}, + { CursorType.ArrowUpRight, "upright.cur"}, + { CursorType.ArrowDown, "down.cur"}, + { CursorType.ArrowDownLeft, "downleft.cur"}, + { CursorType.ArrowDownRight, "downright.cur"}, + { CursorType.ArrowLeft, "left.cur"}, + { CursorType.ArrowRight, "right.cur"}, + { CursorType.LiveNothing, "livenothing.cur"}, + { CursorType.LiveObjectAvail, "liveobjectavail.cur"}, + { CursorType.LiveObjectUnavail, "liveobjectunavail.cur"}, + { CursorType.LivePerson, "liveperson.cur"}, + + { CursorType.SimsRotate, "simsrotate.cur" }, + { CursorType.SimsRotateNE, "simsrotatene.cur" }, + { CursorType.SimsRotateNW, "simsrotatenw.cur" }, + { CursorType.SimsRotateSE, "simsrotatese.cur" }, + { CursorType.SimsRotateSW, "simsrotatesw.cur" }, + + { CursorType.SimsMove, "simsmove.cur" }, + { CursorType.SimsPlace, "simsplace.cur" }, + + { CursorType.Hourglass, "hourglass.cur" } + }; + } + + public void Init(string basepath, bool ts1) + { + var map = GenMap(); + var curPath = "UIGraphics/Shared/cursors/"; + if (!ts1) curPath = curPath.ToLowerInvariant(); + foreach (var item in map) + { + m_CursorMap.Add(item.Key, + LoadCustomCursor( + Path.Combine(basepath, curPath, item.Value) + )); + } + + var starMax = 5; + var stars = LoadUpgradeCursors(Path.Combine(basepath, curPath, "liveobjectavail.cur"), starMax); + for (int i=0; i + /// A screen used for drawing. + /// + public class GameScreen + { + public List Layers = new List(); + public GraphicsDevice Device; + public UpdateState State; + + public static Color ClearColor = new Color(0x72, 0x72, 0x72); + + private int touchedFrames; + private int lastTouchCount; + private MouseState lastMouseState; + private Vector2? prevTouchAvg; + private const int TOUCH_ACCEPT_TIME = 5; + + public GameScreen(GraphicsDevice device) + { + this.Device = device; + + State = new UpdateState(); + } + + private static List TextCharacters = new List(); + public static void TextInput(object sender, TextInputEventArgs e) + { + TextCharacters.Add(e.Character); + } + + /// + /// Adds a graphical element to this scene. + /// + /// Element inheriting from IGraphicsLayer. + public void Add(IGraphicsLayer layer) + { + layer.Initialize(Device); + Layers.Add(layer); + } + + public void Update(GameTime time, bool hasFocus) + { + State.Time = time; + State.PreviousKeyboardState = State.KeyboardState; + State.FrameTextInput = TextCharacters; + + var touchMode = FSOEnvironment.SoftwareKeyboard; + + if (touchMode) + { + if (FSOEnvironment.SoftwareDepth) State.KeyboardState = new KeyboardState(); + TouchCollection touches = TouchPanel.GetState(); + + var missing = new HashSet(State.MouseStates); + //relate touches to their last virtual mouse + foreach (var touch in touches) + { + var mouse = State.MouseStates.FirstOrDefault(x => x.ID == touch.Id); + if (mouse == null) + { + mouse = new MultiMouse { ID = touch.Id }; + State.MouseStates.Add(mouse); + } + missing.Remove(mouse); + + mouse.MouseState = new MouseState( + (int)touch.Position.X, (int)touch.Position.Y, 0, + ButtonState.Pressed, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released + ); + } + + //if virtual mouses no longer have their touch, they are performing a "mouse up" + //if the state has mouseovers, we should record the mouse state as being lifted. + foreach (var miss in missing) + { + if (miss.LastMouseOver == null && miss.LastMouseDown == null) + { + State.MouseStates.Remove(miss); + } else + { + miss.MouseState = new MouseState(miss.MouseState.X, miss.MouseState.Y, 0, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released, ButtonState.Released); + miss.Dead = true; + } + } + } + else + { + //single mouse state + if (hasFocus) + { + State.MouseState = Mouse.GetState(); + State.KeyboardState = Keyboard.GetState(); + } + else + { + State.MouseState = new MouseState(); + State.KeyboardState = new KeyboardState(); + } + + if (State.KeyboardState.IsKeyDown(Keys.LeftAlt) && State.MouseState.LeftButton == ButtonState.Pressed) + { + //emulated middle click with alt + var ms = State.MouseState; + State.MouseState = new MouseState(ms.X, ms.Y, ms.ScrollWheelValue, ButtonState.Released, ButtonState.Pressed, ms.RightButton, ms.XButton1, ms.XButton2); + } + + if (State.MouseStates.Count == 0) + { + State.MouseStates.Add(new MultiMouse { ID = 1 }); + } + + State.MouseStates[0].MouseState = State.MouseState; + } + + + State.SharedData.Clear(); + State.Update(); + + foreach (var layer in Layers){ + layer.Update(State); + } + + TextCharacters.Clear(); + } + + private void TouchStub(UpdateState state) + { + var test = TouchPanel.EnableMouseTouchPoint; + TouchCollection touches = TouchPanel.GetState(); + if (touches.Count != lastTouchCount) touchedFrames = 0; + lastTouchCount = touches.Count; + if (touches.Count > 0) + { + Vector2 avg = new Vector2(); + for (int i = 0; i < touches.Count; i++) + { + avg += touches[i].Position; + } + avg /= touches.Count; + + if (touchedFrames < TOUCH_ACCEPT_TIME) + { + avg = prevTouchAvg ?? avg; + state.MouseState = new MouseState( + (int)avg.X, (int)avg.Y, state.MouseState.ScrollWheelValue, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released + ); + touchedFrames++; + } + else + { + state.MouseState = new MouseState( + (int)avg.X, (int)avg.Y, state.MouseState.ScrollWheelValue, + (touches.Count > 1) ? ButtonState.Released : ButtonState.Pressed, + (touches.Count > 1) ? ButtonState.Pressed : ButtonState.Released, + (touches.Count > 1) ? ButtonState.Pressed : ButtonState.Released, + ButtonState.Released, + ButtonState.Released + ); + prevTouchAvg = avg; + + state.TouchMode = true; + } + } + else + { + prevTouchAvg = null; + touchedFrames = 0; + if (state.TouchMode) state.MouseState = new MouseState( + lastMouseState.X, lastMouseState.Y, state.MouseState.ScrollWheelValue, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released, + ButtonState.Released + ); + //state.TouchMode = false; + } + lastMouseState = state.MouseState; + } + + public void Draw(GameTime time) + { + lock (Device) + { + foreach (var layer in Layers.Reverse()) + { + layer.PreDraw(Device); + } + } + + Device.SetRenderTarget(null); + Device.BlendState = BlendState.AlphaBlend; + Device.Clear(ClearColor); + //Device.RasterizerState.AlphaBlendEnable = true; + //Device.DepthStencilState.DepthBufferEnable = true; + + lock (Device) + { + foreach (var layer in Layers) + { + layer.Draw(Device); + } + } + } + } +} diff --git a/server/tso.common/Rendering/Framework/I3DGeometry.cs b/server/tso.common/Rendering/Framework/I3DGeometry.cs new file mode 100755 index 0000000..8752919 --- /dev/null +++ b/server/tso.common/Rendering/Framework/I3DGeometry.cs @@ -0,0 +1,8 @@ +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering.Framework +{ + public interface I3DGeometry { + void DrawGeometry(GraphicsDevice gd); + } +} diff --git a/server/tso.common/Rendering/Framework/IGraphicsLayer.cs b/server/tso.common/Rendering/Framework/IGraphicsLayer.cs new file mode 100755 index 0000000..c7c7762 --- /dev/null +++ b/server/tso.common/Rendering/Framework/IGraphicsLayer.cs @@ -0,0 +1,13 @@ +using FSO.Common.Rendering.Framework.Model; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering.Framework +{ + public interface IGraphicsLayer + { + void Initialize(GraphicsDevice device); + void Update(UpdateState state); + void PreDraw(GraphicsDevice device); + void Draw(GraphicsDevice device); + } +} diff --git a/server/tso.common/Rendering/Framework/IO/ClipboardHandler.cs b/server/tso.common/Rendering/Framework/IO/ClipboardHandler.cs new file mode 100755 index 0000000..b3c5818 --- /dev/null +++ b/server/tso.common/Rendering/Framework/IO/ClipboardHandler.cs @@ -0,0 +1,10 @@ +namespace FSO.Common.Rendering.Framework.IO +{ + public class ClipboardHandler + { + public static ClipboardHandler Default = new ClipboardHandler(); + + public virtual string Get() { return ""; } + public virtual void Set(string text) { } + } +} diff --git a/server/tso.common/Rendering/Framework/IO/IDepthProvider.cs b/server/tso.common/Rendering/Framework/IO/IDepthProvider.cs new file mode 100755 index 0000000..a8b3322 --- /dev/null +++ b/server/tso.common/Rendering/Framework/IO/IDepthProvider.cs @@ -0,0 +1,10 @@ +namespace FSO.Common.Rendering.Framework.IO +{ + /// + /// Represents an object that has depth + /// + public interface IDepthProvider + { + float Depth { get; } + } +} diff --git a/server/tso.common/Rendering/Framework/IO/IFocusableUI.cs b/server/tso.common/Rendering/Framework/IO/IFocusableUI.cs new file mode 100755 index 0000000..a69829e --- /dev/null +++ b/server/tso.common/Rendering/Framework/IO/IFocusableUI.cs @@ -0,0 +1,13 @@ +namespace FSO.Common.Rendering.Framework.IO +{ + public interface IFocusableUI + { + void OnFocusChanged(FocusEvent newFocus); + } + + public enum FocusEvent + { + FocusIn, + FocusOut + } +} diff --git a/server/tso.common/Rendering/Framework/IO/InputManager.cs b/server/tso.common/Rendering/Framework/IO/InputManager.cs new file mode 100755 index 0000000..6a4868e --- /dev/null +++ b/server/tso.common/Rendering/Framework/IO/InputManager.cs @@ -0,0 +1,571 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Microsoft.Xna.Framework.Input; +using System.Runtime.InteropServices; +using FSO.Common.Rendering.Framework.Model; + +namespace FSO.Common.Rendering.Framework.IO +{ + /// + /// Manages input for the game. + /// + public class InputManager + { + private IFocusableUI LastFocus; + public bool RequireWindowFocus = false; + + public void SetFocus(IFocusableUI ui) + { + /** No change **/ + if (ui == LastFocus) { return; } + + if (LastFocus != null) + { + LastFocus.OnFocusChanged(FocusEvent.FocusOut); + } + + LastFocus = ui; + if (ui != null) + { + LastFocus.OnFocusChanged(FocusEvent.FocusIn); + } + } + + public IFocusableUI GetFocus() + { + return LastFocus; + } + + [DllImport("user32.dll")] + static extern int MapVirtualKey(uint uCode, uint uMapType); + + /// + /// Utility to apply the result of pressing keys against a buffer + /// + /// + /// + public KeyboardInputResult ApplyKeyboardInput(StringBuilder m_SBuilder, UpdateState state, int cursorIndex, int cursorEndIndex, bool allowInput) + { + if (!state.WindowFocused && RequireWindowFocus) { return null; } + + var PressedKeys = state.KeyboardState.GetPressedKeys(); + int charCount = 0; + if (state.FrameTextInput == null) charCount = 0; + else charCount = state.FrameTextInput.Count; + + if (PressedKeys.Length + charCount == 0) { return null; } + //bit of a legacy thing going on here + //we support both "pressed keys" and the keyboard event system. + //todo: clean up a bit + + var didChange = false; + var result = new KeyboardInputResult(); + + var m_CurrentKeyState = state.KeyboardState; + var m_OldKeyState = state.PreviousKeyboardState; + + + result.ShiftDown = PressedKeys.Contains(Keys.LeftShift) || PressedKeys.Contains(Keys.RightShift); + result.CapsDown = state.KeyboardState.CapsLock; + result.NumLockDown = state.KeyboardState.NumLock; + // Right alt aka AltGr is treated as Ctrl+Alt. It is used to type accented letters and other unusual characters so pressing that key cannot cause special actions. + result.CtrlDown = (PressedKeys.Contains(Keys.LeftControl) && !PressedKeys.Contains(Keys.RightAlt)) || PressedKeys.Contains(Keys.RightControl); + + for (int j = 0; j < state.NewKeys.Count + charCount; j++) + { + var key = (j 0) + { + /** + * Delete previous character or delete selection + */ + if (cursorEndIndex == -1 && result.CtrlDown) + { + /** Delete up until the previous whitespace char **/ + int newEndIndex = cursorIndex; + if (newEndIndex == -1) + { + newEndIndex = m_SBuilder.Length; + cursorIndex = m_SBuilder.Length; + } + int dir = (key == Keys.Delete) ? 1 : -1; + int ws = (key == Keys.Delete) ? 0 : -1; + while (newEndIndex+ws >= 0 && newEndIndex+ws < m_SBuilder.Length) + { + if (Char.IsWhiteSpace(m_SBuilder[newEndIndex+ws])) + { + /** Keep the whitespace char **/ + break; + } + newEndIndex += dir; + } + if (cursorIndex > newEndIndex) + { + cursorEndIndex = cursorIndex; + cursorIndex = newEndIndex; + } + else + cursorEndIndex = newEndIndex; + if (cursorEndIndex == cursorIndex) + cursorIndex = cursorEndIndex = -1; + } + + if (cursorEndIndex == -1) + { + /** Previous character **/ + var index = cursorIndex == -1 ? m_SBuilder.Length : cursorIndex; + if ((key == Keys.Back) && (index > 0)) + { + var numToDelete = 1; + if (index > 1 && m_SBuilder[index - 1] == '\n' && m_SBuilder[index - 2] == '\r') + { + numToDelete = 2; + } + + + m_SBuilder.Remove(index - numToDelete, numToDelete); + result.NumDeletes += numToDelete; + + if (cursorIndex != -1) + { + cursorIndex -= numToDelete; + } + } + else if ((key == Keys.Delete) && (index < m_SBuilder.Length)) + { + /** Guys, delete removes the next character, not the last!! **/ + var numToDelete = 1; + if ((index < m_SBuilder.Length - 1) && m_SBuilder[index] == '\r' && m_SBuilder[index + 1] == '\n') + { + numToDelete = 2; + } + + m_SBuilder.Remove(index, numToDelete); + result.NumDeletes += numToDelete; + } + } + else + { + DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result); + } + result.SelectionChanged = true; + didChange = true; + } + } + else if (key == Keys.Enter) + { + if (allowInput) + { + /** Line break **/ + if (cursorEndIndex != -1) + { + /** Delete selected text **/ + DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result); + } + + if (cursorIndex == -1) + { + m_SBuilder.Append("\n"); + } + else + { + cursorIndex = Math.Min(m_SBuilder.Length, cursorIndex); + m_SBuilder.Insert(cursorIndex, "\n"); + cursorIndex += 1; + } + result.NumInsertions += 1; + didChange = true; + result.EnterPressed = true; + } + } + else if (key == Keys.Tab) + { + result.TabPressed = true; + } + else if (result.CtrlDown) + { + switch (key) + { + case Keys.A: + /** Select all **/ + cursorIndex = 0; + cursorEndIndex = m_SBuilder.Length; + result.SelectionChanged = true; + break; + + case Keys.C: + case Keys.X: + /** Copy text to clipboard **/ + if (cursorEndIndex > 0) + { + var selectionStart = Math.Max(0, cursorIndex); + var selectionEnd = cursorEndIndex; + GetSelectionRange(ref selectionStart, ref selectionEnd); + + var str = m_SBuilder.ToString().Substring(selectionStart, selectionEnd - selectionStart); + + ClipboardHandler.Default.Set(str); + + if (key == Keys.X) + { + DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result); + } + } + break; + + case Keys.V: + /** Paste text in **/ + var clipboardText = ClipboardHandler.Default.Get(); + + if (clipboardText != null) + { + /** TODO: Cleanup the clipboard text to make sure its valid **/ + + /** If i have selection, delete it **/ + if (cursorEndIndex != -1) + { + DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result); + } + + /** Paste **/ + if (cursorIndex == -1) + { + m_SBuilder.Append(clipboardText); + } + else + { + m_SBuilder.Insert(Math.Min(cursorIndex, m_SBuilder.Length), clipboardText); + cursorIndex += clipboardText.Length; + } + result.NumInsertions += clipboardText.Length; + didChange = true; + } + break; + } + } else { + result.UnhandledKeys.Add(key); + processChar = true; + } + } + + if (processChar) + { + char value; + if (j >= state.NewKeys.Count) value = state.FrameTextInput[j - state.NewKeys.Count]; + else if (state.FrameTextInput != null) continue; + else value = TranslateChar(key, result.ShiftDown, result.CapsDown, result.NumLockDown); + /** For now we dont support tabs in text **/ + + if (!char.IsControl(value) && value != '\0' && value != '\t' && value != '\b' && value != '\r') + { + if (allowInput) + { + if (cursorEndIndex != -1) + { + /** Delete selected text **/ + DeleteSelectedText(m_SBuilder, ref cursorIndex, ref cursorEndIndex, ref didChange, result); + } + + if (cursorIndex == -1) + { + m_SBuilder.Append(value); + } + else + { + m_SBuilder.Insert(cursorIndex, value); + cursorIndex++; + } + result.NumInsertions++; + didChange = true; + } + } + else + { + result.UnhandledKeys.Add(key); + } + } + } + + result.SelectionStart = cursorIndex; + result.SelectionEnd = cursorEndIndex; + + result.ContentChanged = didChange; + return result; + } + + private void DeleteSelectedText(StringBuilder m_SBuilder, ref int cursorIndex, ref int cursorEndIndex, ref bool didChange, KeyboardInputResult result) + { + /** Remove selected text **/ + var index = cursorIndex == -1 ? m_SBuilder.Length : cursorIndex; + var end = cursorEndIndex; + if (end < index) + { + var temp = index; + index = end; + end = temp; + } + m_SBuilder.Remove(index, end - index); + + cursorIndex = index; + if (cursorIndex >= m_SBuilder.Length) + { + cursorIndex = -1; + } + cursorEndIndex = -1; + result.SelectionChanged = true; + didChange = true; + } + + public void GetSelectionRange(ref int start, ref int end) + { + if (end < start) + { + var temp = start; + start = end; + end = temp; + } + } + + public static char TranslateChar(Keys key, bool shift, bool capsLock, bool numLock) + { + + switch (key) + { + + case Keys.A: return TranslateAlphabetic('a', shift, capsLock); + + case Keys.B: return TranslateAlphabetic('b', shift, capsLock); + + case Keys.C: return TranslateAlphabetic('c', shift, capsLock); + + case Keys.D: return TranslateAlphabetic('d', shift, capsLock); + + case Keys.E: return TranslateAlphabetic('e', shift, capsLock); + + case Keys.F: return TranslateAlphabetic('f', shift, capsLock); + + case Keys.G: return TranslateAlphabetic('g', shift, capsLock); + + case Keys.H: return TranslateAlphabetic('h', shift, capsLock); + + case Keys.I: return TranslateAlphabetic('i', shift, capsLock); + + case Keys.J: return TranslateAlphabetic('j', shift, capsLock); + + case Keys.K: return TranslateAlphabetic('k', shift, capsLock); + + case Keys.L: return TranslateAlphabetic('l', shift, capsLock); + + case Keys.M: return TranslateAlphabetic('m', shift, capsLock); + + case Keys.N: return TranslateAlphabetic('n', shift, capsLock); + + case Keys.O: return TranslateAlphabetic('o', shift, capsLock); + + case Keys.P: return TranslateAlphabetic('p', shift, capsLock); + + case Keys.Q: return TranslateAlphabetic('q', shift, capsLock); + + case Keys.R: return TranslateAlphabetic('r', shift, capsLock); + + case Keys.S: return TranslateAlphabetic('s', shift, capsLock); + + case Keys.T: return TranslateAlphabetic('t', shift, capsLock); + + case Keys.U: return TranslateAlphabetic('u', shift, capsLock); + + case Keys.V: return TranslateAlphabetic('v', shift, capsLock); + + case Keys.W: return TranslateAlphabetic('w', shift, capsLock); + + case Keys.X: return TranslateAlphabetic('x', shift, capsLock); + + case Keys.Y: return TranslateAlphabetic('y', shift, capsLock); + + case Keys.Z: return TranslateAlphabetic('z', shift, capsLock); + + case Keys.D0: return (shift) ? ')' : '0'; + + case Keys.D1: return (shift) ? '!' : '1'; + + case Keys.D2: return (shift) ? '@' : '2'; + + case Keys.D3: return (shift) ? '#' : '3'; + + case Keys.D4: return (shift) ? '$' : '4'; + + case Keys.D5: return (shift) ? '%' : '5'; + + case Keys.D6: return (shift) ? '^' : '6'; + + case Keys.D7: return (shift) ? '&' : '7'; + + case Keys.D8: return (shift) ? '*' : '8'; + + case Keys.D9: return (shift) ? '(' : '9'; + + case Keys.Add: return '+'; + + case Keys.Divide: return '/'; + + case Keys.Multiply: return '*'; + + case Keys.Subtract: return '-'; + + case Keys.Space: return ' '; + + case Keys.Tab: return '\t'; + + case Keys.Decimal: if (numLock && !shift) return '.'; break; + + case Keys.NumPad0: if (numLock && !shift) return '0'; break; + + case Keys.NumPad1: if (numLock && !shift) return '1'; break; + + case Keys.NumPad2: if (numLock && !shift) return '2'; break; + + case Keys.NumPad3: if (numLock && !shift) return '3'; break; + + case Keys.NumPad4: if (numLock && !shift) return '4'; break; + + case Keys.NumPad5: if (numLock && !shift) return '5'; break; + + case Keys.NumPad6: if (numLock && !shift) return '6'; break; + + case Keys.NumPad7: if (numLock && !shift) return '7'; break; + + case Keys.NumPad8: if (numLock && !shift) return '8'; break; + + case Keys.NumPad9: if (numLock && !shift) return '9'; break; + + case Keys.OemBackslash: return shift ? '|' : '\\'; + + case Keys.OemCloseBrackets: return shift ? '}' : ']'; + + case Keys.OemComma: return shift ? '<' : ','; + + case Keys.OemMinus: return shift ? '_' : '-'; + + case Keys.OemOpenBrackets: return shift ? '{' : '['; + + case Keys.OemPeriod: return shift ? '>' : '.'; + + case Keys.OemPipe: return shift ? '|' : '\\'; + + case Keys.OemPlus: return shift ? '+' : '='; + + case Keys.OemQuestion: return shift ? '?' : '/'; + + case Keys.OemQuotes: return shift ? '"' : '\''; + + case Keys.OemSemicolon: return shift ? ':' : ';'; + + case Keys.OemTilde: return shift ? '~' : '`'; + } + + return (char)0; + } + + public static char TranslateAlphabetic(char baseChar, bool shift, bool capsLock) + { + return (capsLock ^ shift) ? char.ToUpper(baseChar) : baseChar; + } + + public void HandleMouseEvents(UpdateState state) + { + foreach (var mouse in state.MouseStates) { + var mouseBtnDown = mouse.MouseState.LeftButton == Microsoft.Xna.Framework.Input.ButtonState.Pressed; + var mouseDif = mouseBtnDown != mouse.LastMouseDownState; + if (mouse.NewMultiMouse) mouse.NewMultiMouse = false; + else + mouse.LastMouseDownState = mouseBtnDown; + state.MouseState = mouse.MouseState; //make sure each event uses the mouse state for this mouse. + state.CurrentMouseID = mouse.ID; + //if anyone accesses vanilla mouse state during the update loop, it will be the last mouse that was present. + + var topMost = + state.MouseEvents.Where(x => x.Item1 == mouse.ID).OrderByDescending(x => x.Item2.Element.Depth).FirstOrDefault(); + + if (topMost != null && !mouse.Dead) + { + + /** different element? **/ + if (mouse.LastMouseOver != topMost.Item2) + { + + if (mouse.LastMouseOver != null) + { + mouse.LastMouseOver.Callback(UIMouseEventType.MouseOut, state); + } + + topMost.Item2.Callback(UIMouseEventType.MouseOver, state); + mouse.LastMouseOver = topMost.Item2; + } + } + else + { + if (mouse.LastMouseOver != null) + { + mouse.LastMouseOver.Callback(UIMouseEventType.MouseOut, state); + mouse.LastMouseOver = null; + } + } + + if (mouseDif) + { + if (mouseBtnDown) + { + if (mouse.LastMouseDown != null) + { + /** We already have mouse down on an object **/ + return; + } + if (mouse.LastMouseOver != null) + { + mouse.LastMouseDown = mouse.LastMouseOver; + mouse.LastMouseDown.Callback(UIMouseEventType.MouseDown, state); + } + } + else + { + if (mouse.LastMouseDown != null) + { + mouse.LastMouseDown.Callback(UIMouseEventType.MouseUp, state); + mouse.LastMouseDown = null; + } + } + } + } + + } + + } + + public class KeyboardInputResult + { + public List UnhandledKeys = new List(); + public bool ContentChanged; + public bool ShiftDown; + public bool CapsDown; + public bool NumLockDown; + public bool CtrlDown; + public bool EnterPressed; + public bool TabPressed; + + public int NumDeletes; + public int NumInsertions; + + public int SelectionStart; + public int SelectionEnd; + public bool SelectionChanged; + } +} diff --git a/server/tso.common/Rendering/Framework/IO/MouseEvent.cs b/server/tso.common/Rendering/Framework/IO/MouseEvent.cs new file mode 100755 index 0000000..dbd9974 --- /dev/null +++ b/server/tso.common/Rendering/Framework/IO/MouseEvent.cs @@ -0,0 +1,25 @@ +using FSO.Common.Rendering.Framework.Model; +using Microsoft.Xna.Framework; + +namespace FSO.Common.Rendering.Framework.IO +{ + public enum UIMouseEventType + { + MouseOver, + MouseOut, + MouseDown, + MouseUp + } + + public delegate void UIMouseEvent(UIMouseEventType type, UpdateState state); + + public class UIMouseEventRef + { + public UIMouseEvent Callback; + public Rectangle Region; + //public UIElement Element; + public UIMouseEventType LastState; + + public IDepthProvider Element; + } +} diff --git a/server/tso.common/Rendering/Framework/Model/UIState.cs b/server/tso.common/Rendering/Framework/Model/UIState.cs new file mode 100755 index 0000000..caa28b8 --- /dev/null +++ b/server/tso.common/Rendering/Framework/Model/UIState.cs @@ -0,0 +1,21 @@ +using Microsoft.Xna.Framework; + +namespace FSO.Common.Rendering.Framework.Model +{ + public class UIState + { + public int Width; + public int Height; + public UITooltipProperties TooltipProperties = new UITooltipProperties(); + public string Tooltip; + } + + public class UITooltipProperties + { + public float Opacity; + public Vector2 Position; + public bool Show; + public Color Color = Color.Black; + public bool UpdateDead; + } +} diff --git a/server/tso.common/Rendering/Framework/Model/UpdateState.cs b/server/tso.common/Rendering/Framework/Model/UpdateState.cs new file mode 100755 index 0000000..1198d79 --- /dev/null +++ b/server/tso.common/Rendering/Framework/Model/UpdateState.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Input; +using FSO.Common.Rendering.Framework.IO; + +namespace FSO.Common.Rendering.Framework.Model +{ + public class MultiMouse + { + public int ID; + public MouseState MouseState; + public UIMouseEventRef LastMouseDown; + public UIMouseEventRef LastMouseOver; + public bool LastMouseDownState = false; + public bool NewMultiMouse = true; + public bool Dead = false; + } + + /// + /// Contains common information used in the update loop + /// + public class UpdateState + { + public GameTime Time; + public List MouseStates = new List(); + public MouseState MouseState; + public int CurrentMouseID; + public KeyboardState KeyboardState; + public bool ShiftDown + { + get { return KeyboardState.IsKeyDown(Keys.LeftShift) || KeyboardState.IsKeyDown(Keys.RightShift); } + } + /// + /// Right alt is treated as LeftCtrl+RightAlt so while right Alt is down, you cannot predict if left Ctrl is also down. + /// For that reason, this variable is false when left Ctrl and right Alt are down, and right Ctrl is not down. + /// + public bool CtrlDown + { + get { return (KeyboardState.IsKeyDown(Keys.LeftControl) && !KeyboardState.IsKeyDown(Keys.RightAlt)) || KeyboardState.IsKeyDown(Keys.RightControl); } + } + public bool AltDown + { + get { return KeyboardState.IsKeyDown(Keys.LeftAlt) || KeyboardState.IsKeyDown(Keys.RightAlt); } + } + + public UIState UIState = new UIState(); + public InputManager InputManager; + public bool TouchMode; + + public KeyboardState PreviousKeyboardState; + public List FrameTextInput; + + /** A Place to keep shared variables, clears every update cycle **/ + public Dictionary SharedData = new Dictionary(); + public List> MouseEvents = new List>(); + + private Dictionary KeyDownTime = new Dictionary(); + private List KeyInRepeatMode = new List(); + + public List NewKeys = new List(); + public int Depth; + + public bool WindowFocused; + public bool MouseOverWindow; + + public bool ProcessMouseEvents + { + get + { + return WindowFocused && MouseOverWindow; + } + } + + public void Update() + { + NewKeys.Clear(); + Depth = 0; + + /** + * If a key has been held down for X duration, treat it as if it is newly + * pressed + */ + for(var i=0; i < KeyInRepeatMode.Count; i++){ + + if (!KeyboardState.IsKeyDown(KeyInRepeatMode[i])) + { + KeyInRepeatMode.RemoveAt(i); + i--; + } + } + + var now = Time.TotalGameTime.Ticks; + var keys = KeyboardState.GetPressedKeys(); + + foreach (var key in keys) + { + var newPress = PreviousKeyboardState.IsKeyUp(key); + if (newPress) + { + KeyDownTime[key] = now; + NewKeys.Add(key); + } + else + { + if (KeyInRepeatMode.Contains(key)) + { + + /** How long has it been down? **/ + if (now - KeyDownTime[key] > 400000) + { + /** Its been down long enough, consider it a new key **/ + KeyDownTime[key] = now; + NewKeys.Add(key); + } + } + else + { + /** How long has it been down? **/ + if (now - KeyDownTime[key] > 9000000) + { + /** Its been down long enough, consider it in repeat mode **/ + KeyDownTime[key] = now; + KeyInRepeatMode.Add(key); + } + } + } + } + } + } +} diff --git a/server/tso.common/Rendering/Framework/Shapes/3DCube.cs b/server/tso.common/Rendering/Framework/Shapes/3DCube.cs new file mode 100755 index 0000000..52a7521 --- /dev/null +++ b/server/tso.common/Rendering/Framework/Shapes/3DCube.cs @@ -0,0 +1,86 @@ +using System.Collections.Generic; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace FSO.Common.Rendering.Framework.Shapes +{ + public class _3DCube : _3DComponent + { + private BasicEffect Effect; + + private VertexPositionColor[] Geom; + private List GeomList; + + private Color Color; + private Vector3 Size; + + public _3DCube(Color color, Vector3 size) + { + this.Color = color; + this.Size = size; + } + + public override void Initialize(){ + + Effect = new BasicEffect(Device); + + /** Bottom Face **/ + var btmTL = new Vector3(0.0f, 0.0f, 0.0f); + var btmTR = new Vector3(Size.X, 0.0f, 0.0f); + var btmBR = new Vector3(Size.X, 0.0f, Size.Z); + var btmBL = new Vector3(0.0f, 0.0f, Size.Z); + + /** Top face **/ + var topTL = new Vector3(0.0f, Size.Y, 0.0f); + var topTR = new Vector3(Size.X, Size.Y, 0.0f); + var topBR = new Vector3(Size.X, Size.Y, Size.Z); + var topBL = new Vector3(0.0f, Size.Y, Size.Z); + + + GeomList = new List(); + AddQuad(Color, topTL, topTR, topBR, topBL); + AddQuad(Color.Yellow, btmTL, btmTR, btmBR, btmBL); + AddQuad(Color.Green, topTL, topTR, btmTR, btmTL); + AddQuad(Color.Blue, topBL, topTL, btmTL, btmBL); + AddQuad(Color.Orange, topBR, topTR, btmTR, btmBR); + AddQuad(Color.White, topBL, topBR, btmBR, btmBL); + + Geom = GeomList.ToArray(); + } + + private void AddQuad(Color color, Vector3 tl, Vector3 tr, Vector3 br, Vector3 bl) + { + GeomList.Add(new VertexPositionColor(tl, color)); + GeomList.Add(new VertexPositionColor(tr, color)); + GeomList.Add(new VertexPositionColor(br, color)); + + GeomList.Add(new VertexPositionColor(br, color)); + GeomList.Add(new VertexPositionColor(bl, color)); + GeomList.Add(new VertexPositionColor(tl, color)); + } + + public override void Draw(GraphicsDevice device) + { + + Effect.World = World; + Effect.View = View; + Effect.Projection = Projection; + Effect.VertexColorEnabled = true; + //Effect.EnableDefaultLighting(); + + foreach (var pass in Effect.CurrentTechnique.Passes) + { + pass.Apply(); + device.DrawUserPrimitives(PrimitiveType.TriangleList, Geom, 0, Geom.Length / 3); + } + } + + public override void Update(FSO.Common.Rendering.Framework.Model.UpdateState state) + { + } + + public override void DeviceReset(GraphicsDevice Device) + { + } + } +} diff --git a/server/tso.common/Rendering/Framework/UpdateHookDelegate.cs b/server/tso.common/Rendering/Framework/UpdateHookDelegate.cs new file mode 100755 index 0000000..fef89fe --- /dev/null +++ b/server/tso.common/Rendering/Framework/UpdateHookDelegate.cs @@ -0,0 +1,6 @@ +using FSO.Common.Rendering.Framework.Model; + +namespace FSO.Common.Rendering.Framework +{ + public delegate void UpdateHookDelegate(UpdateState state); +} diff --git a/server/tso.common/Rendering/TextureInfo.cs b/server/tso.common/Rendering/TextureInfo.cs new file mode 100755 index 0000000..e4b6af0 --- /dev/null +++ b/server/tso.common/Rendering/TextureInfo.cs @@ -0,0 +1,21 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Rendering +{ + public class TextureInfo + { + public Vector2 UVScale; + public Point Size; + public Point Diff; + + public TextureInfo() { } + + public TextureInfo(Texture2D tex, int width, int height) + { + Size = new Point(width, height); + Diff = new Point(tex.Width, tex.Height) - Size; + UVScale = Size.ToVector2() / new Vector2(tex.Width, tex.Height); + } + } +} diff --git a/server/tso.common/Rendering/TimeOfDayConfig.cs b/server/tso.common/Rendering/TimeOfDayConfig.cs new file mode 100755 index 0000000..df31774 --- /dev/null +++ b/server/tso.common/Rendering/TimeOfDayConfig.cs @@ -0,0 +1,69 @@ +using Microsoft.Xna.Framework; +using System; + +namespace FSO.Common.Rendering +{ + public static class TimeOfDayConfig + { + public static float DarknessMultiplier = 0.8f; + private static Color[] m_TimeColors = new Color[] + { + new Color(50, 70, 122)*1.25f, + new Color(50, 70, 122)*1.25f, + new Color(55, 75, 111)*1.25f, + new Color(70, 70, 70)*1.25f, + new Color(217, 109, 50), //sunrise + new Color(255, 255, 255), + new Color(255, 255, 255), //peak + new Color(255, 255, 255), //peak + new Color(255, 255, 255), + new Color(255, 255, 255), + new Color(217, 109, 50), //sunset + new Color(70, 70, 70)*1.25f, + new Color(55, 75, 111)*1.25f, + new Color(50, 70, 122)*1.25f, + }; + + private static float[] m_SkyColors = new float[] + { + 4/8f, + 4/8f, + 4/8f, + 5/8f, + 6/8f, //sunrise + 7/8f, + 8/8f, //peak + 0/8f, //peak + 0/8f, + 0/8f, + 1/8f, //sunset + 2/8f, + 3/8f, + 4/8f, + }; + + private static Color PowColor(Color col, float pow) + { + var vec = col.ToVector4(); + vec.X = (float)Math.Pow(vec.X, pow); + vec.Y = (float)Math.Pow(vec.Y, pow); + vec.Z = (float)Math.Pow(vec.Z, pow); + + return new Color(vec); + } + + public static Color ColorFromTime(double time) + { + Color col1 = m_TimeColors[(int)Math.Floor(time * (m_TimeColors.Length - 1))]; //first colour + Color col2 = m_TimeColors[(int)Math.Floor(time * (m_TimeColors.Length - 1)) + 1]; //second colour + if (DarknessMultiplier != 1.0) + { + col1 = Color.Lerp(Color.White, col1, DarknessMultiplier); + col2 = Color.Lerp(Color.White, col2, DarknessMultiplier); + } + double Progress = (time * (m_TimeColors.Length - 1)) % 1; //interpolation progress (mod 1) + + return PowColor(Color.Lerp(col1, col2, (float)Progress), 2.2f); //linearly interpolate between the two colours for this specific time. + } + } +} diff --git a/server/tso.common/Security/AvatarPermissions.cs b/server/tso.common/Security/AvatarPermissions.cs new file mode 100755 index 0000000..0e6cd3b --- /dev/null +++ b/server/tso.common/Security/AvatarPermissions.cs @@ -0,0 +1,7 @@ +namespace FSO.Common.Security +{ + public enum AvatarPermissions + { + WRITE + } +} diff --git a/server/tso.common/Security/ISecurityContext.cs b/server/tso.common/Security/ISecurityContext.cs new file mode 100755 index 0000000..851deb1 --- /dev/null +++ b/server/tso.common/Security/ISecurityContext.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace FSO.Common.Security +{ + public interface ISecurityContext + { + void DemandAvatar(uint id, AvatarPermissions permission); + void DemandAvatars(IEnumerable id, AvatarPermissions permission); + void DemandInternalSystem(); + } +} diff --git a/server/tso.common/Security/NullSecurityContext.cs b/server/tso.common/Security/NullSecurityContext.cs new file mode 100755 index 0000000..6b9d748 --- /dev/null +++ b/server/tso.common/Security/NullSecurityContext.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace FSO.Common.Security +{ + public class NullSecurityContext : ISecurityContext + { + public static NullSecurityContext INSTANCE = new NullSecurityContext(); + + + public void DemandAvatar(uint id, AvatarPermissions permission) + { + } + + public void DemandAvatars(IEnumerable id, AvatarPermissions permission) + { + } + + public void DemandInternalSystem() + { + } + } +} diff --git a/server/tso.common/Serialization/IModelSerializer.cs b/server/tso.common/Serialization/IModelSerializer.cs new file mode 100755 index 0000000..7f44afd --- /dev/null +++ b/server/tso.common/Serialization/IModelSerializer.cs @@ -0,0 +1,27 @@ +using Mina.Core.Buffer; +using System; + +namespace FSO.Common.Serialization +{ + public interface IModelSerializer + { + object Deserialize(uint clsid, IoBuffer input, ISerializationContext context); + void Serialize(IoBuffer output, object obj, ISerializationContext context); + void Serialize(IoBuffer output, object value, ISerializationContext context, bool clsIdPrefix); + IoBuffer SerializeBuffer(object value, ISerializationContext context, bool clsIdPrefix); + + uint? GetClsid(object value); + void AddTypeSerializer(ITypeSerializer serializer); + } + + public interface ITypeSerializer + { + object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer); + void Serialize(IoBuffer output, object value, ISerializationContext serializer); + + uint? GetClsid(object value); + + bool CanSerialize(Type type); + bool CanDeserialize(uint clsid); + } +} diff --git a/server/tso.common/Serialization/ISerializationContext.cs b/server/tso.common/Serialization/ISerializationContext.cs new file mode 100755 index 0000000..64184e4 --- /dev/null +++ b/server/tso.common/Serialization/ISerializationContext.cs @@ -0,0 +1,10 @@ +using Ninject; + +namespace FSO.Common.Serialization +{ + public interface ISerializationContext + { + IKernel Kernel { get; } + IModelSerializer ModelSerializer { get; } + } +} diff --git a/server/tso.common/Serialization/IoBufferDeserializable.cs b/server/tso.common/Serialization/IoBufferDeserializable.cs new file mode 100755 index 0000000..229d81e --- /dev/null +++ b/server/tso.common/Serialization/IoBufferDeserializable.cs @@ -0,0 +1,9 @@ +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization +{ + public interface IoBufferDeserializable + { + void Deserialize(IoBuffer input, ISerializationContext context); + } +} diff --git a/server/tso.common/Serialization/IoBufferSerializable.cs b/server/tso.common/Serialization/IoBufferSerializable.cs new file mode 100755 index 0000000..2261142 --- /dev/null +++ b/server/tso.common/Serialization/IoBufferSerializable.cs @@ -0,0 +1,9 @@ +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization +{ + public interface IoBufferSerializable + { + void Serialize(IoBuffer output, ISerializationContext context); + } +} diff --git a/server/tso.common/Serialization/IoBufferUtils.cs b/server/tso.common/Serialization/IoBufferUtils.cs new file mode 100755 index 0000000..4b7ab88 --- /dev/null +++ b/server/tso.common/Serialization/IoBufferUtils.cs @@ -0,0 +1,304 @@ +using Mina.Core.Buffer; +using System; +using System.Collections.Generic; +using System.Text; + +namespace FSO.Common.Serialization +{ + public static class IoBufferUtils + { + public static void PutSerializable(this IoBuffer buffer, object obj, ISerializationContext context) + { + buffer.PutSerializable(context, obj, false); + } + + public static byte[] GetBytes(this IoBuffer buffer) + { + var result = new byte[buffer.Limit]; + buffer.Get(result, 0, buffer.Limit); + return result; + } + + public static T Deserialize(byte[] bytes, ISerializationContext context) where T : IoBufferDeserializable + { + var buffer = IoBuffer.Wrap(bytes); + return Deserialize(buffer, context); + } + + public static T Deserialize(IoBuffer buffer, ISerializationContext context) where T : IoBufferDeserializable + { + var model = Activator.CreateInstance(); + model.Deserialize(buffer, context); + return (T)model; + } + + public static IoBuffer SerializableToIoBuffer(object obj, ISerializationContext context) + { + if (obj is IoBuffer) + { + var ioBuffer = (IoBuffer)obj; + return (IoBuffer)ioBuffer; + } + else if (obj is byte[]) + { + var byteArray = (byte[])obj; + return IoBuffer.Wrap(byteArray); + } + else if (obj is IoBufferSerializable) + { + var ioBuffer = IoBuffer.Allocate(0); + ioBuffer.AutoExpand = true; + ioBuffer.Order = ByteOrder.BigEndian; + + var serializable = (IoBufferSerializable)obj; + serializable.Serialize(ioBuffer, context); + ioBuffer.Flip(); + return ioBuffer; + } + + throw new Exception("Unknown serializable type: " + obj); + } + + public static void PutSerializable(this IoBuffer buffer, ISerializationContext context, object obj, bool writeLength) + { + if(obj is IoBuffer) + { + var ioBuffer = (IoBuffer)obj; + if (writeLength){ + buffer.PutUInt32((uint)ioBuffer.Remaining); + } + buffer.Put(ioBuffer); + }else if(obj is byte[]) + { + var byteArray = (byte[])obj; + if (writeLength) + { + buffer.PutUInt32((uint)byteArray.Length); + } + buffer.Put(byteArray); + }else if(obj is IoBufferSerializable) + { + var ioBuffer = IoBuffer.Allocate(0); + ioBuffer.AutoExpand = true; + ioBuffer.Order = ByteOrder.BigEndian; + + var serializable = (IoBufferSerializable)obj; + serializable.Serialize(ioBuffer, context); + ioBuffer.Flip(); + + if (writeLength) + { + buffer.PutUInt32((uint)ioBuffer.Remaining); + } + buffer.Put(ioBuffer); + } + } + + public static void PutBool(this IoBuffer buffer, bool value) + { + buffer.Put(value ? (byte)0x01 : (byte)0x00); + } + + public static bool GetBool(this IoBuffer buffer) + { + return buffer.Get() == 1 ? true : false; + } + + public static void PutUInt32(this IoBuffer buffer, uint value) + { + int converted = unchecked((int)value); + buffer.PutInt32(converted); + } + + public static uint GetUInt32(this IoBuffer buffer) + { + return (uint)buffer.GetInt32(); + } + + public static void PutUInt16(this IoBuffer buffer, ushort value) + { + buffer.PutInt16((short)value); + } + + public static void PutUInt64(this IoBuffer buffer, ulong value) + { + buffer.PutInt64((long)value); + } + + + public static void PutEnum(this IoBuffer buffer, T enumValue) + { + ushort value = Convert.ToUInt16((object)enumValue); + buffer.PutUInt16(value); + } + + + public static void PutUTF8(this IoBuffer buffer, string value) + { + if (value == null) + { + buffer.PutInt16(-1); + } + else + { + buffer.PutInt16((short)value.Length); + buffer.PutString(value, Encoding.UTF8); + } + } + + public static string GetUTF8(this IoBuffer buffer) + { + short len = buffer.GetInt16(); + if (len == -1) + { + return null; + } + return buffer.GetString(len, Encoding.UTF8); + } + + public static ushort GetUInt16(this IoBuffer buffer) + { + return (ushort)buffer.GetInt16(); + } + + public static ulong GetUInt64(this IoBuffer buffer) + { + return (ulong)buffer.GetInt64(); + } + + public static T GetEnum(this IoBuffer buffer) + { + return (T)System.Enum.Parse(typeof(T), buffer.GetUInt16().ToString()); + } + + public static String GetPascalVLCString(this IoBuffer buffer) + { + byte lengthByte = 0; + uint length = 0; + int shift = 0; + + do + { + lengthByte = buffer.Get(); + length |= (uint)((lengthByte & (uint)0x7F) << shift); + shift += 7; + } while ( + (lengthByte >> 7) == 1 + ); + + + + if (length > 0) + { + var data = new List(); + for (int i = 0; i < length; i++) + { + data.Add(buffer.Get()); + } + return Encoding.UTF8.GetString(data.ToArray()); + } + else + { + return ""; + } + } + + public static byte[] GetPascalVLCString(String value) + { + if(value == null) + { + return new byte[] { 0x00 }; + } + + //TODO: Support strings bigger than 128 chars + var buffer = new byte[1 + value.Length]; + buffer[0] = (byte)value.Length; + + var chars = value.ToCharArray(); + + for(int i=0; i < chars.Length; i++){ + buffer[i + 1] = (byte)chars[i]; + } + + return buffer; + } + + public static void PutPascalVLCString(this IoBuffer buffer, String value) + { + byte[] encode = null; + long strlen = 0; + if (value != null) + { + encode = Encoding.UTF8.GetBytes(value); + strlen = encode.Length; + } + + bool write = strlen > 0; + bool first = true; + while (strlen > 0 || first) + { + buffer.Put((byte)(((strlen > 127) ? (uint)128 : 0) | (strlen & 127))); + strlen >>= 7; + first = false; + } + + if (write) + { + buffer.Put(encode); + } + } + + public static String GetPascalString(this IoBuffer buffer) + { + byte len1 = buffer.Get(); + byte len2 = buffer.Get(); + byte len3 = buffer.Get(); + byte len4 = buffer.Get(); + len1 &= 0x7F; + + long len = len1 << 24 | len2 << 16 | len3 << 8 | len4; + if (len > 0) + { + StringBuilder str = new StringBuilder(); + for (int i = 0; i < len; i++) + { + str.Append((char)buffer.Get()); + } + return str.ToString(); + + } + else + { + return ""; + } + } + + public static void PutPascalString(this IoBuffer buffer, String value) + { + + long strlen = 0; + if (value != null) + { + strlen = value.Length; + } + + byte len1 = (byte)((strlen >> 24) | 0x80); + byte len2 = (byte)((strlen >> 16) & 0xFF); + byte len3 = (byte)((strlen >> 8) & 0xFF); + byte len4 = (byte)(strlen & 0xFF); + + buffer.Put(len1); + buffer.Put(len2); + buffer.Put(len3); + buffer.Put(len4); + + if (strlen > 0) + { + foreach (char ch in value.ToCharArray()) + { + buffer.Put((byte)ch); + } + } + } + } +} diff --git a/server/tso.common/Serialization/ModelSerializer.cs b/server/tso.common/Serialization/ModelSerializer.cs new file mode 100755 index 0000000..68d32dc --- /dev/null +++ b/server/tso.common/Serialization/ModelSerializer.cs @@ -0,0 +1,106 @@ +using FSO.Common.Serialization.TypeSerializers; +using Mina.Core.Buffer; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.Serialization +{ + public class ModelSerializer : IModelSerializer + { + private List TypeSerializers = new List(); + private ConcurrentDictionary SerialCache = new ConcurrentDictionary(); + private ConcurrentDictionary DeserialCache = new ConcurrentDictionary(); + + public ModelSerializer(){ + //Built-in + AddTypeSerializer(new cTSOValueBoolean()); + AddTypeSerializer(new cTSOValueBooleanVector()); + AddTypeSerializer(new cTSOValueBooleanMap()); + AddTypeSerializer(new cTSOValueString()); + AddTypeSerializer(new cTSOValueStringVector()); + AddTypeSerializer(new cTSOValueByte()); + AddTypeSerializer(new cTSOValueByteVector()); + AddTypeSerializer(new cTSOValueSByte()); + AddTypeSerializer(new cTSOValueSByteVector()); + + AddTypeSerializer(new cTSOValueUInt32()); + AddTypeSerializer(new cTSOValueUInt32Vector()); + + AddTypeSerializer(new cTSOValueUInt16()); + AddTypeSerializer(new cTSOValueDecorated()); + AddTypeSerializer(new cTSOValueUInt64()); + + AddTypeSerializer(new cTSOValueGenericData()); + } + + + public uint? GetClsid(object value) + { + if (value == null) { return null; } + var serializer = GetSerializer(value.GetType()); + if (serializer == null) { return null; } + return serializer.GetClsid(value); + } + + public void Serialize(IoBuffer output, object obj, ISerializationContext context) + { + if (obj == null) { return; } + var serializer = GetSerializer(obj.GetType()); + if (serializer == null) { return; } + + serializer.Serialize(output, obj, context); + } + + + public void Serialize(IoBuffer output, object value, ISerializationContext context, bool clsIdPrefix) + { + if (value == null) { return; } + var serializer = GetSerializer(value.GetType()); + if (serializer == null) { return; } + + if (clsIdPrefix){ + output.PutUInt32(serializer.GetClsid(value).Value); + } + serializer.Serialize(output, value, context); + } + + public IoBuffer SerializeBuffer(object value, ISerializationContext context, bool clsIdPrefix) + { + var buffer = IoBuffer.Allocate(256); + buffer.AutoExpand = true; + buffer.Order = ByteOrder.BigEndian; + Serialize(buffer, value, context, clsIdPrefix); + buffer.Flip(); + return buffer; + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext context) + { + var serializer = GetSerializer(clsid); + if (serializer == null) { return null; } + + return serializer.Deserialize(clsid, input, context); + } + + public void AddTypeSerializer(ITypeSerializer serializer) + { + TypeSerializers.Add(serializer); + } + + private ITypeSerializer GetSerializer(uint clsid){ + return DeserialCache.GetOrAdd(clsid, (t) => + { + return TypeSerializers.FirstOrDefault(x => x.CanDeserialize(clsid)); + }); + } + + private ITypeSerializer GetSerializer(Type type){ + return SerialCache.GetOrAdd(type, (t) => + { + return TypeSerializers.FirstOrDefault(x => x.CanSerialize(type)); + }); + } + } +} diff --git a/server/tso.common/Serialization/Primitives/cTSOGenericData.cs b/server/tso.common/Serialization/Primitives/cTSOGenericData.cs new file mode 100755 index 0000000..0ccacc0 --- /dev/null +++ b/server/tso.common/Serialization/Primitives/cTSOGenericData.cs @@ -0,0 +1,13 @@ +namespace FSO.Common.Serialization.Primitives +{ + public class cTSOGenericData + { + public byte[] Data; + + public cTSOGenericData() { } + public cTSOGenericData(byte[] data) + { + Data = data; + } + } +} diff --git a/server/tso.common/Serialization/Primitives/cTSONetMessageStandard.cs b/server/tso.common/Serialization/Primitives/cTSONetMessageStandard.cs new file mode 100755 index 0000000..841ba06 --- /dev/null +++ b/server/tso.common/Serialization/Primitives/cTSONetMessageStandard.cs @@ -0,0 +1,114 @@ +using System; +using Mina.Core.Buffer; +using System.ComponentModel; +using FSO.Common.Serialization.TypeSerializers; + +namespace FSO.Common.Serialization.Primitives +{ + [cTSOValue(0x125194E5)] + public class cTSONetMessageStandard : IoBufferSerializable, IoBufferDeserializable + { + public uint Unknown_1 { get; set; } + public uint SendingAvatarID { get; set; } + public cTSOParameterizedEntityFlags Flags { get; set; } + public uint MessageID { get; set; } + + public uint? DatabaseType { get; set; } + public uint? DataServiceType { get; set; } + + public uint? Parameter { get; set; } + public uint RequestResponseID { get; set; } + + [TypeConverter(typeof(ExpandableObjectConverter))] + public object ComplexParameter { get; set; } + + public uint Unknown_2 { get; set; } + + public cTSONetMessageStandard(){ + } + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + this.Unknown_1 = input.GetUInt32(); + this.SendingAvatarID = input.GetUInt32(); + var flagsByte = input.Get(); + this.Flags = (cTSOParameterizedEntityFlags)flagsByte; + this.MessageID = input.GetUInt32(); + + if ((this.Flags & cTSOParameterizedEntityFlags.HAS_DS_TYPE) == cTSOParameterizedEntityFlags.HAS_DS_TYPE) + { + this.DataServiceType = input.GetUInt32(); + }else if ((this.Flags & cTSOParameterizedEntityFlags.HAS_DB_TYPE) == cTSOParameterizedEntityFlags.HAS_DB_TYPE){ + this.DatabaseType = input.GetUInt32(); + } + + if ((this.Flags & cTSOParameterizedEntityFlags.HAS_BASIC_PARAMETER) == cTSOParameterizedEntityFlags.HAS_BASIC_PARAMETER) + { + this.Parameter = input.GetUInt32(); + } + + if ((this.Flags & cTSOParameterizedEntityFlags.UNKNOWN) == cTSOParameterizedEntityFlags.UNKNOWN) + { + this.Unknown_2 = input.GetUInt32(); + } + + if ((this.Flags & cTSOParameterizedEntityFlags.HAS_COMPLEX_PARAMETER) == cTSOParameterizedEntityFlags.HAS_COMPLEX_PARAMETER) + { + uint typeId = DatabaseType.HasValue ? DatabaseType.Value : DataServiceType.Value; + this.ComplexParameter = context.ModelSerializer.Deserialize(typeId, input, context); + } + } + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(Unknown_1); + output.PutUInt32(SendingAvatarID); + + byte flags = 0; + if (this.DatabaseType.HasValue){ + flags |= (byte)cTSOParameterizedEntityFlags.HAS_DB_TYPE; + } + + if (this.DataServiceType.HasValue){ + flags |= (byte)cTSOParameterizedEntityFlags.HAS_DB_TYPE; + flags |= (byte)cTSOParameterizedEntityFlags.HAS_DS_TYPE; + } + + if (this.Parameter != null){ + flags |= (byte)cTSOParameterizedEntityFlags.HAS_BASIC_PARAMETER; + } + + if(this.ComplexParameter != null){ + flags |= (byte)cTSOParameterizedEntityFlags.HAS_COMPLEX_PARAMETER; + } + + output.Put(flags); + output.PutUInt32(MessageID); + + if (this.DataServiceType.HasValue) + { + output.PutUInt32(this.DataServiceType.Value); + }else if (this.DatabaseType.HasValue){ + output.PutUInt32(this.DatabaseType.Value); + } + + if (this.Parameter.HasValue){ + output.PutUInt32(this.Parameter.Value); + } + + if (this.ComplexParameter != null){ + context.ModelSerializer.Serialize(output, ComplexParameter, context, false); + } + } + } + + [Flags] + public enum cTSOParameterizedEntityFlags + { + HAS_DB_TYPE = 1, + HAS_DS_TYPE = 2, + HAS_BASIC_PARAMETER = 4, + UNKNOWN = 8, + HAS_COMPLEX_PARAMETER = 32 + } +} diff --git a/server/tso.common/Serialization/Primitives/cTSOProperty.cs b/server/tso.common/Serialization/Primitives/cTSOProperty.cs new file mode 100755 index 0000000..4982714 --- /dev/null +++ b/server/tso.common/Serialization/Primitives/cTSOProperty.cs @@ -0,0 +1,53 @@ +using System.Collections.Generic; +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization.Primitives +{ + + public class cTSOProperty : IoBufferSerializable, IoBufferDeserializable + { + public uint StructType; + public List StructFields; + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(0x89739A79); + output.PutUInt32(StructType); + output.PutUInt32((uint)StructFields.Count); + + foreach (var item in StructFields) + { + output.PutUInt32(item.StructFieldID); + context.ModelSerializer.Serialize(output, item.Value, context, true); + } + } + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + //Unknown + input.GetUInt32(); + StructType = input.GetUInt32(); + + StructFields = new List(); + + var numFields = input.GetUInt32(); + for(int i=0; i < numFields; i++){ + var fieldId = input.GetUInt32(); + var typeId = input.GetUInt32(); + var value = context.ModelSerializer.Deserialize(typeId, input, context); + + StructFields.Add(new cTSOPropertyField + { + StructFieldID = fieldId, + Value = value + }); + } + } + } + + public class cTSOPropertyField + { + public uint StructFieldID; + public object Value; + } +} diff --git a/server/tso.common/Serialization/Primitives/cTSOTopicUpdateMessage.cs b/server/tso.common/Serialization/Primitives/cTSOTopicUpdateMessage.cs new file mode 100755 index 0000000..1017cd3 --- /dev/null +++ b/server/tso.common/Serialization/Primitives/cTSOTopicUpdateMessage.cs @@ -0,0 +1,70 @@ +using Mina.Core.Buffer; +using FSO.Common.Serialization.TypeSerializers; + +namespace FSO.Common.Serialization.Primitives +{ + [cTSOValue(0x9736027)] + public class cTSOTopicUpdateMessage : IoBufferSerializable, IoBufferDeserializable + { + public uint MessageId { get; set; } = 0xA97360C5; + + public uint StructType { get; set; } + public uint StructId { get; set; } + public uint StructField { get; set; } + + public uint[] DotPath { get; set; } + + public uint Unknown1 { get; set; } + public uint Unknown2 { get; set; } + + public object Value { get; set; } + + public string ReasonText { get; set; } + + + public void Serialize(IoBuffer output, ISerializationContext context) + { + output.PutUInt32(Unknown1); //Update counter + output.PutUInt32(MessageId); //Message id + output.PutUInt32(Unknown2); //Unknown + + if (DotPath != null) + { + output.PutUInt32((uint)DotPath.Length); + foreach(var component in DotPath){ + output.PutUInt32(component); + } + } + else + { + //Vector size + output.PutUInt32(3); + output.PutUInt32(StructType); + output.PutUInt32(StructId); + output.PutUInt32(StructField); + } + + //Write value + context.ModelSerializer.Serialize(output, Value, context, true); + + output.PutPascalVLCString(ReasonText); + } + + public void Deserialize(IoBuffer input, ISerializationContext context) + { + Unknown1 = input.GetUInt32(); + MessageId = input.GetUInt32(); + Unknown2 = input.GetUInt32(); + + var vectorSize = input.GetUInt32(); + DotPath = new uint[vectorSize]; + for(int i=0; i < vectorSize; i++){ + DotPath[i] = input.GetUInt32(); + } + + var valueType = input.GetUInt32(); + this.Value = context.ModelSerializer.Deserialize(valueType, input, context); + //this.ReasonText = input.GetPascalVLCString(); + } + } +} diff --git a/server/tso.common/Serialization/SerializationContext.cs b/server/tso.common/Serialization/SerializationContext.cs new file mode 100755 index 0000000..430679b --- /dev/null +++ b/server/tso.common/Serialization/SerializationContext.cs @@ -0,0 +1,16 @@ +using Ninject; + +namespace FSO.Common.Serialization +{ + public class SerializationContext : ISerializationContext + { + public IKernel Kernel { get; internal set; } + public IModelSerializer ModelSerializer { get; internal set; } + + public SerializationContext(IKernel Kernel, IModelSerializer ModelSerializer) + { + this.Kernel = Kernel; + this.ModelSerializer = ModelSerializer; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueBoolean.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueBoolean.cs new file mode 100755 index 0000000..2a4a985 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueBoolean.cs @@ -0,0 +1,37 @@ +using Mina.Core.Buffer; +using System; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueBoolean : ITypeSerializer + { + private readonly uint CLSID = 0x696D1183; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(bool)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var byteValue = input.Get(); + return byteValue == 0x01 ? true : false; + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + bool boolValue = (bool)value; + output.Put(boolValue ? (byte)0x01 : (byte)0x00); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanMap.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanMap.cs new file mode 100755 index 0000000..e85b77b --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanMap.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueBooleanMap : ITypeSerializer + { + private readonly uint CLSID = 0xC97757F5; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(ImmutableDictionary).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer buffer, ISerializationContext serializer) + { + var result = new Dictionary(); + var count = buffer.GetUInt32(); + for(int i=0; i < count; i++){ + var key = buffer.GetUInt32(); + result.Add(key, buffer.Get() > 0); + } + + return ImmutableDictionary.ToImmutableDictionary(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + var dict = (ImmutableDictionary)value; + output.PutUInt32((uint)dict.Count); + foreach (var elem in dict) + { + output.PutUInt32(elem.Key); + output.Put((byte)(elem.Value ? 1 : 0)); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanVector.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanVector.cs new file mode 100755 index 0000000..08bfecb --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueBooleanVector.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueBooleanVector : ITypeSerializer + { + private readonly uint CLSID = 0x89738492; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(IList).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer buffer, ISerializationContext serializer) + { + var result = new List(); + var count = buffer.GetUInt32(); + for(int i=0; i < count; i++){ + result.Add(buffer.Get() > 0); + } + return ImmutableList.ToImmutableList(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + IList list = (IList)value; + output.PutUInt32((uint)list.Count); + byte last = 0; + int pos = 0; + for (int i = 0; i < list.Count; i++) + { + output.Put((byte)(list[i]?1:0)); + //output.Put((byte)(1)); + /*last |= (byte)((list[i] ? 1 : 0) << pos++); + + if (pos >= 8) + { + output.Put(last); + pos = 0; + last = 0; + }*/ + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueByte.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueByte.cs new file mode 100755 index 0000000..c3ea42c --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueByte.cs @@ -0,0 +1,35 @@ +using System; +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueByte : ITypeSerializer + { + private readonly uint CLSID = 0xC976087C; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(byte)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return input.Get(); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.Put((byte)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueByteVector.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueByteVector.cs new file mode 100755 index 0000000..dbc2ef3 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueByteVector.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueByteVector : ITypeSerializer + { + private readonly uint CLSID = 0x097608AB; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(IList).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer buffer, ISerializationContext serializer) + { + var result = new List(); + var count = buffer.GetUInt32(); + for(int i=0; i < count; i++){ + result.Add(buffer.Get()); + } + return ImmutableList.ToImmutableList(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + IList list = (IList)value; + output.PutUInt32((uint)list.Count); + for (int i = 0; i < list.Count; i++) + { + output.Put(list[i]); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueDecorated.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueDecorated.cs new file mode 100755 index 0000000..263c631 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueDecorated.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Reflection; +using FSO.Common.Utils; + +namespace FSO.Common.Serialization.TypeSerializers +{ + /// + /// Serializes / deserializes anything that implements IoBufferSerializable & IoBufferDeserializable and has a cTSOValue decoration + /// + public class cTSOValueDecorated : ITypeSerializer + { + protected Dictionary ClsIdToType = new Dictionary(); + protected Dictionary TypeToClsId = new Dictionary(); + + public cTSOValueDecorated(){ + // + //var assembly = Assembly.GetAssembly(typeof(cTSOSerializer)); + var assemblies = AssemblyUtils.GetFreeSOLibs(); + foreach(var asm in assemblies) + { + ScanAssembly(asm); + } + } + + protected virtual void ScanAssembly(Assembly assembly) + { + try + { + foreach (Type type in assembly.GetTypes()) + { + System.Attribute[] attributes = System.Attribute.GetCustomAttributes(type); + + foreach (Attribute attribute in attributes) + { + if (attribute is cTSOValue) + { + foreach (uint clsid in ((cTSOValue)attribute).ClsId) + { + ClsIdToType.Add(clsid, type); + TypeToClsId.Add(type, clsid); + } + } + } + } + } catch (Exception) + { + + } + } + + public bool CanDeserialize(uint clsid) + { + return ClsIdToType.ContainsKey(clsid); + } + + public bool CanSerialize(Type type) + { + return TypeToClsId.ContainsKey(type); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var instance = Activator.CreateInstance(ClsIdToType[clsid]); + ((IoBufferDeserializable)instance).Deserialize(input, serializer); + return instance; + } + + public uint? GetClsid(object value) + { + Type type = value.GetType(); + if (TypeToClsId.ContainsKey(type)) + { + return TypeToClsId[type]; + } + return null; + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + ((IoBufferSerializable)value).Serialize(output, serializer); + } + } + + + [System.AttributeUsage(System.AttributeTargets.Class)] + public class cTSOValue : System.Attribute + { + public uint[] ClsId; + + public cTSOValue(params uint[] ClsId) + { + this.ClsId = ClsId; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueGenericData.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueGenericData.cs new file mode 100755 index 0000000..909e090 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueGenericData.cs @@ -0,0 +1,50 @@ +using FSO.Common.Serialization.Primitives; +using Mina.Core.Buffer; +using System; +using System.Collections.Generic; + +namespace FSO.Common.Serialization.TypeSerializers +{ + class cTSOValueGenericData : ITypeSerializer + { + private readonly uint CLSID = 0xA99AF3B7; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(cTSOGenericData)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var result = new List(); + var iclsid = input.GetUInt32(); + var count = input.GetUInt32(); + for (int i = 0; i < count; i++) + { + result.Add(input.Get()); + } + return new cTSOGenericData(result.ToArray()); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + var dat = (cTSOGenericData)value; + output.PutUInt32(0x0A2C6585); + output.PutUInt32((uint)dat.Data.Length); + for (int i = 0; i < dat.Data.Length; i++) + { + output.Put(dat.Data[i]); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueSByte.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueSByte.cs new file mode 100755 index 0000000..d5e941c --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueSByte.cs @@ -0,0 +1,35 @@ +using System; +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueSByte : ITypeSerializer + { + private readonly uint CLSID = 0xE976088A; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(sbyte)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return (sbyte)input.Get(); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.Put((byte)(sbyte)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueSByteVector.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueSByteVector.cs new file mode 100755 index 0000000..189bf76 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueSByteVector.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueSByteVector : ITypeSerializer + { + private readonly uint CLSID = 0x097608AF; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(IList).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var result = new List(); + var count = input.GetUInt32(); + for(int i=0; i < count; i++){ + result.Add((sbyte)input.Get()); + } + return ImmutableList.ToImmutableList(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + IList list = (IList)value; + output.PutUInt32((uint)list.Count); + for (int i = 0; i < list.Count; i++) + { + output.Put((byte)list[i]); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueString.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueString.cs new file mode 100755 index 0000000..54d05b9 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueString.cs @@ -0,0 +1,35 @@ +using System; +using Mina.Core.Buffer; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueString : ITypeSerializer + { + private readonly uint CLSID = 0x896D1688; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(string)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return IoBufferUtils.GetPascalVLCString(input); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.PutPascalVLCString((string)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueStringVector.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueStringVector.cs new file mode 100755 index 0000000..cbd09fa --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueStringVector.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using Mina.Core.Buffer; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueStringVector : ITypeSerializer + { + private readonly uint CLSID = 0x8973849E; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(IList).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var result = new List(); + var count = input.GetUInt32(); + for(int i=0; i < count; i++){ + result.Add(IoBufferUtils.GetPascalVLCString(input)); + } + return ImmutableList.ToImmutableList(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + IList list = (IList)value; + output.PutUInt32((uint)list.Count); + for(int i=0; i < list.Count; i++){ + output.PutPascalVLCString(list[i]); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt16.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt16.cs new file mode 100755 index 0000000..0e69c6a --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt16.cs @@ -0,0 +1,36 @@ +using Mina.Core.Buffer; +using System; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueUInt16 : ITypeSerializer + { + //0xE9760891: cTSOValue + private readonly uint CLSID = 0xE9760891; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(ushort)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return input.GetUInt16(); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.PutUInt16((ushort)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32.cs new file mode 100755 index 0000000..ca53bf4 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32.cs @@ -0,0 +1,36 @@ +using Mina.Core.Buffer; +using System; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueUInt32 : ITypeSerializer + { + //0x696D1189: cTSOValue + private readonly uint CLSID = 0x696D1189; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(uint)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return input.GetUInt32(); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.PutUInt32((uint)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32Vector.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32Vector.cs new file mode 100755 index 0000000..64342e1 --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt32Vector.cs @@ -0,0 +1,49 @@ +using Mina.Core.Buffer; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace FSO.Common.Serialization.TypeSerializers +{ + class cTSOValueUInt32Vector : ITypeSerializer + { + //0x89738496: cTSOValueVector + private readonly uint CLSID = 0x89738496; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return typeof(IList).IsAssignableFrom(type); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + var result = new List(); + var count = input.GetUInt32(); + for (int i = 0; i < count; i++) + { + result.Add((uint)input.GetUInt32()); + } + return ImmutableList.ToImmutableList(result); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + IList list = (IList)value; + output.PutUInt32((uint)list.Count); + for (int i = 0; i < list.Count; i++) + { + output.PutUInt32((uint)list[i]); + } + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt64.cs b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt64.cs new file mode 100755 index 0000000..d40be9d --- /dev/null +++ b/server/tso.common/Serialization/TypeSerializers/cTSOValueUInt64.cs @@ -0,0 +1,36 @@ +using Mina.Core.Buffer; +using System; + +namespace FSO.Common.Serialization.TypeSerializers +{ + public class cTSOValueUInt64 : ITypeSerializer + { + //0x69D3E3DB: cTSOValue + private readonly uint CLSID = 0x69D3E3DB; + + public bool CanDeserialize(uint clsid) + { + return clsid == CLSID; + } + + public bool CanSerialize(Type type) + { + return type.IsAssignableFrom(typeof(ulong)); + } + + public object Deserialize(uint clsid, IoBuffer input, ISerializationContext serializer) + { + return input.GetUInt64(); + } + + public void Serialize(IoBuffer output, object value, ISerializationContext serializer) + { + output.PutUInt64((ulong)value); + } + + public uint? GetClsid(object value) + { + return CLSID; + } + } +} diff --git a/server/tso.common/TS1/TS1Curve.cs b/server/tso.common/TS1/TS1Curve.cs new file mode 100755 index 0000000..a4b3866 --- /dev/null +++ b/server/tso.common/TS1/TS1Curve.cs @@ -0,0 +1,109 @@ +using Microsoft.Xna.Framework; +using System; +using System.Linq; + +namespace FSO.Common.TS1 +{ + /// + /// + /// + public class TS1Curve + { + public Point[] Points; // ordered by x + + public int CacheStart; + public float[] Cache; + public int[] CacheFixed; + + public TS1Curve(string input) + { + input = input.Replace(");(", ") ("); + var points = input.Split(' '); + var pointParse = points.Select(pointStr => + { + var pointClean = pointStr.Substring(1, pointStr.Length - 2); + var split = pointClean.Split(';'); + return new Point(int.Parse(split[0]), int.Parse(split[1])); + }); + + Points = pointParse.OrderBy(pt => pt.X).ToArray(); + } + + public float GetPoint(float input) + { + if (input < Points[0].X) return Points[0].Y; + // find the first point we're ahead of + // we want to interpolate between that point and the one after it + int i = 0; + for (i = Points.Length-1; i >= 0; i--) + { + var point = Points[i]; + if (input >= point.X) + { + break; + } + } + if (i == Points.Length-1) + { + return Points[i].Y; + } + + var start = Points[i]; + var end = Points[i + 1]; + var iF = (input - start.X) / (float)(end.X - start.X); + return (1 - iF) * start.Y + iF * end.Y; + } + + public int GetPointFixed(int input) + { + if (input < Points[0].X) return Points[0].Y; + // find the first point we're ahead of + // we want to interpolate between that point and the one after it + int i = 0; + for (i = 0; i < Points.Length; i++) + { + var point = Points[i]; + if (input >= point.X) + { + break; + } + } + if (i == Points.Length - 1) + { + return Points[i].Y; + } + + var start = Points[i]; + var end = Points[i + 1]; + var iF = ((input - start.X) * 65536) / (end.X - start.X); + return (65536 - iF) * start.Y + iF * end.Y; + } + + // CACHED ACCESS + + public void BuildCache(int min, int max) + { + Cache = new float[(max - min) + 1]; + CacheFixed = new int[(max - min) + 1]; + CacheStart = min; + + for (int i=min; i<=max; i++) + { + Cache[i - min] = GetPoint(i); + CacheFixed[i - min] = GetPointFixed(i); + } + } + + public float GetCachedPoint(int point) + { + point = Math.Max(CacheStart, Math.Min(CacheStart + Cache.Length - 1, point)); + return Cache[point]; + } + + public int GetCachedPointFixed(int point) + { + point = Math.Max(CacheStart, Math.Min(CacheStart + CacheFixed.Length - 1, point)); + return CacheFixed[point]; + } + } +} diff --git a/server/tso.common/Utils/AssemblyUtils.cs b/server/tso.common/Utils/AssemblyUtils.cs new file mode 100755 index 0000000..ce103ed --- /dev/null +++ b/server/tso.common/Utils/AssemblyUtils.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace FSO.Common.Utils +{ + public class AssemblyUtils + { + public static Assembly Entry; + public static List GetFreeSOLibs() + { + var map = new Dictionary(); + if (Entry == null) Entry = Assembly.GetEntryAssembly(); + RecurseAssembly(Entry, map); + return map.Values.ToList(); + } + + private static void RecurseAssembly(Assembly assembly, Dictionary map) + { + var refs = assembly.GetReferencedAssemblies(); + foreach (var refAsm in refs) + { + if ((refAsm.Name.StartsWith("FSO.") || refAsm.Name.Equals("FreeSO") || refAsm.Name.Equals("server")) && !map.ContainsKey(refAsm.Name)) + { + var loadedAssembly = Assembly.Load(refAsm); + map.Add(refAsm.Name, loadedAssembly); + RecurseAssembly(loadedAssembly, map); + } + }; + } + } +} diff --git a/server/tso.common/Utils/BBCodeParser.cs b/server/tso.common/Utils/BBCodeParser.cs new file mode 100755 index 0000000..daba4ad --- /dev/null +++ b/server/tso.common/Utils/BBCodeParser.cs @@ -0,0 +1,126 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; + +namespace FSO.Common.Utils +{ + + /// + /// In: + /// - String Containing BBCode + /// + /// [color=red]Hello![/color] + /// [color=#FF0000]Also [size=20]red[/size][/color] + /// \[ escaped \] square brackets. + /// + /// Out: + /// - String Without BBCode + /// - Ordered list of BBCodeCommands, and the index in the converted string they occur at. + /// + public class BBCodeParser + { + public string Stripped; + public List Commands = new List(); + + public BBCodeParser(string input) + { + var stripped = new StringBuilder(); + int index = 0; + while (index < input.Length) + { + var newIndex = input.IndexOf('[', index); + if (newIndex == -1) + { + newIndex = input.Length; + //no more commands. + //render the rest of the string and break out. + stripped.Append(input.Substring(index, newIndex - index)); + break; + } + stripped.Append(input.Substring(index, newIndex - index)); + //we found the start of a bbcode. is it escaped? + if (newIndex > 0 && input[newIndex - 1] == '\\') + { + //draw the bracket. + stripped[stripped.Length - 1] = '['; //replace the backslash with the leftbracket + index = newIndex + 1; //continue after the bracket + } else + { + //find our right bracket + var endIndex = input.IndexOf(']', newIndex); + if (endIndex == -1) + { + //fail safe. + stripped.Append('['); + index = newIndex + 1; //continue after the bracket + } else + { + Commands.Add(new BBCodeCommand(input.Substring(newIndex + 1, (endIndex - newIndex) - 1), stripped.Length)); + index = endIndex + 1; + } + } + } + Stripped = stripped.ToString(); + } + + public static string SanitizeBB(string input) + { + if (input.LastOrDefault() == '\\') input += ' '; + return input.Replace("[", "\\["); + } + } + + public class BBCodeCommand + { + public BBCodeCommandType Type; + public string Parameter; + public int Index; + public bool Close; + + public BBCodeCommand(string cmd, int index) + { + Index = index; + if (cmd[0] == '/') + { + Close = true; + cmd = cmd.Substring(1); + } + var split = cmd.Split('='); + if (split.Length > 1) Parameter = split[1]; + System.Enum.TryParse(split[0], out Type); + } + + public Color ParseColor() + { + if (Parameter == null || Parameter.Length == 0) return Color.White; + //todo: search color static members for named colours + //for now we only support hex + if (Parameter.Length == 7 && Parameter[0] == '#') + { + uint rgb; + if (uint.TryParse(Parameter.Substring(1), NumberStyles.HexNumber, CultureInfo.CurrentCulture, out rgb)) { + return new Color((byte)(rgb >> 16), (byte)(rgb >> 8), (byte)(rgb), (byte)255); + } + } else + { + var color = typeof(Color).GetProperties().Where(x => x.PropertyType == typeof(Color) && x.Name.ToLowerInvariant() == Parameter.ToLowerInvariant()).FirstOrDefault(); + if (color != null) + { + return (Color)color.GetValue(null); + } + } + return Color.White; + } + } + + public enum BBCodeCommandType + { + unknown, + color, + size, + emoji, + s + } +} diff --git a/server/tso.common/Utils/Base64JsonConverter.cs b/server/tso.common/Utils/Base64JsonConverter.cs new file mode 100755 index 0000000..4402f83 --- /dev/null +++ b/server/tso.common/Utils/Base64JsonConverter.cs @@ -0,0 +1,29 @@ +using System; +using Newtonsoft.Json; + +namespace FSO.Common.Utils +{ + public class Base64JsonConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + if (typeof(byte[]).IsAssignableFrom(objectType)) + { + return true; + } + return false; + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + string data = (string)reader.Value; + return Convert.FromBase64String(data); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + byte[] bytes = (byte[])value; + writer.WriteValue(Convert.ToBase64String(bytes)); + } + } +} diff --git a/server/tso.common/Utils/Binding.cs b/server/tso.common/Utils/Binding.cs new file mode 100755 index 0000000..12323fe --- /dev/null +++ b/server/tso.common/Utils/Binding.cs @@ -0,0 +1,301 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace FSO.Common.Utils +{ + public class Binding : IDisposable where T : INotifyPropertyChanged + { + private List Bindings = new List(); + private HashSet Watching = new HashSet(); + private T _Value; + + public event Callback ValueChanged; + + public Binding() + { + lock(Binding.All) + Binding.All.Add(this); + } + + ~Binding() + { + //i don't think the garbage collector will remove this if there is still a reference to its callback function. + ClearWatching(); + } + + public void Dispose() + { + ClearWatching(); + Bindings = null; + } + + public T Value + { + get + { + return _Value; + } + set + { + ClearWatching(); + _Value = value; + if(_Value != null){ + Watch(_Value, null); + } + Digest(); + + if(ValueChanged != null) + { + ValueChanged(_Value); + } + } + } + + private void ClearWatching() + { + lock (Watching) + { + var clone = new List(Watching); + foreach (var item in clone) + { + item.PropertyChanged -= OnPropertyChanged; + Watching.Remove(item); + } + } + } + + private void Watch(INotifyPropertyChanged source, HashSet toWatch) + { + lock (Watching) + { + if (!Watching.Contains(source)) + { + source.PropertyChanged += OnPropertyChanged; + Watching.Add(source); + } + toWatch?.Add(source); + + var properties = source.GetType().GetProperties(); + foreach (var property in properties) + { + if (typeof(INotifyPropertyChanged).IsAssignableFrom(property.PropertyType)) + { + var value = (INotifyPropertyChanged)property.GetValue(source, null); + if (value != null) + { + Watch(value, toWatch); + } + } + } + } + } + + private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) + { + lock (Watching) + { + var property = sender.GetType().GetProperty(e.PropertyName); + if (typeof(INotifyPropertyChanged).IsAssignableFrom(property.PropertyType)) + { + //We may have a new nested object to watch + //ClearWatching(); + if (_Value != null) + { + var toWatch = new HashSet(); + Watch(_Value, toWatch); + + var toRemove = Watching.Except(toWatch).ToList(); + foreach (var rem in toRemove) + { + Watching.Remove(rem); + rem.PropertyChanged -= OnPropertyChanged; + } + } + } + } + Digest(); + } + + //Using a dumb digest system for now, not very efficient but works + private void Digest() + { + GameThread.InUpdate(() => _Digest()); + } + + private void _Digest() + { + lock (this) + { + if (Bindings == null) return; + foreach (var binding in Bindings) + { + binding.Digest(_Value); + } + } + } + + public Binding WithBinding(object target, string targetProperty, string sourcePath) + { + //If top level changes, we need to update children + //If member of top level changes, we need to update children + var binding = new DotPathBinding(target, targetProperty, DotPath.CompileDotPath(typeof(T), sourcePath)); + Bindings.Add(binding); + return this; + } + + public Binding WithBinding(object target, string targetProperty, string sourcePath, Func valueConverter) + { + //If top level changes, we need to update children + //If member of top level changes, we need to update children + var binding = new DotPathBinding(target, targetProperty, DotPath.CompileDotPath(typeof(T), sourcePath), valueConverter); + Bindings.Add(binding); + return this; + } + + public Binding WithMultiBinding(Callback callback, params string[] paths) + { + var compiledPaths = new PropertyInfo[paths.Length][]; + for(int i=0; i < paths.Length; i++){ + compiledPaths[i] = DotPath.CompileDotPath(typeof(T), paths[i]); + } + + var binding = new MultiDotPathBinding(callback, paths, compiledPaths); + Bindings.Add(binding); + return this; + } + } + + public class BindingChange + { + public string Path; + public object PreviousValue; + public object Value; + } + + class MultiDotPathBinding : IBinding + { + private Callback Callback; + private PropertyInfo[][] Paths; + private string[] PathStrings; + private object[] Values; + + public MultiDotPathBinding(Callback callback, string[] pathStrings, PropertyInfo[][] paths) + { + Callback = callback; + Paths = paths; + PathStrings = pathStrings; + Values = new object[Paths.Length]; + } + + public void Digest(object source) + { + List changes = null; + for(int i=0; i < Paths.Length; i++){ + var path = Paths[i]; + var value = DotPath.GetDotPathValue(source, path); + + if(value != Values[i]){ + //Changed + if (changes == null) { changes = new List(); } + changes.Add(new BindingChange() + { + Path = PathStrings[i], + PreviousValue = Values[i], + Value = value + }); + Values[i] = value; + } + } + + if(changes != null) + { + Callback(changes.ToArray()); + } + } + } + + class DotPathBinding : Binding + { + private PropertyInfo[] Path; + private object LastValue; + private Func Converter; + + public DotPathBinding(object target, string targetProperty, PropertyInfo[] path, Func converter) : this(target, targetProperty, path) + { + this.Converter = converter; + } + + public DotPathBinding(object target, string targetProperty, PropertyInfo[] path) : base(target, targetProperty) + { + this.Path = path; + } + + public override void Digest(object source){ + var value = GetValue(source); + if(value != LastValue){ + LastValue = value; + if (Converter != null) + { + SetValue(Converter(value)); + } + else + { + SetValue(value); + } + } + } + + private object GetValue(object source) + { + return DotPath.GetDotPathValue(source, Path); + } + } + + public abstract class Binding : IBinding + { + private object Target; + private string TargetProperty; + private PropertyInfo[] TargetPropertyPath; + + public Binding(object target, string targetProperty) + { + Target = target; + TargetProperty = targetProperty; + TargetPropertyPath = DotPath.CompileDotPath(target.GetType(), targetProperty); + } + + protected void SetValue(object value) + { + DotPath.SetDotPathValue(Target, TargetPropertyPath, value); + } + + public abstract void Digest(object source); + + public virtual void Dispose() { Target = null; } + + public static List All = new List(); + public static void DisposeAll() + { + //dispose of all bindings that are left over (city leave return) + lock (All) + { + foreach (var item in All) + { + item.Dispose(); + } + All.Clear(); + } + } + } + + interface IBinding + { + void Digest(object source); + + //object GetValue(object source); + //void SetValue(object value); + } +} diff --git a/server/tso.common/Utils/Cache/CacheKey.cs b/server/tso.common/Utils/Cache/CacheKey.cs new file mode 100755 index 0000000..f7fcb04 --- /dev/null +++ b/server/tso.common/Utils/Cache/CacheKey.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.Utils.Cache +{ + public class CacheKey : IEqualityComparer, IEquatable + { + public static CacheKey Root = CacheKey.For(); + + public string[] Components { get; internal set; } + + protected CacheKey(string[] components) + { + this.Components = components; + } + + public override int GetHashCode() + { + return GetHashCode(this); + } + + public bool Equals(CacheKey x, CacheKey y) + { + return x.Components.SequenceEqual(y.Components); + } + + public bool Equals(CacheKey other) + { + return Equals(this, other); + } + + public int GetHashCode(CacheKey obj) + { + int hashcode = 0; + foreach (string value in obj.Components) + { + if (value != null) + hashcode += value.GetHashCode(); + } + return hashcode; + } + + public static CacheKey For(params object[] components) + { + return new CacheKey(components.Select(x => "" + x).ToArray()); + } + + public static CacheKey Combine(CacheKey domain, params object[] components) + { + var newComponents = new string[domain.Components.Length+components.Length]; + Array.Copy(domain.Components, newComponents, domain.Components.Length); + Array.Copy(components.Select(x => "" + x).ToArray(), 0, newComponents, domain.Components.Length, components.Length); + return new CacheKey(newComponents); + } + + } +} diff --git a/server/tso.common/Utils/Cache/FileSystemCache.cs b/server/tso.common/Utils/Cache/FileSystemCache.cs new file mode 100755 index 0000000..877d854 --- /dev/null +++ b/server/tso.common/Utils/Cache/FileSystemCache.cs @@ -0,0 +1,340 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace FSO.Common.Utils.Cache +{ + public class FileSystemCache : ICache + { + private const int DIGEST_DELAY = 10000; + + private string _Directory { get; set; } + private Queue _Mutations; + private Thread _DigestThread; + private bool _Active; + private long _CacheSize; + private long _MaxCacheSize; + private Thread _MainThread; + + private LinkedList _Cache; + private Dictionary _Index; + + + public FileSystemCache(string directory, long maxSize) + { + _MainThread = Thread.CurrentThread; + _Directory = directory; + _Mutations = new Queue(); + _CacheSize = 0; + _MaxCacheSize = maxSize; + _Cache = new LinkedList(); + _Index = new Dictionary(); + } + + public void Init() + { + var tempList = new List(); + _ScanDirectory(CacheKey.Root, tempList); + + foreach(var item in tempList.OrderByDescending(x => x.LastRead)){ + _Cache.AddLast(item); + _Index.Add(item.Key, item); + _CacheSize += item.Length; + } + + _Active = true; + _DigestThread = new Thread(DigestLoop); + _DigestThread.Priority = ThreadPriority.BelowNormal; + _DigestThread.Start(); + } + + + private void DigestLoop() + { + while (_Active && _MainThread?.IsAlive != false) + { + Digest(); + Thread.Sleep(DIGEST_DELAY); + } + } + + private void Digest() + { + lock (_Mutations) + { + /** + * We can avoid some work & disk hits by removing tasks for keys modified in later tasks + */ + List tasks = new List(); + Dictionary taskIndex = new Dictionary(); + FileSystemCacheMutation mutation; + while (_Mutations.Count > 0 && (mutation = _Mutations.Dequeue()) != null) + { + tasks.Add(mutation); + + FileSystemCacheMutation previousTask = null; + taskIndex.TryGetValue(mutation.Key, out previousTask); + if (previousTask == null) { + taskIndex[mutation.Key] = mutation; + continue; + } + + tasks.Remove(previousTask); + taskIndex[mutation.Key] = mutation; + } + + + int bytesRequired = 0; + foreach(var task in tasks){ + bytesRequired += task.GetBytesRequired(this); + } + + if(bytesRequired > 0 && (_CacheSize + bytesRequired) >= _MaxCacheSize) + { + //We need to evict some entries to make room + while((_CacheSize + bytesRequired) >= _MaxCacheSize && _Cache.Count > 0) + { + var last = _Cache.Last; + try { + new FileSystemCacheRemoveMutation() { + Key = last.Value.Key + }.Execute(this); + }catch(Exception ex){ + } + CalculateCacheSize(); + } + } + + foreach (var task in tasks) + { + try + { + task.Execute(this); + } + catch (Exception ex) + { + } + } + + //Recalculate cache size if we made changes + if(tasks.Count > 0){ + CalculateCacheSize(); + } + } + } + + private void CalculateCacheSize() + { + long size = 0; + foreach(var item in _Cache){ + size += item.Length; + } + _CacheSize = size; + } + + private void _ScanDirectory(CacheKey parent, List tempList) + { + var dir = GetFilePath(parent); + if (!Directory.Exists(dir)) { return; } + + var info = new DirectoryInfo(dir); + + foreach(FileInfo file in info.GetFiles()) + { + var key = CacheKey.Combine(parent, file.Name); + tempList.Add(new FileSystemCacheEntry { + Key = key, + LastRead = file.LastAccessTime, + LastWrite = file.LastWriteTime, + Length = file.Length + }); + } + + foreach(var subDir in info.GetDirectories()) + { + var key = CacheKey.Combine(parent, subDir.Name); + _ScanDirectory(key, tempList); + } + } + + public bool ContainsKey(CacheKey key) + { + return _Index.ContainsKey(key); + } + + public void Add(CacheKey key, byte[] bytes) + { + var clone = new byte[bytes.Length]; + Buffer.BlockCopy(bytes, 0, clone, 0, bytes.Length); + + lock (_Mutations) + { + _Mutations.Enqueue(new FileSystemCacheAddMutation + { + Key = key, + Data = clone + }); + } + } + + public void Remove(CacheKey key) + { + lock (_Mutations) + { + _Mutations.Enqueue(new FileSystemCacheRemoveMutation + { + Key = key + }); + } + } + + public Task Get(CacheKey key) + { + if(typeof(T) == typeof(byte[])) + { + return Task.Factory.StartNew(() => + { + var file = GetFilePath(key); + byte[] result = null; + if (File.Exists(file)){ + result = File.ReadAllBytes(file); + }else{ + throw new Exception("File not found"); + } + TouchEntry(key); + return (T)(object)result; + }); + } + + throw new Exception("Not implemented yet"); + } + + public void Dispose() + { + _Active = false; + } + + internal string GetFilePath(CacheKey key) + { + return Path.Combine(_Directory, Path.Combine(key.Components)); + } + + internal FileSystemCacheEntry GetEntry(CacheKey key) + { + FileSystemCacheEntry entry = null; + _Index.TryGetValue(key, out entry); + return entry; + } + + internal void AddEntry(FileSystemCacheEntry entry) + { + var existing = GetEntry(entry.Key); + if(existing != null){ + _Cache.Remove(existing); + } + + _Cache.AddLast(entry); + _Index[entry.Key] = entry; + } + + internal void RemoveEntry(CacheKey key) + { + var existing = GetEntry(key); + if (existing != null) + { + _Cache.Remove(existing); + _Index.Remove(key); + } + } + + internal void TouchEntry(CacheKey key) + { + var existing = GetEntry(key); + if (existing != null) + { + _Cache.AddFirst(existing); + } + } + } + + public interface FileSystemCacheMutation + { + CacheKey Key { get; } + + int GetBytesRequired(FileSystemCache cache); + void Execute(FileSystemCache cache); + } + + public class FileSystemCacheAddMutation : FileSystemCacheMutation + { + public CacheKey Key { get; set; } + public byte[] Data { get; set; } + + public void Execute(FileSystemCache cache) + { + var path = cache.GetFilePath(Key); + var finalPart = path.LastIndexOf('/'); + Directory.CreateDirectory((finalPart == -1)?path:path.Substring(0, finalPart)); + File.WriteAllBytes(path, Data); + + var entry = cache.GetEntry(Key); + if (entry == null) + { + entry = new FileSystemCacheEntry(); + entry.Key = Key; + entry.LastRead = DateTime.MinValue; + entry.LastWrite = DateTime.Now; + entry.Length = Data.Length; + + cache.AddEntry(entry); + } + else + { + entry.Length = Data.Length; + } + } + + public int GetBytesRequired(FileSystemCache cache) + { + var existingFile = cache.GetEntry(Key); + if(existingFile != null) + { + return Data.Length - (int)existingFile.Length; + } + + return Data.Length; + } + } + + public class FileSystemCacheRemoveMutation : FileSystemCacheMutation + { + public CacheKey Key { get; set; } + + public void Execute(FileSystemCache cache) + { + File.Delete(cache.GetFilePath(Key)); + cache.RemoveEntry(Key); + } + + public int GetBytesRequired(FileSystemCache cache) + { + var existingFile = cache.GetEntry(Key); + if (existingFile != null) + { + return -((int)existingFile.Length); + } + return 0; + } + } + + public class FileSystemCacheEntry + { + public CacheKey Key; + public DateTime LastWrite; + public DateTime LastRead; + public long Length; + } +} diff --git a/server/tso.common/Utils/Cache/ICache.cs b/server/tso.common/Utils/Cache/ICache.cs new file mode 100755 index 0000000..5b6a71d --- /dev/null +++ b/server/tso.common/Utils/Cache/ICache.cs @@ -0,0 +1,20 @@ +using System; +using System.Threading.Tasks; + +namespace FSO.Common.Utils.Cache +{ + public interface ICache : IDisposable + { + bool ContainsKey(CacheKey key); + void Add(CacheKey key, byte[] bytes); + void Remove(CacheKey key); + + Task Get(CacheKey key); + + //bool IsReady { get; } + //bool Contains(string type, string key); + //Task GetBytes(string type, string key); + //Task PutBytes(string type, string key, byte[] bytes); + //Task Init(); + } +} diff --git a/server/tso.common/Utils/Callback.cs b/server/tso.common/Utils/Callback.cs new file mode 100755 index 0000000..010196a --- /dev/null +++ b/server/tso.common/Utils/Callback.cs @@ -0,0 +1,8 @@ +namespace FSO.Common.Utils +{ + + public delegate void Callback(); + public delegate void Callback(T data); + public delegate void Callback(T data, T2 data2); + public delegate void Callback(T data, T2 data2, T3 data3); +} diff --git a/server/tso.common/Utils/CollectionUtils.cs b/server/tso.common/Utils/CollectionUtils.cs new file mode 100755 index 0000000..cdeab6f --- /dev/null +++ b/server/tso.common/Utils/CollectionUtils.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Client.Utils +{ + public static class CollectionUtils + { + public static void Shuffle(this IList list) + { + Random rng = new Random(); + int n = list.Count; + while (n > 1) + { + n--; + int k = rng.Next(n + 1); + T value = list[k]; + list[k] = list[n]; + list[n] = value; + } + } + + public static IEnumerable Select(this Array items, Func converter) + { + var result = new List(); + foreach (var item in items) + { + result.Add(converter((TSource)item)); + } + return result; + } + + + public static Dictionary Clone(Dictionary input) + { + var result = new Dictionary(); + foreach (var val in input) + { + result.Add(val.Key, val.Value); + } + return result; + } + + + private static Random RAND = new Random(); + public static T RandomItem(this T[] items) + { + var index = RAND.Next(items.Length); + return items[index]; + } + } +} diff --git a/server/tso.common/Utils/CurLoader.cs b/server/tso.common/Utils/CurLoader.cs new file mode 100755 index 0000000..71708f8 --- /dev/null +++ b/server/tso.common/Utils/CurLoader.cs @@ -0,0 +1,110 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework.Input; +using System; +using System.IO; + +namespace FSO.Common.Utils +{ + public static class CurLoader + { + + public static MouseCursor LoadMonoCursor(GraphicsDevice gd, Stream stream) + { + var cur = LoadCursor(gd, stream); + return MouseCursor.FromTexture2D(cur.Item1, cur.Item2.X, cur.Item2.Y); + } + + public static MouseCursor[] LoadUpgradeCursors(GraphicsDevice gd, Stream stream, int maxStars) + { + var cur = LoadCursor(gd, stream); + Texture2D starTex; + using (var str = File.Open("Content/uigraphics/upgrade_star.png", FileMode.Open, FileAccess.Read, FileShare.Read)) + { + starTex = Texture2D.FromStream(gd, str); + } + + var batch = new SpriteBatch(gd); + var results = new MouseCursor[maxStars]; + for (int i = 0; i < maxStars; i++) { + var starPos = cur.Item1.Width - 12; + var width = Math.Max(starPos + 8 * i + 9, cur.Item1.Width); + var tex = new RenderTarget2D(gd, width, Math.Max(width, cur.Item1.Height)); + gd.SetRenderTarget(tex); + gd.Clear(Color.Transparent); + batch.Begin(SpriteSortMode.Immediate); + batch.Draw(cur.Item1, Vector2.Zero, Color.White); + for (int j=0; j<=i; j++) + { + batch.Draw(starTex, new Vector2(starPos, 5), Color.White); + starPos += 8; + } + batch.End(); + gd.SetRenderTarget(null); + results[i] = MouseCursor.FromTexture2D(tex, cur.Item2.X, cur.Item2.Y); + } + starTex.Dispose(); + + return results; + } + + public static Func BmpLoaderFunc; + + public static Tuple LoadCursor(GraphicsDevice gd, Stream stream) + { + using (var io = new BinaryReader(stream)) + { + //little endian + var tempbmp = new MemoryStream(); + var outIO = new BinaryWriter(tempbmp); + + var reserved = io.ReadInt16(); + var type = io.ReadInt16(); + if (type != 2) throw new Exception("Not a cursor!"); + var images = io.ReadInt16(); //currently discard extra images... + + //read first image + var width = io.ReadByte(); + var height = io.ReadByte(); + var colors = io.ReadByte(); + var reserved2 = io.ReadByte(); + var xOffset = io.ReadInt16(); + var yOffset = io.ReadInt16(); + var size = io.ReadInt32(); + var offset = io.ReadInt32(); + stream.Seek(offset - 22, SeekOrigin.Current); + + //ok... now write the bitmap data to a fake bitmap + outIO.Write(new char[] { 'B', 'M' }); + outIO.Write(size + 14); //size, plus header + outIO.Write(0); + outIO.Write(14); + var data = new byte[size]; + stream.Read(data, 0, size); + outIO.Write(data); + + tempbmp.Seek(0, SeekOrigin.Begin); + var tex = BmpLoaderFunc(gd, tempbmp); + + //our mask is on top. the image is on bottom. + var odata = new byte[tex.Width * tex.Height * 4]; + tex.GetData(odata); + var ndata = new byte[tex.Width * tex.Height * 2]; + var limit = ndata.Length; + for (int i=0; i< limit; i+=4) + { + var j = i + limit; + ndata[i] = (byte)((~odata[i]) & odata[j]); + ndata[i+1] = ndata[i]; + ndata[i+2] = ndata[i]; + ndata[i+3] = (byte)(~odata[i]); + } + var oTex = new Texture2D(gd, width, height); + oTex.SetData(ndata); + tex.Dispose(); + + return new Tuple(oTex, new Point(xOffset, yOffset)); + } + } + } +} diff --git a/server/tso.common/Utils/DebugUtils.cs b/server/tso.common/Utils/DebugUtils.cs new file mode 100755 index 0000000..4c6fcd7 --- /dev/null +++ b/server/tso.common/Utils/DebugUtils.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace FSO.Common.Utils +{ + public static class DebugUtils + { + public static string LogObject(object obj) + { + return JsonConvert.SerializeObject(obj); + } + } +} diff --git a/server/tso.common/Utils/DirectionUtils.cs b/server/tso.common/Utils/DirectionUtils.cs new file mode 100755 index 0000000..6df2f68 --- /dev/null +++ b/server/tso.common/Utils/DirectionUtils.cs @@ -0,0 +1,75 @@ +using Microsoft.Xna.Framework; +using System; + +namespace FSO.Common.Utils +{ + public static class DirectionUtils + { + + /// + /// Finds the difference between two radian directions. + /// + /// The direction to subtract from. + /// The direction to subtract. + public static double Difference(double a, double b) { + double value = PosMod(b-a, Math.PI*2); + if (value > Math.PI) value -= Math.PI * 2; + return value; + } + + /// + /// Normalizes a direction to the range -PI through PI. + /// + /// The direction to normalize. + public static double Normalize(double dir) + { + dir = PosMod(dir, Math.PI * 2); + if (dir > Math.PI) dir -= Math.PI * 2; + return dir; + } + + /// + /// Normalizes a direction in degrees to the range -180 through 180. + /// + /// The direction to normalize. + public static double NormalizeDegrees(double dir) + { + dir = PosMod(dir, 360); + if (dir > 180) dir -= 360; + return dir; + } + + /// + /// Calculates the mathematical modulus of a value. + /// + /// The number to mod. + /// The factor to use. + public static double PosMod(double x, double m) + { + return (x % m + m) % m; + } + + private static int[] tab32 = new int[] { + 0, 9, 1, 10, 13, 21, 2, 29, + 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, + 19, 27, 23, 6, 26, 5, 4, 31 + }; + + public static int Log2Int(uint value) + { + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + return tab32[(uint)(value * 0x07C4ACDD) >> 27]; + } + + public static float QuaternionDistance(Quaternion q1, Quaternion q2) + { + var inner = q1.X * q2.X + q1.Y * q2.Y + q1.Z * q2.Z + q1.W * q2.W; + return (float)Math.Acos(2 * (inner * inner) - 1); + } + } +} diff --git a/server/tso.common/Utils/DotPath.cs b/server/tso.common/Utils/DotPath.cs new file mode 100755 index 0000000..d300975 --- /dev/null +++ b/server/tso.common/Utils/DotPath.cs @@ -0,0 +1,54 @@ +using System; +using System.Reflection; + +namespace FSO.Common.Utils +{ + public static class DotPath + { + public static PropertyInfo[] CompileDotPath(Type sourceType, string sourcePath) + { + //Dot path + var path = sourcePath.Split(new char[] { '.' }); + var properties = new PropertyInfo[path.Length]; + + var currentType = sourceType; + for (int i = 0; i < path.Length; i++) + { + var property = currentType.GetProperty(path[i]); + properties[i] = property; + currentType = property.PropertyType; + } + + return properties; + } + + public static object GetDotPathValue(object source, PropertyInfo[] path) + { + if (source == null) { return null; } + + var currentValue = source; + for (var i = 0; i < path.Length; i++) + { + currentValue = path[i].GetValue(currentValue, null); + if (currentValue == null) { return null; } + } + + return currentValue; + } + + public static void SetDotPathValue(object source, PropertyInfo[] path, object value) + { + if (source == null) { return; } + + var currentValue = source; + for (var i = 0; i < path.Length - 1; i++) + { + currentValue = path[i].GetValue(currentValue, null); + if (currentValue == null) { return; } + } + + var member = path[path.Length - 1]; + member.SetValue(currentValue, value, null); + } + } +} diff --git a/server/tso.common/Utils/FeatureLevelTest.cs b/server/tso.common/Utils/FeatureLevelTest.cs new file mode 100755 index 0000000..53bcf58 --- /dev/null +++ b/server/tso.common/Utils/FeatureLevelTest.cs @@ -0,0 +1,68 @@ +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using System; + +namespace FSO.Common.Utils +{ + public class FeatureLevelTest + { + public static bool UpdateFeatureLevel(GraphicsDevice gd) + { + //if 3d is enabled, check if we support non-power-of-two mipmaps + if (FSOEnvironment.SoftwareKeyboard && FSOEnvironment.SoftwareDepth) + { + FSOEnvironment.EnableNPOTMip = false; + return true; + } + try + { + using (var mipTest = new Texture2D(gd, 11, 11, true, SurfaceFormat.Color)) + { + var data = new Color[11 * 11]; + TextureUtils.UploadWithMips(mipTest, gd, data); + } + } + catch (Exception e) + { + FSOEnvironment.EnableNPOTMip = false; + } + + try + { + using (var mipTest = new Texture2D(gd, 4, 4, true, SurfaceFormat.Dxt5)) + { + var data = new byte[16]; + mipTest.SetData(data); + } + } + catch (Exception e) + { + FSOEnvironment.TexCompressSupport = false; + } + + //msaa test + try + { + var msaaTarg = new RenderTarget2D(gd, 1, 1, false, SurfaceFormat.Color, DepthFormat.None, 8, RenderTargetUsage.PreserveContents); + gd.SetRenderTarget(msaaTarg); + gd.Clear(Color.Red); + + var tex = TextureUtils.CopyAccelerated(gd, msaaTarg); + + var result = new Color[1]; + tex.GetData(result); + FSOEnvironment.MSAASupport = result[0] == Color.Red; + gd.SetRenderTarget(null); + msaaTarg.Dispose(); + tex.Dispose(); + } + catch + { + gd.SetRenderTarget(null); + FSOEnvironment.MSAASupport = false; + } + + return true; + } + } +} diff --git a/server/tso.common/Utils/FileUtils.cs b/server/tso.common/Utils/FileUtils.cs new file mode 100755 index 0000000..5f11e45 --- /dev/null +++ b/server/tso.common/Utils/FileUtils.cs @@ -0,0 +1,25 @@ +using System; +using System.IO; +using System.Security.Cryptography; + +namespace FSO.Common.Utils +{ + public class FileUtils + { + public static string ComputeMD5(string filePath){ + var bytes = ComputeMD5Bytes(filePath); + return BitConverter.ToString(bytes).Replace("-", "").ToLowerInvariant(); + } + + public static byte[] ComputeMD5Bytes(string filePath) + { + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(filePath)) + { + return md5.ComputeHash(stream); + } + } + } + } +} diff --git a/server/tso.common/Utils/GameThread.cs b/server/tso.common/Utils/GameThread.cs new file mode 100755 index 0000000..24a3f63 --- /dev/null +++ b/server/tso.common/Utils/GameThread.cs @@ -0,0 +1,274 @@ +using FSO.Common.Rendering.Framework.Model; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace FSO.Common.Utils +{ + public class GameThreadInterval + { + private Callback Callback; + private long Interval; + private double EndTime = -1; + + private UpdateHook _TickHook; + private bool _Clear; + + public GameThreadInterval(Callback callback, long interval) + { + Callback = callback; + Interval = interval; + _TickHook = GameThread.EveryUpdate(Tick); + } + + public void Clear() + { + _Clear = true; + } + + private void Tick(UpdateState state) + { + if (_Clear) + { + _TickHook.Remove(); + return; + } + + var now = state.Time.TotalGameTime.TotalMilliseconds; + if (EndTime == -1) + { + EndTime = now + Interval; + } + + if (EndTime <= now) + { + Callback(); + EndTime = now + Interval; + } + } + } + + public class GameThreadTimeout + { + private Callback Callback; + private long Delay; + private double EndTime = -1; + + private UpdateHook _TickHook; + private bool _Clear; + + public GameThreadTimeout(Callback callback, long delay) + { + Callback = callback; + Delay = delay; + _TickHook = GameThread.EveryUpdate(Tick); + } + + public void Clear(){ + _Clear = true; + } + + private void Tick(UpdateState state) + { + if (_Clear){ + _TickHook.Remove(); + return; + } + + var now = state.Time.TotalGameTime.TotalMilliseconds; + if (EndTime == -1){ + EndTime = now + Delay; + } + + if(EndTime <= now){ + _TickHook.Remove(); + Callback(); + } + } + } + + public class UpdateHook + { + public bool RemoveNext = false; + public Callback Callback; + + public void Remove(){ + RemoveNext = true; + } + } + + public class GameThread + { + public static bool Killed; + public static bool NoGame; + public static EventWaitHandle OnKilled = new EventWaitHandle(false, EventResetMode.ManualReset); + public static event Action KilledEvent; + public static Thread Game; + public static bool UpdateExecuting; + private static List _UpdateHooks = new List(); + private static UpdateHook[] _UpdateHooksCopy = new UpdateHook[0]; + private static List _UpdateHooksRemove = new List(); + private static Queue> _UpdateCallbacks = new Queue>(); + private static Queue> _UpdateCallbacksSwap = new Queue>(); + public static AutoResetEvent OnWork = new AutoResetEvent(false); + + public static void SetKilled() + { + Killed = true; + OnKilled.Set(); + KilledEvent?.Invoke(); + } + + public static GameThreadTimeout SetTimeout(Callback callback, long delay) + { + var result = new GameThreadTimeout(callback, delay); + return result; + } + + public static GameThreadInterval SetInterval(Callback callback, long delay) + { + var result = new GameThreadInterval(callback, delay); + return result; + } + + //I know we already have a way to do this with IUIProcess but we need a way for other libs that dont + //have the UI code for reference + public static UpdateHook EveryUpdate(Callback callback) + { + var newHook = new UpdateHook() + { + Callback = callback + }; + + lock (_UpdateHooks) + { + _UpdateHooks.Add(newHook); + } + + return newHook; + } + + public static void NextUpdate(Callback callback) + { + lock (_UpdateCallbacks) + { + _UpdateCallbacks.Enqueue(callback); + } + OnWork.Set(); + } + + public static void InUpdate(Callback callback) + { + if (IsInGameThread() && UpdateExecuting){ + callback(); + }else{ + NextUpdate(x => callback()); + } + } + + public static bool IsInGameThread() + { + var thread = Thread.CurrentThread; + if (thread == Game || NoGame) + { + return true; + } + return false; + } + + public static Task NextUpdate(Func callback) + { + TaskCompletionSource task = new TaskCompletionSource(); + lock (_UpdateCallbacks) + { + _UpdateCallbacks.Enqueue(x => + { + task.SetResult(callback(x)); + }); + } + return TimeoutAfter(task.Task, new TimeSpan(0, 0, 5)); + } + + public static async Task TimeoutAfter(Task task, TimeSpan timeout) + { + using (var timeoutCancellationTokenSource = new CancellationTokenSource()) + { + + var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token)); + if (completedTask == task) + { + timeoutCancellationTokenSource.Cancel(); + return await task; // Very important in order to propagate exceptions + } + else + { + return default(TResult); + } + } + } + + public static void DigestUpdate(UpdateState state) + { + Queue> _callbacks; + + lock (_UpdateCallbacks) + { + // Swap the active callbacks queue with the second one, so we can + // process entries without fear of more being added. + + _callbacks = _UpdateCallbacks; + _UpdateCallbacks = _UpdateCallbacksSwap; + _UpdateCallbacksSwap = _callbacks; + } + + while (_callbacks.Count > 0) + { + _callbacks.Dequeue()(state); + } + + int hookCount; + UpdateHook[] _hooks; + List toRemove = _UpdateHooksRemove; + + lock (_UpdateHooks) + { + hookCount = _UpdateHooks.Count; + + if (_UpdateHooksCopy.Length < _UpdateHooks.Count) + { + _UpdateHooksCopy = _UpdateHooks.ToArray(); + } + else + { + _UpdateHooks.CopyTo(_UpdateHooksCopy); + } + + _hooks = _UpdateHooksCopy; + } + + for (int i = 0; i < hookCount; i++) + { + var item = _hooks[i]; + item.Callback(state); + if (item.RemoveNext) + { + toRemove.Add(item); + } + } + + if (toRemove.Count > 0) + { + lock (_UpdateHooks) + { + foreach (var rem in toRemove) _UpdateHooks.Remove(rem); + } + + toRemove.Clear(); + } + + //finally, check cache controller + TimedReferenceController.Tick(); + } + } +} diff --git a/server/tso.common/Utils/HTMLPrinter.cs b/server/tso.common/Utils/HTMLPrinter.cs new file mode 100755 index 0000000..3639b59 --- /dev/null +++ b/server/tso.common/Utils/HTMLPrinter.cs @@ -0,0 +1,348 @@ +//disabled for now so FSO.Files can reference this project. + + /* +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.IO; +using System.Security.Cryptography; +using FSO.Files.Formats.IFF.Chunks; +using Microsoft.Xna.Framework.Graphics; + +namespace FSO.Common.Utils +{ + /// + /// This tool helps export internal structures such as floor catalogs, + /// wall catalogs etc to a html file to check that file parsing is working correctly + /// + public class HTMLPrinter : IDisposable + { + private List sections = new List(); + private Dictionary patterns = new Dictionary(); + private string dir; + private string id; + private GraphicsDevice Gd; + + public HTMLPrinter(GraphicsDevice gd, string directory, string id) + { + this.Gd = gd; + this.dir = directory; + this.id = id; + + sections.Add(""); + + //Add the default patterns + patterns.Add("h1", "

{0}

"); + patterns.Add("h2", "

{0}

"); + patterns.Add("h3", "

{0}

"); + } + + public void H1(string text){ + Print("h1", text); + } + + public void H2(string text){ + Print("h2", text); + } + + public void H3(string text){ + Print("h3", text); + } + + public Table CreateTable() + { + return new Table(); + } + + public void Add(object item){ + this.sections.Add(item); + } + + public Table CreateTable(params string[] columns) + { + var t = new Table(); + foreach (var col in columns) + { + t.WithColumn(new TableColumn(col)); + } + return t; + } + + public DataTable AddDataTable(IEnumerable values) + { + var table = CreateDataTable(values); + sections.Add(table); + return table; + } + + public DataTable CreateDataTable(IEnumerable values) + { + return new DataTable(values); + } + + private string ObjectToString(object obj) + { + if (obj != null) + { + return obj.ToString(); + } + return string.Empty; + } + + + public void Print(string pattern, params object[] args) + { + var value = string.Format(patterns[pattern], args); + sections.Add(value); + } + + #region IDisposable Members + + public void Dispose() + { + Directory.CreateDirectory(Path.Combine(dir, id + "_files")); + + var sb = new StringBuilder(); + + foreach (var item in sections) + { + AppendItem(sb, item); + } + + File.WriteAllText(Path.Combine(dir, id + ".html"), sb.ToString()); + } + + #endregion + + + public void AppendItem(StringBuilder sb, object item) + { + if (item is IHTMLAppender) + { + ((IHTMLAppender)item).Append(this, sb); + }else if(item is SPR2Frame){ + + try + { + var path = ExportSpriteFrame((SPR2Frame)item); + sb.Append(""); + } + catch (Exception) + { + sb.Append("Failed to export"); + } + } + else if (item is SPRFrame) + { + try + { + var path = ExportSpriteFrame((SPRFrame)item); + sb.Append(""); + } + catch (Exception) + { + sb.Append("Failed to export"); + } + } + else if (item != null) + { + sb.Append(item.ToString()); + } + + /**else if(item is SPR){ + + var t = CreateTable() + .WithColumn(new TableColumn("Sprite", 2)); + + var sprP = (SPR)item; + for (var i = 0; i < sprP.FrameCount; i++){ + try + { + var frame = sprP.GetFrame(i); + t.AddRow((i + 1), frame); + } + catch (Exception ex) + { + t.AddRow((i + 1), "Failed to export frame"); + } + } + + AppendItem(sb, t); + + }**/ + + /** + } + + private string ExportSpriteFrame(SPRFrame frame) + { + var texture = frame.GetTexture(this.Gd); + + var temp = Path.GetTempFileName(); + texture.SaveAsPng(new FileStream(temp, FileMode.OpenOrCreate), texture.Width, texture.Height); + + var hash = FileUtils.ComputeMD5(temp); + var filename = id + "_files/" + hash + ".png"; + var newDest = Path.Combine(dir, filename); + if (File.Exists(newDest)) + { + File.Delete(temp); + } + else + { + File.Move(temp, newDest); + } + + return filename; + } + + private string ExportSpriteFrame(SPR2Frame frame) + { + var texture = frame.GetTexture(this.Gd); + + var temp = Path.GetTempFileName(); + texture.SaveAsPng(new FileStream(temp, FileMode.OpenOrCreate), texture.Width, texture.Height); + + var hash = FileUtils.ComputeMD5(temp); + var filename = id + "_files/" + hash + ".png"; + var newDest = Path.Combine(dir, filename); + if (File.Exists(newDest)) + { + File.Delete(temp); + } + else + { + File.Move(temp, newDest); + } + + return filename; + } + + + } + + public class TableColumn + { + public TableColumn(string header) + { + this.Header = header; + } + public TableColumn(string header, int span) + { + this.Header = header; + this.Span = span; + } + + public string Header; + public int Span; + } + + public class Table : IHTMLAppender + { + private List Columns = new List(); + private List Rows = new List(); + + public Table WithColumn(TableColumn col) + { + Columns.Add(col); + return this; + } + + public Table AddRow(params object[] values) + { + Rows.Add(values); + return this; + } + + #region IHTMLAppender Members + + public void Append(HTMLPrinter printer, StringBuilder sb) + { + sb.Append(""); + + if (Columns.Count > 0) + { + sb.Append(""); + foreach (var col in Columns) + { + sb.Append(""); + } + sb.Append(""); + } + + foreach (var item in Rows) + { + sb.Append(""); + foreach(var col in item){ + sb.Append(""); + } + sb.Append(""); + } + sb.Append("
" + col.Header + "
"); + printer.AppendItem(sb, col); + sb.Append("
"); + } + + #endregion + } + + + public class DataTable : IHTMLAppender + { + private IEnumerable Items; + private List> Columns; + + public DataTable(IEnumerable items) + { + this.Items = items; + this.Columns = new List>(); + } + + + public DataTable WithColumn(string label, Func value) + { + Columns.Add(new DataTableColumn { Heading = label, Value = value }); + return this; + } + + #region IHTMLAppender Members + + public void Append(HTMLPrinter printer, StringBuilder sb) + { + sb.Append(""); + sb.Append(""); + foreach (var col in Columns) + { + sb.Append(""); + } + sb.Append(""); + + foreach (var item in Items) + { + sb.Append(""); + foreach (var col in Columns) + { + sb.Append(""); + } + sb.Append(""); + } + sb.Append("
" + col.Heading + "
"); + printer.AppendItem(sb, col.Value(item)); + sb.Append("
"); + } + + #endregion + } + + public interface IHTMLAppender + { + void Append(HTMLPrinter printer, StringBuilder sb); + } + + public class DataTableColumn { + public string Heading; + public Func Value; + } +} +*/ \ No newline at end of file diff --git a/server/tso.common/Utils/ITimedCachable.cs b/server/tso.common/Utils/ITimedCachable.cs new file mode 100755 index 0000000..d32e937 --- /dev/null +++ b/server/tso.common/Utils/ITimedCachable.cs @@ -0,0 +1,7 @@ +namespace FSO.Common.Utils +{ + public interface ITimedCachable + { + void Rereferenced(bool save); + } +} diff --git a/server/tso.common/Utils/IXMLEntity.cs b/server/tso.common/Utils/IXMLEntity.cs new file mode 100755 index 0000000..06db0f3 --- /dev/null +++ b/server/tso.common/Utils/IXMLEntity.cs @@ -0,0 +1,43 @@ +using System; +using System.Xml; + +namespace FSO.Common.Utils +{ + public interface IXMLEntity + { + XmlElement Serialize(XmlDocument doc); + void Parse(XmlElement element); + } + + public static class XMLUtils + { + public static T Parse(string data) where T : IXMLEntity + { + var doc = new XmlDocument(); + doc.LoadXml(data); + + T result = (T)Activator.CreateInstance(typeof(T)); + result.Parse((XmlElement)doc.FirstChild); + return result; + } + + public static void AppendTextNode(this XmlElement e, string nodeName, string value) + { + var node = e.OwnerDocument.CreateElement(nodeName); + node.AppendChild(e.OwnerDocument.CreateTextNode(value)); + e.AppendChild(node); + } + + public static string ReadTextNode(this XmlElement e, string nodeName) + { + foreach (XmlElement child in e.ChildNodes) + { + if (child.Name == nodeName && child.FirstChild != null) + { + return child.FirstChild?.Value; + } + } + return null; + } + } +} diff --git a/server/tso.common/Utils/IffPrinter.cs b/server/tso.common/Utils/IffPrinter.cs new file mode 100755 index 0000000..ac8affa --- /dev/null +++ b/server/tso.common/Utils/IffPrinter.cs @@ -0,0 +1,106 @@ + /* +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FSO.Files.Formats.IFF; +using FSO.Files.Formats.IFF.Chunks; + +namespace FSO.Common.Utils +{ + public class IffPrinter + { + private HTMLPrinter Printer; + + public IffPrinter(HTMLPrinter printer){ + this.Printer = printer; + } + + public void PrintAll(IffFile iff){ + this.Print(iff); + this.Print(iff); + this.Print(iff); + } + + public void Print(IffFile iff){ + var type = typeof(T); + var items = iff.List(); + + if (items == null) { return; } + + if (type == typeof(SPR2)){ + Printer.H1("SPR2"); + foreach (var item in items){ + PrintSPR2((SPR2)(object)item); + } + } + else if (type == typeof(OBJD)) + { + Printer.H1("OBJD"); + foreach (var item in items){ + PrintOBJD((OBJD)(object)item); + } + }else if (type == typeof(SPR)) + { + Printer.H1("SPR"); + foreach (var item in items) + { + PrintSPR((SPR)(object)item); + } + } + } + + private void PrintSPR(SPR spr) + { + Printer.H2("#" + spr.ChunkID + " (" + spr.ChunkLabel + ")"); + var table = Printer.CreateTable(new string[] { "Index", "Pixel" }); + var frameIndex = 0; + foreach (var frame in spr.Frames) + { + table.AddRow(new object[] { frameIndex, frame }); + frameIndex++; + } + Printer.Add(table); + } + + private void PrintOBJD(OBJD item){ + string[] fieldLabels = null; + switch (item.Version) + { + case 142: + fieldLabels = OBJD.VERSION_142_Fields; + break; + } + + Printer.H1(item.ChunkID + " (" + item.ChunkLabel + ") GUID = " + item.GUID.ToString("x") + " Version = " + item.Version); + var table = Printer.CreateTable(new string[] { "Field", "Value" }); + for (var i = 0; i < item.RawData.Length; i++) + { + if (fieldLabels != null && i < fieldLabels.Length) + { + table.AddRow(new object[] { i.ToString() + " (" + fieldLabels[i] + ")", item.RawData[i].ToString() }); + } + else + { + table.AddRow(new object[] { i.ToString(), item.RawData[i].ToString() }); + } + } + Printer.Add(table); + } + + private void PrintSPR2(SPR2 spr) + { + Printer.H2("#" + spr.ChunkID + " (" + spr.ChunkLabel + ")"); + var table = Printer.CreateTable(new string[] { "Index", "Pixel" }); + var frameIndex = 0; + foreach (var frame in spr.Frames){ + table.AddRow(new object[] { frameIndex, frame }); + frameIndex++; + } + Printer.Add(table); + } + + + } +} +*/ \ No newline at end of file diff --git a/server/tso.common/Utils/LinqUtils.cs b/server/tso.common/Utils/LinqUtils.cs new file mode 100755 index 0000000..80170da --- /dev/null +++ b/server/tso.common/Utils/LinqUtils.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.Utils +{ + public static class LinqUtils + { + public static IEnumerable> Batch(this IEnumerable items, int maxItems) + { + return items.Select((item, index) => new { item, index }) + .GroupBy(x => x.index / maxItems) + .Select(g => g.Select(x => x.item)); + } + } +} diff --git a/server/tso.common/Utils/MoneyFormatter.cs b/server/tso.common/Utils/MoneyFormatter.cs new file mode 100755 index 0000000..56f6b62 --- /dev/null +++ b/server/tso.common/Utils/MoneyFormatter.cs @@ -0,0 +1,17 @@ +using System.Globalization; + +namespace FSO.Common.Utils +{ + public class MoneyFormatter + { + public static string Format(uint money) + { + var val = money.ToString("N", new CultureInfo("en-US")); + var io = val.LastIndexOf("."); + if(io != -1){ + val = val.Substring(0, io); + } + return "$" + val; + } + } +} diff --git a/server/tso.common/Utils/PPXDepthEngine.cs b/server/tso.common/Utils/PPXDepthEngine.cs new file mode 100755 index 0000000..a505459 --- /dev/null +++ b/server/tso.common/Utils/PPXDepthEngine.cs @@ -0,0 +1,213 @@ +using System; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace FSO.Common.Utils +{ + public class PPXDepthEngine + { + private static GraphicsDevice GD; + private static RenderTarget2D BackbufferDepth; + private static RenderTarget2D Backbuffer; + private static SpriteBatch SB; + public static int SSAA = 1; + public static int MSAA = 0; + + public static void InitGD(GraphicsDevice gd) + { + GD = gd; + SB = new SpriteBatch(gd); + } + public static void InitScreenTargets() + { + if (GD == null) return; + if (BackbufferDepth != null) BackbufferDepth.Dispose(); + BackbufferDepth = null; + if (Backbuffer != null) Backbuffer.Dispose(); + var scale = 1;//FSOEnvironment.DPIScaleFactor; + if (!FSOEnvironment.Enable3D) + BackbufferDepth = CreateRenderTarget(GD, 1, MSAA, SurfaceFormat.Color, SSAA*GD.Viewport.Width/scale, SSAA * GD.Viewport.Height / scale, DepthFormat.None); + Backbuffer = CreateRenderTarget(GD, 1, MSAA, SurfaceFormat.Color, SSAA * GD.Viewport.Width / scale, SSAA * GD.Viewport.Height / scale, DepthFormat.Depth24Stencil8); + } + + private static RenderTarget2D ActiveColor; + private static RenderTarget2D ActiveDepth; + private static int StencilValue; + + public static void SetPPXTarget(RenderTarget2D color, RenderTarget2D depth, bool clear) + { + SetPPXTarget(color, depth, clear, Color.TransparentBlack); + } + + public static void SetPPXTarget(RenderTarget2D color, RenderTarget2D depth, bool clear, Color clearColor) + { + if (color == null && depth == null && Backbuffer != null) color = Backbuffer; + ActiveColor = color; + if (color == Backbuffer && depth == null && BackbufferDepth != null) depth = BackbufferDepth; + ActiveDepth = depth; + + //if (color != null && depth != null) depth.InheritDepthStencil(color); + var gd = GD; + gd.SetRenderTarget(color); //can be null + if (clear) + { + StencilValue = 1; + + gd.Clear(clearColor);// FSO.Common.Rendering.Framework.GameScreen.ClearColor); + if (depth != null) + { + gd.SetRenderTarget(depth); + gd.Clear(Color.White); + } + } + if (FSOEnvironment.UseMRT) + { + if (depth != null) gd.SetRenderTargets(color, depth); + } + } + + public static RenderTarget2D GetBackbuffer() + { + return Backbuffer; + } + + public delegate void RenderPPXProcedureDelegate(bool depthPass); + public static void RenderPPXDepth(Effect effect, bool forceDepth, + RenderPPXProcedureDelegate proc) + { + var color = ActiveColor; + var depth = ActiveDepth; + var gd = GD; + if (FSOEnvironment.SoftwareDepth && depth != null) + { + var oldDS = gd.DepthStencilState; + //completely special case. + gd.SetRenderTarget(color); + gd.DepthStencilState = new DepthStencilState + { + StencilEnable = true, + StencilFunction = CompareFunction.Always, + StencilFail = StencilOperation.Keep, + StencilPass = StencilOperation.Replace, + CounterClockwiseStencilPass = StencilOperation.Replace, + StencilDepthBufferFail = StencilOperation.Keep, + DepthBufferEnable = forceDepth, //(ActiveColor == null), + DepthBufferWriteEnable = forceDepth, //(ActiveColor == null), + ReferenceStencil = StencilValue, + TwoSidedStencilMode = true + }; + effect.Parameters["depthMap"].SetValue(depth); + effect.Parameters["depthOutMode"].SetValue(false); + proc(false); + + //now draw the depth using the depth test information we got previously. + + //unbind depth map since we are writing to it + effect.Parameters["depthMap"].SetValue((Texture2D)null); + effect.Parameters["depthOutMode"].SetValue(true); + gd.SetRenderTarget(depth); + gd.DepthStencilState = new DepthStencilState + { + StencilEnable = true, + StencilFunction = CompareFunction.Equal, + DepthBufferEnable = forceDepth, + DepthBufferWriteEnable = forceDepth, + ReferenceStencil = StencilValue, + }; + proc(true); + + gd.DepthStencilState = oldDS; + StencilValue++; //can increment up to 254 times. Assume we're not going to be rendering that much between clears. + if (StencilValue > 255) StencilValue = 1; + gd.SetRenderTarget(color); + effect.Parameters["depthOutMode"].SetValue(false); + } + else if (!FSOEnvironment.UseMRT && depth != null) + { + //draw color then draw depth + gd.SetRenderTarget(color); + proc(false); + effect.Parameters["depthOutMode"].SetValue(true); + gd.SetRenderTarget(depth); + proc(true); + effect.Parameters["depthOutMode"].SetValue(false); + } + else + { + //mrt already bound. draw in both. + proc(false); + } + } + + public static Action SSAAFunc; + public static bool WithOpacity = true; + + public static void DrawBackbuffer(float opacity, float scale) + { + if (Backbuffer == null) return; //this gfx mode does not use a rendertarget backbuffer + if (SSAA > 1) + { + SSAAFunc(GD, Backbuffer); + } + else + { + if (!WithOpacity) + { + SB.Begin(blendState: BlendState.Opaque); + opacity = 1; + } + else + SB.Begin(blendState: BlendState.AlphaBlend); + SB.Draw(Backbuffer, new Vector2(Backbuffer.Width * (1 - scale) / 2, Backbuffer.Height * (1 - scale) / 2), null, Color.White * opacity, 0f, new Vector2(), scale, + SpriteEffects.None, 0); + SB.End(); + } + } + + public static Point GetWidthHeight() + { + return new Point(Backbuffer.Width, Backbuffer.Height); + } + + public static RenderTarget2D CreateRenderTarget(GraphicsDevice device, int numberLevels, int multisample, SurfaceFormat surface, int width, int height, DepthFormat dformat) + { + //apparently in xna4, there is no way to check device format... (it looks for the closest format if desired is not supported) need to look into if this affects anything. + + /*MultiSampleType type = device.PresentationParameters.MultiSampleType; + + // If the card can't use the surface format + if (!GraphicsAdapter.DefaultAdapter.CheckDeviceFormat( + DeviceType.Hardware, + GraphicsAdapter.DefaultAdapter.CurrentDisplayMode.Format, + TextureUsage.None, + QueryUsages.None, + ResourceType.RenderTarget, + surface)) + { + // Fall back to current display format + surface = device.DisplayMode.Format; + } + // Or it can't accept that surface format + // with the current AA settings + else if (!GraphicsAdapter.DefaultAdapter.CheckDeviceMultiSampleType( + DeviceType.Hardware, surface, + device.PresentationParameters.IsFullScreen, type)) + { + // Fall back to no antialiasing + type = MultiSampleType.None; + }*/ + + /*int width, height; + + // See if we can use our buffer size as our texture + CheckTextureSize(device.PresentationParameters.BackBufferWidth, + device.PresentationParameters.BackBufferHeight, + out width, out height);*/ + + // Create our render target + return new RenderTarget2D(device, + width, height, (numberLevels>1), surface, + DepthFormat.Depth24Stencil8, multisample, RenderTargetUsage.PreserveContents); + } + } +} diff --git a/server/tso.common/Utils/PathCaseTools.cs b/server/tso.common/Utils/PathCaseTools.cs new file mode 100755 index 0000000..b758c28 --- /dev/null +++ b/server/tso.common/Utils/PathCaseTools.cs @@ -0,0 +1,14 @@ +using System.IO; +using System.Linq; + +namespace FSO.Common.Utils +{ + public static class PathCaseTools + { + public static string Insensitive(string file) + { + var dir = Directory.GetFiles(Path.GetDirectoryName(file)); + return dir.FirstOrDefault(x => x.ToLowerInvariant().Replace('\\', '/') == file.ToLowerInvariant().Replace('\\', '/')); + } + } +} diff --git a/server/tso.common/Utils/Promise.cs b/server/tso.common/Utils/Promise.cs new file mode 100755 index 0000000..16ce4e3 --- /dev/null +++ b/server/tso.common/Utils/Promise.cs @@ -0,0 +1,35 @@ +using System; + +namespace FSO.Common.Utils +{ + public class Promise + { + private Func Getter; + private T Value; + private bool HasRun = false; + + + public Promise(Func getter) + { + this.Getter = getter; + } + + public void SetValue(T value) + { + this.HasRun = true; + this.Value = value; + } + + + public T Get() + { + if (HasRun == false) + { + Value = Getter(null); + HasRun = true; + } + + return Value; + } + } +} diff --git a/server/tso.common/Utils/StateMachine.cs b/server/tso.common/Utils/StateMachine.cs new file mode 100755 index 0000000..77aafec --- /dev/null +++ b/server/tso.common/Utils/StateMachine.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; + +namespace FSO.Common.Utils +{ + public class StateMachine where STATES : IConvertible + { + public STATES CurrentState { get; internal set; } + private Dictionary> LegalMoves; + + public event Callback OnTransition; + + public StateMachine(STATES startState) + { + this.CurrentState = startState; + } + + + public bool TransitionTo(STATES state) + { + + lock (CurrentState) + { + if (CurrentState.Equals(state)) + { + return true; + } + + /*if (!LegalMoves.ContainsKey(CurrentState)) + { + return false; + } + if (!LegalMoves[CurrentState].Contains(state)) + { + return false; + }*/ + + var previousState = CurrentState; + this.CurrentState = state; + if (OnTransition != null) + { + OnTransition(previousState, CurrentState); + } + return true; + } + } + + /*public StateMachine AllowTransition(STATES from, STATES to) + { + if (!LegalMoves.ContainsKey(from)) + { + LegalMoves.Add(from, new List()); + } + LegalMoves[from].Add(to); + return this; + }*/ + } +} diff --git a/server/tso.common/Utils/TSOTime.cs b/server/tso.common/Utils/TSOTime.cs new file mode 100755 index 0000000..1e3d7d8 --- /dev/null +++ b/server/tso.common/Utils/TSOTime.cs @@ -0,0 +1,27 @@ +using System; + +namespace FSO.Common.Utils +{ + public class TSOTime + { + public static Tuple FromUTC(DateTime time) + { + //var count = time.Minute * 60 * 1000 + time.Second * 1000 + time.Millisecond; + //count *= 8; + //count %= 1000 * 60 * 24; + + //var hour = count / (1000 * 60); + //var min = (count / 1000) % 60; + //var sec = ((count * 60) / 1000) % 60; + + var hour = time.Hour; + var min = time.Minute; + var sec = time.Second; + var ms = time.Millisecond; + + var cycle = (hour % 2 == 1) ? 3600 : 0; + cycle += min * 60 + sec; + return new Tuple(cycle / 300, (cycle % 300) / 5, (cycle % 5)*12 + ((ms * 12) / 1000)); + } + } +} diff --git a/server/tso.common/Utils/TextureGenerator.cs b/server/tso.common/Utils/TextureGenerator.cs new file mode 100755 index 0000000..a1d67a2 --- /dev/null +++ b/server/tso.common/Utils/TextureGenerator.cs @@ -0,0 +1,582 @@ +using System; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; + +namespace FSO.Common.Utils +{ + public class TextureGenerator //a fun class for cpu generating textures + { + private static Texture2D PxWhite; + private static Texture2D DefaultAdvLight; + private static Texture2D PieButtonImg; + + private static Texture2D InteractionInactive; + private static Texture2D InteractionActive; + private static Texture2D CatalogInactive; + private static Texture2D CatalogActive; + private static Texture2D CatalogDisabled; + private static Texture2D PieBG; + private static Texture2D[] WallZBuffer; + private static Texture2D[] AirTiles; + private static Texture2D MotiveArrow; //actually a diamond, clip to get required direction + private static Texture2D TerrainNoise; + private static Texture2D UniformNoise; + + public static Texture2D GetPxWhite(GraphicsDevice gd) + { + if (PxWhite == null) PxWhite = TextureUtils.TextureFromColor(gd, Color.White); + return PxWhite; + } + + public static Texture2D GetDefaultAdv(GraphicsDevice gd) + { + if (DefaultAdvLight == null) DefaultAdvLight = TextureUtils.TextureFromColor(gd, new Color(128, 0, 0, 255)); //outdoors color max + return DefaultAdvLight; + } + + public static Texture2D GetPieButtonImg(GraphicsDevice gd) + { + if (PieButtonImg == null) PieButtonImg = GenerateRoundedRectangle(gd, new Color(0, 40, 140), 27, 27, 6); + return PieButtonImg; + } + + public static Texture2D GetInteractionActive(GraphicsDevice gd) + { + if (InteractionActive == null) InteractionActive = GenerateObjectIconBorder(gd, new Color(255, 255, 0), new Color(56, 88, 120)); + return InteractionActive; + } + + public static Texture2D GetInteractionInactive(GraphicsDevice gd) + { + if (InteractionInactive == null) InteractionInactive = GenerateObjectIconBorder(gd, new Color(128, 128, 128), new Color(56, 88, 120)); + return InteractionInactive; + } + + public static Texture2D GetCatalogInactive(GraphicsDevice gd) + { + if (CatalogInactive == null) CatalogInactive = GenerateCatalogIconBorder(gd, new Color(140, 170, 206), new Color(56, 88, 120)); + return CatalogInactive; + } + + public static Texture2D GetCatalogDisabled(GraphicsDevice gd) + { + if (CatalogDisabled == null) CatalogDisabled = GenerateCatalogIconBorder(gd, new Color(255, 0, 0), new Color(56, 88, 120)); + return CatalogDisabled; + } + + public static Texture2D GetCatalogActive(GraphicsDevice gd) + { + if (CatalogActive == null) CatalogActive = GenerateCatalogIconBorder(gd, new Color(140, 170, 206), new Color(189, 215, 247)); + return CatalogActive; + } + + public static Texture2D GetPieBG(GraphicsDevice gd) + { + if (PieBG == null) + { + PieBG = new Texture2D(gd, 200, 200); + Color[] data = new Color[200 * 200]; + int offset = 0; + for (int y = 0; y < 200; y++) + { + for (int x = 0; x < 200; x++) + { + data[offset++] = new Color(0, 0, 0, (float)Math.Min(1, 2 - Math.Sqrt(Math.Pow(y - 100, 2) + Math.Pow(x - 100, 2)) / 50) * 0.5f); + } + } + PieBG.SetData(data); + } + + return PieBG; + } + + public static Texture2D GetMotiveArrow(GraphicsDevice gd) + { + if (MotiveArrow == null) + { + MotiveArrow = new Texture2D(gd, 5, 5); + Color[] data = new Color[5 * 5]; + var size = new Vector2(5, 5); + + FillRect(data, size, new Rectangle(2, 0, 1, 1), Color.White); + FillRect(data, size, new Rectangle(1, 1, 3, 1), Color.White); + FillRect(data, size, new Rectangle(0, 2, 5, 1), Color.White); + FillRect(data, size, new Rectangle(1, 3, 3, 1), Color.White); + FillRect(data, size, new Rectangle(2, 4, 1, 1), Color.White); + + MotiveArrow.SetData(data); + } + return MotiveArrow; + } + + public static Texture2D GetTerrainNoise(GraphicsDevice gd) + { + if (TerrainNoise == null) + { + TerrainNoise = new Texture2D(gd, 512, 512, true, SurfaceFormat.Color); + Color[] data = new Color[512 * 512]; + + var rd = new Random(); + for (int i = 0; i < data.Length; i++) + { + //distribution is an average of two noise functions. + data[i].R = (byte)((rd.Next(255) + rd.Next(255)) / 2); + data[i].G = (byte)((rd.Next(255) + rd.Next(255)) / 2); + data[i].B = (byte)((rd.Next(255) + rd.Next(255)) / 2); + data[i].A = (byte)((rd.Next(255) + rd.Next(255)) / 2); + } + TextureUtils.UploadWithMips(TerrainNoise, gd, data); + } + return TerrainNoise; + } + + public static Texture2D GetUniformNoise(GraphicsDevice gd) + { + if (UniformNoise == null) + { + UniformNoise = new Texture2D(gd, 512, 512, true, SurfaceFormat.Color); + Color[] data = new Color[512 * 512]; + + var rd = new Random(); + for (int i = 0; i < data.Length; i++) + { + //distribution is an average of two noise functions. + data[i].R = (byte)(rd.Next(255)); + data[i].G = (byte)(rd.Next(255)); + data[i].B = (byte)(rd.Next(255)); + data[i].A = (byte)(rd.Next(255)); + } + TextureUtils.UploadWithMips(UniformNoise, gd, data); + } + return UniformNoise; + } + + public static float FLAT_Z_INC = 1.525f; + public static float[][] WallZBufferConfig = new float[][] { + // format: width, height, startIntensity, Xdiff, Ydiff + + new float[] {64, 271, 74, 1, 0.5f}, //near top left + new float[] {64, 271, 135, -1, 0.5f}, //near top right + new float[] {128, 240, 89.5f, 0, 0.5f}, //near horiz diag + new float[] {16, 232, 45, 0, 0.5f}, //near vert diag + + new float[] {32, 135, 74, 2, 1f}, //med top left + new float[] {32, 135, 135, -2, 1f}, //med top right + new float[] {64, 120, 89.5f, 0, 1f}, //med horiz diag + new float[] {8, 116, 45, 0, 1f}, //med vert diag + + new float[] {16, 67, 74, 4, 2f}, //far top left + new float[] {16, 67, 135, -4, 2f}, //far top right + new float[] {32, 60, 89.5f, 0, 2f}, //far horiz diag + new float[] {4, 58, 45, 0, 2f}, //far vert diag + + //12 + new float[] {128, 64, 255, 0, -FLAT_Z_INC}, //near floor + new float[] {64, 32, 255, 0, -FLAT_Z_INC*2}, //med floor + new float[] {32, 16, 255, 0, -FLAT_Z_INC*4}, //far floor + + //vert flips of the above + //15 + new float[] {128, 64, 153, 0, FLAT_Z_INC}, + new float[] {64, 32, 153, 0, FLAT_Z_INC*2}, + new float[] {32, 16, 153, 0, FLAT_Z_INC*4}, + + //18 + new float[] {128, 64, 263, 0, -FLAT_Z_INC}, //near junction walls up + new float[] {64, 32, 263, 0, -FLAT_Z_INC*2}, //med junction walls up + new float[] {32, 16, 263, 0, -FLAT_Z_INC*4}, //far junction walls up + + + //versions for corners (man this is getting complicated) + //21 + //top corner + new float[] {43, 22, 254, 0, -FLAT_Z_INC}, //near + new float[] {21, 12, 254, 0, -FLAT_Z_INC*2}, //med + new float[] {13, 7, 254, 0, -FLAT_Z_INC*4}, //far + + //24 + //side corner + new float[] {35, 21, 254 - (FLAT_Z_INC* 22), 0, -FLAT_Z_INC}, //near + new float[] {16, 13, 254 - (FLAT_Z_INC * 22), 0, -FLAT_Z_INC*2}, //med + new float[] {11, 8, 254 - (FLAT_Z_INC * 22), 0, -FLAT_Z_INC*4}, //far + + //27 + new float[] {41, 23, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC}, //near + new float[] {18, 13, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC*2}, //med + new float[] {9, 8, 254 - (FLAT_Z_INC * (64 - 23)), 0, -FLAT_Z_INC*4}, //far + + //30 + new float[] {1, 1, 49, 0, 0} //balloon + }; + + public static Texture2D[] GetWallZBuffer(GraphicsDevice gd) + { + float bias = 0f; + if (WallZBuffer == null) + { + var count = WallZBufferConfig.Length; + WallZBuffer = new Texture2D[count]; + for (int i = 0; i < count; i++) + { + var config = WallZBufferConfig[i]; + int width = (int)config[0]; + int height = (int)config[1]; + + WallZBuffer[i] = new Texture2D(gd, width, height); + Color[] data = new Color[width * height]; + int offset = 0; + + float yInt = config[2]; + for (int y = 0; y < height; y++) + { + float xInt = yInt; + for (int x = 0; x < width; x++) + { + byte zCol = (byte)Math.Round(Math.Min(255, xInt + bias)); + data[offset++] = new Color(zCol, zCol, zCol, zCol); + xInt += config[3]; + } + yInt += config[4]; + } + WallZBuffer[i].SetData(data); + } + } + + return WallZBuffer; + } + + public static Texture2D[] GetAirTiles(GraphicsDevice gd) + { + if (AirTiles == null) + { + AirTiles = new Texture2D[3]; + AirTiles[0] = GenerateAirTile(gd, 127, 64); + AirTiles[1] = GenerateAirTile(gd, 63, 32); + AirTiles[2] = GenerateAirTile(gd, 31, 16); + + } + return AirTiles; + } + + private static Texture2D GenerateAirTile(GraphicsDevice gd, int width, int height) + { + var tex = new Texture2D(gd, width+1, height); + Color[] data = new Color[width * height]; + + int center = width/2; + int middleOff = 0; + for (int i=0; i height / 2)?Color.Black:Color.White; + for (int j = 0; j < (middleOff * 2) - 3; j++) + if (i % 2 == 0 && (i + (center - middleOff)+j) % 4 == 0) data[index++] = Color.Black; + else index++; + if (middleOff != 0) + { + for (int j = 0; j < 2; j++) + data[index++] = (i + (1-j) > height / 2) ? Color.Black : Color.White; + } + + middleOff += (i == height/2-1)?1:((i(FloorCopy(data, width, height)); + return tex; + } + + public static Color[] FloorCopy(Color[] data, int width, int height) + { + if (width % 2 != 0) + { + var target = new Color[(width + 1) * height]; + for (int y = 0; y < height; y++) + { + Array.Copy(data, y * width, target, y * (width + 1), width); + } + data = target; + width += 1; + } + var ndat = new Color[data.Length]; + int hw = (width) / 2; + int hh = (height) / 2; + int idx = 0; + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + var xp = (x + hw) % width; + var yp = (y + hh) % height; + var rep = data[xp + yp * width]; + if (rep.A >= 254) ndat[idx] = rep; + else ndat[idx] = data[idx]; + idx++; + } + } + return ndat; + } + + public static Texture2D GenerateObjectIconBorder(GraphicsDevice gd, Color highlight, Color bg) + { + var tex = new Texture2D(gd, 45, 45); + Color[] data = new Color[45*45]; + var size = new Vector2(45, 45); + + //border + FillRect(data, size, new Rectangle(3, 0, 39, 2), highlight); + FillRect(data, size, new Rectangle(0, 3, 2, 39), highlight); + FillRect(data, size, new Rectangle(3, 43, 39, 2), highlight); + FillRect(data, size, new Rectangle(43, 3, 2, 39), highlight); + //end border + + //bg + FillRect(data, size, new Rectangle(2, 2, 41, 41), bg); + //end bg + + //top left rounded + FillRect(data, size, new Rectangle(2, 1, 2, 2), highlight); + FillRect(data, size, new Rectangle(1, 2, 2, 2), highlight); + + //top right rounded + FillRect(data, size, new Rectangle(41, 1, 2, 2), highlight); + FillRect(data, size, new Rectangle(42, 2, 2, 2), highlight); + + //btm left rounded + FillRect(data, size, new Rectangle(1, 41, 2, 2), highlight); + FillRect(data, size, new Rectangle(2, 42, 2, 2), highlight); + + //btm right rounded + FillRect(data, size, new Rectangle(41, 42, 2, 2), highlight); + FillRect(data, size, new Rectangle(42, 41, 2, 2), highlight); + + tex.SetData(data); + return tex; + } + + public static Texture2D GenerateCatalogIconBorder(GraphicsDevice gd, Color highlight, Color bg) + { + var tex = new Texture2D(gd, 41, 41); + Color[] data = new Color[41 * 41]; + var size = new Vector2(41, 41); + + //border + FillRect(data, size, new Rectangle(2, 0, 37, 1), highlight); + FillRect(data, size, new Rectangle(0, 2, 1, 37), highlight); + FillRect(data, size, new Rectangle(2, 40, 37, 1), highlight); + FillRect(data, size, new Rectangle(40, 2, 1, 37), highlight); + //end border + + //bg + FillRect(data, size, new Rectangle(1, 1, 39, 39), bg); + //end bg + + //top left rounded + FillRect(data, size, new Rectangle(1, 1, 1, 1), highlight); + + //top right rounded + FillRect(data, size, new Rectangle(39, 1, 1, 1), highlight); + + //btm left rounded + FillRect(data, size, new Rectangle(1, 39, 1, 1), highlight); + + //btm right rounded + FillRect(data, size, new Rectangle(39, 39, 1, 1), highlight); + + tex.SetData(data); + return tex; + } + + public static Texture2D GenerateRoundedRectangle(GraphicsDevice gd, Color color, int width, int height, int radius) + { + var tex = new Texture2D(gd, width, height); + Color[] data = new Color[width * height]; + var size = new Vector2(width, height); + + //rect fills + FillRect(data, size, new Rectangle(radius, radius, width - radius * 2, height - radius * 2), color); + FillRect(data, size, new Rectangle(radius, 0, width - radius * 2, radius), color); + FillRect(data, size, new Rectangle(radius, height-radius, width - radius * 2, radius), color); + FillRect(data, size, new Rectangle(0, radius, radius, height-radius*2), color); + FillRect(data, size, new Rectangle(width - radius, radius, radius, height - radius * 2), color); + + //corners now + for (int i = 0; i < radius; i++) + { + int seg = (int)Math.Round(Math.Sin(Math.Acos((radius-(i+0.5))/radius))*radius); + FillRect(data, size, new Rectangle(radius-seg, i, seg, 1), color); + FillRect(data, size, new Rectangle(width-radius, i, seg, 1), color); + FillRect(data, size, new Rectangle(radius - seg, height - i - 1, seg, 1), color); + FillRect(data, size, new Rectangle(width-radius, height - i - 1, seg, 1), color); + } + + tex.SetData(data); + return tex; + } + + private static void FillRect(Color[] data, Vector2 texSize, Rectangle dest, Color fillColor) + { + int x; + int y=dest.Y; + for (int i = 0; i < dest.Height; i++) + { + x = dest.X; + for (int j = 0; j < dest.Width; j++) + { + data[y * (int)texSize.X + x] = fillColor; + x++; + } + y++; + } + } + + private static Texture2D Sun; + public static Texture2D GetSun(GraphicsDevice gd) + { + if (Sun == null) + { + Sun = new Texture2D(gd, 256, 256); + Color[] data = new Color[256 * 256]; + int offset = 0; + for (int y = 0; y < 256; y++) + { + for (int x = 0; x < 256; x++) + { + var distance = Math.Sqrt((y - 128) * (y - 128) + (x - 128) * (x - 128)); + var intensity = (1 - (distance - 25) / 103f); + if (intensity < 0) data[offset++] = Color.Transparent; + else + { + intensity *= intensity; + data[offset++] = new Color(1, 1, 1, (float)intensity); + } + } + } + Sun.SetData(data); + } + + return Sun; + } + + private static Texture2D Moon; + public static Texture2D GetMoon(GraphicsDevice gd) + { + if (Moon == null) + { + Moon = new Texture2D(gd, 64, 64); + Color[] data = new Color[64 * 64]; + int offset = 0; + for (int y = 0; y < 64; y++) + { + for (int x = 0; x < 64; x++) + { + var distance = Math.Sqrt((y - 32) * (y - 32) + (x - 32) * (x - 32)); + var intensity = Math.Min(1, Math.Max(0, 32 - distance)); + + if (intensity > 0) + { + //calculate crescent + if (x < 32) distance = 0; + else distance = Math.Sqrt((y - 32) * (y - 32) + (x - 32)*2 * (x - 32)*2); + + intensity *= 0.2f+(1-Math.Min(1, Math.Max(0, 32 - distance)))*0.8f; + } + + data[offset++] = new Color(1, 1, 1, (float)intensity); + } + } + Moon.SetData(data); + } + + return Moon; + } + + public static Color FromHSV(float h, float s, float v) + { + var h2 = (int)h / 60; + var chroma = s * v; //times value, but it is always one + var X = chroma * (1 - Math.Abs(((h / 60f) % 2) - 1)); + Color result; + switch (h2) + { + case 0: + result = new Color(chroma, X, 0); break; + case 1: + result = new Color(X, chroma, 0); break; + case 2: + result = new Color(0, chroma, X); break; + case 3: + result = new Color(0, X, chroma); break; + case 4: + result = new Color(X, 0, chroma); break; + case 5: + result = new Color(chroma, 0, X); break; + default: + result = Color.Black; break; //undefined + } + var m = v - chroma; + var blend = Color.White * m; + result.R += blend.R; + result.G += blend.G; + result.B += blend.B; + return result; + } + + public static Tuple ToHSV(Color color) + { + var r = color.R / 255f; + var g = color.G / 255f; + var b = color.B / 255f; + var min = Math.Min(Math.Min(r, g), b); + var max = Math.Max(Math.Max(r, g), b); + if (min == max) return new Tuple(0, 0, min); + + var d = (r == min) ? (g - b) : ((b == min) ? r - g : b - r); + var h = (r == min) ? 3 : ((b == min) ? 1 : 5); + return new Tuple( + 60 * (h - d / (max - min)), + (max - min) / max, + max); + } + + private static Texture2D HSMatrix; + public static Texture2D GetHSMatrix(GraphicsDevice gd) + { + if (HSMatrix == null) + { + HSMatrix = new Texture2D(gd, 360, 256); + Color[] data = new Color[360 * 256]; + int offset = 0; + for (int y = 0; y < 256; y++) //y is saturation + { + for (int x = 0; x < 360; x++) //x is hue + { + data[offset++] = FromHSV(x, 1 - (y / 256f), 1f); + } + } + HSMatrix.SetData(data); + } + + return HSMatrix; + } + + private static Texture2D HSGrad; + public static Texture2D GetHSGrad(GraphicsDevice gd) + { + if (HSGrad == null) + { + HSGrad = new Texture2D(gd, 1, 256); + Color[] data = new Color[1 * 256]; + int offset = 0; + for (int y = 0; y < 256; y++) //y is saturation + { + var mod = Color.White * (1 - y / 255f); + mod.A = 255; + data[offset++] = mod; + } + HSGrad.SetData(data); + } + + return HSGrad; + } + } +} diff --git a/server/tso.common/Utils/TextureUtils.cs b/server/tso.common/Utils/TextureUtils.cs new file mode 100755 index 0000000..468213d --- /dev/null +++ b/server/tso.common/Utils/TextureUtils.cs @@ -0,0 +1,1049 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Xna.Framework.Graphics; +using Microsoft.Xna.Framework; +using System.IO; + +namespace FSO.Common.Utils +{ + public class TextureUtils + { + public static Texture2D TextureFromFile(GraphicsDevice gd, string filePath) + { + using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + return Texture2D.FromStream(gd, stream); + } + } + + public static Texture2D MipTextureFromFile(GraphicsDevice gd, string filePath) + { + var tex = TextureFromFile(gd, filePath); + var data = new Color[tex.Width * tex.Height]; + tex.GetData(data); + var newTex = new Texture2D(gd, tex.Width, tex.Height, true, SurfaceFormat.Color); + UploadWithAvgMips(newTex, gd, data); + tex.Dispose(); + return newTex; + } + + private static Dictionary _TextureColors = new Dictionary(); + + public static Texture2D TextureFromColor(GraphicsDevice gd, Color color) + { + if (_TextureColors.ContainsKey(color.PackedValue)) + { + return _TextureColors[color.PackedValue]; + } + + var tex = new Texture2D(gd, 1, 1); + tex.SetData(new[] { color }); + _TextureColors[color.PackedValue] = tex; + return tex; + } + + public static Texture2D TextureFromColor(GraphicsDevice gd, Color color, int width, int height) + { + var tex = new Texture2D(gd, width, height); + var data = new Color[width * height]; + for (var i = 0; i < data.Length; i++) + { + data[i] = color; + } + tex.SetData(data); + return tex; + } + + /** + * Because the buffers can be fairly big, its much quicker to just keep some + * in memory and reuse them for resampling textures + * + * rhy: yeah, maybe, if the code actually did that. i'm also not sure about keeping ~32MB + * of texture buffers in memory at all times when the game is largely single threaded. + */ + private static List ResampleBuffers = new List(); + private static ulong MaxResampleBufferSize = 1024 * 768; + + static TextureUtils() + { + /*for (var i = 0; i < 10; i++) + { + ResampleBuffers.Add(new uint[MaxResampleBufferSize]); + }*/ + } + + private static uint[] GetBuffer(int size) //todo: maybe implement something like described, old implementation was broken + { + var newBuffer = new uint[size]; + return newBuffer; + } + + private static void FreeBuffer(uint[] buffer) + { + } + + public static void MaskFromTexture(ref Texture2D Texture, Texture2D Mask, uint[] ColorsFrom) + { + if (Texture.Width != Mask.Width || Texture.Height != Mask.Height) + { + return; + } + + var ColorTo = Color.Transparent.PackedValue; + + var size = Texture.Width * Texture.Height; + uint[] buffer = GetBuffer(size); + Texture.GetData(buffer, 0, size); + + var sizeMask = Mask.Width * Mask.Height; + var bufferMask = GetBuffer(sizeMask); + Mask.GetData(bufferMask, 0, sizeMask); + + var didChange = false; + for (int i = 0; i < size; i++) + { + if (ColorsFrom.Contains(bufferMask[i])) + { + didChange = true; + buffer[i] = ColorTo; + } + } + + if (didChange) + { + Texture.SetData(buffer, 0, size); + } + } + + public static Texture2D Clip(GraphicsDevice gd, Texture2D texture, Rectangle source) + { + var newTexture = new Texture2D(gd, source.Width, source.Height); + var size = source.Width * source.Height; + uint[] buffer = GetBuffer(size); + if (FSOEnvironment.SoftwareDepth) + { + //opengl es does not like this + var texBuf = GetBuffer(texture.Width * texture.Height); + texture.GetData(texBuf); + var destOff = 0; + for (int y=source.Y; y> 24 == 0) + { + //This is a hack, not sure why monogame is not multiplying alpha correctly. + buffer[i] = 0x00000000; + } + else + { + buffer[i] = (buffer[i] & 0x00FFFFFF) | (bufferFrom[i] & 0xFF000000); + } + } + + TextureTo.SetData(buffer, 0, size); + } + + /// + /// Manually replaces a specified color in a texture with transparent black, + /// thereby masking it. + /// + /// The texture on which to apply the mask. + /// The color to mask away. + public static void ManualTextureMask(ref Texture2D Texture, uint[] ColorsFrom) + { + var ColorTo = Color.Transparent.PackedValue; + + //lock (TEXTURE_MASK_BUFFER) + //{ + + var size = Texture.Width * Texture.Height; + uint[] buffer = GetBuffer(size); + //uint[] buffer = new uint[size]; + + //var buffer = TEXTURE_MASK_BUFFER; + Texture.GetData(buffer, 0, size); + + var didChange = false; + + for (int i = 0; i < size; i++) + { + if (ColorsFrom.Contains(buffer[i])) + { + didChange = true; + buffer[i] = ColorTo; + } + } + + if (didChange) + { + Texture.SetData(buffer, 0, size); + } + } + + private static uint[] SINGLE_THREADED_TEXTURE_BUFFER = new uint[MaxResampleBufferSize]; + public static void ManualTextureMaskSingleThreaded(ref Texture2D Texture, uint[] ColorsFrom) + { + var ColorTo = Color.Transparent.PackedValue; + + var size = Texture.Width * Texture.Height; + uint[] buffer = new uint[size]; + + Texture.GetData(buffer); + + var didChange = false; + + for (int i = 0; i < size; i++) + { + + if (ColorsFrom.Contains(buffer[i])) + { + didChange = true; + buffer[i] = ColorTo; + } + } + + if (didChange) + { + Texture.SetData(buffer, 0, size); + } + else return; + } + + public static Texture2D Decimate(Texture2D Texture, GraphicsDevice gd, int factor, bool disposeOld) + { + if (Texture.Width < factor || Texture.Height < factor) return Texture; + var size = Texture.Width * Texture.Height*4; + byte[] buffer = new byte[size]; + + Texture.GetData(buffer); + + var newWidth = Texture.Width / factor; + var newHeight = Texture.Height / factor; + var target = new byte[newWidth * newHeight * 4]; + + for (int y=0; y= newHeight || targx >= newWidth) continue; + int avg = 0; + int total = 0; + for (int yo = y; yo < y+factor && yo < Texture.Height; yo++) + { + for (int xo = x; xo < x+factor && xo < Texture.Width; xo++) + { + avg += (int)buffer[(yo * Texture.Width + xo)*4 + c]; + total++; + } + } + + avg /= total; + target[(targy * newWidth + targx)*4 + c] = (byte)avg; + } + } + } + if (disposeOld) Texture.Dispose(); + + var outTex = new Texture2D(gd, newWidth, newHeight); + outTex.SetData(target); + return outTex; + } + + public static void UploadWithMips(Texture2D Texture, GraphicsDevice gd, Color[] data) + { + int level = 0; + int w = Texture.Width; + int h = Texture.Height; + while (data != null) + { + Texture.SetData(level++, null, data, 0, data.Length); + data = Decimate(data, w, h); + w /= 2; + h /= 2; + } + } + + public static void UploadWithAvgMips(Texture2D Texture, GraphicsDevice gd, Color[] data) + { + int level = 0; + int w = Texture.Width; + int h = Texture.Height; + while (data != null) + { + Texture.SetData(level++, null, data, 0, data.Length); + data = AvgDecimate(data, w, h); + w /= 2; + h /= 2; + } + } + + private static bool IsPowerOfTwo(int x) + { + return (x & (x - 1)) == 0; + } + + public static bool OverrideCompression(int w, int h) + { + return (!FSOEnvironment.DirectX && !(IsPowerOfTwo(w) && IsPowerOfTwo(h))); + } + + public static void UploadDXT5WithMips(Texture2D Texture, int w, int h, GraphicsDevice gd, Color[] data) + { + int level = 0; + int dw = ((w + 3) / 4) * 4; + int dh = ((h + 3) / 4) * 4; + Tuple dxt = null; + while (data != null) + { + dxt = DXT5Compress(data, Math.Max(1,w), Math.Max(1,h), Math.Max(1, (dw+3)/4), Math.Max(1, (dh+3)/4)); + Texture.SetData(level++, null, dxt.Item1, 0, dxt.Item1.Length); + data = Decimate(data, w, h); + w /= 2; + h /= 2; + dw /= 2; + dh /= 2; + } + + while (dw > 0 || dh > 0) + { + Texture.SetData(level++, null, dxt.Item1, 0, dxt.Item1.Length); + dw /= 2; + dh /= 2; + } + } + + public static void UploadDXT1WithMips(Texture2D Texture, int w, int h, GraphicsDevice gd, Color[] data) + { + int level = 0; + int dw = ((w + 3) / 4) * 4; + int dh = ((h + 3) / 4) * 4; + Tuple dxt = null; + while (data != null) + { + dxt = DXT1Compress(data, Math.Max(1, w), Math.Max(1, h), Math.Max(1, (dw + 3) / 4), Math.Max(1, (dh + 3) / 4)); + Texture.SetData(level++, null, dxt.Item1, 0, dxt.Item1.Length*2); + data = Decimate(data, w, h); + w /= 2; + h /= 2; + dw /= 2; + dh /= 2; + } + + while (dw > 0 || dh > 0) + { + Texture.SetData(level++, null, dxt.Item1, 0, dxt.Item1.Length*2); + dw /= 2; + dh /= 2; + } + } + + + public static Tuple DXT5Compress(Color[] data, int width, int height) + { + return DXT5Compress(data, width, height, (width + 3) / 4, (height + 3) / 4); + } + + public static Color[] DXT5Decompress(byte[] data, int width, int height) + { + var result = new Color[width * height]; + var blockW = width >> 2; + var blockH = height >> 2; + var blockI = 0; + var targI = 0; + + for (int by = 0; by < blockH; by++) + { + for (int bx = 0; bx < blockW; bx++) + { + // + var maxA = data[blockI++]; + var minA = data[blockI++]; + + var targ2I = targI; + ulong alpha = data[blockI++]; + alpha |= (ulong)data[blockI++] << 8; + alpha |= (ulong)data[blockI++] << 16; + alpha |= (ulong)data[blockI++] << 24; + alpha |= (ulong)data[blockI++] << 32; + alpha |= (ulong)data[blockI++] << 40; + + var maxCI = (uint)data[blockI++]; + maxCI |= (uint)data[blockI++] << 8; + + var minCI = (uint)data[blockI++]; + minCI |= (uint)data[blockI++] << 8; + + var maxCol = new Color((int)((maxCI >> 11) & 31), (int)((maxCI >> 6) & 31), (int)(maxCI & 31)) * (255f/31f); + var minCol = new Color((int)((minCI >> 11) & 31), (int)((minCI >> 6) & 31), (int)(minCI & 31)) * (255f / 31f); + + uint col = data[blockI++]; + col |= (uint)data[blockI++] << 8; + col |= (uint)data[blockI++] << 16; + col |= (uint)data[blockI++] << 24; + + var i = 0; + for (int y=0; y<4; y++) + { + for (int x=0; x<4; x++) + { + var abit = (alpha >> (i*3)) & 0x7; + var cbit = (col >> (i * 2)) & 0x3; + i++; + Color col2; + switch (cbit) + { + case 1: + col2 = minCol;break; + case 2: + col2 = Color.Lerp(minCol, maxCol, 2/3f); break; + case 3: + col2 = Color.Lerp(minCol, maxCol, 1 / 3f); break; + default: + col2 = maxCol; break; + } + if (abit == 0) col2.A = maxA; + else if (abit == 1) col2.A = minA; + else + { + var a = (8 - abit) / 7f; + col2.A = (byte)(maxA*a + minA * (1-a)); + } + + result[targ2I++] = col2; + } + targ2I += width - 4; + } + targI += 4; + } + targI += width * 3; + } + + return result; + } + + public static Tuple DXT5Compress(Color[] data, int width, int height, int blockW, int blockH) + { + var result = new byte[blockW * blockH * 16]; + var blockI = 0; + for (int by = 0; by < blockH; by++) + { + for (int bx = 0; bx < blockW; bx++) { + var block = new Color[16]; + + var ti = 0; + for (int y = 0; y < 4; y++) + { + var realy = ((by << 2) + y); + if (realy >= height) break; + var i = realy * width + (bx<<2); + + + for (int x = 0; x < 4; x++) + { + if ((x + (bx << 2)) >= width) + ti++; + else + block[ti++] = data[i++]; + } + } + + byte minAlpha, maxAlpha; + GetMinMaxAlpha(block, out minAlpha, out maxAlpha); + + //emit alpha data + + // Always reversed to use 8-bit alpha block + result[blockI++] = maxAlpha; + result[blockI++] = minAlpha; + + var alpha = GetAlphaIndices(block, minAlpha, maxAlpha); + + result[blockI++] = (byte)((alpha[0] >> 0) | (alpha[1] << 3) | (alpha[2] << 6)); + result[blockI++] = (byte)((alpha[2] >> 2) | (alpha[3] << 1) | (alpha[4] << 4) | (alpha[5] << 7)); + result[blockI++] = (byte)((alpha[5] >> 1) | (alpha[6] << 2) | (alpha[7] << 5)); + result[blockI++] = (byte)((alpha[8] >> 0) | (alpha[9] << 3) | (alpha[10] << 6)); + result[blockI++] = (byte)((alpha[10] >> 2) | (alpha[11] << 1) | (alpha[12] << 4) | (alpha[13] << 7)); + result[blockI++] = (byte)((alpha[13] >> 1) | (alpha[14] << 2) | (alpha[15] << 5)); + + //emit color data + + Color color0, color1; + ushort colorBin0, colorBin1; + GetExtremeColors(block, out color0, out colorBin0, out color1, out colorBin1, false); + + result[blockI++] = (byte)(colorBin0 & 0xFF); + result[blockI++] = (byte)((colorBin0 >> 8) & 0xFF); + + result[blockI++] = (byte)(colorBin1 & 0xFF); + result[blockI++] = (byte)((colorBin1 >> 8) & 0xFF); + + var indices = GetColorIndices(block, color0, color1); + result[blockI++] = (byte)indices; + result[blockI++] = (byte)(indices >> 8); + result[blockI++] = (byte)(indices >> 16); + result[blockI++] = (byte)(indices >> 24); + } + } + + return new Tuple(result, new Point(blockW * 4, blockH * 4)); + } + + public static Tuple DXT1Compress(Color[] data, int width, int height) + { + return DXT1Compress(data, width, height, (width + 3) / 4, (height + 3) / 4); + } + + public static Tuple DXT1Compress(Color[] data, int width, int height, int blockW, int blockH) + { + var result = new byte[blockW * blockH * 8]; + var blockI = 0; + for (int by = 0; by < blockH; by++) + { + for (int bx = 0; bx < blockW; bx++) + { + var block = new Color[16]; + + var ti = 0; + for (int y = 0; y < 4; y++) + { + var realy = ((by << 2) + y); + if (realy >= height) break; + var i = realy * width + (bx << 2); + + for (int x = 0; x < 4; x++) + { + if ((x + (bx << 2)) >= width) + ti++; + else + block[ti++] = data[i++]; + } + } + + Color color0, color1; + ushort colorBin0, colorBin1; + GetExtremeColors(block, out color0, out colorBin0, out color1, out colorBin1, true); + + //emit color data + + result[blockI++] = (byte)(colorBin0 & 0xFF); + result[blockI++] = (byte)((colorBin0 >> 8) & 0xFF); + result[blockI++] = (byte)(colorBin1 & 0xFF); + result[blockI++] = (byte)((colorBin1 >> 8) & 0xFF); + + uint indices; + //if this block contains a transparent colour, it should be stored in alpha 1bit format. + //we invert the max and min color in GetExtremeColors to tell the gpu. + if (colorBin0 > colorBin1) + { + // Opaque + indices = GetColorIndices(block, color0, color1); + } + else + { + // Transparent + indices = GetA1ColorIndices(block, color0, color1); + } + + result[blockI++] = (byte)indices; + result[blockI++] = (byte)(indices >> 8); + result[blockI++] = (byte)(indices >> 16); + result[blockI++] = (byte)(indices >> 24); + } + } + + return new Tuple(result, new Point(blockW * 4, blockH * 4)); + } + + private static byte[] GetAlphaIndices(Color[] block, int minAlpha, int maxAlpha) + { + var result = new byte[16]; + int alphaRange = maxAlpha - minAlpha; + if (alphaRange == 0) return result; + int halfAlpha = alphaRange / 2; + for (int ai = 0; ai < 16; ai++) + { + var a = block[ai].A; + //result alpha + //round point on line where the alpha is. + var aindex = Math.Min(7, Math.Max(0, ((a - minAlpha) * 7 + halfAlpha) / alphaRange)); + if (aindex == 7) aindex = 0; + else if (aindex == 0) aindex = 1; + else aindex = (8 - aindex); + result[ai] = (byte)aindex; + } + return result; + } + + private static uint GetColorIndices(Color[] block, Color color0, Color color1) + { + Color color2 = Color.Lerp(color0, color1, 1 / 3f); // Nearest to color0 + Color color3 = Color.Lerp(color0, color1, 2 / 3f); // Nearest to color1 + + uint result = 0; + + for (int i = 0; i < 16; i++) + { + var c = block[i]; + + int dist0 = ColorDistanceSq(c, color0); + int dist1 = ColorDistanceSq(c, color1); + + // If we already know it's nearer to color0 or color1, + // we only need to check against the second nearest + uint besti = dist0 < dist1 + ? ((ColorDistanceSq(c, color2) < dist0) ? 2u : 0u) + : ((ColorDistanceSq(c, color3) < dist1) ? 3u : 1u); + + result |= besti << (i * 2); + } + + return result; + } + + private static uint GetA1ColorIndices(Color[] block, Color color0, Color color1) + { + // transparent = 3 + Color color2 = Color.Lerp(color0, color1, .5f); + + uint result = 0; + + for (int i = 0; i < 16; i++) + { + var c = block[i]; + + uint besti; + if (c.A == 0) besti = 3; + else + { + int dist0 = ColorDistanceSq(c, color0); + int dist1 = ColorDistanceSq(c, color1); + int dist2 = ColorDistanceSq(c, color2); + + besti = dist0 < dist1 + ? ((dist2 < dist0) ? 2u : 0u) + : ((dist2 < dist1) ? 2u : 1u); + } + result |= besti << (i * 2); + } + + return result; + } + + private static int ColorDistanceSq(Color c0, Color c1) + { + // Vector distance + int r = (c0.R - c1.R) * 5; // Weigh in BT.601 luma coefficients + int g = (c0.G - c1.G) * 9; + int b = (c0.B - c1.B) * 2; + return (r * r) + (g * g) + (b * b); + } + + private static void GetMinMaxAlpha(Color[] block, out byte minAlpha, out byte maxAlpha) + { + byte minA = 255; + byte maxA = 0; + for (int i = 0; i < 16; i++) + { + byte a = block[i].A; + if (a < minA) minA = a; + if (a > maxA) maxA = a; + } + minAlpha = minA; + maxAlpha = maxA; + } + + private static void GetExtremeColors(Color[] block, out Color color0, out ushort colorBin0, out Color color1, out ushort colorBin1, bool dxt1a) + { + // Calculate average of colors, skip all colors with Alpha equal to 0 + bool hasAlpha0 = false; + int r = 0, g = 0, b = 0, t = 0; + for (int i = 0; i < 16; i++) + { + if (block[i].A > 0) + { + r += block[i].R; + g += block[i].G; + b += block[i].B; + ++t; + } + else + { + hasAlpha0 = true; + } + } + Color avg = (t == 0) + ? new Color(0, 0, 0) + : new Color(r / t, g / t, b / t); + + // Find color furthest from average + int leftDist = 0; + int leftIdx = 0; + for (int i = 0; i < 16; i++) + { + if (block[i].A == 0 && t != 0) + continue; + + int dist = ColorDistanceSq(block[i], avg); + if (dist > leftDist) + { + leftDist = dist; + leftIdx = i; + } + } + Color leftCol = block[leftIdx]; + + // Find color furthest to furthest + int rightDist = 0; + int rightIdx = 0; + for (int i = 0; i < 16; i++) + { + if (block[i].A == 0 && t != 0) + continue; + + int dist = ColorDistanceSq(block[i], leftCol); + if (dist > rightDist) + { + rightDist = dist; + rightIdx = i; + } + } + Color rightCol = block[rightIdx]; + + // RGB565 conversion + ushort leftBin = (ushort)((leftCol.B >> 3) | ((leftCol.G >> 2) << 5) | ((leftCol.R >> 3) << 11)); + ushort rightBin = (ushort)((rightCol.B >> 3) | ((rightCol.G >> 2) << 5) | ((rightCol.R >> 3) << 11)); + + // Alpha is determined in RGB565 representation + // If alpha, Color 1 is greater or equal to color 0 + // If no alpha, Color 0 is greater than color 1 + if ((hasAlpha0 && dxt1a) != (leftBin < rightBin)) + { + // hasAlpha0 && (leftBin >= rightbin) + // !hasAlpha && (leftBin < rightbin) + color0 = rightCol; + colorBin0 = rightBin; + color1 = leftCol; + colorBin1 = leftBin; + } + else + { + // hasAlpha0 && (leftBin < rightbin) + // !hasAlpha && (leftBin >= rightbin) + color0 = leftCol; + colorBin0 = leftBin; + color1 = rightCol; + colorBin1 = rightBin; + } + } + + public static Color[] Decimate(Color[] old, int w, int h) + { + var nw = w / 2; + var nh = h / 2; + bool linex = false, liney = false; + if (nw == 0 && nh == 0) return null; + if (nw == 0) { nw = 1; liney = true; } + if (nh == 0) { nh = 1; linex = true; } + var size = nw*nh; + Color[] buffer = new Color[size]; + + int tind = 0; + int fyind = 0; + for (int y = 0; y < nh; y ++) + { + var yb = y * 2 == h || linex; + int find = fyind; + for (int x = 0; x < nw; x ++) + { + var xb = x * 2 == h || liney; + var c1 = old[find]; + var c2 = (xb)?Color.Transparent:old[find + 1]; + var c3 = (yb)?Color.Transparent:old[find + w]; + var c4 = (xb || yb)?Color.Transparent:old[find + 1 + w]; + + int r=0, g=0, b=0, t=0; + if (c1.A > 0) + { + r += c1.R; g += c1.G; b += c1.B; t++; + } + if (c2.A > 0) + { + r += c2.R; g += c2.G; b += c2.B; t++; + } + if (c3.A > 0) + { + r += c3.R; g += c3.G; b += c3.B; t++; + } + if (c4.A > 0) + { + r += c4.R; g += c4.G; b += c4.B; t++; + } + if (t == 0) t = 1; + + buffer[tind++] = new Color( + (byte)(r / t), + (byte)(g / t), + (byte)(b / t), + Math.Max(Math.Max(Math.Max(c1.A, c2.A), c3.A), c4.A) + ); + find += 2; + } + fyind += w * 2; + } + return buffer; + } + + public static Color[] AvgDecimate(Color[] old, int w, int h) + { + var nw = w / 2; + var nh = h / 2; + bool linex = false, liney = false; + if (nw == 0 && nh == 0) return null; + if (nw == 0) { nw = 1; liney = true; } + if (nh == 0) { nh = 1; linex = true; } + var size = nw * nh; + Color[] buffer = new Color[size]; + + int tind = 0; + int fyind = 0; + for (int y = 0; y < nh; y++) + { + var yb = y * 2 == h || linex; + int find = fyind; + for (int x = 0; x < nw; x++) + { + var xb = x * 2 == w || liney; + var c1 = old[find]; + var c2 = (xb) ? Color.Transparent : old[find + 1]; + var c3 = (yb) ? Color.Transparent : old[find + w]; + var c4 = (xb || yb) ? Color.Transparent : old[find + 1 + w]; + + int r = 0, g = 0, b = 0, a=0, t = 0; + if (c1.A > 0) + { + r += c1.R; g += c1.G; b += c1.B; a += c1.A; t++; + } + if (c2.A > 0) + { + r += c2.R; g += c2.G; b += c2.B; a += c2.A; t++; + } + if (c3.A > 0) + { + r += c3.R; g += c3.G; b += c3.B; a += c3.A; t++; + } + if (c4.A > 0) + { + r += c4.R; g += c4.G; b += c4.B; a += c4.A; t++; + } + if (t == 0) t = 1; + + buffer[tind++] = new Color( + (byte)(r / t), + (byte)(g / t), + (byte)(b / t), + (byte)(a / 4) + ); + find += 2; + } + fyind += w * 2; + } + return buffer; + } + + + /// + /// Combines multiple textures into a single texture + /// + /// + /// + /// + public static Texture2D MergeHorizontal(GraphicsDevice gd, params Texture2D[] textures) + { + return MergeHorizontal(gd, 0, textures); + } + + /// + /// Combines multiple textures into a single texture + /// + /// + /// + /// + public static Texture2D MergeHorizontal(GraphicsDevice gd, int tailPx, params Texture2D[] textures) + { + var width = 0; + var maxHeight = 0; + var maxWidth = 0; + + foreach (var texture in textures) + { + width += texture.Width; + maxHeight = Math.Max(maxHeight, texture.Height); + maxWidth = Math.Max(maxWidth, texture.Width); + } + + width += tailPx; + + Texture2D newTexture = new Texture2D(gd, width, maxHeight); + Color[] newTextureData = new Color[width * maxHeight]; + Color[] tempTexData = new Color[maxWidth * maxHeight]; + + var xo = 0; + for (var i = 0; i < textures.Length; i++) + { + var tx = textures[i]; + tx.GetData(tempTexData); + for (var y = 0; y < tx.Height; y++) + { + var yOffset = y * width; + + for (var x = 0; x < tx.Width; x++) + { + newTextureData[yOffset + xo + x] = tempTexData[tx.Width * y + x]; + } + } + xo += tx.Width; + } + + newTexture.SetData(newTextureData); + tempTexData = null; + + return newTexture; + } + + public static Texture2D Resize(GraphicsDevice gd, Texture2D texture, int newWidth, int newHeight) + { + RenderTarget2D renderTarget = new RenderTarget2D( + gd, + newWidth, newHeight, false, + SurfaceFormat.Color, DepthFormat.None); + + Rectangle destinationRectangle = new Rectangle(0, 0, newWidth, newHeight); + lock (gd) + { + gd.SetRenderTarget(renderTarget); + gd.Clear(Color.TransparentBlack); + SpriteBatch batch = new SpriteBatch(gd); + batch.Begin(); + batch.Draw(texture, destinationRectangle, Color.White); + batch.End(); + gd.SetRenderTarget(null); + } + var newTexture = renderTarget; + return newTexture; + } + + public static Texture2D Scale(GraphicsDevice gd, Texture2D texture, float scaleX, float scaleY) + { + var newWidth = (int)(Math.Round(texture.Width * scaleX)); + var newHeight = (int)(Math.Round(texture.Height * scaleY)); + + RenderTarget2D renderTarget = new RenderTarget2D( + gd, + newWidth, newHeight, false, + SurfaceFormat.Color, DepthFormat.None); + + gd.SetRenderTarget(renderTarget); + + SpriteBatch batch = new SpriteBatch(gd); + + Rectangle destinationRectangle = new Rectangle(0, 0, newWidth, newHeight); + + batch.Begin(); + batch.Draw(texture, destinationRectangle, Color.White); + batch.End(); + + gd.SetRenderTarget(null); + + var newTexture = renderTarget; + return newTexture; + } + } +} diff --git a/server/tso.common/Utils/TimedReferenceCache.cs b/server/tso.common/Utils/TimedReferenceCache.cs new file mode 100755 index 0000000..002da03 --- /dev/null +++ b/server/tso.common/Utils/TimedReferenceCache.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; + +namespace FSO.Common.Utils +{ + public static class TimedReferenceController + { + private static int CurRingNum = 0; + private static List> ReferenceRing; + private static Dictionary ObjectToRing; + private static int CheckFreq = 0; + private static int TicksToNextCheck; + private static CacheType Type; + private static object InternalLock = new object { }; + public static CacheType CurrentType { get { return Type; } } + + static TimedReferenceController() + { + SetMode(CacheType.ACTIVE); + } + + public static void Clear() + { + lock (InternalLock) + { + ObjectToRing = new Dictionary(); + foreach (var item in ReferenceRing) + { + foreach (var obj in item) + { + (obj as ITimedCachable)?.Rereferenced(false); + } + item.Clear(); + } + GC.Collect(2); + } + } + + public static void SetMode(CacheType type) + { + lock (InternalLock) { + ObjectToRing = new Dictionary(); + switch (type) + { + case CacheType.AGGRESSIVE: + ReferenceRing = new List>(); + CheckFreq = 1 * 60; + for (int i = 0; i < 5; i++) ReferenceRing.Add(new HashSet()); + break; + case CacheType.ACTIVE: + ReferenceRing = new List>(); + CheckFreq = 5 * 60; + for (int i = 0; i < 3; i++) ReferenceRing.Add(new HashSet()); + break; + case CacheType.PERMANENT: + case CacheType.PASSIVE: + ReferenceRing = new List>(); + CheckFreq = int.MaxValue; + ReferenceRing.Add(new HashSet()); + break; + } + Type = type; + } + } + + public static void Tick() + { + if (Type == CacheType.PERMANENT) return; + if (TicksToNextCheck-- <= 0) + { + lock (InternalLock) + { + var toDereference = ReferenceRing[CurRingNum]; + foreach (var obj in toDereference) ObjectToRing.Remove(obj); + toDereference.Clear(); + CurRingNum = (CurRingNum + 1) % ReferenceRing.Count; + } + TicksToNextCheck = CheckFreq; + //GC.Collect(); + if (CurRingNum == 0) GC.Collect(); + } + } + + public static void KeepAlive(object o, KeepAliveType type) + { + if (type == KeepAliveType.ACCESS && (o is ITimedCachable)) ((ITimedCachable)o).Rereferenced(true); + //should be called whenever the object is referenced + lock (InternalLock) + { + var offset = ReferenceRing.Count - 1; + var becomes = (CurRingNum + offset) % ReferenceRing.Count; + int oldring; + if (ObjectToRing.TryGetValue(o, out oldring)) + { + if (becomes != oldring) + { + ReferenceRing[oldring].Remove(o); + ObjectToRing.Remove(oldring); + } + } + else + { + ReferenceRing[becomes].Add(o); + ObjectToRing.Add(o, becomes); + } + } + } + } + + public enum KeepAliveType + { + ACCESS, + DEREFERENCED + } + + public enum CacheType + { + AGGRESSIVE, + ACTIVE, + PASSIVE, + PERMANENT + } + + + public class TimedReferenceCache + { + private ConcurrentDictionary Cache = new ConcurrentDictionary(); + private bool PermaMode = false; + private List PermaRef = new List(); + private VALUE GetOrAddInternal(KEY key, Func valueFactory) + { + bool didCreate = false; + VALUE created = default(VALUE); + var value = Cache.GetOrAdd(key, (k) => + { + //ConcurrentDictionary does not ensure we don't accidentally create things twice. This lock will help us, but I don't think it ensures a perfect world. + lock (this) { + WeakReference prev; + if (Cache.TryGetValue(key, out prev) && prev.IsAlive) return prev; //already created this value. + created = valueFactory(k); + didCreate = true; + return new WeakReference(created, true); + } + }); + + var refVal = value.Target; + if (didCreate && refVal == (object)created) + { + //i made this. if we're perma cache ensure a permanent reference. + if (TimedReferenceController.CurrentType == CacheType.PERMANENT) + { + PermaRef.Add(created); + PermaMode = true; + } + return created; + } + else if (refVal != null || value.IsAlive) + return (VALUE)refVal; + else + { + //refrerence died. must recache. + WeakReference resultRemove; + var removed = Cache.TryRemove(key, out resultRemove); + return GetOrAddInternal(key, valueFactory); + } + } + + public VALUE GetOrAdd(KEY key, Func valueFactory) + { + var result = GetOrAddInternal(key, valueFactory); + if (result != null && !PermaMode) + { + TimedReferenceController.KeepAlive(result, KeepAliveType.ACCESS); + } + return result; + } + + public bool TryRemove(KEY key, out VALUE value) + { + WeakReference resultRef; + if (Cache.TryRemove(key, out resultRef)) + { + value = (VALUE)resultRef.Target; + return true; + } else + { + value = default(VALUE); + return false; + } + } + } +} diff --git a/server/tso.common/Utils/ValuePointer.cs b/server/tso.common/Utils/ValuePointer.cs new file mode 100755 index 0000000..662a660 --- /dev/null +++ b/server/tso.common/Utils/ValuePointer.cs @@ -0,0 +1,53 @@ +using System.Reflection; + +namespace FSO.Common.Utils +{ + /// + /// Helps UI controls like lists refer to a data service value + /// for labels such that when updates come in the labels update + /// + public class ValuePointer + { + private object Item; + private PropertyInfo Field; + + public ValuePointer(object item, string field) + { + this.Item = item; + this.Field = item.GetType().GetProperty(field); + } + + public object Get() + { + return Field.GetValue(Item); + } + + public override string ToString() + { + var value = Get(); + if(value != null) + { + return value.ToString(); + } + else + { + return string.Empty; + } + } + + public static T Get(object value) + { + if(value == null) + { + return default(T); + } + + if(value is ValuePointer) + { + return (T)((ValuePointer)value).Get(); + } + + return (T)value; + } + } +} diff --git a/server/tso.common/Utils/XMLList.cs b/server/tso.common/Utils/XMLList.cs new file mode 100755 index 0000000..e62c0da --- /dev/null +++ b/server/tso.common/Utils/XMLList.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Xml; + +namespace FSO.Common.Utils +{ + public class XMLList : List, IXMLEntity where T : IXMLEntity + { + private string NodeName; + + public XMLList(string nodeName) + { + this.NodeName = nodeName; + } + + public XMLList() + { + this.NodeName = "Unknown"; + } + + #region IXMLPrinter Members + + public System.Xml.XmlElement Serialize(System.Xml.XmlDocument doc) + { + var element = doc.CreateElement(NodeName); + foreach (var child in this) + { + element.AppendChild(child.Serialize(doc)); + } + return element; + } + + public void Parse(System.Xml.XmlElement element) + { + var type = typeof(T); + + foreach (XmlElement child in element.ChildNodes) + { + var instance = (T)Activator.CreateInstance(type); + instance.Parse(child); + this.Add(instance); + } + } + + #endregion + } +} diff --git a/server/tso.common/WorldGeometry/MeshProjector.cs b/server/tso.common/WorldGeometry/MeshProjector.cs new file mode 100755 index 0000000..4b82e57 --- /dev/null +++ b/server/tso.common/WorldGeometry/MeshProjector.cs @@ -0,0 +1,253 @@ +using FSO.SimAntics.Model.Routing; +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.WorldGeometry +{ + /// + /// Projects one mesh onto another mesh on a given axis, potentially with an offset from the surface. + /// Example use case: Projecting a road onto a terrain mesh + /// + public class MeshProjector + { + public MeshProjector(IEnumerable baseMesh, IEnumerable projMesh) + { + foreach (var tri in baseMesh) tri.GenBounds(); + foreach (var tri in projMesh) tri.GenBounds(); + + BaseMesh = baseMesh; + ProjectMesh = projMesh; + + BaseSet = BaseTriangleSet.RoughBalanced(baseMesh.ToList()); + } + + IEnumerable BaseMesh; + BaseTriangleSet BaseSet; + IEnumerable ProjectMesh; + + public List Indices; + public List Vertices; + + public void Project() + { + Indices = new List(); + Vertices = new List(); + //find list of potential intersect tris for a projtri + //build clipping edges for projtri + + foreach (var projTri in ProjectMesh) + { + //find candidate baseTris + var candidates = BaseSet.AllIntersect(projTri); + foreach (var baseTri in candidates) + { + //if (projTri.RoughIntersects(baseTri)) + //{ + ClipTriangles(baseTri, projTri, Vertices, Indices); + //} + } + } + } + + private void ClipTriangles(BaseMeshTriangle baseTri, MeshTriangle projTri, List outverts, List inds) + { + //Sutherland–Hodgman algorithm + //clip a triangle against another by iteratively clipping each edge of the second one + + //we want to clip against base tri + var outputList = new MeshPolygon(projTri); + var basePlane = new Plane(baseTri.Vertices[0], baseTri.Vertices[1], baseTri.Vertices[2]); + + for (int i=0; i<3; i++) + { + if (outputList.Points.Count == 0) return; + var inputList = outputList; + var edge = new ClipEdge(baseTri.Vertices[i], baseTri.Vertices[(i + 1) % 3]); + outputList = new MeshPolygon(); + var lastPoint = inputList.Points.Last(); + int j = inputList.Points.Count-1; + foreach (var point in inputList.Points) + { + if (!edge.ShouldClip(point.Position)) + { + if (edge.ShouldClip(lastPoint.Position)) + { + outputList.Points.Add(edge.IntersectLine(inputList, j)); + } + //we still need to project the point onto the surface... + var ray = new Ray(point.Position, new Vector3(0, -1, 0)); + var intersect2 = ray.Intersects(basePlane); + if (intersect2 == null) { + ray.Direction *= -1; + intersect2 = ray.Intersects(basePlane); + if (intersect2 == null) { } + intersect2 = -(intersect2 ?? 0f); + } + point.Position.Y -= intersect2.Value; + outputList.Points.Add(point); + } else + { + if (!edge.ShouldClip(lastPoint.Position)) + { + outputList.Points.Add(edge.IntersectLine(inputList, j)); + } + } + j = (j + 1) % inputList.Points.Count; + lastPoint = point; + } + } + + if (outputList.Points.Count < 3) return; //? + + outputList.Triangulate(outverts, inds); + } + } + + public class ClipEdge + { + Vector3 EdgeVec; + Vector2 DotVec; + Vector3 EdgePos; + Vector2 EdgePos2; + + public ClipEdge(Vector3 from, Vector3 to) + { + //xz + //we assume the triangle is winding clockwise, so points on the left should be clipped + + EdgeVec = to - from; + EdgePos = from; + EdgePos2 = new Vector2(from.X, from.Z); + DotVec = new Vector2(-EdgeVec.Z, EdgeVec.X); + } + + public bool ShouldClip(Vector3 pos) + { + return (Vector2.Dot(DotVec, new Vector2(pos.X, pos.Z) - EdgePos2) < 0); + } + + public MeshPoint IntersectLine(MeshPolygon tri, int lineInd) + { + var points = tri.Points; + var lineInd2 = (lineInd + 1) % points.Count; + var pt1 = tri.Points[lineInd]; + var pt2 = tri.Points[lineInd2]; + + Vector3 a = EdgeVec; //line 1 + Vector3 b = pt2.Position - pt1.Position; //line 2 + Vector3 c = EdgePos - pt1.Position; //vec between starts + + //percent of line 1 where we intersect with line 2 + float ip = 1 / (-b.X * a.Z + a.X * b.Z); //projection + float t = (b.X * c.Z - b.Z * c.X) * ip; + + //percent of line 2 where we intersect line 1 + float ip2 = 1 / (-a.X * b.Z + b.X * a.Z); + float s = (a.X * (-c.Z) - a.Z * (-c.X)) * ip2; + + //pos + vec * t = pos2 + vec2 * s + //vec * t - vec2 * s = pos2 - pos1 + float[] newTC = new float[pt1.TexCoords.Length]; + float ms = 1 - s; + for (int i=0; i x2) x2 = v.X; + if (v.Z > y2) y2 = v.Z; + } + } + + public bool RoughIntersects(BaseMeshTriangle other) + { + return !(x1 > other.x2 || x2 < other.x1 || y1 > other.y2 || y2 < other.y1); + } + } + + public class MeshTriangle : BaseMeshTriangle + { + public float[][] TexCoords; + } + + public class MeshPoint + { + public Vector3 Position; + public float[] TexCoords; + + public MeshPoint(Vector3 pos, float[] texCoords) + { + Position = pos; + TexCoords = texCoords; + } + + public MeshPoint(Vector3 pos, Vector2 texCoords) + { + Position = pos; + TexCoords = new float[] { texCoords.X, texCoords.Y }; + } + } + + public class MeshPolygon { + public List Points; + + public MeshPolygon() + { + Points = new List(); + } + + public MeshPolygon(MeshTriangle tri) + { + Points = new List(); + for (int i=0; i<3; i++) + { + Points.Add(new MeshPoint(tri.Vertices[i], tri.TexCoords[i])); + } + } + + public void Triangulate(List outverts, List inds) + { + //simple fan triangle fill + var baseInd = outverts.Count; + outverts.AddRange(Points); + + for (int i=2; i Segments = new List(); + public bool SharpStart; + public bool SharpEnd; + public int TemplateNum; + + public float StartOffset; + public float Length; + + public LinePath() + { + + } + + public LinePath(List line) + { + for (int i=0; i GetPositionNormalAt(float offset) + { + foreach (var seg in Segments) + { + //is the given offset in this segment? + if (offset < seg.Length) + { + var i = offset / seg.Length; + return new Tuple(Vector2.Lerp(seg.Start, seg.End, i), Vector2.Lerp(seg.StartNormal, seg.EndNormal, i)); + } + offset -= seg.Length; + } + var last = Segments.Last(); + return new Tuple(last.End, last.EndNormal); + } + + public List Split(float dist, float gap) + { + var result = new List(); + var startGap = dist - gap / 2; + var endGap = dist + gap / 2; + + bool before = 0 < startGap; + LinePath current = new LinePath(); + if (before) + { + current.SharpStart = SharpStart; + current.SharpEnd = true; + current.StartOffset = StartOffset; + } + else + { + current.SharpStart = true; + current.SharpEnd = SharpEnd; + current.StartOffset = StartOffset + endGap; + } + current.TemplateNum = TemplateNum; + + float soFar = 0; + foreach (var segment in Segments) + { + if (before) + { + if (soFar + segment.Length <= startGap) + { + //add this segment + current.Segments.Add(segment); + } + else + { + //this segment extends over the gap. + //an additional segment must be added to reach the start gap + if (soFar != startGap && segment.Length != 0) + { + var bridge = new LinePathSegment(segment.Start, Vector2.Lerp(segment.Start, segment.End, (startGap - soFar) / segment.Length)); + bridge.StartNormal = segment.StartNormal; + current.Segments.Add(bridge); + } + + current.Length = current.Segments.Sum(x => x.Length); + result.Add(current); + current = new LinePath(); + current.SharpStart = true; + current.SharpEnd = SharpEnd; + current.StartOffset = StartOffset + endGap; + current.TemplateNum = TemplateNum; + before = false; + } + } + if (!before) + { + if (current.Segments.Count == 0) + { + //waiting to get to a segment that ends after the gap. + if (soFar + segment.Length > endGap) + { + var bridge = new LinePathSegment(Vector2.Lerp(segment.Start, segment.End, (endGap - soFar) / segment.Length), segment.End); + bridge.EndNormal = segment.EndNormal; + current.Segments.Add(bridge); + } + } + else + { + //add this segment + current.Segments.Add(segment); + } + } + + soFar += segment.Length; + } + current.Length = current.Segments.Sum(x => x.Length); + result.Add(current); + return result; + } + + public List Intersections(LinePath other) + { + var epsilon = (0.9f * 0.9f) / 0.5f; + + //finds intersections between this linepath and another. + var result = new List(); + float soFar = 0; + for (int i=0; i x.Z).ToList(); + for (int i = 0; i < result.Count - 1; i++) + { + var first = result[i]; + while (i < result.Count - 1) + { + var second = result[i + 1]; + var distance = second - first; + distance.Z = 0; + if (distance.LengthSquared() < epsilon) + { + result.RemoveAt(i); + } + else; + { + break; + } + } + } + + return result; + } + + public void PrepareJoins() + { + LinePathSegment last = null; + foreach (var line in Segments) + { + if (last != null) + { + last.EndNormal = line.StartNormal = Vector2.Normalize(last.EndNormal + line.StartNormal); + } + last = line; + } + } + } + + public class LinePathSegment + { + public Vector2 Start; + public Vector2 End; + + public Vector2 Direction; + + //normals are used when constucting geometry from a line. they face to the right from the line. + //to create a seamless line, we average the end normal of this line and the start normal of the last, setting both to the result. + public Vector2 StartNormal; + public Vector2 EndNormal; + + public float Length; + + public LinePathSegment(Vector2 start, Vector2 end) + { + Start = start; + End = end; + Direction = end - start; + Length = Direction.Length(); + + var dirn = Direction; + dirn.Normalize(); + StartNormal = EndNormal = new Vector2(-dirn.Y, dirn.X); + } + + public Vector3? Intersect(LinePathSegment other) //xy: point, z: distance along line + { + if (this.Length == 0 || other.Length == 0) return null; + var epsilon = 0.0001f; + + Vector2 a = Direction; + Vector2 b = other.Direction; + Vector2 c = Start - other.Start; + + //percent of line 1 where we intersect with line 2 + float ip = 1 / (-b.X * a.Y + a.X * b.Y); //projection + float t = (b.X * c.Y - b.Y * c.X) * ip; + + //percent of line 2 where we intersect line 1 + float ip2 = 1 / (-a.X * b.Y + b.X * a.Y); + float s = (a.X * (-c.Y) - a.Y * (-c.X)) * ip2; + + if (float.IsNaN(t) || t < -epsilon || t > 1 + epsilon || float.IsNaN(s) || s < -epsilon || s > 1 + epsilon) + { + return null; + } + return new Vector3(Direction * t + Start, t * Length); + } + } +} diff --git a/server/tso.common/WorldGeometry/Paths/SVGParser.cs b/server/tso.common/WorldGeometry/Paths/SVGParser.cs new file mode 100755 index 0000000..940c0e7 --- /dev/null +++ b/server/tso.common/WorldGeometry/Paths/SVGParser.cs @@ -0,0 +1,161 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Xml; + +namespace FSO.Common.WorldGeometry.Paths +{ + public enum SVGPathSegmentType + { + MoveTo, + LineTo, + CurveTo, + Close + } + + public class SVGPathSegment + { + public SVGPathSegmentType Type; + public Vector2 Position; + public Vector2 ControlPoint1; + public Vector2 ControlPoint2; + } + + public class SVGPath + { + public string ID; + public List Segments; + + public SVGPath(string id, List segs) + { + ID = id; + Segments = segs; + } + } + + public class SVGParser + { + public List Paths; + + public SVGParser(string svgText) + { + var xml = new XmlDocument(); + xml.XmlResolver = null; + xml.LoadXml(svgText); + + Paths = new List(); + + var paths = xml.GetElementsByTagName("path"); + foreach (XmlNode path in paths) + { + var str = path.Attributes["d"].InnerText.Replace(',', ' '); + int template = 0; + var id = path.Attributes["id"]?.InnerText; + var elems = str.Split(' '); + var pos = new Vector2(0, 0); + + var newPath = new List(); + for (int i = 0; i < elems.Length; i += 0) + { + var type = elems[i++]; + if (type.Length == 0) continue; + var relative = char.IsLower(type[0]); + if (!relative) pos = new Vector2(); + switch (type.ToLower()) + { + case "m": + case "l": + //lineto + pos += new Vector2(float.Parse(elems[i++], CultureInfo.InvariantCulture), float.Parse(elems[i++], CultureInfo.InvariantCulture)); + newPath.Add(new SVGPathSegment() + { + Position = pos, + Type = (type.ToLower() == "l") ? SVGPathSegmentType.LineTo : SVGPathSegmentType.MoveTo + }); + break; + case "c": + var cp1 = new Vector2(float.Parse(elems[i++], CultureInfo.InvariantCulture), float.Parse(elems[i++], CultureInfo.InvariantCulture)) + pos; + var cp2 = new Vector2(float.Parse(elems[i++], CultureInfo.InvariantCulture), float.Parse(elems[i++], CultureInfo.InvariantCulture)) + pos; + pos += new Vector2(float.Parse(elems[i++], CultureInfo.InvariantCulture), float.Parse(elems[i++], CultureInfo.InvariantCulture)); + + newPath.Add(new SVGPathSegment() + { + Position = pos, + ControlPoint1 = cp1, + ControlPoint2 = cp2, + Type = SVGPathSegmentType.CurveTo + }); + break; + case "z": + //close + newPath.Add(new SVGPathSegment() + { + Type = SVGPathSegmentType.Close + }); + break; + } + } + Paths.Add(new SVGPath(id, newPath)); + } + } + + public LinePath ToLinePath(SVGPath inpath) + { + var segs = inpath.Segments; + var line = new List(); + + var closed = false; + var pos = new Vector2(0, 0); + foreach (var seg in segs) + { + switch (seg.Type) + { + case SVGPathSegmentType.MoveTo: + case SVGPathSegmentType.LineTo: + line.Add(seg.Position); + break; + case SVGPathSegmentType.CurveTo: + //subdivided curve. currently 20 subdivisions. + var subdiv = 20; + var lastPos = line.Last(); + for (int i=1; i 0) { + var first = path.Segments.First(); + var last = path.Segments.Last(); + first.StartNormal = last.EndNormal = (first.StartNormal + last.EndNormal) / 2; + path.SharpEnd = true; + path.SharpStart = true; + } + return path; + } + + public List ToLinePaths() + { + return Paths.Select(x => ToLinePath(x)).ToList(); + } + } +} diff --git a/server/tso.common/WorldGeometry/RoadGeometry.cs b/server/tso.common/WorldGeometry/RoadGeometry.cs new file mode 100755 index 0000000..27a5633 --- /dev/null +++ b/server/tso.common/WorldGeometry/RoadGeometry.cs @@ -0,0 +1,484 @@ +using FSO.Common.WorldGeometry.Paths; +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.WorldGeometry +{ + public class RoadMesh + { + public int LastIndex; + public List Indices = new List(); + public List Vertices = new List(); + } + + public class RoadDetectedIntersection + { + public LinePath MainPath; + public LinePath SubPath; + public RoadGeometryTemplate Template; + public float MainDist; + public float SubDist; + public bool ThreeWay; + + public Vector2 Center; + public Vector2 AlignmentY; //how to transform Y coords + public Vector2 AlignmentX; //how to transform X coords + } + + public class RoadGeometry + { + public List Paths; + public List Intersections; + public List Templates; + + public RoadGeometry(List paths, List templates) + { + Paths = paths; + Templates = templates; + } + + private float IntersectionDistance(Vector3 inter1, Vector3 inter2) + { + return Vector2.Distance(new Vector2(inter1.X, inter1.Y), new Vector2(inter2.X, inter2.Y)); + } + + public void GenerateIntersections() + { + Intersections = new List(); + for (int i = 0; i < Paths.Count; i++) + { + var path1 = Paths[i]; + for (int j = i + 1; j < Paths.Count; j++) + { + var path2 = Paths[j]; + + var inters = path1.Intersections(path2); + foreach (var inter in inters) + { + //find corresponding intersection in path2 + var inter2n = path2.Intersections(path1).Cast().FirstOrDefault(x => IntersectionDistance(x.Value, inter) < 1); + if (inter2n != null) + { + var inter2 = inter2n.Value; + + int primaryLine = 0; + if (inter2.Z < 1 || inter2.Z > path2.Length-1) + { + primaryLine = 1; + } + if (inter.Z < 1 || inter.Z > path1.Length-1) + { + if (primaryLine != 0) + { + throw new Exception("2 way intersection currently not supported. Make a curve instead."); + } + primaryLine = 2; + } + + bool threeWay = primaryLine != 0; + if (!threeWay) primaryLine = 1; + + var mainPath = (primaryLine == 1) ? path1 : path2; + var subPath = (primaryLine == 2) ? path1 : path2; + var mainDist = (primaryLine == 1) ? inter.Z : inter2.Z; + var subDist = (primaryLine == 2) ? inter.Z : inter2.Z; + + var primaryAlign = mainPath.GetPositionNormalAt(mainDist); + + var vert = primaryAlign.Item2; + vert = new Vector2(vert.Y, -vert.X); + + float xflip = 1; + if (threeWay) + { + var normalSub = subPath.GetPositionNormalAt(subDist).Item2; + if (subDist < 1) normalSub = -normalSub; + + if (Vector2.Dot(vert, normalSub) < 0) xflip = -1; + } + + Intersections.Add(new RoadDetectedIntersection() + { + MainPath = mainPath, + SubPath = subPath, + MainDist = mainDist, + SubDist = subDist, + ThreeWay = threeWay, + + Center = new Vector2(inter.X, inter.Y), + AlignmentY = vert, //how to transform Y coords + AlignmentX = primaryAlign.Item2 * xflip //how to transform X coords + }); + } + } + } + } + + //split the road paths based on these intersections. + foreach (var intersection in Intersections) + { + Paths.Remove(intersection.MainPath); + Paths.Remove(intersection.SubPath); + + intersection.Template = Templates[Math.Max(intersection.MainPath.TemplateNum, intersection.SubPath.TemplateNum)]; + + var mSplit = intersection.MainPath.Split(intersection.MainDist - intersection.MainPath.StartOffset, intersection.Template.IntersectionSize); + var sSplit = intersection.SubPath.Split(intersection.SubDist - intersection.SubPath.StartOffset, intersection.Template.IntersectionFromSize); + Paths.AddRange(mSplit); + Paths.AddRange(sSplit); + if (mSplit.Any(x => float.IsNaN(x.Length)) || sSplit.Any(x => float.IsNaN(x.Length))) { } + + //update intersections that use these paths to reference the new split paths + foreach (var inter2 in Intersections) + { + if (inter2 == intersection) continue; + if (inter2.MainPath == intersection.MainPath) + { + if (inter2.MainDist > intersection.MainDist) inter2.MainPath = mSplit.Last(); + else inter2.MainPath = mSplit[0]; + } + if (inter2.MainPath == intersection.SubPath) + { + if (inter2.MainDist > intersection.SubDist) inter2.MainPath = sSplit.Last(); + else inter2.MainPath = sSplit[0]; + } + + if (inter2.SubPath == intersection.MainPath) + { + if (inter2.SubDist > intersection.MainDist) inter2.SubPath = mSplit.Last(); + else inter2.SubPath = mSplit[0]; + } + if (inter2.SubPath == intersection.SubPath) + { + if (inter2.SubDist > intersection.SubDist) inter2.SubPath = sSplit.Last(); + else inter2.SubPath = sSplit[0]; + } + } + } + } + + public Dictionary Meshes; + + private void AddTriangle(List indices, int i1, int i2, int i3) + { + indices.Add(i1); + indices.Add(i2); + indices.Add(i3); + } + + public void GenerateRoadGeometry() + { + Meshes = new Dictionary(); + + foreach (var seg in Templates[0].Segments) + { + foreach (var line in seg.Lines) + { + if (!Meshes.ContainsKey(line.FloorTile)) Meshes[line.FloorTile] = new RoadMesh(); + } + } + + foreach (var path in Paths) + { + path.PrepareJoins(); + var template = Templates[path.TemplateNum]; + + if (path.Segments.Count == 0) continue; + if (path.Length < 1) { } + if (!path.SharpStart) + { + var seg = path.Segments.First(); + CapEnd(template, seg.Start, -seg.StartNormal); + } + + //generate the line + + float linePosition = 0; + float virtualPosition = 0;// path.StartOffset; + var startSegment = template.GetSegmentForOffset(virtualPosition); + RoadGeometryTemplateSegment currentSegment = startSegment.Item1; + float remaining = startSegment.Item2; + + bool end; + int i = 0; + do + { + end = linePosition + remaining >= path.Length; + if (end) remaining = path.Length - linePosition; + + foreach (var mesh in Meshes.Values) mesh.LastIndex = mesh.Vertices.Count; + for (int j = 0; j < 2; j++) + { + var basePos = path.GetPositionNormalAt(linePosition); + foreach (var line in currentSegment.Lines) + { + var mesh = Meshes[line.FloorTile]; + if (j > 0) + { + //create triangles + AddTriangle(mesh.Indices, mesh.LastIndex, mesh.Vertices.Count, mesh.LastIndex + 1); + AddTriangle(mesh.Indices, mesh.Vertices.Count, mesh.Vertices.Count + 1, mesh.LastIndex + 1); + + mesh.LastIndex += 2; + } + + var spos2d = basePos.Item1 + basePos.Item2 * line.Start.X; + var stc = FloorTC(new Vector2(line.Start.X, virtualPosition) + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(spos2d.X, line.Start.Y, spos2d.Y), stc)); + + var epos2d = basePos.Item1 + basePos.Item2 * line.End.X; + var etc = FloorTC(new Vector2(line.End.X, virtualPosition) + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(epos2d.X, line.End.Y, epos2d.Y), etc)); + } + + i++; + if (j == 0) + { + virtualPosition += remaining; + linePosition += remaining; + } + } + currentSegment = currentSegment.Next; + } while (!end); + + + if (!path.SharpEnd) + { + var seg = path.Segments.Last(); + CapEnd(template, seg.End, seg.EndNormal); + } + } + + if (Intersections != null) + { + foreach (var intersection in Intersections) + { + PlaceIntersection(intersection); + } + } + } + + private Vector2 FloorTC(Vector2 vec) + { + return new Vector2(-0.5f + vec.X - vec.Y, 0.5f + vec.X + vec.Y) * 0.5f; + } + + public void PlaceIntersection(RoadDetectedIntersection intersection) { + var template = intersection.Template; + var iTemplate = intersection.ThreeWay ? template.Intersection3Way : template.Intersection4Way; + var off = new Vector2(template.IntersectionFromSize, template.IntersectionSize)/2; + var ctr = intersection.Center; + + var xm = intersection.AlignmentX; + var ym = intersection.AlignmentY; + foreach (var rect in iTemplate) + { + RoadMesh mesh; + if (!Meshes.TryGetValue(rect.FloorTile, out mesh)) + { + mesh = new RoadMesh(); + Meshes[rect.FloorTile] = mesh; + } + + var ind = mesh.Vertices.Count; + var pos = rect.Rect.Location.ToVector2() - off + rect.Offset; + var tcOff = off + new Vector2(0.5f, 0f) - rect.Offset; + var pos2 = xm * pos.X + ym * pos.Y + ctr; + mesh.Vertices.Add(new MeshPoint(new Vector3(pos2.X, 0, pos2.Y), FloorTC(pos + tcOff))); + + pos += new Vector2(rect.Rect.Width, 0); + pos2 = xm * pos.X + ym * pos.Y + ctr; + mesh.Vertices.Add(new MeshPoint(new Vector3(pos2.X, 0, pos2.Y), FloorTC(pos + tcOff))); + + pos += new Vector2(0, rect.Rect.Height); + pos2 = xm * pos.X + ym * pos.Y + ctr; + mesh.Vertices.Add(new MeshPoint(new Vector3(pos2.X, 0, pos2.Y), FloorTC(pos + tcOff))); + + pos += new Vector2(-rect.Rect.Width, 0); + pos2 = xm * pos.X + ym * pos.Y + ctr; + mesh.Vertices.Add(new MeshPoint(new Vector3(pos2.X, 0, pos2.Y), FloorTC(pos + tcOff))); + + AddTriangle(mesh.Indices, ind, ind + 1, ind + 2); + AddTriangle(mesh.Indices, ind, ind + 2, ind + 3); + } + } + + public void CapEnd(RoadGeometryTemplate template, Vector2 position, Vector2 normal) + { + foreach (var mesh in Meshes.Values) mesh.LastIndex = mesh.Vertices.Count; + + var lines = template.EndLines; + for (int i=0; i<=template.EndRepeats; i++) { + var angle = (i * Math.PI) / template.EndRepeats; + var c = (float)Math.Cos(angle); + var s = (float)Math.Sin(angle); + Vector2 xToCoord = new Vector2(c * normal.X - s * normal.Y, s * normal.X + c * normal.Y); + Vector2 xToTc = new Vector2(c, s); + + foreach (var line in lines) + { + var mesh = Meshes[line.FloorTile]; + if (line.TriangleCap) + { + if (i == 0) + { //create the point we rotate around + line.TempIndex = mesh.Vertices.Count; + var pos2d = position + xToCoord * line.End.X; + var tc = FloorTC(xToTc * line.End.X + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(pos2d.X, line.End.Y, pos2d.Y), tc)); + mesh.LastIndex++; + } + + if (i > 0) + { + //create triangles + AddTriangle(mesh.Indices, mesh.LastIndex++, mesh.Vertices.Count, line.TempIndex); + } + + var spos2d = position + xToCoord * line.Start.X; + var stc = FloorTC(xToTc * line.Start.X + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(spos2d.X, line.Start.Y, spos2d.Y), stc)); + } + else + { + if (i > 0) + { + //create triangles + AddTriangle(mesh.Indices, mesh.LastIndex, mesh.Vertices.Count, mesh.LastIndex + 1); + AddTriangle(mesh.Indices, mesh.Vertices.Count, mesh.Vertices.Count + 1, mesh.LastIndex + 1); + + mesh.LastIndex += 2; + } + + var spos2d = position + xToCoord * line.Start.X; + var stc = FloorTC(new Vector2(line.Start.X, i) + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(spos2d.X, line.Start.Y, spos2d.Y), stc)); + + var epos2d = position + xToCoord * line.End.X; + var etc = FloorTC(new Vector2(line.End.X, i) + line.UVOff); + mesh.Vertices.Add(new MeshPoint(new Vector3(epos2d.X, line.End.Y, epos2d.Y), etc)); + } + } + } + } + } + + public class RoadGeometryTemplate + { + private RoadGeometryTemplateSegment[] _Segments; + + public RoadGeometryTemplateSegment[] Segments + { + get + { + return _Segments; + } + set + { + RepeatLength = 0; + for (int i=0; i + /// Same as Intersection4Way, but inserted when there are only three connecting lines. + /// This template represents the y direction being the route for the straight 2 lines, and then x positive being the third (to the right). + /// This is appropriately flipped if the intersection is on the left. + /// + public RoadGeometryTemplateRect[] Intersection3Way; + + public Tuple GetSegmentForOffset(float offset) + { + var moffset = offset % RepeatLength; + var result = Segments.First(); + float soFar = 0; + + foreach (var seg in Segments) + { + if (soFar + seg.Extent > moffset) + { + //this segment has not ended yet + return new Tuple(seg, (soFar + seg.Extent) - moffset); + } + //otherwise move onto the next + soFar += seg.Extent; + } + return new Tuple(Segments.Last(), (soFar + Segments.Last().Extent) - moffset); + } + } + + public class RoadGeometryTemplateSegment + { + public float Extent; //the extent of this segment before moving onto the next segment + public RoadGeometryTemplateLine[] Lines; //(x, y) lines to extend into z. x is a horizontal offset depending on the direction of the line + + public RoadGeometryTemplateSegment Next; + } + + public class RoadGeometryTemplateLine + { + public Vector2 Start; + public Vector2 End; + public Vector2 UVOff; + public ushort FloorTile; + + public bool TriangleCap; + public int TempIndex; + + /// + /// Liney + /// + /// The start of this line. + /// + /// The floor tile to use for this line. + public RoadGeometryTemplateLine(Vector2 start, Vector2 end, ushort floorTile) + { + Start = start; + End = end; + FloorTile = floorTile; + + TriangleCap = End == Vector2.Zero; + } + + public RoadGeometryTemplateLine(Vector2 start, Vector2 end, Vector2 uvOff, ushort floorTile) : this(start, end, floorTile) + { + UVOff = uvOff; + } + } + + public class RoadGeometryTemplateRect + { + public Rectangle Rect; + public ushort FloorTile; + public Vector2 Offset; + + public RoadGeometryTemplateRect(Rectangle rect, ushort floorTile) + { + Rect = rect; + FloorTile = floorTile; + } + + public RoadGeometryTemplateRect(Rectangle rect, ushort floorTile, Vector2 offset) + { + Rect = rect; + FloorTile = floorTile; + Offset = offset; + } + } +} diff --git a/server/tso.common/WorldGeometry/SimplifiedHeightmap.cs b/server/tso.common/WorldGeometry/SimplifiedHeightmap.cs new file mode 100755 index 0000000..070ef01 --- /dev/null +++ b/server/tso.common/WorldGeometry/SimplifiedHeightmap.cs @@ -0,0 +1,493 @@ +using Microsoft.Xna.Framework; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.Common.WorldGeometry +{ + public class SimplifiedHeightmap + { + public float HeightMultiplier = 1 / 40f; + public int Size; + public int Size1; + public ushort[] Map; //10x resolution of ts1 terrain. + public ushort[][] SecondDerivativePyramid; + public SimplifiedHeightmap(int size, ushort[] data) + { + Size = size; + Size1 = size - 1; + Map = data; + BuildSecondDerivative(); + } + + public void BuildSecondDerivative() + { + //first, build the full res second derivative map + var sd = new ushort[Map.Length]; + int i = 0; + + //x derivative + for (int y = 0; y < Size; y++) + { + ushort lastValue = Map[i++]; + ushort firstDerivative = 0; + for (int x = 1; x < Size; x++) + { + ushort value = Map[i]; + ushort newFirstDerivative = (ushort)Math.Abs(value - lastValue); + sd[(i++) - 1] = (ushort)Math.Abs(newFirstDerivative - firstDerivative); + firstDerivative = newFirstDerivative; + lastValue = value; + } + } + + //y derivative + i = 0; + for (int y = 0; y < Size; y++) + { + i = y; + ushort lastValue = Map[i]; + i += Size; + ushort firstDerivative = 0; + for (int x = 1; x < Size; x++) + { + ushort value = Map[i]; + ushort newFirstDerivative = (ushort)Math.Abs(value - lastValue); + sd[i-Size] = Math.Max(sd[i-Size], (ushort)Math.Abs(newFirstDerivative - firstDerivative)); + i += Size; + firstDerivative = newFirstDerivative; + lastValue = value; + } + } + + //build mipLevels + var levels = 7; //gen 2x2 through 64x64 + SecondDerivativePyramid = new ushort[levels][]; + SecondDerivativePyramid[0] = sd; + + var curLevel = sd; + for (int mip = 1; mip < levels; mip++) + { + var size = (int)Math.Sqrt(curLevel.Length); + var mipLevel = new ushort[curLevel.Length / 4]; + i = 0; + for (int y = 0; y < size; y++) + { + var target = (y / 2) * size / 2; + for (int x = 0; x < size; x += 2) + { + mipLevel[target] = Math.Max(mipLevel[target], Math.Max(curLevel[i++], curLevel[i++])); + target++; + } + } + SecondDerivativePyramid[mip] = mipLevel; + curLevel = mipLevel; + } + } + + //second derivitive required to subdivide further. + public short[] HighDetailThresholds = + { + 20, //1x1 + 16, //2x2: at least one derivative about half as tall as a block + 10, //4x4 + 7, //8x8 + 4, //16x16 + 2, //32x32 + 1, //64x64 + }; + + List Chunks; + + private Dictionary PointToIndex; + public List Indices; + public List Vertices; + + //how the simplification works: + //we generate a "maximum second derivative" map from the heightmap. + //we then create a maximum value image pyramid with the maximum value in the 4 pixels beneath + //when generating the mesh, we fall into quadrants below if the second derivative is above a threshold. + + public void GenerateFullTree() + { + //how the algorithm works: + //build a base structure with quad trees + Chunks = new List(); + + var levels = SecondDerivativePyramid.Length; + var chunkSize = 1 << levels; + + var cw = Size / chunkSize; + + for (int y = 0; y < Size; y += chunkSize) + { + for (int x = 0; x < Size; x += chunkSize) + { + var chunk = new HeightmapChunk(new Rectangle(x, y, chunkSize, chunkSize), levels, + (x == 0) ? null : Chunks.Last(), + (y == 0) ? null : Chunks[Chunks.Count - cw]); + Chunks.Add(chunk); + } + } + + var thresholds = HighDetailThresholds; + var toTraverse = new Queue(Chunks); + while (toTraverse.Count > 0) + { + var node = toTraverse.Dequeue(); + var mipLevel = node.MipLevel; + var sd = SecondDerivativePyramid[mipLevel-1]; + var mipWidth = Size >> (mipLevel-1); + var pos = (node.Range.X >> (mipLevel - 1)) + (node.Range.Y >> (mipLevel - 1)) * mipWidth; + + //check the max second derivative of the 4 potential derivatives. + var threshold = HighDetailThresholds[mipLevel - 1]; + if (sd[pos] >= threshold) //top left + { + var newNode = node.GetOrAdd(0, true); + if (mipLevel > 1) toTraverse.Enqueue(newNode); + } + if (sd[pos+1] >= threshold) //top right + { + var newNode = node.GetOrAdd(1, true); + if (mipLevel > 1) toTraverse.Enqueue(newNode); + } + if (sd[pos + mipWidth] >= threshold) //bottom left + { + var newNode = node.GetOrAdd(2, true); + if (mipLevel > 1) toTraverse.Enqueue(newNode); + } + if (sd[pos + mipWidth + 1] >= threshold) //top right + { + var newNode = node.GetOrAdd(3, true); + if (mipLevel > 1) toTraverse.Enqueue(newNode); + } + } + } + + public void GenerateMesh() + { + //traverse the chunk tree, generating meshes for each. + PointToIndex = new Dictionary(); + Vertices = new List(); + Indices = new List(); + + foreach (var chunk in Chunks) + { + chunk.Triangulate(this); + } + } + + public int GetVertex(Point pt) + { + int index; + if (!PointToIndex.TryGetValue(pt, out index)) + { + index = Vertices.Count; + var x = Math.Min(Size1, pt.X); + var y = Math.Min(Size1, pt.Y); + Vertices.Add(new Vector3(pt.X, Map[x + y * Size] * HeightMultiplier, pt.Y)); + PointToIndex[pt] = index; + } + return index; + } + + public void AddTri(int i1, int i2, int i3) + { + Indices.Add(i1); + Indices.Add(i2); + Indices.Add(i3); + } + } + + public class HeightmapQuadTreeNode + { + public bool Reduced; + public int MipLevel; + public int ParentInd = -1; //the + HeightmapQuadTreeNode Parent; + public Rectangle Range; + public HeightmapQuadTreeNode[] Children = new HeightmapQuadTreeNode[] + { + null, null, null, null //top left, top right, bottom left, bottom right (row order) + }; + + public HeightmapQuadTreeNode(HeightmapQuadTreeNode parent, Rectangle range) + { + Parent = parent; + Range = range; + MipLevel = (parent?.MipLevel ?? 6) - 1; + } + + public HeightmapQuadTreeNode GetOrAdd(int index, bool doSpread) + { + HeightmapQuadTreeNode result; + if (Children[index] == null) + { + var rect = Range; + rect.Width /= 2; + rect.Height /= 2; + if ((index % 2) == 1) rect.X += rect.Width; + if (index > 1) rect.Y += rect.Height; + result = new HeightmapQuadTreeNode(this, rect); + result.ParentInd = index; + Children[index] = result; + doSpread = true; + } else { + result = Children[index]; + } + + if (doSpread) { + if (Parent != null) + { + //find adjacent quad to add to. + //for example if we are in index 0 (top left), make sure there is: + // - a subdivision in the top right (1) of the tile to our left, + // - a subdivision in the bottom left (2) of the tile above us, + // - a subdivision in the bottom right (3) of the tile above and left + + //index 1 (top right + switch (index) + { + case 0: //top left + { + var left = result.FindOrCreateQuadInDirection(3); + var up = result.FindOrCreateQuadInDirection(0); + if (up != null) up.FindOrCreateQuadInDirection(3); + break; + } + case 1: //top right + { + var right = result.FindOrCreateQuadInDirection(1); + var up = result.FindOrCreateQuadInDirection(0); + if (up != null) up.FindOrCreateQuadInDirection(1); + break; + } + case 2: //bottom left + { + var left = result.FindOrCreateQuadInDirection(3); + var bottom = result.FindOrCreateQuadInDirection(2); + if (bottom != null) bottom.FindOrCreateQuadInDirection(3); + break; + } + case 3: //bottom right + { + var right = result.FindOrCreateQuadInDirection(1); + var bottom = result.FindOrCreateQuadInDirection(2); + if (bottom != null) bottom.FindOrCreateQuadInDirection(1); + break; + } + } + } + } + return result; + } + + public virtual HeightmapQuadTreeNode FindOrCreateQuadInDirection(int dir) + { + //dir: up, right, down, left + + if (Parent == null) return null; + switch (dir) + { + case 0: //up + //if we're on the bottom row, finding the quad is easy. + if (ParentInd > 1) + { + return Parent.GetOrAdd(ParentInd - 2, false); + } + else + { + //on the top row. we need to break out to add a quad above. + var aboveParent = Parent.FindOrCreateQuadInDirection(dir); + //our adjacent should be on the above parent's bottom row. + return aboveParent?.GetOrAdd(ParentInd + 2, false); + } + case 1: //right + //if we're on the left row, finding the quad is easy. + if ((ParentInd % 2) == 0) + { + return Parent.GetOrAdd(ParentInd + 1, false); + } + else + { + //on the right row. we need to break out to add a quad above. + var rightParent = Parent.FindOrCreateQuadInDirection(dir); + //our adjacent should be on the right parent's left row. + return rightParent?.GetOrAdd(ParentInd - 1, false); + } + case 2: //down + //if we're on the top row, finding the quad is easy. + if (ParentInd < 2) + { + return Parent.GetOrAdd(ParentInd + 2, false); + } + else + { + //on the right row. we need to break out to add a quad above. + var belowParent = Parent.FindOrCreateQuadInDirection(dir); + //our adjacent should be on the below parent's top row. + return belowParent?.GetOrAdd(ParentInd - 2, false); + } + case 3: //left + //if we're on the right row, finding the quad is easy. + if ((ParentInd % 2) == 1) + { + return Parent.GetOrAdd(ParentInd - 1, false); + } + else + { + //on the left row. we need to break out to add a quad above. + var leftParent = Parent.FindOrCreateQuadInDirection(dir); + //our adjacent should be on the left parent's right row. + return leftParent?.GetOrAdd(ParentInd + 1, false); + } + } + return null; + } + + public void Triangulate(SimplifiedHeightmap parent) + { + var cTriangulated = 0; + foreach (var child in Children) + { + if (child != null) + { + child.Triangulate(parent); + cTriangulated++; + } + } + if (cTriangulated == 0) + { + //no children means we are a leaf. triangulate, cause nobody else is doing it for me. + var lt = parent.GetVertex(Range.Location); + var rt = parent.GetVertex(Range.Location + new Point(Range.Width, 0)); + var rb = parent.GetVertex(Range.Location + Range.Size); + var lb = parent.GetVertex(Range.Location + new Point(0, Range.Height)); + + parent.AddTri(lt, rt, rb); + parent.AddTri(lt, rb, lb); + } + else if (cTriangulated < 4) + { + //complex: we have children, but we also need to make our own geometry. + var ctr = parent.GetVertex(Range.Location + new Point(Range.Width/2, Range.Height/2)); + var lt = parent.GetVertex(Range.Location); + var rt = parent.GetVertex(Range.Location + new Point(Range.Width, 0)); + var rb = parent.GetVertex(Range.Location + Range.Size); + var lb = parent.GetVertex(Range.Location + new Point(0, Range.Height)); + if (Children[0] == null) //from top left + { + if (Children[1] == null) //top right + { + //triangle lt to rt: \/ + parent.AddTri(lt, rt, ctr); + } + else + { + //triangle lt to mt: \| + var mt = parent.GetVertex(Range.Location + new Point(Range.Width / 2, 0)); + parent.AddTri(lt, mt, ctr); + } + + if (Children[2] == null) //bottom left + { + //triangle lt to lb: \ + // / + parent.AddTri(lt, ctr, lb); + } + else + { + //triangle lt to lm: _\ + var lm = parent.GetVertex(Range.Location + new Point(0, Range.Height / 2)); + parent.AddTri(lt, ctr, lm); + } + } + else + { + if (Children[1] == null) //top right but no top left + { + //triangle mt to rt: |/ + var mt = parent.GetVertex(Range.Location + new Point(Range.Width / 2, 0)); + parent.AddTri(mt, rt, ctr); + } + + if (Children[2] == null) //bottom left but no top left + { + //triangle lm to lb: _ + // / + var lm = parent.GetVertex(Range.Location + new Point(0, Range.Height / 2)); + parent.AddTri(lm, ctr, lb); + } + } + + if (Children[3] == null) //from bottom right + { + if (Children[1] == null) //top right + { + //triangle rt to rb: / + // \ + parent.AddTri(rt, rb, ctr); + } + else + { + //triangle rm to rb: _ + // \ + var rm = parent.GetVertex(Range.Location + new Point(Range.Width, Range.Height / 2)); + parent.AddTri(rm, rb, ctr); + } + + if (Children[2] == null) //bottom left + { + //triangle lb to rb: /\ + parent.AddTri(lb, ctr, rb); + } + else + { + //triangle mb to rb: |\ + var mb = parent.GetVertex(Range.Location + new Point(Range.Width / 2, Range.Height)); + parent.AddTri(mb, ctr, rb); + } + } + else + { + if (Children[1] == null) //top right, no bottom right + { + //triangle rt to rm: /_ + var rm = parent.GetVertex(Range.Location + new Point(Range.Width, Range.Height / 2)); + parent.AddTri(rt, rm, ctr); + } + + if (Children[2] == null) //bottom left, no bottom right + { + //triangle mb to lb: /| + var mb = parent.GetVertex(Range.Location + new Point(Range.Width / 2, Range.Height)); + parent.AddTri(mb, lb, ctr); + } + } + } + } + } + + public class HeightmapChunk : HeightmapQuadTreeNode + { + public HeightmapChunk[] Adjacent = new HeightmapChunk[] + { + null, null, null, null //up, right, down, left + }; + + public HeightmapChunk(Rectangle range, int mipLevel, HeightmapChunk left, HeightmapChunk top) : base(null, range) + { + Adjacent[3] = left; + Adjacent[0] = top; + if (left != null) left.Adjacent[1] = this; + if (top != null) top.Adjacent[2] = this; + MipLevel = mipLevel; + } + + public override HeightmapQuadTreeNode FindOrCreateQuadInDirection(int dir) + { + return Adjacent[dir]; + } + } +} diff --git a/server/tso.common/WorldGeometry/TS1RoadTemplates.cs b/server/tso.common/WorldGeometry/TS1RoadTemplates.cs new file mode 100755 index 0000000..edd8252 --- /dev/null +++ b/server/tso.common/WorldGeometry/TS1RoadTemplates.cs @@ -0,0 +1,230 @@ +using Microsoft.Xna.Framework; +using System.Collections.Generic; + +namespace FSO.Common.WorldGeometry +{ + public static class TS1RoadTemplates + { + private static ushort ROAD_TILE = 9; + private static ushort ROAD_LINE_LT_RB = 10; + private static ushort ROAD_LINE_LB_RT = 11; + private static ushort PAVEMENT_TILE = 12; + + private static ushort DOWNTOWN_PAVEMENT_LIGHT = 352; + private static ushort DOWNTOWN_GRATE_LIGHT = 350; + private static ushort DOWNTOWN_MANHOLE_LIGHT = 351; + + private static ushort DOWNTOWN_PAVEMENT_DARK = 355; + private static ushort DOWNTOWN_GRATE_DARK = 353; + private static ushort DOWNTOWN_MANHOLE_DARK = 354; + + private static ushort VACATION_ROAD = 359; //awfully flat + + private static Vector2 Flat(float xOff) + { + return new Vector2(xOff, 0); + } + + public static RoadGeometryTemplate OLD_TOWN = new RoadGeometryTemplate() + { + Segments = new RoadGeometryTemplateSegment[] + { + //without middle line (3 tiles long) + new RoadGeometryTemplateSegment() + { + Extent = 3f, + Lines = new RoadGeometryTemplateLine[] + { + new RoadGeometryTemplateLine(Flat(-5.5f), Flat(-4.5f), PAVEMENT_TILE), + new RoadGeometryTemplateLine(Flat(-3.5f), Flat(3.5f), ROAD_TILE), + new RoadGeometryTemplateLine(Flat(4.5f), Flat(5.5f), PAVEMENT_TILE), + } + }, + + //with middle line (3 tiles long) + new RoadGeometryTemplateSegment() + { + Extent = 3f, + Lines = new RoadGeometryTemplateLine[] + { + new RoadGeometryTemplateLine(Flat(-5.5f), Flat(-4.5f), PAVEMENT_TILE), + new RoadGeometryTemplateLine(Flat(-3.5f), Flat(-0.5f), ROAD_TILE), + new RoadGeometryTemplateLine(Flat(-0.5f), Flat(0.5f), ROAD_LINE_LT_RB), + new RoadGeometryTemplateLine(Flat(0.5f), Flat(3.5f), ROAD_TILE), + new RoadGeometryTemplateLine(Flat(4.5f), Flat(5.5f), PAVEMENT_TILE), + } + }, + }, + RepeatLength = 6f, + EndLines = new RoadGeometryTemplateLine[] + { + new RoadGeometryTemplateLine(Flat(-5.5f), Flat(-4.5f), PAVEMENT_TILE), + new RoadGeometryTemplateLine(Flat(-3.5f), Flat(0f), ROAD_TILE), + }, + EndRepeats = 17, + + IntersectionSize = 13, //7 wide road, 1 tile gap on each side, 1 tile pavement on each side, 1 tile gap again + IntersectionFromSize = 13, + Intersection4Way = new RoadGeometryTemplateRect[] + { + //pavement + new RoadGeometryTemplateRect(new Rectangle(1, 0, 1, 3), PAVEMENT_TILE), //top left cross + new RoadGeometryTemplateRect(new Rectangle(0, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(2, 1, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 0, 1, 3), PAVEMENT_TILE), //top right cross + new RoadGeometryTemplateRect(new Rectangle(10, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 1, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(1, 10, 1, 3), PAVEMENT_TILE), //bottom left cross + new RoadGeometryTemplateRect(new Rectangle(0, 11, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(2, 11, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 10, 1, 3), PAVEMENT_TILE), //bottom right cross + new RoadGeometryTemplateRect(new Rectangle(10, 11, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 11, 1, 1), PAVEMENT_TILE), + + //road + new RoadGeometryTemplateRect(new Rectangle(3, 3, 7, 7), ROAD_TILE), //center + new RoadGeometryTemplateRect(new Rectangle(3, 1, 7, 1), ROAD_TILE), //top + new RoadGeometryTemplateRect(new Rectangle(3, 11, 7, 1), ROAD_TILE), //bottom + new RoadGeometryTemplateRect(new Rectangle(1, 3, 1, 7), ROAD_TILE), //left + new RoadGeometryTemplateRect(new Rectangle(11, 3, 1, 7), ROAD_TILE), //right + + //road lines (vertical) + new RoadGeometryTemplateRect(new Rectangle(0, 3, 1, 7), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(2, 3, 1, 7), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(10, 3, 1, 7), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(12, 3, 1, 7), ROAD_LINE_LT_RB), + + //road lines (horizontal) + new RoadGeometryTemplateRect(new Rectangle(3, 0, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 2, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 10, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 12, 7, 1), ROAD_LINE_LB_RT), + + }, + + Intersection3Way = new RoadGeometryTemplateRect[] + { + //pavement + new RoadGeometryTemplateRect(new Rectangle(1, 0, 1, 13), PAVEMENT_TILE), //left pavement (with 2 joins) + new RoadGeometryTemplateRect(new Rectangle(2, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(2, 11, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 0, 1, 3), PAVEMENT_TILE), //top right cross + new RoadGeometryTemplateRect(new Rectangle(10, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 1, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 10, 1, 3), PAVEMENT_TILE), //bottom right cross + new RoadGeometryTemplateRect(new Rectangle(10, 11, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 11, 1, 1), PAVEMENT_TILE), + + //road + new RoadGeometryTemplateRect(new Rectangle(3, 3, 7, 7), ROAD_TILE), //center + new RoadGeometryTemplateRect(new Rectangle(3, 1, 7, 1), ROAD_TILE), //top + new RoadGeometryTemplateRect(new Rectangle(3, 11, 7, 1), ROAD_TILE), //bottom + new RoadGeometryTemplateRect(new Rectangle(11, 3, 1, 7), ROAD_TILE), //right + + //road lines (vertical) + new RoadGeometryTemplateRect(new Rectangle(10, 3, 1, 7), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(12, 3, 1, 7), ROAD_LINE_LT_RB), + + //road lines (horizontal) + new RoadGeometryTemplateRect(new Rectangle(3, 0, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 2, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 10, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 12, 7, 1), ROAD_LINE_LB_RT), + + } + }; + + public static RoadGeometryTemplate OLD_TOWN_DUAL = new RoadGeometryTemplate() + { + Segments = new RoadGeometryTemplateSegment[] + { + //this road type does not have a middle line. + new RoadGeometryTemplateSegment() + { + Extent = 3f, + Lines = new RoadGeometryTemplateLine[] + { + new RoadGeometryTemplateLine(Flat(-8.5f), Flat(-7.5f), PAVEMENT_TILE), + + new RoadGeometryTemplateLine(Flat(-6.5f), Flat(-2.5f), ROAD_TILE), + + new RoadGeometryTemplateLine(Flat(-2f), Flat(-1f), new Vector2(0.5f, 0), PAVEMENT_TILE), + new RoadGeometryTemplateLine(Flat(1f), Flat(2f), new Vector2(0.5f, 0), PAVEMENT_TILE), + + new RoadGeometryTemplateLine(Flat(2.5f), Flat(6.5f), ROAD_TILE), + + new RoadGeometryTemplateLine(Flat(7.5f), Flat(8.5f), PAVEMENT_TILE), + } + }, + }, + RepeatLength = 3f, + EndLines = new RoadGeometryTemplateLine[] + { + new RoadGeometryTemplateLine(Flat(-8.5f), Flat(-7.5f), PAVEMENT_TILE), + + new RoadGeometryTemplateLine(Flat(-6.5f), Flat(-2.5f), ROAD_TILE), + + new RoadGeometryTemplateLine(Flat(-2f), Flat(-1f), new Vector2(0.5f, 0), PAVEMENT_TILE), + }, + EndRepeats = 22, + + IntersectionSize = 19, //7 wide road, 1 tile gap on each side, 1 tile pavement on each side, 1 tile gap again + IntersectionFromSize = 13, //used for 3 way intersection on special road types. here it is the width of the normal road + + //UNUSED + Intersection4Way = OLD_TOWN.Intersection4Way, + + Intersection3Way = new RoadGeometryTemplateRect[] + { //19 tall, 13 wide + //pavement + new RoadGeometryTemplateRect(new Rectangle(1, 0, 1, 19), PAVEMENT_TILE), //left pavement (with 2 joins) + new RoadGeometryTemplateRect(new Rectangle(2, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(2, 17, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 0, 1, 3), PAVEMENT_TILE), //top right cross + new RoadGeometryTemplateRect(new Rectangle(10, 1, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 1, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 16, 1, 3), PAVEMENT_TILE), //bottom right cross + new RoadGeometryTemplateRect(new Rectangle(10, 17, 1, 1), PAVEMENT_TILE), + new RoadGeometryTemplateRect(new Rectangle(12, 17, 1, 1), PAVEMENT_TILE), + + new RoadGeometryTemplateRect(new Rectangle(11, 7, 1, 5), PAVEMENT_TILE), //right path + new RoadGeometryTemplateRect(new Rectangle(12, 7, 1, 1), PAVEMENT_TILE, new Vector2(0, 0.5f)), //right off1 + new RoadGeometryTemplateRect(new Rectangle(12, 10, 1, 1), PAVEMENT_TILE, new Vector2(0, 0.5f)), //right off2 + + //road + new RoadGeometryTemplateRect(new Rectangle(3, 3, 7, 13), ROAD_TILE), //center + new RoadGeometryTemplateRect(new Rectangle(3, 1, 7, 1), ROAD_TILE), //top + new RoadGeometryTemplateRect(new Rectangle(3, 17, 7, 1), ROAD_TILE), //bottom + + new RoadGeometryTemplateRect(new Rectangle(11, 3, 1, 4), ROAD_TILE), //right + new RoadGeometryTemplateRect(new Rectangle(11, 12, 1, 4), ROAD_TILE), //right + + //road lines (vertical) + new RoadGeometryTemplateRect(new Rectangle(10, 3, 1, 4), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(12, 3, 1, 4), ROAD_LINE_LT_RB), + + new RoadGeometryTemplateRect(new Rectangle(10, 12, 1, 4), ROAD_LINE_LT_RB), + new RoadGeometryTemplateRect(new Rectangle(12, 12, 1, 4), ROAD_LINE_LT_RB), + + //road lines (horizontal) + new RoadGeometryTemplateRect(new Rectangle(3, 0, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 2, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 16, 7, 1), ROAD_LINE_LB_RT), + new RoadGeometryTemplateRect(new Rectangle(3, 18, 7, 1), ROAD_LINE_LB_RT), + } + }; + + public static List OLD_TOWN_DEFAULT_TEMPLATES = new List() + { + OLD_TOWN, + OLD_TOWN_DUAL + }; + } +} diff --git a/server/tso.common/WorldGeometry/Utils/TriangleSet.cs b/server/tso.common/WorldGeometry/Utils/TriangleSet.cs new file mode 100755 index 0000000..1caaf19 --- /dev/null +++ b/server/tso.common/WorldGeometry/Utils/TriangleSet.cs @@ -0,0 +1,359 @@ +using FSO.Common.Model; +using FSO.Common.WorldGeometry; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace FSO.SimAntics.Model.Routing +{ + /// + /// (copied from VMObstacleSet) + /// A k-d Tree for looking up rectangle intersections + /// Ideally much faster lookups for routing rectangular cover, avatar and object movement. O(log n) vs O(n) + /// + /// Concerns: + /// - Tree balancing: a random insert may be the best solution, as algorithms for this can be quite complex. + /// - Should be mutable, as rect cover routing will add new entries. We also may want to add or remove elements from a "static" set. + /// - Tree cloning: wall and object sets would be nice, but for routing ideally we want to add new free-rects to the set dynamically. This means we need to clone the tree. + /// - Return true if ANY found, or return ALL found. First useful for routing, second for checking collision validity. + /// + public class BaseTriangleSet + { + public VMObstacleSetNode[] Nodes; + protected List FreeList = new List(); + protected int PoolInd = 0; + public int Root = -1; + public int Count; + + public BaseTriangleSet() + { + InitNodes(64); + } + + public BaseTriangleSet(BaseTriangleSet last) + { + if (last.Root != -1) + { + Count = last.Count; + Nodes = (VMObstacleSetNode[])last.Nodes.Clone(); + Root = last.Root; + FreeList = last.FreeList.ToList(); + PoolInd = last.PoolInd; + } + else + { + InitNodes(64); + } + } + + public BaseTriangleSet(IEnumerable obstacles) + { + InitNodes(obstacles.Count()); + foreach (var obstacle in obstacles) + Add(obstacle); + } + + private void InitNodes(int capacity) + { + if (Nodes == null) + { + Nodes = new VMObstacleSetNode[capacity]; + } + else + { + Array.Resize(ref Nodes, capacity); + } + } + + private int GetNode() + { + if (FreeList.Count > 0) + { + var free = FreeList.Last(); + FreeList.RemoveAt(FreeList.Count - 1); + return free; + } + else + { + return PoolInd++; + } + } + + private int GetNode(IntersectRectDimension dir, BaseMeshTriangle rect) + { + var ind = GetNode(); + Nodes[ind] = new VMObstacleSetNode() + { + Dimension = dir, + Rect = rect, + LeftChild = -1, + RightChild = -1, + Index = ind, + + x1 = rect.x1, + x2 = rect.x2, + y1 = rect.y1, + y2 = rect.y2 + }; + return ind; + } + + private void Reclaim(int index) + { + if (index == PoolInd - 1) PoolInd--; + else FreeList.Add(index); + } + + public void Add(BaseMeshTriangle rect) + { + if (PoolInd >= Nodes.Length && FreeList.Count == 0) InitNodes(Nodes.Length * 2); + Count++; + if (Root == -1) + { + Root = GetNode(IntersectRectDimension.Left, rect); + } + else + { + AddAsChild(ref Nodes[Root], rect); + } + } + + private void AddAsChild(ref VMObstacleSetNode node, BaseMeshTriangle rect) + { + bool rightSide = false; + switch (node.Dimension) + { + case IntersectRectDimension.Top: + rightSide = rect.y1 > node.Rect.y1; break; + case IntersectRectDimension.Left: + rightSide = rect.x1 > node.Rect.x1; break; + case IntersectRectDimension.Bottom: + rightSide = rect.y2 > node.Rect.y2; break; + case IntersectRectDimension.Right: + rightSide = rect.x2 > node.Rect.x2; break; + } + if (rightSide) + { + if (node.RightChild != -1) AddAsChild(ref Nodes[node.RightChild], rect); + else + { + node.RightChild = GetNode((IntersectRectDimension)(((int)node.Dimension + 1) % 4), rect); + } + } + else + { + if (node.LeftChild != -1) AddAsChild(ref Nodes[node.LeftChild], rect); + else + { + node.LeftChild = GetNode((IntersectRectDimension)(((int)node.Dimension + 1) % 4), rect); + } + } + } + + public void RecursiveReAdd(VMObstacleSetNode node) + { + Count--; + Reclaim(node.Index); + Add(node.Rect); + if (node.LeftChild != -1) RecursiveReAdd(Nodes[node.LeftChild]); + if (node.RightChild != -1) RecursiveReAdd(Nodes[node.RightChild]); + } + + public bool SearchForIntersect(BaseMeshTriangle rect) + { + if (Root == -1) return false; + else + { + return SearchForIntersect(ref Nodes[Root], rect); + } + } + + public bool SearchForIntersect(ref VMObstacleSetNode node, BaseMeshTriangle rect) + { + if (node.Intersects(rect)) return true; + //search in child nodes. + int dontSearch = 0; + switch (node.Dimension) + { + case IntersectRectDimension.Top: + dontSearch = (rect.y2 <= node.y1) ? 2 : 0; break; //if true, do not have to search right (where top greater) + case IntersectRectDimension.Left: + dontSearch = (rect.x2 <= node.x1) ? 2 : 0; break; //if true, do not have to search right (where left greater) + case IntersectRectDimension.Bottom: + dontSearch = (rect.y1 >= node.y2) ? 1 : 0; break; //if true, do not have to search left (where bottom less) + case IntersectRectDimension.Right: + dontSearch = (rect.x1 >= node.x2) ? 1 : 0; break; //if true, do not have to search left (where right less) + } + + //may need to search both :'( won't happen often with our small rectangles over large space though. + return ((dontSearch != 1 && node.LeftChild != -1 && SearchForIntersect(ref Nodes[node.LeftChild], rect)) + || (dontSearch != 2 && node.RightChild != -1 && SearchForIntersect(ref Nodes[node.RightChild], rect))); + } + + public List AllIntersect(BaseMeshTriangle rect) + { + var result = new List(); + if (Root == -1) return result; + else + { + AllIntersect(ref Nodes[Root], rect, result); + return result; + } + } + + public void AllIntersect(ref VMObstacleSetNode node, BaseMeshTriangle rect, List result) + { + if (node.Intersects(rect)) result.Add(node.Rect); + //search in child nodes. + int dontSearch = 0; + switch (node.Dimension) + { + case IntersectRectDimension.Top: + dontSearch = (rect.y2 <= node.y1) ? 2 : 0; break; //if true, do not have to search right (where top greater) + case IntersectRectDimension.Left: + dontSearch = (rect.x2 <= node.x1) ? 2 : 0; break; //if true, do not have to search right (where left greater) + case IntersectRectDimension.Bottom: + dontSearch = (rect.y1 >= node.y2) ? 1 : 0; break; //if true, do not have to search left (where bottom less) + case IntersectRectDimension.Right: + dontSearch = (rect.x1 >= node.x2) ? 1 : 0; break; //if true, do not have to search left (where right less) + } + + //may need to search both :'( won't happen often with our small rectangles over large space though. + //if (node.LeftChild != -1) AllIntersect(ref Nodes[node.LeftChild], rect, result); + //if (node.RightChild != -1) AllIntersect(ref Nodes[node.RightChild], rect, result); + + if (dontSearch != 1 && node.LeftChild != -1) AllIntersect(ref Nodes[node.LeftChild], rect, result); + if (dontSearch != 2 && node.RightChild != -1) AllIntersect(ref Nodes[node.RightChild], rect, result); + } + + public List OnEdge(BaseMeshTriangle rect) + { + var result = new List(); + if (Root == -1) return result; + else + { + OnEdge(ref Nodes[Root], rect, result); + return result; + } + } + + public void OnEdge(ref VMObstacleSetNode node, BaseMeshTriangle rect, List result) + { + if (node.OnEdge(rect)) result.Add(node.Rect); + //search in child nodes. + //binary search to find equal opposing edges. + int dontSearch = 0; + switch (node.Dimension) + { + case IntersectRectDimension.Top: + dontSearch = (rect.y2 < node.y1) ? 2 : 0; break; //if true, do not have to search right (where top greater) + case IntersectRectDimension.Left: + dontSearch = (rect.x2 < node.x1) ? 2 : 0; break; //if true, do not have to search right (where left greater) + case IntersectRectDimension.Bottom: + dontSearch = (rect.y1 > node.y2) ? 1 : 0; break; //if true, do not have to search left (where bottom less) + case IntersectRectDimension.Right: + dontSearch = (rect.x1 > node.x2) ? 1 : 0; break; //if true, do not have to search left (where right less) + } + + //may need to search both :'( won't happen often with our small rectangles over large space though. + //if (node.LeftChild != -1) OnEdge(ref Nodes[node.LeftChild], rect, result); + //if (node.RightChild != -1) OnEdge(ref Nodes[node.RightChild], rect, result); + + if (dontSearch != 1 && node.LeftChild != -1) OnEdge(ref Nodes[node.LeftChild], rect, result); + if (dontSearch != 2 && node.RightChild != -1) OnEdge(ref Nodes[node.RightChild], rect, result); + } + + public static BaseTriangleSet RoughBalanced(List input) + { + //roughly attempts to balance the set. + //...currently by random shuffle. at least it's deterministic? + var rand = new Random(1); + for (int i = 1; i < input.Count; i++) + { + var swap = input[i - 1]; + var ind = rand.Next(input.Count - i) + i; + input[i - 1] = input[ind]; + input[ind] = swap; + } + + return new BaseTriangleSet(input); + } + + /* + public bool Delete(VMEntityObstacle rect) + { + if (Root == -1) return false; + else + { + var result = Delete(ref Nodes[Root], rect, ref Nodes[Root]); + if (result) { Count--; } + return result; + } + } + */ + + /* + public bool Delete(ref VMObstacleSetNode node, VMEntityObstacle rect, ref VMObstacleSetNode parent) + { + if (rect.Parent == (node.Rect as VMEntityObstacle).Parent) + { + if (parent.Index == node.Index) + { + Root = -1; + } + else + { + if (parent.LeftChild == node.Index) parent.LeftChild = -1; + if (parent.RightChild == node.Index) parent.RightChild = -1; + } + if (node.LeftChild != -1) RecursiveReAdd(Nodes[node.LeftChild]); + if (node.RightChild != -1) RecursiveReAdd(Nodes[node.RightChild]); + Reclaim(node.Index); + return true; + } + //search in child nodes. + //binary search to find equal opposing edges. + + bool rightSide = false; + switch (node.Dimension) + { + case IntersectRectDimension.Top: + rightSide = rect.y1 > node.y1; break; + case IntersectRectDimension.Left: + rightSide = rect.x1 > node.x1; break; + case IntersectRectDimension.Bottom: + rightSide = rect.y2 > node.y2; break; + case IntersectRectDimension.Right: + rightSide = rect.x2 > node.x2; break; + } + + return ((rightSide && node.RightChild != -1 && Delete(ref Nodes[node.RightChild], rect, ref node)) + || (!rightSide && node.LeftChild != -1 && Delete(ref Nodes[node.LeftChild], rect, ref node))); + } + */ + } + + public struct VMObstacleSetNode + { + public int LeftChild; + public int RightChild; + public IntersectRectDimension Dimension; + public BaseMeshTriangle Rect; + public int Index; + + public float x1; + public float x2; + public float y1; + public float y2; + + public bool Intersects(BaseMeshTriangle other) + { + return !((other.x1 >= x2 || other.x2 <= x1) || (other.y1 >= y2 || other.y2 <= y1)); + } + + public bool OnEdge(BaseMeshTriangle other) + { + return (x2 == other.x1) || (x1 == other.x2) || (y1 == other.y2) || (y2 == other.y1); + } + } +} diff --git a/server/tso.common/app.config b/server/tso.common/app.config new file mode 100755 index 0000000..057fb30 --- /dev/null +++ b/server/tso.common/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/server/tso.common/packages.config b/server/tso.common/packages.config new file mode 100755 index 0000000..e0fd635 --- /dev/null +++ b/server/tso.common/packages.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/server/tso.common/version.txt b/server/tso.common/version.txt new file mode 100755 index 0000000..27a3ecb --- /dev/null +++ b/server/tso.common/version.txt @@ -0,0 +1 @@ +dev-0.88.101 diff --git a/Client/Bootstrap/Bootstrap.hpp b/src/api/auth.zig similarity index 100% rename from Client/Bootstrap/Bootstrap.hpp rename to src/api/auth.zig diff --git a/src/version.txt b/src/version.txt new file mode 100644 index 0000000..157c689 --- /dev/null +++ b/src/version.txt @@ -0,0 +1 @@ +dev-0.88.101 \ No newline at end of file