24 Commits

Author SHA1 Message Date
  Thomas Cheyney 2726913f3d Turn debug back off, add skrillex, bump version 2 years ago
  Thomas Cheyney 9c3967f705 Turn off unreal analytics 2 years ago
  Thomas Cheyney 5e953465f3 Fix writing json as UTF16. Add new environments to dropdown 2 years ago
  Thomas Cheyney f98d0b4fac Fix characteristic names again 3 years ago
  Thomas Cheyney a05bf36ed1 Hide editor offset. Save editor scale. Fix max time auto value. 3 years ago
  Thomas Cheyney d4a279b125 Fix strobing right laser, guard against writing nothing, fix custom platforms with spaces 3 years ago
  Thomas Cheyney 13d624068d Bugfixes 3 years ago
  Thomas Cheyney 75401345f2 Boost events set light colours 3 years ago
  Thomas Cheyney acb7dd590b New environments, light colours 3 years ago
  Thomas Cheyney 2415420080 Add close button to dialog 3 years ago
  Thomas Cheyney bc804ed1e9 Add songcore colour pickers 3 years ago
  Thomas Cheyney eb2ab56213 Fix copy pasting special events 3 years ago
  Thomas Cheyney 6b5ce295d8 Upgrade map files to 2.2.0 schema 3 years ago
  Thomas Cheyney a8c49a1199 Is this... error handling? 3 years ago
  Thomas Cheyney a692c817d8 Darken default not colour to match old MMA2 builds 3 years ago
  Thomas Cheyney 33e67146ea Add basic songcore colour support, add boost events 3 years ago
  Thomas Cheyney 8b2fa3647f Add server files 3 years ago
  Thomas Cheyney 343ea27e68 Prevent crash when audio file is empty 3 years ago
  Thomas Cheyney 98cac55eae Include crash reporter, small UI tweaks 3 years ago
  Thomas Cheyney 070850e4ee Improve block placement raytracing 3 years ago
  Thomas Cheyney 384c567886 Fix offset being ignored in distance calculation 3 years ago
  Thomas Cheyney 2c87cf0339 Refactor beat numbering 3 years ago
  Qwasyx 1c956a1210 made beat numberings not depend on editor scale 3 years ago
  Thomas Cheyney 2440e9d650 Clear custom platform fields if empty, default error checker to half jump duration 3 years ago
66 changed files with 1248 additions and 33 deletions
Split View
  1. +24
    -3
      Config/DefaultEngine.ini
  2. +2
    -1
      Config/DefaultGame.ini
  3. BIN
      Content/Blueprints/BPFL_editor.uasset
  4. BIN
      Content/Blueprints/BPSG_config.uasset
  5. BIN
      Content/Blueprints/BP_bookmark.uasset
  6. BIN
      Content/Blueprints/BP_controller.uasset
  7. BIN
      Content/Blueprints/BP_event.uasset
  8. BIN
      Content/Blueprints/BP_eventSelection.uasset
  9. BIN
      Content/Blueprints/BP_event_ghost.uasset
  10. BIN
      Content/Blueprints/BP_event_gradient.uasset
  11. BIN
      Content/Blueprints/BP_event_manager.uasset
  12. BIN
      Content/Blueprints/BP_lasers.uasset
  13. BIN
      Content/Blueprints/BP_note.uasset
  14. BIN
      Content/Blueprints/BP_wall.uasset
  15. BIN
      Content/Blueprints/VarTypes/StructDifficultyInfos.uasset
  16. BIN
      Content/Blueprints/VarTypes/StructSong.uasset
  17. BIN
      Content/Blueprints/VarTypes/structBeatMapSet.uasset
  18. BIN
      Content/Blueprints/WidgetEditorMenu.uasset
  19. BIN
      Content/Blueprints/WidgetExtraFields.uasset
  20. BIN
      Content/Blueprints/WidgetMapMenu.uasset
  21. BIN
      Content/Blueprints/WidgetSongInfos.uasset
  22. BIN
      Content/Blueprints/WidgetSpawnDistance.uasset
  23. BIN
      Content/Levels/Level_Startup.umap
  24. BIN
      Content/Materials/Events/MI_light_RGB.uasset
  25. BIN
      Content/Materials/Events/MI_light_RGB_ghost.uasset
  26. BIN
      Content/Materials/Events/MI_light_off.uasset
  27. BIN
      Content/Materials/Events/MI_light_on_blue.uasset
  28. BIN
      Content/Materials/Events/MI_light_on_blue_fade.uasset
  29. BIN
      Content/Materials/Events/MI_light_on_blue_flash.uasset
  30. BIN
      Content/Materials/Events/MI_light_on_red.uasset
  31. BIN
      Content/Materials/Events/MI_light_on_red_fade.uasset
  32. BIN
      Content/Materials/Events/MI_light_on_red_flash.uasset
  33. BIN
      Content/Materials/Events/M_light_event.uasset
  34. BIN
      Content/Materials/Events/ghostbluefade.uasset
  35. BIN
      Content/Materials/Events/ghostblueflash.uasset
  36. BIN
      Content/Materials/Events/ghostblueon.uasset
  37. BIN
      Content/Materials/Events/ghostredfade.uasset
  38. BIN
      Content/Materials/Events/ghostredflash.uasset
  39. BIN
      Content/Materials/Events/ghostredon.uasset
  40. BIN
      Content/Materials/MI_boost.uasset
  41. BIN
      Content/Materials/M_CubeNote.uasset
  42. BIN
      Content/Materials/M_CubeNote_red.uasset
  43. BIN
      Content/Materials/M_bomb_ghost.uasset
  44. BIN
      Content/Meshes/Cube.uasset
  45. BIN
      Content/Meshes/untitled.uasset
  46. BIN
      Content/Textures/Icons/VisionBlockCat.uasset
  47. BIN
      Content/Textures/Icons/bigcat.uasset
  48. BIN
      Content/Textures/Icons/donateCat.uasset
  49. BIN
      Content/Textures/Icons/fileextensionimage.uasset
  50. BIN
      Content/Textures/Icons/good_mapping_practice.uasset
  51. BIN
      Content/Textures/Icons/pfp.uasset
  52. BIN
      Content/Textures/Icons/visionblock1.uasset
  53. BIN
      Content/Textures/Icons/visionblock2.uasset
  54. BIN
      Content/Textures/Icons/visionblock3.uasset
  55. BIN
      Content/Textures/Icons/visionblockcatfull.uasset
  56. +28
    -24
      Plugins/eXiSoundVis/Source/eXiSoundVis/Private/AudioDecompressWorker.cpp
  57. +6
    -2
      Plugins/eXiSoundVis/Source/eXiSoundVis/Private/SoundVisComponent.cpp
  58. +3
    -1
      Plugins/eXiSoundVis/Source/eXiSoundVis/eXiSoundVis.Build.cs
  59. +44
    -0
      Server/ServerReadme.md
  60. +7
    -0
      Server/config.json
  61. +346
    -0
      Server/package-lock.json
  62. +15
    -0
      Server/package.json
  63. +730
    -0
      Server/server.js
  64. +35
    -0
      Source/MediocreMapAssistant2/BPFileIO.cpp
  65. +7
    -1
      Source/MediocreMapAssistant2/BPFileIO.h
  66. +1
    -1
      Source/MediocreMapAssistant2/RenderWaveform.cpp

+ 24
- 3
Config/DefaultEngine.ini View File

@ -114,9 +114,6 @@ SmoothedFrameRateRange=(LowerBound=(Type=Inclusive,Value=22.000000),UpperBound=(
+ActiveGameNameRedirects=(OldGameName="MediocreMapper",NewGameName="MediocreMapAssistant2")
bSmoothFrameRate=True
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
Compiler=VisualStudio2017
[/Script/Engine.CollisionProfile]
-Profiles=(Name="NoCollision",CollisionEnabled=NoCollision,ObjectTypeName="WorldStatic",CustomResponses=((Channel="Visibility",Response=ECR_Ignore),(Channel="Camera",Response=ECR_Ignore)),HelpMessage="No collision",bCanModify=False)
-Profiles=(Name="BlockAll",CollisionEnabled=QueryAndPhysics,ObjectTypeName="WorldStatic",CustomResponses=,HelpMessage="WorldStatic object that blocks all actors by default. All new custom channels will use its own default response. ",bCanModify=False)
@ -187,6 +184,30 @@ Compiler=VisualStudio2017
[/Script/IOSRuntimeSettings.IOSRuntimeSettings]
bGenerateCrashReportSymbols=True
[CrashReportClient]
CrashReportClientVersion=4.7.1
DataRouterUrl="https://o462013.ingest.sentry.io/api/5464708/unreal/40d9818b9fee4b72be61bcd0cc2c5e3b/"
[/Script/WindowsTargetPlatform.WindowsTargetSettings]
Compiler=VisualStudio2017
-TargetedRHIs=PCD3D_SM5
-TargetedRHIs=PCD3D_SM4
+TargetedRHIs=PCD3D_SM5
+TargetedRHIs=PCD3D_SM4
MinimumOSVersion=MSOS_Vista
AudioDevice=
AudioSampleRate=48000
AudioCallbackBufferFrameSize=1024
AudioNumBuffersToEnqueue=1
AudioMaxChannels=0
AudioNumSourceWorkers=4
SpatializationPlugin=
ReverbPlugin=
OcclusionPlugin=
[/Script/Engine.EndUserSettings]
bSendAnonymousUsageDataToEpic=False
[/Script/Engine.PhysicsSettings]
DefaultGravityZ=-980.000000
DefaultTerminalVelocity=4000.000000


+ 2
- 1
Config/DefaultGame.ini View File

@ -3,7 +3,7 @@ ProjectID=F5529D354BF9DDA5B4BC06BB62D10933
bShouldWindowPreserveAspectRatio=False
ProjectName=MediocreMapAssistant2
ProjectDisplayedTitle=NSLOCTEXT("[/Script/EngineSettings]", "A4F171D24A09E6B0C435A39031D526F5", "Mediocre Map Assistant 2")
ProjectVersion=4.5.0
ProjectVersion=4.8.4
[/Script/UnrealEd.ProjectPackagingSettings]
Build=IfProjectHasCode
@ -39,3 +39,4 @@ bSkipEditorContent=True
+MapsToCook=(FilePath="/Game/Levels/Level_Startup")
bNativizeBlueprintAssets=False
bNativizeOnlySelectedBlueprints=False

BIN
Content/Blueprints/BPFL_editor.uasset View File


BIN
Content/Blueprints/BPSG_config.uasset View File


BIN
Content/Blueprints/BP_bookmark.uasset View File


BIN
Content/Blueprints/BP_controller.uasset View File


BIN
Content/Blueprints/BP_event.uasset View File


BIN
Content/Blueprints/BP_eventSelection.uasset View File


BIN
Content/Blueprints/BP_event_ghost.uasset View File


BIN
Content/Blueprints/BP_event_gradient.uasset View File


BIN
Content/Blueprints/BP_event_manager.uasset View File


BIN
Content/Blueprints/BP_lasers.uasset View File


BIN
Content/Blueprints/BP_note.uasset View File


BIN
Content/Blueprints/BP_wall.uasset View File


BIN
Content/Blueprints/VarTypes/StructDifficultyInfos.uasset View File


BIN
Content/Blueprints/VarTypes/StructSong.uasset View File


BIN
Content/Blueprints/VarTypes/structBeatMapSet.uasset View File


BIN
Content/Blueprints/WidgetEditorMenu.uasset View File


BIN
Content/Blueprints/WidgetExtraFields.uasset View File


BIN
Content/Blueprints/WidgetMapMenu.uasset View File


BIN
Content/Blueprints/WidgetSongInfos.uasset View File


BIN
Content/Blueprints/WidgetSpawnDistance.uasset View File


BIN
Content/Levels/Level_Startup.umap View File


BIN
Content/Materials/Events/MI_light_RGB.uasset View File


BIN
Content/Materials/Events/MI_light_RGB_ghost.uasset View File


BIN
Content/Materials/Events/MI_light_off.uasset View File


BIN
Content/Materials/Events/MI_light_on_blue.uasset View File


BIN
Content/Materials/Events/MI_light_on_blue_fade.uasset View File


BIN
Content/Materials/Events/MI_light_on_blue_flash.uasset View File


BIN
Content/Materials/Events/MI_light_on_red.uasset View File


BIN
Content/Materials/Events/MI_light_on_red_fade.uasset View File


BIN
Content/Materials/Events/MI_light_on_red_flash.uasset View File


BIN
Content/Materials/Events/M_light_event.uasset View File


BIN
Content/Materials/Events/ghostbluefade.uasset View File


BIN
Content/Materials/Events/ghostblueflash.uasset View File


BIN
Content/Materials/Events/ghostblueon.uasset View File


BIN
Content/Materials/Events/ghostredfade.uasset View File


BIN
Content/Materials/Events/ghostredflash.uasset View File


BIN
Content/Materials/Events/ghostredon.uasset View File


BIN
Content/Materials/MI_boost.uasset View File


BIN
Content/Materials/M_CubeNote.uasset View File


BIN
Content/Materials/M_CubeNote_red.uasset View File


BIN
Content/Materials/M_bomb_ghost.uasset View File


BIN
Content/Meshes/Cube.uasset View File


BIN
Content/Meshes/untitled.uasset View File


BIN
Content/Textures/Icons/VisionBlockCat.uasset View File


BIN
Content/Textures/Icons/bigcat.uasset View File


BIN
Content/Textures/Icons/donateCat.uasset View File


BIN
Content/Textures/Icons/fileextensionimage.uasset View File


BIN
Content/Textures/Icons/good_mapping_practice.uasset View File


BIN
Content/Textures/Icons/pfp.uasset View File


BIN
Content/Textures/Icons/visionblock1.uasset View File


BIN
Content/Textures/Icons/visionblock2.uasset View File


BIN
Content/Textures/Icons/visionblock3.uasset View File


BIN
Content/Textures/Icons/visionblockcatfull.uasset View File


+ 28
- 24
Plugins/eXiSoundVis/Source/eXiSoundVis/Private/AudioDecompressWorker.cpp View File

@ -67,37 +67,41 @@ uint32 FAudioDecompressWorker::Run()
if (AudioInfo != NULL)
{
FSoundQualityInfo QualityInfo = { 0 };
try {
FSoundQualityInfo QualityInfo = { 0 };
// Parse the audio header for the relevant information
if (!(SoundWaveRef->ResourceData))
{
return 0;
}
// Parse the audio header for the relevant information
if (!(SoundWaveRef->ResourceData))
{
return 0;
}
if (AudioInfo->ReadCompressedInfo(SoundWaveRef->ResourceData, SoundWaveRef->ResourceSize, &QualityInfo))
{
FScopeCycleCounterUObject WaveObject(SoundWaveRef);
if (AudioInfo->ReadCompressedInfo(SoundWaveRef->ResourceData, SoundWaveRef->ResourceSize, &QualityInfo))
{
FScopeCycleCounterUObject WaveObject(SoundWaveRef);
// Extract the data
SoundWaveRef->SampleRate = QualityInfo.SampleRate;
SoundWaveRef->NumChannels = QualityInfo.NumChannels;
// Extract the data
SoundWaveRef->SampleRate = QualityInfo.SampleRate;
SoundWaveRef->NumChannels = QualityInfo.NumChannels;
if (QualityInfo.Duration > 0.0f)
{
SoundWaveRef->Duration = QualityInfo.Duration;
}
if (QualityInfo.Duration > 0.0f)
{
SoundWaveRef->Duration = QualityInfo.Duration;
}
const uint32 PCMBufferSize = SoundWaveRef->Duration * SoundWaveRef->SampleRate * SoundWaveRef->NumChannels;
const uint32 PCMBufferSize = SoundWaveRef->Duration * SoundWaveRef->SampleRate * SoundWaveRef->NumChannels;
SoundWaveRef->CachedRealtimeFirstBuffer = new uint8[PCMBufferSize * 2];
SoundWaveRef->CachedRealtimeFirstBuffer = new uint8[PCMBufferSize * 2];
AudioInfo->SeekToTime(0.0f);
AudioInfo->ReadCompressedData(SoundWaveRef->CachedRealtimeFirstBuffer, false, PCMBufferSize * 2);
}
else if (SoundWaveRef->DecompressionType == DTYPE_RealTime || SoundWaveRef->DecompressionType == DTYPE_Native)
{
SoundWaveRef->RemoveAudioResource();
AudioInfo->SeekToTime(0.0f);
AudioInfo->ReadCompressedData(SoundWaveRef->CachedRealtimeFirstBuffer, false, PCMBufferSize * 2);
}
else if (SoundWaveRef->DecompressionType == DTYPE_RealTime || SoundWaveRef->DecompressionType == DTYPE_Native)
{
SoundWaveRef->RemoveAudioResource();
}
} catch (const std::exception&) {
// Yo, bad things happened
}
delete AudioInfo;


+ 6
- 2
Plugins/eXiSoundVis/Source/eXiSoundVis/Private/SoundVisComponent.cpp View File

@ -351,8 +351,12 @@ void USoundVisComponent::Notify_SoundDecompressed()
// ..clear the timer and..
GetWorld()->GetTimerManager().ClearTimer(AudioDecompressTimer);
//..broadcast the result to the Blueprint
OnFileLoadCompleted.Broadcast(FAudioDecompressWorker::Runnable->GetSoundWaveRef());
try {
//..broadcast the result to the Blueprint
OnFileLoadCompleted.Broadcast(FAudioDecompressWorker::Runnable->GetSoundWaveRef());
} catch (const std::exception&) {
// Yo, bad things happened
}
PrintLog(TEXT("Worker finished!"));
}


+ 3
- 1
Plugins/eXiSoundVis/Source/eXiSoundVis/eXiSoundVis.Build.cs View File

@ -5,7 +5,9 @@ public class eXiSoundVis : ModuleRules
{
public eXiSoundVis(ReadOnlyTargetRules Target) : base(Target)
{
PrivateIncludePaths.AddRange(new string[] { "eXiSoundVis/Private" });
this.bEnableExceptions = true;
PrivateIncludePaths.AddRange(new string[] { "eXiSoundVis/Private" });
PublicIncludePaths.AddRange(new string[] { "eXiSoundVis/Public" });
PublicDependencyModuleNames.AddRange(new string[] { "Engine", "Core", "CoreUObject", "InputCore", "RHI", "Kiss_FFT" });


+ 44
- 0
Server/ServerReadme.md View File

@ -0,0 +1,44 @@
# Mediocre Mapper Multi-Mapper Server setup
## What you need to start
* install node.js from https://nodejs.org/en/
* move your song into the /Songs/ directory
* port forward a TCP port of your choosing. 17425 is default.
* create a song in MediocreMapper and set up difficulties, offset and BPM
## Setting up the server
### config.json setup
```
"folder" - Folder name of the song
"characteristic" - Characteristic to be used (Standard/No Arrows/One Saber)
"difficulty": - Difficulty to be used (Easy/Normal/Hard/Expert/ExpertPlus)
"port": - Port you'll be using
"password": - Password to the server, can be left empty for no password
```
### config.json example
```
{
"folder": "The Other Side",
"characteristic": "Standard",
"difficulty": "ExpertPlus",
"port": 17425,
"password": "967"
}
```
## Starting the server
* copy the song from your Mediocre Mapper's /CustomSongs/ Directory into your Server's /Songs/ directory
* set up the config.json as above
* open up a command line and navigate to the folder containing server.js. Or shift + right click in the folder in Windows Explorer to and open up PowerShell
* run command: `npm install`
* run command: `node ./server.js`
* all done!
## Other info
Server saves every 5 minutes, so at most 5 minutes of progress is lost in the case of a crash.
No more than one person using the same name can be in a session. sometimes this bugs out and there's an improper disconnect. Have server restarted after a save if you're unable to join with the same name and really don't wanna change it. or just change it.
Full or partial information can be supplied to the server by typing for example `node ./server.js --difficulty "ExpertPlus"`

+ 7
- 0
Server/config.json View File

@ -0,0 +1,7 @@
{
"folder": "Song",
"characteristic": "Standard",
"difficulty": "ExpertPlus",
"port": 17425,
"password": ""
}

+ 346
- 0
Server/package-lock.json View File

@ -0,0 +1,346 @@
{
"name": "mediocremapperserver",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ajv": {
"version": "6.6.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
"requires": {
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
},
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
"requires": {
"safer-buffer": "~2.1.0"
}
},
"assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
},
"asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
},
"aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
},
"aws4": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
"requires": {
"tweetnacl": "^0.14.3"
}
},
"caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
},
"combined-stream": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz",
"integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==",
"requires": {
"delayed-stream": "~1.0.0"
}
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
},
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
"requires": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
},
"fast-deep-equal": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
},
"forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
},
"form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
}
},
"getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
"requires": {
"assert-plus": "^1.0.0"
}
},
"har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
},
"har-validator": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
"requires": {
"ajv": "^6.5.5",
"har-schema": "^2.0.0"
}
},
"http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
"requires": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
}
},
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
},
"jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
},
"json-schema": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
},
"json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.2.3",
"verror": "1.10.0"
}
},
"mime-db": {
"version": "1.37.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz",
"integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg=="
},
"mime-types": {
"version": "2.1.21",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz",
"integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==",
"requires": {
"mime-db": "~1.37.0"
}
},
"oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
},
"psl": {
"version": "1.1.31",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz",
"integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw=="
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
"request": {
"version": "2.88.0",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
"requires": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.0",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sshpk": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.2.tgz",
"integrity": "sha512-Ra/OXQtuh0/enyl4ETZAfTaeksa6BXks5ZcjpSUNrjBr0DvrJKX+1fsKDPpT9TBXgHAFsa4510aNVgI8g/+SzA==",
"requires": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
}
},
"tough-cookie": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
"requires": {
"psl": "^1.1.24",
"punycode": "^1.4.1"
},
"dependencies": {
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
}
}
},
"tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
"requires": {
"safe-buffer": "^5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
},
"uri-js": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
"requires": {
"punycode": "^2.1.0"
}
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
"integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
},
"verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
"requires": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
}
}
}

+ 15
- 0
Server/package.json View File

@ -0,0 +1,15 @@
{
"name": "mediocremapperserver",
"version": "1.0.0",
"description": "Server for Mediocre Mapper Multi-Mapper",
"main": "server.js",
"scripts": {
"test": "start",
"start": "node server.js"
},
"author": "squeaksies",
"license": "ISC",
"dependencies": {
"request": "^2.88.0"
}
}

+ 730
- 0
Server/server.js View File

@ -0,0 +1,730 @@
"use strict";
const fs = require("fs");
var clients = [];
var net = require('net');
try{
var request = require('request');
}
catch(err){
console.log(err);
console.log('Go read the damn readme. Run "npm install" or install the request module in some other way.');
process.exit()
}
var https = require('https');
var config = {};
var diff;
var fileSize;
var diffIndex;
var charIndex;
var diffFound = false;
var charFound = false;
var changesMade = false;
var downloadURL = "";
console.log("\n\n\n");
// Loading up json files and such that you need
try{
config = require('./config.json');
}
catch(err){
}
process.argv.shift();
process.argv.shift();
var type = "";
while(process.argv.length > 0)
{
var input = process.argv.shift()
if (input.startsWith("--"))
{
type = input.replace('--','');
}
else
{
if (type == "")
{
console.log('you fucked up');
process.exit()
}
else
{
config[type] = input;
}
}
}
// Check and display relevant info
try{
if(config.folder !== "" && config.folder !== undefined){
console.log(' Song folder: ' + config.folder);
}
else{
console.log('\nError: Fill in folder field');
process.exit()
}
if(config.difficulty !== "" && config.characteristic !== undefined){
console.log(' Song characteristic: ' + config.characteristic);
}
else{
console.log(' Song characteristic: Standard');
}
if(config.difficulty !== "" && config.difficulty !== undefined){
console.log(' Song difficulty: ' + config.difficulty);
}
else{
console.log('\nError: Fill in difficulty field');
process.exit()
}
if(config.port !== "" && config.port !== undefined){
console.log(' Port: ' + config.port);
}
else{
console.log('\nError: Fill in port field');
process.exit()
}
if(config.password != "" && config.password !== undefined){
console.log(' Password: ' + config.password);
}
else{
config.password = "";
console.log(' Password: no password being used');
}
if(config.download !== "" && config.download !== undefined){
console.log(' Song download: ' + config.download);
downloadURL = config.download;
}
}
catch(err){
console.log('config file is not formatted correctly');
process.exit()
}
var data = fs.readFileSync('./Songs/' + config.folder + '/info.dat');
// Loading stuff
try{
var info = loadJSON('./Songs/' + config.folder + '/info.dat');
}
catch(err){
console.log('Could not find file: Songs/' + config.folder + '/info.dat');
process.exit()
}
if (!config.characteristic)
{
config.characteristic = "Standard";
}
for (var i = 0; i < info._difficultyBeatmapSets.length; i++)
{
if (info._difficultyBeatmapSets[i]._beatmapCharacteristicName == config.characteristic)
{
for(var j = 0; j < info._difficultyBeatmapSets[i]._difficultyBeatmaps.length; j++)
{
if (info._difficultyBeatmapSets[i]._difficultyBeatmaps[j]._difficulty == config.difficulty)
{
diff = loadJSON('./Songs/' + config.folder + '/' + info._difficultyBeatmapSets[i]._difficultyBeatmaps[j]._beatmapFilename);
try{
fileSize = fs.statSync('./Songs/' + config.folder + '/' + info._songFilename);
}catch(err)
{
//console.log('\nFailed to find '+info.difficultyLevels[i].audioPath+'. now using fileSize argument');
if(!config.hasOwnProperty('fileSize'))
{
//console.log('could not use fileSize argument, finding from download URL');
request({
url: downloadURL,
method: "HEAD"
}, function(err, response, body) {
var downloadResponse = response.headers;
if (downloadResponse.hasOwnProperty('content-length'))
{
fileSize = downloadResponse['content-length'];
}
else
{
console.log('Unable to get file size. Please specify fileSize in config.json or as an argument');
process.exit();
}
});
}
fileSize = config['content-length'];
}
diffIndex = j;
charIndex = i;
diffFound = true;
break;
}
}
}
}
if (diff === null)
{
console.log('No proper difficulty found.');
process.exit();
}
if (diffFound == false)
{
console.log('Difficulty/Characteristic not found');
process.exit();
}
setInterval(saveFile, 300000);//save every 5 minutes
// if(config.download === "")
// {
// config.download = 'none';
// }
var server = net.createServer(function(socket){
socket.name = "wait";
socket.send = false;
//add new client to the list
clients.push(socket);
// Handle incoming messages from clients.
socket.on('data', function (data) {
if(socket.name == "wait")
{
if (config.password !== "" && data.toString().includes(";|;"))
{
console.log("attempted connection: " + data.toString().split(";|;")[1] + "\nPassword: " +data.toString().split(";|;")[0]);
if (config.password == data.toString().split(";|;")[0])
{
for (var i = 0; i < clients.length; i++)
{
if (clients[i].name == data.toString().split(";|;")[1] || "wait" == data.toString().split(";|;")[1])
{
if (socket.address == clients[i].address)
{
console.log('duplicate from same client. Destroying old client.')
clients[i].destroy();
clients.splice(i, 1);
}
else
{
socket.write('dc:duplicate name');
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
}
}
socket.name = data.toString().split(";|;")[1];
// Send a nice welcome message and announce
socket.write(config.folder.split('/').pop()+"::"+diffIndex*100+ charIndex+";;;"); //0
socket.write(JSON.stringify(info)+";;;"); //1
socket.write(info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename+";;;"); //2
socket.write(JSON.stringify(diff)+";;;");//3
socket.write(info._songFilename+";;;"+fileSize+";;;");//4 & 5
socket.write(downloadURL +";;;" );//6
socket.send = true;
}
else
{
socket.write('dc:wrong password');
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
}
else if (config.password === "")
{
if(data.toString().includes(";|;"))
{
data = data.toString().split(";|;")[1];
}
console.log("attempted connection: " + data);
for (var i = 0; i < clients.length; i++)
{
if (clients[i].name == data || "wait" == data)
{
socket.write('dc:duplicate name');
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
}
socket.name = data.toString();
// Send a nice welcome message and announce
socket.write(config.folder.split('/').pop()+"::"+diffIndex*100+ charIndex+";;;"); //0
socket.write(JSON.stringify(info)+";;;"); //1
socket.write(info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename+";;;"); //2
socket.write(JSON.stringify(diff)+";;;");//3
socket.write(info._songFilename+";;;"+fileSize+";;;");//4 & 5
socket.write(downloadURL +";;;" );//6
socket.send = true;
}
else if (config.password !== "" && !data.toString().includes(";|;"))
{
socket.write('dc:password required');
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
else
{
socket.write('dc:uhhh something else');
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
console.log(socket.name + " joined the session.");
broadcast("System:,:sy:,:"+ socket.name + " joined the session.;:;");
}
else
{
broadcast(data.toString(), socket);
var commands = data.toString().split(";:;");
for (var i = 0; i < commands.length; i++)
{
readMessage(commands[i]);
}
}
});
// Remove the client from the list when it leaves
socket.on('end', function () {
try
{
clients.splice(clients.indexOf(socket), 1);
console.log(socket.name + " left the session.");
broadcast("System:,:sy:,:"+ socket.name + " left the session.;:;");
broadcast(socket.name + ":,:rc;:;");
}
catch(err)
{
console.log(err);
}
});
socket.on('error',function () {
try
{
clients.splice(clients.indexOf(socket), 1);
broadcast("System:,:sy:,:"+ socket.name + " left the session.;:;");
broadcast(socket.name + ":,:rc;:;");
}
catch(err)
{
console.log(err);
}
});
// Send a message to all clients
function broadcast(message, sender) {
clients.forEach(function (client) {
// Don't want to send it to sender
if (client === sender)
{
return;
}
if (client.send == false)
{
return;
}
client.write(message);
});
}
});
//Get IP address
console.log('\n\n\n');
if (downloadURL === undefined || downloadURL === "")
{
var req = request.post('https://catbox.moe/user/api.php', function (err, resp, body) {
if (err) {
console.log(err);
} else {
// var downloadInfo = JSON.parse(body)
downloadURL = body;
console.log('Download URL generated: ' + body);
https.get('https://ifconfig.co/ip', function(res){
res.setEncoding('utf8');
res.on('data', function(chunk){
server.listen(config.port, '0.0.0.0');
process.stdout.write("Server Started on IP address: ")
console.log(chunk);
});
res.on('error', function(err) {
server.listen(config.port, '0.0.0.0');
process.stdout.write("Server Started");
});
});
}
});
var form = req.form();
form.append('reqtype', 'fileupload');
form.append('fileToUpload', fs.createReadStream('./Songs/'+config.folder+'/'+info._songFilename));
}else
{
https.get('https://ifconfig.co/ip', function(res){
res.setEncoding('utf8');
res.on('data', function(chunk){
server.listen(config.port, '0.0.0.0');
process.stdout.write("Server Started on IP address: ")
console.log(chunk);
});
res.on('error', function(err) {
server.listen(config.port, '0.0.0.0');
process.stdout.write("Server Started");
});
});
}
function readMessage(message)
{
changesMade = true;
var type = message.split(":,:")[1];
switch(type)
{
case 'an':
try{
addNote(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 'rn':
try{
removeNote(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 'ae':
try{
addEvent(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 're':
try{
removeEvent(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 'aw':
try{
addWall(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 'rw':
try{
removeWall(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
case 'ab':
try{
addBookmark(message.split(':,:')[2].split("|||"));
}
catch(err){
}
break;
case 'rb':
try{
removeBookmark(message.split(':,:')[2].split(" "));
}
catch(err){
}
break;
default:
//console.log(message);
break;
}
}
function addNote(data)
{
var note = stringToNote(data)
if (!hasNull(note))
{
diff._notes.push(note);
}
}
function removeNote(data)
{
for (var j = diff._notes.length -1 ; j >= 0; j--)
{
if (sameNote(diff._notes[j],stringToNote(data)))
{
diff._notes.splice(j,1);
break;
}
}
}
function stringToNote(data)
{
return {_time: parseFloat(data[0]),
_lineIndex: parseInt(data[1]),
_lineLayer: parseInt(data[2]),
_type: parseInt(data[3]),
_cutDirection: parseInt(data[4])};
}
function sameNote(note1,note2)
{
if (Math.abs(note1._time - note2._time) > 0.001)
return false;
if (note1._lineIndex != note2._lineIndex)
return false;
if (note1._lineLayer != note2._lineLayer)
return false;
if (note1._type != note2._type)
return false;
if (note1._cutDirection != note2._cutDirection)
return false;
return true;
}
function addEvent(data)
{
if (data.length == 3)
{
var event = stringToEvent(data)
if (!hasNull(event))
{
diff._events.push(event);
}
}
else
{
var event = stringToEvent(data)
if (!hasNull(event))
{
diff._BPMChanges.push(stringToBPM(data));
}
}
}
function removeEvent(data)
{
if (data.length == 3)
{
for (var j = diff._events.length -1 ; j >= 0; j--)
{
if (sameEvent(diff._events[j],stringToEvent(data)))
{
diff._events.splice(j,1);
break;
}
}
}
else
{
for (var j = diff._BPMChanges.length -1 ; j >= 0; j--)
{
if (sameBPM(stringToBPM(data), diff._BPMChanges[j]))
{
diff._BPMChanges.splice(j,1);
}
}
}
}
function sameEvent(event1,event2)
{
if (Math.abs(event1._time - event2._time) > 0.001)
return false;
if (event1._type != event2._type)
return false;
if (event1._value != event2._value)
return false;
return true;
}
function sameBPM(event1,event2)
{
if (Math.abs(event1._BPM - event2._BPM) > 0.02)
return false;
if (Math.abs(event1._time - event2._time) > 0.001)
return false;
return true;
}
function stringToEvent(data)
{
return {
_time: parseFloat(data[0]),
_type: parseInt(data[1]),
_value: parseInt(data[2])
};
}
function stringToBPM(data)
{
return {
_BPM:parseFloat(data[0]),
_time:parseFloat(data[1]),
_beatsPerBar:parseFloat(data[2]),
_metronomeOffset:parseFloat(data[3])}
}
function addWall(data)
{
var wall = stringToWall(data)
if (!hasNull(wall))
{
diff._obstacles.push(wall);
}
}
function removeWall(data)
{
for (var j = diff._obstacles.length -1 ; j >= 0; j--)
{
if (sameWall(diff._obstacles[j],stringToWall(data)))
{
diff._obstacles.splice(j,1);
break;
}
}
}
function stringToWall(data)
{
return {_time: parseFloat(data[0]),
_lineIndex: parseInt(data[1]),
_type: parseInt(data[2]),
_duration: parseFloat(data[3]),
_width: parseInt(data[4])
};
}
function sameWall(wall1,wall2)
{
if (Math.abs(wall1._time - wall2._time) > 0.001)
return false;
if (wall1._lineIndex != wall2._lineIndex)
return false;
if (wall1._type != wall2._type)
return false;
if (Math.abs(wall1._duration - wall2._duration) > 0.001)
return false;
if (wall1._width != wall2._width)
return false;
return true;
}
function addBookmark(data)
{
diff._bookmarks.push(stringToBookmark(data));
}
function removeBookmark(data)
{
for (var j = diff._bookmarks.length - 1; j >= 0; j--)
{
if (Math.abs(diff._bookmarks[j]._time - stringToBookmark(data)._time) < 0.001)
{
diff._bookmarks.splice(j,1);
break;
}
}
}
function stringToBookmark(data)
{
return {
_time: parseFloat(data[0]),
_name: data[1]
};
}
function saveFile()
{
if (changesMade)
{
fs.writeFile('./Songs/' + config.folder + '/' + info._difficultyBeatmapSets[charIndex]._difficultyBeatmaps[diffIndex]._beatmapFilename, JSON.stringify(diff), function(err) {
if (err)
console.log(err);
else
{
console.log ("file successfully saved.\nNote Count: "+ diff._notes.length+"\nEvent Count: "+diff._events.length);
}
});
}
changesMade = false;
}
// server.getConnections(function(err,count){
// console.log(count);
// });
function disconnectSoon(socket)
{
if(socket.name == "wait" || socket.name.length > 30)
{
clients.splice(clients.indexOf(socket), 1);
socket.destroy();
return;
}
}
function hasNull(object)
{
for(var key in object) {
if (object[key] === null)
{
try
{
console.log("null object detected at :" + object._time);
}
catch(err)
{
console.log("null object detected")
}
return true;
}
}
}
function loadJSON(file) {
var data = fs.readFileSync(file);
return JSON.parse(data);
}

+ 35
- 0
Source/MediocreMapAssistant2/BPFileIO.cpp View File

@ -178,6 +178,10 @@ FString UBPFileIO::CheckAudioFormatMatches(const FString & TestPath)
return unknownProblem;
}
if (FileData.Num() < 1024) {
return unknownProblem;
}
for (int i = 0; i < 1024; i++) {
if ((FileData[i] << 8 | (FileData[i+1] & 0xF0)) == 0xFFF0) {
if (CheckFrameInfo(FileData, i, 0) != -1) {
@ -332,4 +336,35 @@ int UBPFileIO::getFileSize(const FString & File)
int UBPFileIO::getTimestamp(const FString & File)
{
return FPlatformFileManager::Get().GetPlatformFile().GetTimeStamp(*File).ToUnixTimestamp();
}
bool UBPFileIO::SaveStringTextToFile(
FString SaveDirectory,
FString JoyfulFileName,
FString SaveText,
bool AllowOverWriting
) {
if (!FPlatformFileManager::Get().GetPlatformFile().CreateDirectoryTree(*SaveDirectory))
{
//Could not make the specified directory
return false;
//~~~~~~~~~~~~~~~~~~~~~~
}
//get complete file path
SaveDirectory += "\\";
SaveDirectory += JoyfulFileName;
//No over-writing?
if (!AllowOverWriting)
{
//Check if file exists already
if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*SaveDirectory))
{
//no overwriting
return false;
}
}
return FFileHelper::SaveStringToFile(SaveText, *SaveDirectory, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
}

+ 7
- 1
Source/MediocreMapAssistant2/BPFileIO.h View File

@ -55,5 +55,11 @@ class MEDIOCREMAPASSISTANT2_API UBPFileIO : public UBlueprintFunctionLibrary
UFUNCTION(BlueprintCallable, Category = "File IO")
static int getTimestamp(const FString& File);
UFUNCTION(BlueprintCallable, Category = "File IO")
static bool SaveStringTextToFile(
FString SaveDirectory,
FString JoyfulFileName,
FString SaveText,
bool AllowOverWriting);
};

+ 1
- 1
Source/MediocreMapAssistant2/RenderWaveform.cpp View File

@ -220,7 +220,7 @@ void URenderWaveform::BP_RenderWaveform(USoundWave* InSoundWaveRef, UProceduralM
for (size_t j = 0; j < 64; ++j){
float height;
if (valid) height = results[j * 8.f] / 50000.f;
if (valid && results.Num() > (j * 8.f)) height = results[j * 8.f] / 50000.f;
else height = 0;
Vertices[To1D(i, j, SizeX)] = FVector(i, j, height);


Loading…
Cancel
Save