load from zip and folder ignorecase

This commit is contained in:
MrBesen 2021-06-04 13:15:13 +02:00
parent 340096b20f
commit 465f32092a
Signed by: MrBesen
GPG Key ID: 596B2350DCD67504
11 changed files with 133 additions and 7 deletions

View File

@ -22,6 +22,8 @@ protected:
const json& base;
std::vector<Note> notes;
public:
BeatLevelImpl(std::weak_ptr<BeatSet> p, std::shared_ptr<FileReader> r, const json& j);
virtual ~BeatLevelImpl();
@ -34,6 +36,7 @@ public:
virtual std::string getCustomData() const override;
//TODO: get level content
virtual const std::vector<Note>& getNotes() const override;
virtual void printDebug() const override;

View File

@ -0,0 +1,12 @@
#pragma once
#include "beatnote.h"
#include <nlohmann/json_fwd.hpp>
using json = nlohmann::json;
namespace Beatsaber {
void from_json(const json& j, Note& n);
}

View File

@ -1,8 +1,9 @@
#pragma once
#include <istream>
#include <memory>
#include <string>
#include <istream>
#include <vector>
// this classes form a abstraction to read from folders and zipfiles the same way. Maybe add other sources too?
@ -15,6 +16,7 @@ public:
virtual ~FileReader() {}
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) = 0;
virtual void getEntrys(std::vector<std::string>& out) const = 0;
};
}

View File

@ -19,6 +19,7 @@ public:
virtual ~FolderReader();
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
virtual void getEntrys(std::vector<std::string>& out) const override;
};
#if BEATSABERZIPSUPPORT == 1
@ -32,6 +33,7 @@ public:
virtual ~ZipReader();
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
virtual void getEntrys(std::vector<std::string>& out) const override;
};
#endif

View File

@ -2,7 +2,9 @@
#include <string>
#include <memory>
#include <vector>
#include "beatnote.h"
#include "difficulties.h"
namespace Beatsaber {
@ -24,6 +26,7 @@ public:
virtual std::string getCustomData() const = 0;
//TODO: get level content
virtual const std::vector<Note>& getNotes() const = 0;
virtual void printDebug() const = 0;

View File

@ -0,0 +1,15 @@
#pragma once
#include <cstdint>
namespace Beatsaber {
struct Note {
std::uint32_t time; //time in beats when the note reaches the player
std::uint_fast8_t line; //colum, 0 = most left, 3 = most right
std::uint_fast8_t layer; //layer 0 = bottom, 2 = top
std::uint_fast8_t type; //0 = rednote, 1 = bluenote, 2 = unused, 3 = bomb
std::uint_fast8_t cutdir;
};
}

View File

@ -4,6 +4,7 @@
#include <nlohmann/json.hpp>
#include "beatset.h"
#include "beatnoteimpl.h"
namespace Beatsaber {
@ -18,9 +19,23 @@ BeatLevelImpl::BeatLevelImpl(std::weak_ptr<BeatSet> p, std::shared_ptr<FileReade
if(!filename.empty()) {
try {
std::shared_ptr<std::istream> stream = r->getFileStream(filename);
json json;
(*stream) >> json;
//TODO
json diffjson;
(*stream) >> diffjson;
const std::string& version = diffjson["_version"];
if(version != "2.0.0") {
//not supported
return;
}
//load notes
const json& jnotes = diffjson["_notes"];
if(jnotes.is_array()) {
notes.reserve(jnotes.size());
for(const json& note : jnotes) {
notes.push_back(note);
}
}
} catch(...) {
std::cout << "Could not load difficulty: " << filename << std::endl;
}
@ -56,11 +71,16 @@ std::string BeatLevelImpl::getCustomData() const {
return "";
}
const std::vector<Note>& BeatLevelImpl::getNotes() const {
return notes;
}
void BeatLevelImpl::printDebug() const {
std::cout <<
" Difficulty: " << Difficulty::toString(dif) << " (" << diffRank << ")"
<< "\n Filename: " << getFilename()
<< "\n njs: " << getNoteJumpSpeed() << " nso: " << getNoteStartOffset()
<< "\n noteCount: " << notes.size()
<< std::endl;
}

View File

@ -9,7 +9,7 @@ namespace Beatsaber {
bool BeatMapImpl::load() {
// try to open info.dat
std::shared_ptr<std::istream> stream = reader->getFileStream("info.dat");
std::shared_ptr<std::istream> stream = reader->getFileStream("Info.dat");
try {
(*stream) >> infobase;

15
src/beatnote.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "beatnoteimpl.h"
#include <nlohmann/json.hpp>
namespace Beatsaber {
void from_json(const json& j, Note& n) {
n.time = j["_time"];
n.line = j["_lineIndex"];
n.layer = j["_lineLayer"];
n.type = j["_type"];
n.cutdir = j["_cutDirection"];
}
}

View File

@ -1,9 +1,19 @@
#include "filereaderimpl.h"
#include <cstring>
#include <fstream>
#include <filesystem> //c++17 required
namespace Beatsaber {
static const std::string* findbest(const std::vector<std::string>& haystack, const std::string& needle) {
for(const auto& it : haystack) {
if(it == needle) return &it;
if(strcasecmp(it.c_str(), needle.c_str()) == 0) return &it;
}
return nullptr;
}
FolderReader::FolderReader(const std::string& path) : path(path) {
// make path end with /
@ -13,10 +23,29 @@ FolderReader::FolderReader(const std::string& path) : path(path) {
FolderReader::~FolderReader() {}
std::shared_ptr<std::istream> FolderReader::getFileStream(const std::string& filename) {
std::shared_ptr<std::istream> stream = std::make_shared<std::ifstream>(path + filename);
std::shared_ptr<std::ifstream> stream = std::make_shared<std::ifstream>(path + filename);
if(!stream->is_open()) {
//search for other files
std::vector<std::string> entrys;
getEntrys(entrys);
const std::string* best = findbest(entrys, filename);
if(best) {
return std::make_shared<std::ifstream>(path + *best);
}
}
return stream;
}
void FolderReader::getEntrys(std::vector<std::string>& out) const {
for(const auto& i : std::filesystem::directory_iterator(path)) {
if(i.is_regular_file() && i.exists()) {
std::string filename = i.path().filename();
if(!filename.empty() && filename[0] != '.') { //ignore dotfiles
out.push_back(filename);
}
}
}
}
#if BEATSABERZIPSUPPORT == 1
@ -27,7 +56,29 @@ ZipReader::~ZipReader() {
}
std::shared_ptr<std::istream> ZipReader::getFileStream(const std::string& filename) {
return file.getInputStream(filename);
std::shared_ptr<std::istream> stream = file.getInputStream(filename);
if(stream) {
//search for other files
std::vector<std::string> entrys;
getEntrys(entrys);
const std::string* best = findbest(entrys, filename);
if(best) {
return file.getInputStream(*best);
}
}
return stream;
}
void ZipReader::getEntrys(std::vector<std::string>& out) const {
const auto entr = file.entries();
out.reserve(entr.size());
for(auto it : entr) {
if(!it->isDirectory() && it->isValid()) {
out.push_back(it->getFileName());
}
}
}
#endif

View File

@ -33,6 +33,9 @@ int main(int argc, char** argv) {
std::shared_ptr<Beatsaber::BeatMap> bmap = Beatsaber::BeatMap::loadFromFolder("/home/yannis/Nextcloud/yannis/Beatsaber/BeatSaverLevel/1dd (Portal - Still Alive (Uppermost Remix) - kryptikos)");
if(!bmap) std::cout << "Could not load File" << std::endl;
else bmap->printDebug();
bmap = Beatsaber::BeatMap::loadFromZip("/home/yannis/Nextcloud/yannis/Beatsaber/BeatSaverLevel/18b92 (Empress of Light - ShadowLantern).zip");
if(!bmap) std::cout << "Could not load File" << std::endl;
else bmap->printDebug();
return failcount > 0;
}