Skip to content

Commit 0c44eef

Browse files
Merge pull request #4 from thetrueoneshots/re-callbacks
Add a modwiget
2 parents e1c1299 + c30af18 commit 0c44eef

File tree

11 files changed

+704
-34
lines changed

11 files changed

+704
-34
lines changed

CubeModLoader/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ add_library (CubeModLoader SHARED
55
crc.cpp
66
DLL.cpp
77
main.cpp
8-
mutex.cpp "macros.h" "callbacks/gui/cube__StartMenuWidget__Draw.h" "callbacks/game/cube__Game__MouseUp.h")
8+
mutex.cpp "macros.h" "callbacks/gui/cube__StartMenuWidget__Draw.h" "callbacks/game/cube__Game__MouseUp.h" "callbacks/gui/cube__GUI__Load.h" "ModWidget.h" "ModWidget.cpp")
99
target_link_libraries (CubeModLoader LINK_PUBLIC CWSDK)

CubeModLoader/CWSDK

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
Subproject commit 6c3c518adec22d591721b96e1d38db5490f6010e
1+
Subproject commit 6a8ea237e2351dc296ba43d7f5093bb97fe1aa5b

CubeModLoader/DLL.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
DLL::DLL(std::string fileName) {
55
this->fileName = fileName;
66
this->handle = nullptr;
7+
this->enabled = true;
78
}
89

910
HMODULE DLL::Load() {

CubeModLoader/DLL.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ class DLL
1818
FARPROC MakeMod;
1919

2020
GenericMod* mod;
21+
bool enabled;
2122

2223
DLL(std::string fileName);
2324
HMODULE Load();

CubeModLoader/ModWidget.cpp

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
#include "ModWidget.h"
2+
#include <iostream>
3+
#include <fstream>
4+
#include <process.h>
5+
6+
static std::string file_name = "mods-settings.cwb";
7+
static const int MODS_PER_PAGE = 7;
8+
void* VTABLE[43];
9+
10+
mod::ModWidget* mod::ModWidget::ctor(cube::Game* game, plasma::Node* node, plasma::Node* background, std::vector<DLL*>* mods)
11+
{
12+
// Construct basewidget
13+
std::wstring wstr_empty(L"");
14+
((cube::BaseWidget*)this)->ctor(game->plasma_engine, node, &wstr_empty);
15+
16+
// Set fields
17+
this->game = game;
18+
this->hover_state = 0;
19+
this->background = background;
20+
this->mods = mods;
21+
this->page = 0;
22+
this->changed = false;
23+
24+
// Set scalable font
25+
std::wstring fontName(L"resource1.dat");
26+
this->SetScalableFont(&fontName);
27+
this->Translate(100, 200, 1);
28+
29+
for (int i = 0; i < 43; ++i)
30+
{
31+
this->artificial_vtable[i] = VTABLE[i];
32+
}
33+
34+
// Manually set vtable
35+
size_t* vptr = (size_t*)this;
36+
*vptr = (size_t)this->artificial_vtable; //(size_t)CWOffset(0x46CED8);
37+
38+
return this;
39+
}
40+
41+
void mod::ModWidget::MouseUp(cube::MouseButton mouse_button)
42+
{
43+
if (mouse_button != cube::MouseButton::LeftMouseButton)
44+
{
45+
return;
46+
}
47+
48+
switch (this->hover_state)
49+
{
50+
case HoverState::Exit:
51+
this->node->SetVisibility(false);
52+
if (this->changed)
53+
{
54+
// Restart the game
55+
char* argument_list[] = { (char *)"cubeworld.exe", NULL };
56+
_execvp("cubeworld.exe", argument_list);
57+
}
58+
break;
59+
case HoverState::Toggle:
60+
if (this->selected < 0 || this->selected >= this->mods->size())
61+
{
62+
return;
63+
}
64+
this->mods->at(this->selected)->enabled = !this->mods->at(this->selected)->enabled;
65+
ModWidget::StoreSave(this->mods);
66+
this->changed = true;
67+
break;
68+
case HoverState::Next:
69+
if (this->NextPageAvailable())
70+
{
71+
this->page++;
72+
}
73+
break;
74+
case HoverState::Previous:
75+
if (this->PreviousPageAvailable())
76+
{
77+
this->page--;
78+
}
79+
break;
80+
default:
81+
82+
break;
83+
}
84+
}
85+
86+
bool mod::ModWidget::NextPageAvailable()
87+
{
88+
return (this->page + 1) * MODS_PER_PAGE < this->mods->size();
89+
}
90+
91+
bool mod::ModWidget::PreviousPageAvailable()
92+
{
93+
return this->page > 0;
94+
}
95+
96+
void mod::ModWidget::Draw(ModWidget* widget)
97+
{
98+
const static float text_size = 18.0f; // Original 18.0f
99+
const static float border_size = 4.0f; // Original 4.0f
100+
const static float title_size = 25.0f;
101+
102+
cube::Game* game = widget->game;
103+
104+
FloatRGBA text_color(1.0f, 1.0f, 1.0f, 1.0f);
105+
FloatRGBA hover_color(0.2f, 1.0f, 1.0f, 1.0f);
106+
FloatRGBA warn_color(1.0f, 0.65f, 0.0f, 1.0f);
107+
FloatRGBA disabled_color(1.0f, 1.0f, 1.0f, 0.2f);
108+
FloatRGBA border_color(0.0f, 0.0f, 0.0f, 1.0f);
109+
110+
FloatVector2 mouse_pos;
111+
FloatVector2 pos(0, 0);
112+
FloatVector2 size(500, 500);
113+
114+
std::wstring wstr_title(L"Mods");
115+
std::wstring wstr_reminder(L"If you change something \n the game restarts to \n reload all the mods!");
116+
std::wstring wstr_next(L">");
117+
std::wstring wstr_prev(L"<");
118+
std::wstring wstr_x(L"X");
119+
120+
// Translate background and node
121+
widget->node->Translate(game->width/2, game->height/2, -size.x/2, -size.y/2);
122+
widget->background->Translate(game->width / 2, game->height / 2, -size.x / 2, -size.y / 2);
123+
124+
// Scale background and node
125+
widget->SetSize(&size);
126+
widget->background->widget1->SetSize(&size);
127+
128+
// Get mouse position in the widget
129+
mouse_pos = *widget->GetRelativeMousePosition(&mouse_pos);
130+
131+
// Set hover to 0
132+
widget->hover_state = ModWidget::HoverState::None;
133+
134+
// Text settings
135+
widget->SetTextSize(text_size);
136+
widget->SetTextColor(&text_color);
137+
widget->SetBorderSize(border_size);
138+
widget->SetBorderColor(&border_color);
139+
widget->SetTextPivot(plasma::TextPivot::Center);
140+
141+
// Draw title
142+
widget->SetTextSize(title_size);
143+
widget->DrawString(&pos, &wstr_title, size.x/2, 20 + text_size);
144+
145+
// Draw x to exit
146+
widget->SetTextPivot(plasma::TextPivot::Right);
147+
if (plasma::Widget::IsSquareHovered(&mouse_pos, size.x - 30, 20, 20, 30))
148+
{
149+
widget->SetTextColor(&hover_color);
150+
widget->hover_state = ModWidget::HoverState::Exit;
151+
}
152+
widget->DrawString(&pos, &wstr_x, size.x - 10, 20 + text_size);
153+
154+
// Draw reminder
155+
widget->SetTextColor(&warn_color);
156+
widget->SetTextSize(text_size - 5);
157+
widget->SetTextPivot(plasma::TextPivot::Center);
158+
widget->DrawString(&pos, &wstr_reminder, size.x / 2, 2 * (10 + text_size));
159+
160+
// Draw mods
161+
int y_count = 0;
162+
163+
for (int i = widget->page * 7; i < (widget->page + 1)*7 && i < widget->mods->size(); i++)
164+
{
165+
DLL* dll = widget->mods->at(i);
166+
widget->SetTextPivot(plasma::TextPivot::Left);
167+
widget->SetTextColor(&text_color);
168+
if (!dll->enabled)
169+
{
170+
widget->SetTextColor(&disabled_color);
171+
}
172+
173+
int y_pos = (4 + 2 * y_count) * (10 + text_size);
174+
if (plasma::Widget::IsSquareHovered(&mouse_pos, 0, y_pos - 20, size.x, 30))
175+
{
176+
widget->SetTextColor(&hover_color);
177+
widget->hover_state = HoverState::Toggle;
178+
widget->selected = i;
179+
}
180+
std::wstring name = L"- " + std::wstring(dll->fileName.begin() + 5, dll->fileName.end());
181+
if (name.size() > 45)
182+
{
183+
name = name.substr(0, 42) + L"...";
184+
}
185+
widget->DrawString(&pos, &name, 20, y_pos);
186+
187+
y_count++;
188+
if (y_pos > size.y - 2 * (10 + text_size))
189+
{
190+
break;
191+
}
192+
}
193+
194+
// Draw prev button
195+
widget->SetTextColor(&text_color);
196+
if (!widget->PreviousPageAvailable())
197+
{
198+
widget->SetTextColor(&disabled_color);
199+
}
200+
else if (plasma::Widget::IsSquareHovered(&mouse_pos, 20, size.y - text_size - 20, 20, 30))
201+
{
202+
widget->hover_state = HoverState::Previous;
203+
widget->SetTextColor(&hover_color);
204+
}
205+
widget->DrawString(&pos, &wstr_prev, 20, size.y - text_size);
206+
207+
// Draw next button
208+
widget->SetTextPivot(plasma::TextPivot::Right);
209+
widget->SetTextColor(&text_color);
210+
211+
if (!widget->NextPageAvailable())
212+
{
213+
widget->SetTextColor(&disabled_color);
214+
}
215+
else if (plasma::Widget::IsSquareHovered(&mouse_pos, size.x - text_size - 20, size.y - text_size - 20, 20, 30))
216+
{
217+
widget->hover_state = HoverState::Next;
218+
widget->SetTextColor(&hover_color);
219+
}
220+
widget->DrawString(&pos, &wstr_next, size.x - 20, size.y - text_size);
221+
222+
// Draw current page
223+
widget->SetTextColor(&text_color);
224+
widget->SetTextPivot(plasma::TextPivot::Center);
225+
std::wstring page = std::to_wstring(widget->page + 1) + L"/" + std::to_wstring((int)(widget->mods->size() / MODS_PER_PAGE) + 1);
226+
widget->DrawString(&pos, &page, size.x / 2, size.y - text_size);
227+
}
228+
229+
void mod::ModWidget::Init()
230+
{
231+
void* NULLSUB = CWOffset(0xE8A20);
232+
void* RETZERO = CWOffset(0x368230);
233+
234+
void* vtab[43] = {
235+
CWOffset(0x268B40),
236+
Draw, // void Draw(plasma::Widget*)
237+
CWOffset(0x26A720),
238+
CWOffset(0x26A720),
239+
RETZERO,
240+
RETZERO,
241+
NULLSUB,
242+
CWOffset(0x32B830),
243+
CWOffset(0x32BFD0),
244+
CWOffset(0x32BD70),
245+
NULLSUB,
246+
CWOffset(0x32B990),
247+
CWOffset(0x32BB40),
248+
NULLSUB,
249+
NULLSUB,
250+
NULLSUB,
251+
NULLSUB,
252+
NULLSUB,
253+
NULLSUB,
254+
NULLSUB,
255+
NULLSUB,
256+
CWOffset(0x32BB80), // void OnMouseOver(plasma::Widget*)
257+
NULLSUB,
258+
NULLSUB,
259+
NULLSUB,
260+
NULLSUB,
261+
NULLSUB,
262+
NULLSUB,
263+
NULLSUB,
264+
NULLSUB,
265+
NULLSUB,
266+
NULLSUB,
267+
NULLSUB,
268+
NULLSUB,
269+
NULLSUB,
270+
CWOffset(0x32B5A0),
271+
CWOffset(0x32B6B0),
272+
NULLSUB,
273+
NULLSUB,
274+
CWOffset(0x32B6E0),
275+
CWOffset(0x32A2C0), // plasma::Widget* CreateCopy(plasma::Widget*);
276+
CWOffset(0x32A8D0),
277+
NULLSUB
278+
};
279+
280+
for (int i = 0; i < 43; ++i)
281+
{
282+
VTABLE[i] = vtab[i];
283+
}
284+
}
285+
286+
void mod::ModWidget::LoadSave(std::vector<DLL*>* mods)
287+
{
288+
std::ifstream in(file_name.c_str());
289+
std::string line;
290+
291+
while (getline(in, line)) {
292+
auto pos = line.find(":");
293+
if (pos != std::string::npos)
294+
{
295+
std::string name(line.substr(0, pos));
296+
bool enabled = stoi(line.substr(pos + 1, line.size() - 1));
297+
for (DLL* dll : *mods)
298+
{
299+
if (!name.compare(dll->fileName))
300+
{
301+
dll->enabled = enabled;
302+
}
303+
}
304+
}
305+
}
306+
}
307+
308+
void mod::ModWidget::StoreSave(std::vector<DLL*>* mods)
309+
{
310+
std::ofstream out(file_name.c_str());
311+
for (DLL* dll : *mods)
312+
{
313+
out << dll->fileName << ":" << dll->enabled << "\n";
314+
}
315+
out.close();
316+
}

CubeModLoader/ModWidget.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "CWSDK/cwsdk.h"
4+
#include "DLL.h"
5+
6+
namespace mod {
7+
class ModWidget : public cube::BaseWidget
8+
{
9+
public:
10+
enum HoverState
11+
{
12+
None = 0,
13+
Exit = 1,
14+
Next = 2,
15+
Previous = 3,
16+
Toggle = 4
17+
};
18+
cube::Game* game;
19+
int hover_state;
20+
int selected;
21+
int page;
22+
bool changed;
23+
plasma::Node* background;
24+
std::vector<DLL*>* mods;
25+
void* artificial_vtable[43];
26+
27+
28+
ModWidget* ctor(cube::Game* game, plasma::Node* node, plasma::Node* background, std::vector<DLL*>* mods);
29+
30+
void MouseUp(cube::MouseButton mouse_button);
31+
bool NextPageAvailable();
32+
bool PreviousPageAvailable();
33+
34+
static void Draw(ModWidget* widget);
35+
static void Init();
36+
static void LoadSave(std::vector<DLL*>* mods);
37+
static void StoreSave(std::vector<DLL*>* mods);
38+
};
39+
}

0 commit comments

Comments
 (0)