Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ else()
set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64")
endif()

project(AvalancheIndex VERSION 1.1.2)
project(AvalancheIndex VERSION 1.2.0)

file(GLOB_RECURSE SOURCES
src/*.cpp
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ When viewing level cells or pages, you may notice the changes in the background

Level cells with a glow emerging from the side represent levels in Avalanche's hall of fame. These levels stand out the most among the team's creations. By default, unrated or unlisted levels will not be highlighted.

If a level is featured on Avalanche's servers, you may see a button with the Avalanche logo appear on the left-hand side menu on the level's information page, or the right-hand side menu on the pause menu while playing the level. Pressing this will create a pop-up showing its showcase video thumbnail as the background, and gives more information about the level as a project by the team or its members, the type of project it is, its host, etc. You will also see a button to watch its full showcase video.
If a level is featured on Cubic's servers for Avalanche, you may see a button with the Avalanche logo appear on the left-hand side menu on the level's information page, or the right-hand side menu on the pause menu while playing the level. Pressing this will create a pop-up showing its level thumbnail as the background, and gives more information about the level as a project by the team or its members, the type of project it is, its host, etc. You will also see a button to watch its full showcase video.

---

Expand Down
6 changes: 4 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
List of versions of this mod that are currently being supported with security updates.

| Version | Supported |
| ------- | --------- |
| 1.0.x | ✅ |
| ------- | :-------: |
| 1.2.x | ✅ |
| 1.1.x | ✅ |
| 1.0.x | ❌ |

## Reporting a Vulnerability
If you discover a security vulnerability, please follow the steps below:
Expand Down
2 changes: 1 addition & 1 deletion about.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ When viewing level cells or pages, you may notice the changes in the background

Level cells with a glow emerging from the side represent levels in Avalanche's hall of fame. These levels stand out the most among the team's creations. By default, unrated or unlisted levels will not be highlighted.

If a level is featured on Avalanche's servers, you may see a button with the Avalanche logo appear on the left-hand side menu on the level's information page, or the right-hand side menu on the pause menu while playing the level. Pressing this will create a pop-up showing its showcase video thumbnail as the background, and gives more information about the level as a project by the team or its members, the type of project it is, its host, etc. You will also see a button to watch its full showcase video.
If a level is featured on Cubic's servers for Avalanche, you may see a button with the Avalanche logo appear on the left-hand side menu on the level's information page, or the right-hand side menu on the pause menu while playing the level. Pressing this will create a pop-up showing its level thumbnail as the background, and gives more information about the level as a project by the team or its members, the type of project it is, its host, etc. You will also see a button to watch its full showcase video.

---

Expand Down
20 changes: 16 additions & 4 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
## v1.2.0
#### Team Project pop-up

#### Changes
- **Updated** Geode compatibility to version `4.6.3`
- **Added** level thumbnail background to Team Project information pop-up
- **Added** promotional container for parent Team Project, if any, in information pop-up for independent levels
- **Reworked** level showcase menu in Team Project information pop-up

#### Developers
- **Updated** URLs to use Cubic Studios API endpoints for all web requests

###### Latest
---
###### Older

### v1.1.2
##### Patches

Expand All @@ -7,10 +23,6 @@
- **Added** toggle setting `Collaboration Level Pages`
- Minor tweaks

###### Latest
---
###### Older

### v1.1.1
##### Patches

Expand Down
75 changes: 49 additions & 26 deletions incl/Avalanche.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,53 +20,76 @@ namespace avalanche { // Avalanche Index mod namespace

extern int ACC_PUBLISHER; // Account ID of Avalanche's level publisher account

constexpr const char* URL_CUBIC = "https://www.cubicstudios.xyz/"; // URL to Cubic Studios's official website
constexpr const char* URL_CUBIC = "https://www.cubicstudios.xyz/"; // URL to Cubic Studios's official website
constexpr const char* URL_AVALANCHE = "https://avalanche.cubicstudios.xyz/"; // URL to Avalanche's official website

constexpr const char* URL_API_BADGES = "https://gh.cubicstudios.xyz/WebLPS/data/avalProfiles.json"; // URL to remote JSON file containing all data on profiles
constexpr const char* URL_API_LEVELS = "https://gh.cubicstudios.xyz/WebLPS/data/avalProjects.json"; // URL to remote JSON file containing all data on projects
constexpr const char* URL_API_BADGES = "https://api.cubicstudios.xyz/avalanche/v1/profiles"; // URL to remote JSON file containing all data on profiles
constexpr const char* URL_API_LEVELS = "https://api.cubicstudios.xyz/avalanche/v1/projects"; // URL to remote JSON file containing all data on projects

constexpr const char* und = "undefined";
constexpr const char* err = "404: Not Found";

// Profile class
class Profile {
public:
enum class Badge {
NONE, // No badge
CUBIC, // Staff of Cubic Studios
DIRECTOR, // Leads the whole team
MANAGER, // Helps keep things in check
MEMBER, // Participates in projects
NONE, // No badge
CUBIC, // Staff of Cubic Studios
DIRECTOR, // Leads the whole team
MANAGER, // Helps keep things in check
MEMBER, // Participates in projects
COLLABORATOR, // Non-members of the team who also worked on a project
};

static std::map<std::string, Badge> profileBadgeEnum; // Convert a string to a Badge enum

std::string name; // Official pseudonym of the member
Badge badge; // ID of the member's badge
Badge badge; // ID of the member's badge

Profile(std::string n = "Name", Badge b = Badge::NONE) : name(n), badge(b) {};
Profile(
std::string n = "Name",
Badge b = Badge::NONE
) : name(n), badge(b) {};
};

// Avalanche project class
class Project {
public:
enum class Type {
NONE, // Not a project
SOLO, // A project that a member worked on by themself
TEAM, // A project that members of the team worked on
NONE, // Not a project
SOLO, // A project that a member worked on by themself
TEAM, // A project that members of the team worked on
COLLAB, // A project that involves the work of Collaborators
EVENT, // A project that resulted from a public or private event hosted by Avalanche
EVENT, // A project that resulted from a public or private event hosted by Avalanche
};

static std::map<std::string, Type> projectTypeEnum; // Convert a string to a Type enum
// Link to the main team project
class LinkToMain {
public:
bool enabled; // If the link is enabled
int level_id; // ID of the in-game level for the linked project
};

std::string name; // Official name of the level
std::string host; // Team member that hosted the level
std::string showcase_url; // Tiny YouTube video URL of the full showcase of the level
Type type; // Type of project the level is featured as
bool fame; // If the level will be highlighted on lists
static std::map<std::string, Type> projectTypeEnum; // Convert a string to a Type enum

Project(std::string n = "Name", std::string h = "Host", std::string su = URL_AVALANCHE, Type t = Type::NONE, bool f = false) : name(n), host(h), showcase_url(su), type(t), fame(f) {};
std::string name; // Official name of the level
std::string host; // Team member that hosted the level
std::string showcase; // Tiny YouTube video URL of the full showcase of the level
std::string thumbnail; // Imgur URL for a custom thumbnail for the level
Type type; // Type of project the level is featured as
bool fame; // If the level will be highlighted on lists

LinkToMain link_to_main; // Optional link to the main team project

Project(
std::string n = "Name",
std::string h = "Host",
std::string su = URL_AVALANCHE,
std::string ct = "",
Type t = Type::NONE,
bool f = false,
LinkToMain ltm = LinkToMain()
) : name(n), host(h), showcase(su), thumbnail(ct), type(t), fame(f), link_to_main(ltm) {};
};

class Handler {
Expand All @@ -81,10 +104,10 @@ namespace avalanche { // Avalanche Index mod namespace
void scanAll();

static std::map<Profile::Badge, std::string> badgeStringID; // Convert a Badge enum to a string ID
static std::map<std::string, std::string> badgeSpriteName; // Get the sprite from the string badge ID
static std::map<std::string, ccColor3B> badgeColor; // Get the color from the string badge ID
static std::map<std::string, std::string> badgeToAPI; // Convert badge node ID to API ID
static std::map<std::string, std::string> apiToString; // Convert API-provided string to string ID
static std::map<std::string, std::string> badgeSpriteName; // Get the sprite from the string badge ID
static std::map<std::string, ccColor3B> badgeColor; // Get the color from the string badge ID
static std::map<std::string, std::string> badgeToAPI; // Convert badge node ID to API ID
static std::map<std::string, std::string> apiToString; // Convert API-provided string to string ID

// Get profile data on a player
Profile GetProfile(int id);
Expand All @@ -103,7 +126,7 @@ namespace avalanche { // Avalanche Index mod namespace
log::debug("Creating badge for {}...", profile.name);

std::string idString = avalanche::Handler::badgeStringID[profile.badge]; // gets the string equivalent
bool idFailTest = idString.empty(); // checks the map for this value to see if its invalid
bool idFailTest = idString.empty(); // checks the map for this value to see if its invalid

if (idFailTest) {
log::error("Badge is invalid.");
Expand Down
16 changes: 14 additions & 2 deletions incl/src/Avalanche.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,27 @@ namespace avalanche {
auto c_name = cacheStd["name"].asString().unwrapOr(und);
auto c_host = cacheStd["host"].asString().unwrapOr(und);
auto c_showcase = cacheStd["showcase"].asString().unwrapOr(und);
auto c_thumbnail = cacheStd["thumbnail"].asString().unwrapOr("");
auto c_type = (lType != avalanche::Project::projectTypeEnum.end()) ? lType->second : avalanche::Project::Type::NONE;
auto c_fame = cacheStd["fame"].asBool().unwrapOr(false);

avalanche::Project res(c_name, c_host, c_showcase, c_type, c_fame);
auto c_linked = cacheStd["project"];
avalanche::Project::LinkToMain ltm;

if (c_linked.isObject()) {
ltm.enabled = c_linked["enabled"].asBool().unwrapOr(false);
ltm.level_id = c_linked["id"].asInt().unwrapOr(0);
} else {
ltm.enabled = false;
ltm.level_id = 0;
};

avalanche::Project res(c_name, c_host, c_showcase, c_thumbnail, c_type, c_fame, ltm);
return res;
} else {
log::error("Project ID is invalid");

avalanche::Project res("Name", "Host", URL_AVALANCHE, avalanche::Project::Type::NONE, false);
avalanche::Project res("Name", "Host", URL_AVALANCHE, "", avalanche::Project::Type::NONE, false, avalanche::Project::LinkToMain());
return res;
};
};
Expand Down
4 changes: 2 additions & 2 deletions mod.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"geode": "4.6.2",
"geode": "4.6.3",
"gd": {
"win": "2.2074",
"android": "2.2074",
Expand All @@ -8,7 +8,7 @@
},
"id": "cubicstudios.avalancheindex",
"name": "Avalanche Index",
"version": "1.1.2",
"version": "1.2.0",
"developers": [
"Cheeseworks"
],
Expand Down
2 changes: 1 addition & 1 deletion src/headers/ParticleHelper.hpp → src/ParticleHelper.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef PARTICLEHELPER_H
#define PARTICLEHELPER_H

#include "../Debugger.hpp"
#include "./Debugger.hpp"

#include <Geode/Geode.hpp>

Expand Down
9 changes: 8 additions & 1 deletion src/headers/ProjectInfoPopup.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,32 @@ class ProjectInfoPopup : public geode::Popup<> {
ProjectInfoPopup* setProject(GJGameLevel* level);

void show() override;

protected:
std::string m_avalPublisher = "Avalanche";
std::string m_linkedPublisher = "Avalanche";
std::string m_cornerArtType = "rewardCorner_001.png";

Project m_avalProject;
Project m_linkedProject;

GJGameLevel* m_level;

CCMenu* m_overlayMenu;

CCClippingNode* m_clippingNode;

void doInfo(Project proj, std::string publisher);
void doShowcase(Project proj, std::string publisher);

void infoPopup(CCObject*);
void settingsPopup(CCObject*);

void onFameInfo(CCObject*);

void onPlayShowcase(CCObject*);

void infoPopupLinked(CCObject*);
void onPlayShowcaseLinked(CCObject*);

bool setup() override;
};
12 changes: 6 additions & 6 deletions src/headers/src/AvalancheFeatured.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ bool AvalancheFeatured::setup() {
art_bottomLeft->setID("bottom-left-corner");
art_bottomLeft->setAnchorPoint({ 0, 0 });
art_bottomLeft->setPosition({ 0, 0 });
art_bottomLeft->setScale(1.250);
art_bottomLeft->setScale(1.250f);
art_bottomLeft->setFlipX(false);
art_bottomLeft->setFlipY(false);
art_bottomLeft->setZOrder(0);
Expand All @@ -127,7 +127,7 @@ bool AvalancheFeatured::setup() {
art_bottomRight->setID("bottom-right-corner");
art_bottomRight->setAnchorPoint({ 1, 0 });
art_bottomRight->setPosition({ m_overlayMenu->getScaledContentWidth(), 0 });
art_bottomRight->setScale(1.250);
art_bottomRight->setScale(1.250f);
art_bottomRight->setFlipX(true);
art_bottomRight->setFlipY(false);
art_bottomLeft->setZOrder(0);
Expand All @@ -138,7 +138,7 @@ bool AvalancheFeatured::setup() {
art_topLeft->setID("top-left-corner");
art_topLeft->setAnchorPoint({ 0, 1 });
art_topLeft->setPosition({ 0, m_overlayMenu->getScaledContentHeight() });
art_topLeft->setScale(1.250);
art_topLeft->setScale(1.250f);
art_topLeft->setFlipX(false);
art_topLeft->setFlipY(true);
art_topLeft->setZOrder(0);
Expand All @@ -149,7 +149,7 @@ bool AvalancheFeatured::setup() {
art_topRight->setID("top-right-corner");
art_topRight->setAnchorPoint({ 1, 1 });
art_topRight->setPosition({ m_overlayMenu->getScaledContentWidth(), m_overlayMenu->getScaledContentHeight() });
art_topRight->setScale(1.250);
art_topRight->setScale(1.250f);
art_topRight->setFlipX(true);
art_topRight->setFlipY(true);
art_topRight->setZOrder(0);
Expand Down Expand Up @@ -209,7 +209,7 @@ bool AvalancheFeatured::setup() {
projThumb->setPosition({ m_mainLayer->getContentWidth() / 2.f, m_mainLayer->getContentHeight() / 2.f });

projThumb->setLoadCallback([this, projThumb](Result<> res) {
if (res) {
if (res.isOk()) {
// Success: scale and position the sprite
AVAL_LOG_INFO("Sprite loaded successfully");
} else {
Expand All @@ -223,7 +223,7 @@ bool AvalancheFeatured::setup() {
projThumb->setScale(scale);
});

projThumb->loadFromUrl("https://gh.cubicstudios.xyz/WebLPS/aval-project/thumbnail.png", LazySprite::Format::kFmtUnKnown, false);
projThumb->loadFromUrl("https://api.cubicstudios.xyz/avalanche/v1/featured/thumbnail", LazySprite::Format::kFmtUnKnown, false);
m_clippingNode->addChild(projThumb);

if (AVAL_GEODE_MOD->getSettingValue<bool>("dev-mode")) {
Expand Down
Loading