reading basic structure
This commit is contained in:
parent
37edb342fa
commit
fd6f908671
31
Makefile
31
Makefile
|
@ -7,7 +7,7 @@
|
|||
|
||||
NAME = libBeatsaber.a
|
||||
NAMETEST = test
|
||||
CFLAGS = -std=c++17 -O2 -pipe -Wall -Wextra -Wno-unused-parameter -Wpedantic -rdynamic
|
||||
CFLAGS = -std=c++17 -O2 -pipe -Wall -Wextra -Wno-unused-parameter -Wpedantic -rdynamic -g
|
||||
CXX = g++
|
||||
SRCF = src/
|
||||
BUILDDIR = build/
|
||||
|
@ -20,25 +20,38 @@ INCLUDES = $(addprefix -I, $(INCFS))
|
|||
LDFLAGS =
|
||||
|
||||
SRCFILES = $(shell find $(SRCF) -name "*.cpp")
|
||||
OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.cpp, %.o, $(SRCFILES))) $(LOGO)
|
||||
OBJFILES = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(patsubst %.cpp, %.o, $(SRCFILES)))
|
||||
DEPFILES = $(wildcard $(DEPF)*.d)
|
||||
|
||||
SOURCEDIRS = $(shell find $(SRCF) -type d -printf "%p/\n")
|
||||
BUILDDIRS = $(patsubst $(SRCF)%, $(BUILDDIR)%, $(SOURCEDIRS))
|
||||
|
||||
OBJFILESTEST = $(OBJFILES)
|
||||
|
||||
INCLUDES += $(addprefix -I, $(SOURCEDIRS))
|
||||
|
||||
# FEATURES
|
||||
|
||||
# zipFile support
|
||||
DEFINES += -DBEATSABERZIPSUPPORT=1
|
||||
|
||||
# link zipios dynamic
|
||||
LDFLAGS += -lzipios
|
||||
|
||||
# OR link zipios static (path to static lib)
|
||||
#OBJFILES += /usr/local/lib/libzipios.a
|
||||
#LDFLAGS += -lz #libzlib is still required dynamic
|
||||
|
||||
|
||||
OBJFILESTEST = $(OBJFILES)
|
||||
|
||||
all: $(NAME) runtest
|
||||
|
||||
$(NAME): | $(BUILDDIRS) $(DEPF) $(OBJFILES)
|
||||
$(NAME): $(OBJFILES) | $(BUILDDIRS) $(DEPF)
|
||||
@$(AR) rvs $@ $(filter %.o, $^)
|
||||
|
||||
$(BUILDDIR)%.o: $(SRCF)%.cpp
|
||||
$(BUILDDIR)%.o: $(SRCF)%.cpp | $(BUILDDIRS) $(DEPF)
|
||||
@echo "Compiling: $@"
|
||||
@$(CXX) $(CFLAGS) $(INCLUDES) $< -MM -MT $@ > $(DEPF)$(subst /,_,$*).d
|
||||
@$(CXX) -c -o $@ $(CFLAGS) $(INCLUDES) $<
|
||||
@$(CXX) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -MM -MT $@ > $(DEPF)$(subst /,_,$*).d
|
||||
@$(CXX) -c -o $@ $(CFLAGS) $(DEFINES) $(INCLUDES) $<
|
||||
|
||||
%/:
|
||||
mkdir -p $@
|
||||
|
@ -51,7 +64,7 @@ clean:
|
|||
|
||||
$(NAMETEST): $(BUILDDIRS) $(DEPF) $(TESTF)*.cpp $(OBJFILESTEST) $(NAME)
|
||||
@echo "Compiling tests"
|
||||
@$(CXX) -o $@ $(filter %.o, $^) $(filter %.cpp, $^) $(filter %.a, $^) $(CFLAGS) $(INCLUDES) $(LDFLAGS)
|
||||
@$(CXX) -o $@ $(filter %.o, $^) $(filter %.cpp, $^) $(filter %.a, $^) $(CFLAGS) $(DEFINES) $(INCLUDES) $(LDFLAGS)
|
||||
|
||||
runtest: $(NAMETEST)
|
||||
@echo "Running tests"
|
||||
|
|
|
@ -8,7 +8,7 @@ using json = nlohmann::json;
|
|||
|
||||
namespace Beatsaber {
|
||||
|
||||
class BeatLevelImpl : public BeatLevel, protected std::enable_shared_from_this<BeatLevelImpl> {
|
||||
class BeatLevelImpl : public BeatLevel, public std::enable_shared_from_this<BeatLevelImpl> {
|
||||
protected:
|
||||
std::weak_ptr<BeatSet> parent;
|
||||
|
||||
|
@ -34,6 +34,8 @@ public:
|
|||
|
||||
//TODO: get level content
|
||||
|
||||
virtual void printDebug() const override;
|
||||
|
||||
virtual std::shared_ptr<BeatSet> getBeatSet() const override;
|
||||
virtual std::shared_ptr<BeatMap> getBeatMap() const override;
|
||||
};
|
||||
|
|
|
@ -11,7 +11,7 @@ using json = nlohmann::json;
|
|||
|
||||
namespace Beatsaber {
|
||||
|
||||
class BeatMapImpl : public BeatMap, protected std::enable_shared_from_this<BeatMapImpl> {
|
||||
class BeatMapImpl : public BeatMap, public std::enable_shared_from_this<BeatMapImpl> {
|
||||
|
||||
protected:
|
||||
const std::string path;
|
||||
|
@ -50,8 +50,8 @@ public:
|
|||
|
||||
virtual void printDebug() const override;
|
||||
|
||||
friend std::unique_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath);
|
||||
friend std::unique_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath);
|
||||
friend std::shared_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath);
|
||||
friend std::shared_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -6,12 +6,13 @@ using json = nlohmann::json;
|
|||
|
||||
namespace Beatsaber {
|
||||
|
||||
class BeatSetImpl : public BeatSet, protected std::enable_shared_from_this<BeatSetImpl> {
|
||||
class BeatSetImpl : public BeatSet, public std::enable_shared_from_this<BeatSetImpl> {
|
||||
protected:
|
||||
|
||||
std::weak_ptr<BeatMap> parent;
|
||||
BeatmapCharacteristic::BeatmapCharacteristic characteristic;
|
||||
|
||||
std::vector<std::shared_ptr<BeatLevel>> level;
|
||||
|
||||
public:
|
||||
BeatSetImpl(std::weak_ptr<BeatMap> p, const json& j);
|
||||
|
@ -19,6 +20,8 @@ public:
|
|||
BeatSetImpl() = default;
|
||||
virtual ~BeatSetImpl();
|
||||
|
||||
virtual void printDebug() const override;
|
||||
|
||||
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const override;
|
||||
virtual std::shared_ptr<BeatMap> getBeatMap() const override;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <istream>
|
||||
|
||||
|
||||
// this classes form a abstraction to read from folders and zipfiles the same way. Maybe add other sources too?
|
||||
|
||||
namespace Beatsaber {
|
||||
|
||||
//Interface
|
||||
class FileReader {
|
||||
public:
|
||||
virtual ~FileReader() {}
|
||||
|
||||
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "filereader.h"
|
||||
|
||||
#if BEATSABERZIPSUPPORT == 1
|
||||
#include <zipios/zipfile.hpp>
|
||||
#endif
|
||||
|
||||
namespace Beatsaber {
|
||||
|
||||
//implementation for folders
|
||||
class FolderReader : public FileReader {
|
||||
protected:
|
||||
std::string path;
|
||||
|
||||
public:
|
||||
FolderReader(const std::string& path);
|
||||
virtual ~FolderReader();
|
||||
|
||||
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
|
||||
};
|
||||
|
||||
#if BEATSABERZIPSUPPORT == 1
|
||||
//implementation for zipfiles
|
||||
class ZipReader : public FileReader {
|
||||
protected:
|
||||
zipios::ZipFile file;
|
||||
|
||||
public:
|
||||
ZipReader(const std::string& path);
|
||||
virtual ~ZipReader();
|
||||
|
||||
virtual std::shared_ptr<std::istream> getFileStream(const std::string& filename) override;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
|
@ -25,6 +25,8 @@ public:
|
|||
|
||||
//TODO: get level content
|
||||
|
||||
virtual void printDebug() const = 0;
|
||||
|
||||
virtual std::shared_ptr<BeatSet> getBeatSet() const = 0; // parent
|
||||
virtual std::shared_ptr<BeatMap> getBeatMap() const = 0; // grandparent
|
||||
|
||||
|
|
|
@ -40,8 +40,8 @@ public:
|
|||
|
||||
virtual void printDebug() const = 0;
|
||||
|
||||
static std::unique_ptr<BeatMap> loadFromFolder(const std::string& folderPath);
|
||||
static std::unique_ptr<BeatMap> loadFromZip(const std::string& zipPath);
|
||||
static std::shared_ptr<BeatMap> loadFromFolder(const std::string& folderPath);
|
||||
static std::shared_ptr<BeatMap> loadFromZip(const std::string& zipPath);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -20,5 +20,7 @@ namespace Beatsaber {
|
|||
const std::uint8_t characteristicsNameSize = sizeof(characteristicsName)/sizeof(std::string);
|
||||
|
||||
BeatmapCharacteristic getByString(const std::string& str);
|
||||
|
||||
const std::string& toString(BeatmapCharacteristic c);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@ class BeatSet {
|
|||
public:
|
||||
virtual ~BeatSet() {}
|
||||
|
||||
virtual void printDebug() const = 0;
|
||||
|
||||
virtual BeatmapCharacteristic::BeatmapCharacteristic getCharacteristic() const = 0;
|
||||
virtual std::shared_ptr<BeatMap> getBeatMap() const = 0;
|
||||
};
|
||||
|
|
|
@ -17,5 +17,8 @@ namespace Beatsaber {
|
|||
const std::uint8_t difficultyNameSize = sizeof(difficultyName)/sizeof(std::string);
|
||||
|
||||
Difficulty getByString(const std::string& str);
|
||||
|
||||
const std::string& toString(Difficulty d);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#include "beatlevelimpl.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "beatset.h"
|
||||
|
@ -48,6 +49,14 @@ std::string BeatLevelImpl::getCustomData() const {
|
|||
return "";
|
||||
}
|
||||
|
||||
void BeatLevelImpl::printDebug() const {
|
||||
std::cout <<
|
||||
" Difficulty: " << Difficulty::toString(dif) << " (" << diffRank << ")"
|
||||
<< "\n Filename: " << getFilename()
|
||||
<< "\n njs: " << getNoteJumpSpeed() << " nso: " << getNoteStartOffset()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
std::shared_ptr<BeatSet> BeatLevelImpl::getBeatSet() const {
|
||||
return parent.lock();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ bool BeatMapImpl::load() {
|
|||
try {
|
||||
info >> infobase;
|
||||
|
||||
|
||||
//load the beatset
|
||||
const json& beatsets = infobase["_difficultyBeatmapSets"];
|
||||
if(beatsets.is_array()) {
|
||||
|
@ -24,12 +23,14 @@ bool BeatMapImpl::load() {
|
|||
|
||||
//load all the beatsets
|
||||
for(const json& jsonbeatset : beatsets) {
|
||||
beatSets.push_back(std::make_shared<BeatSetImpl>(shared_from_this(), jsonbeatset));
|
||||
beatSets.push_back(std::make_shared<BeatSetImpl>(weak_from_this(), jsonbeatset));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch(...) {} //catch any json errors
|
||||
} catch(const nlohmann::detail::exception& e) { //catch any json errors
|
||||
std::cout << "Could not Read BeatMap: " << e.what() << std::endl;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -132,30 +133,40 @@ std::shared_ptr<BeatSet> BeatMapImpl::getBeatSet(BeatmapCharacteristic::BeatmapC
|
|||
|
||||
void BeatMapImpl::printDebug() const {
|
||||
std::cout << "SongName: " << getSongName() << " - " << getSongAuthorName() << " (" << getSubName() << ")"
|
||||
<< "\nMapper: " << getMapperName()
|
||||
<< "\nVersion: " << getVersion()
|
||||
<< "\nBPM: " << getBPM() << " offset: " << getTimeOffset()
|
||||
<< "\nSchuffle " << getSchuffle() << " period: " << getSchufflePeriod()
|
||||
<< "\nPreviewStart: " << getPreviewStart() << " duration: " << getPreviewDuration()
|
||||
<< "\nSongFile: " << getSongFilename()
|
||||
<< "\nImageFile: " << getImageFilename()
|
||||
<< "\nEnvName: " << getEnvName() << " 360Env: " << get360EnvName()
|
||||
<< "\ncustomData: " << getCustomData()
|
||||
<< "\nBeatSetCount: " << getBeatSetCount()
|
||||
<< "\n Mapper: " << getMapperName()
|
||||
<< "\n Version: " << getVersion()
|
||||
<< "\n BPM: " << getBPM() << " offset: " << getTimeOffset()
|
||||
<< "\n Schuffle " << getSchuffle() << " period: " << getSchufflePeriod()
|
||||
<< "\n PreviewStart: " << getPreviewStart() << " duration: " << getPreviewDuration()
|
||||
<< "\n SongFile: " << getSongFilename()
|
||||
<< "\n ImageFile: " << getImageFilename()
|
||||
<< "\n EnvName: " << getEnvName() << " 360Env: " << get360EnvName()
|
||||
<< "\n customData: " << getCustomData()
|
||||
<< "\n BeatSetCount: " << getBeatSetCount()
|
||||
<< std::endl;
|
||||
|
||||
for(auto it : beatSets) {
|
||||
it->printDebug();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath) {
|
||||
auto map = std::make_unique<BeatMapImpl>(folderPath, false);
|
||||
std::shared_ptr<BeatMap> BeatMap::loadFromFolder(const std::string& folderPath) {
|
||||
auto map = std::make_shared<BeatMapImpl>(folderPath, false);
|
||||
if(!map->load()) return nullptr;
|
||||
return map;
|
||||
}
|
||||
|
||||
std::unique_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath) {
|
||||
auto map = std::make_unique<BeatMapImpl>(zipPath, true);
|
||||
std::shared_ptr<BeatMap> BeatMap::loadFromZip(const std::string& zipPath) {
|
||||
#if BEATSABERZIPSUPPORT == 1
|
||||
auto map = std::make_shared<BeatMapImpl>(zipPath, true);
|
||||
if(!map->load()) return nullptr;
|
||||
return map;
|
||||
#else
|
||||
// Zip not supported
|
||||
std::cerr << "Zip not supported" << std::endl;
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,41 @@
|
|||
#include "beatsetimpl.h"
|
||||
|
||||
#include <iostream> //debug print
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "beatlevelimpl.h"
|
||||
|
||||
namespace Beatsaber {
|
||||
|
||||
BeatSetImpl::BeatSetImpl(std::weak_ptr<BeatMap> p, const json& j) : parent(p), characteristic(BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"])) {
|
||||
BeatSetImpl::BeatSetImpl(std::weak_ptr<BeatMap> p, const json& j) : parent(p) {
|
||||
try {
|
||||
characteristic = BeatmapCharacteristic::getByString(j["_beatmapCharacteristicName"]);
|
||||
|
||||
//load level
|
||||
const json& arr = j["_difficultyBeatmaps"];
|
||||
if(arr.is_array()) {
|
||||
level.reserve(arr.size());
|
||||
std::cout << "Try to load: " << arr.size() << std::endl;
|
||||
for(const json& beat : arr) {
|
||||
level.push_back(std::make_shared<BeatLevelImpl>(weak_from_this(), beat));
|
||||
}
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "Could not read BeatSet: " << e.what() << std::endl;
|
||||
characteristic = BeatmapCharacteristic::NONE;
|
||||
}
|
||||
}
|
||||
|
||||
BeatSetImpl::~BeatSetImpl() {}
|
||||
|
||||
void BeatSetImpl::printDebug() const {
|
||||
std::cout << " Characteristic: " << BeatmapCharacteristic::toString(characteristic) << std::endl;
|
||||
|
||||
for(auto it : level) {
|
||||
it->printDebug();
|
||||
}
|
||||
}
|
||||
|
||||
BeatmapCharacteristic::BeatmapCharacteristic BeatSetImpl::getCharacteristic() const {
|
||||
return characteristic;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,12 @@ BeatmapCharacteristic getByString(const std::string& str) {
|
|||
return BeatmapCharacteristic::NONE;
|
||||
}
|
||||
|
||||
const std::string& toString(BeatmapCharacteristic c) {
|
||||
uint8_t ic = (uint8_t) c;
|
||||
if(ic >= characteristicsNameSize) return characteristicsName[0]; //none
|
||||
return characteristicsName[ic];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Difficulty {
|
||||
|
@ -24,5 +30,12 @@ Difficulty getByString(const std::string& str) {
|
|||
}
|
||||
return Difficulty::NONE;
|
||||
}
|
||||
|
||||
const std::string& toString(Difficulty d) {
|
||||
uint8_t id = (uint8_t) d;
|
||||
if(id >= difficultyNameSize) return difficultyName[0]; //none
|
||||
return difficultyName[id];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#include "filereaderimpl.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace Beatsaber {
|
||||
|
||||
|
||||
FolderReader::FolderReader(const std::string& path) : path(path) {
|
||||
// make path end with /
|
||||
if(path.rfind('/') != path.size()-1)
|
||||
this->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);
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if BEATSABERZIPSUPPORT == 1
|
||||
ZipReader::ZipReader(const std::string& path) : file(path) {}
|
||||
|
||||
ZipReader::~ZipReader() {
|
||||
file.close();
|
||||
}
|
||||
|
||||
std::shared_ptr<std::istream> ZipReader::getFileStream(const std::string& filename) {
|
||||
return file.getInputStream(filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
|
@ -30,7 +30,7 @@ int main(int argc, char** argv) {
|
|||
printf("\033[1;93m%d\033[0;1m/%d failed\n", failcount, testcount);
|
||||
|
||||
//simple read test
|
||||
std::unique_ptr<Beatsaber::BeatMap> bmap = Beatsaber::BeatMap::loadFromFolder("/media/satassd/steam/steamapps/common/Beat Saber/Beat Saber_Data/CustomLevels/1dd (Portal - Still Alive (Uppermost Remix) - kryptikos)");
|
||||
std::shared_ptr<Beatsaber::BeatMap> bmap = Beatsaber::BeatMap::loadFromFolder("/media/satassd/steam/steamapps/common/Beat Saber/Beat Saber_Data/CustomLevels/1dd (Portal - Still Alive (Uppermost Remix) - kryptikos)");
|
||||
if(!bmap) std::cout << "Could not load File" << std::endl;
|
||||
else bmap->printDebug();
|
||||
|
||||
|
|
Loading…
Reference in New Issue