Skip to content

Commit f8c582d

Browse files
committed
Implement server-controlled lvz modification
1 parent 7340412 commit f8c582d

3 files changed

Lines changed: 104 additions & 14 deletions

File tree

src/null/LvzController.cpp

Lines changed: 97 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@
1818
#include <assert.h>
1919
#include <stdio.h>
2020

21-
// TODO: register for lvz packets and update objects
22-
2321
namespace null {
2422

2523
#define MAKE_MAGIC(c1, c2, c3, c4) (c1 | c2 << 8 | c3 << 16 | c4 << 24)
@@ -209,11 +207,24 @@ LvzController::LvzController(MemoryArena& perm_arena, MemoryArena& temp_arena, F
209207
dispatcher.Register(ProtocolS2C::ModifyLVZ, OnLvzModifyPkt, this);
210208
}
211209

210+
LvzObject* LvzController::FindObjectById(u16 id) {
211+
for (size_t i = 0; i < object_count; ++i) {
212+
LvzObject* check = objects + i;
213+
if (check->object_id == id) {
214+
return check;
215+
}
216+
}
217+
return nullptr;
218+
}
219+
212220
void LvzController::Update(float dt) {
213221
for (size_t i = 0; i < animation_count; ++i) {
214222
Animation* anim = animations + i;
215223

216224
anim->t += dt;
225+
if (anim->t >= anim->GetDuration()) {
226+
anim->t -= anim->GetDuration();
227+
}
217228
}
218229

219230
u32 tick = GetCurrentTick();
@@ -250,7 +261,7 @@ void LvzController::Render(Camera& ui_camera, Camera& game_camera, Player* self,
250261
Vector2f base_y = GetScreenReferencePoint(*self, specview, ui_camera, reference_y);
251262

252263
Vector2f position(base_x.x + (float)obj->x_screen, base_y.y + (float)obj->y_screen);
253-
Animation* anim = animations + obj->animation_index;
264+
Animation* anim = animations + obj->animation_base + obj->image_index;
254265

255266
if (anim->sprite->frames == nullptr) continue;
256267

@@ -263,7 +274,7 @@ void LvzController::Render(Camera& ui_camera, Camera& game_camera, Player* self,
263274
LvzObject* obj = active_map_objects[i];
264275

265276
Vector2f position(obj->x_map / 16.0f, obj->y_map / 16.0f);
266-
Animation* anim = animations + obj->animation_index;
277+
Animation* anim = animations + obj->animation_base + obj->image_index;
267278

268279
if (anim->sprite->frames == nullptr) continue;
269280

@@ -292,7 +303,7 @@ void LvzController::OnLvzToggle(u8* pkt, size_t size) {
292303
// Disable any previous ones with this id before adding it in again
293304
DisableObject(toggle->id);
294305

295-
animations[obj->animation_index].t = 0.0f;
306+
animations[obj->animation_base + obj->image_index].t = 0.0f;
296307
obj->enabled_tick = GetCurrentTick();
297308

298309
if (obj->map_object) {
@@ -334,14 +345,87 @@ void LvzController::OnLvzModify(u8* pkt, size_t size) {
334345
u8 mode : 1;
335346
u8 reserved : 3;
336347
};
348+
349+
struct ModifyData {
350+
u16 map_object : 1;
351+
u16 id : 15;
352+
353+
union {
354+
struct {
355+
s16 map_x;
356+
s16 map_y;
357+
};
358+
359+
struct {
360+
u16 reference_point_x : 4; // ReferencePoint
361+
s16 screen_x : 12;
362+
u16 reference_point_y : 4; // ReferencePoint
363+
s16 screen_y : 12;
364+
};
365+
};
366+
367+
u8 image_id;
368+
u8 layer;
369+
u16 time : 12;
370+
u16 mode : 4;
371+
};
337372
#pragma pack(pop)
338373

339-
ModifyBitfield* mod = (ModifyBitfield*)(pkt + 1);
374+
ModifyBitfield* mod_changed = (ModifyBitfield*)(pkt + 1);
375+
ModifyData* mod = (ModifyData*)(pkt + 2);
376+
377+
LvzObject* obj = FindObjectById(mod->id);
378+
if (!obj) {
379+
Log(LogLevel::Warning, "Got lvz modify for object id %d, but wasn't found.", (s32)mod->id);
380+
return;
381+
}
382+
383+
// Check if this switched between screen/map.
384+
// I don't know if this is even possible, but handle it anyway.
385+
if (obj->map_object != mod->map_object) {
386+
obj->map_object = mod->map_object;
387+
388+
// Remove it from both map and screen object lists, then add it back to the appropriate one.
389+
DisableObject(obj->object_id);
390+
391+
if (obj->map_object) {
392+
if (active_map_object_count < NULLSPACE_ARRAY_SIZE(active_map_objects)) {
393+
active_map_objects[active_map_object_count++] = obj;
394+
}
395+
} else {
396+
if (active_screen_object_count < NULLSPACE_ARRAY_SIZE(active_screen_objects)) {
397+
active_screen_objects[active_screen_object_count++] = obj;
398+
}
399+
}
400+
}
401+
402+
if (mod_changed->mode) {
403+
obj->display_mode = mod->mode;
404+
}
340405

341-
#if 0
342-
printf("Lvz modify (%zd): %d %d %d %d %d %d\n", size, mod->xy, mod->image, mod->layer, mod->time, mod->mode,
343-
mod->reserved);
344-
#endif
406+
if (mod_changed->xy) {
407+
if (obj->map_object) {
408+
obj->x_map = mod->map_x;
409+
obj->y_map = mod->map_y;
410+
} else {
411+
obj->x_screen = mod->screen_x;
412+
obj->y_screen = mod->screen_y;
413+
obj->x_type = mod->reference_point_x;
414+
obj->y_type = mod->reference_point_y;
415+
}
416+
}
417+
418+
if (mod_changed->image) {
419+
obj->image_index = mod->image_id;
420+
}
421+
422+
if (mod_changed->layer) {
423+
obj->layer = (Layer)mod->layer;
424+
}
425+
426+
if (mod_changed->time) {
427+
obj->display_time = mod->time;
428+
}
345429
}
346430

347431
void LvzController::OnMapInformation(u8* pkt, size_t size) {
@@ -507,7 +591,7 @@ void LvzController::ProcessObjects(struct ObjectImageList* object_images, u8* da
507591
// Skip over object definitions first to simplify image creation
508592
ptr += sizeof(ObjectDefinition) * header->object_count;
509593

510-
size_t animation_base = animation_count;
594+
size_t animation_base = this->animation_count;
511595

512596
for (u32 i = 0; i < header->image_count; ++i) {
513597
ImageDefinition* image = (ImageDefinition*)ptr;
@@ -583,7 +667,8 @@ void LvzController::ProcessObjects(struct ObjectImageList* object_images, u8* da
583667
obj->object_id = def->object_id;
584668
obj->x_map = def->x_map;
585669
obj->y_map = def->y_map;
586-
obj->animation_index = animation_base + def->image_number;
670+
obj->animation_base = animation_base;
671+
obj->image_index = def->image_number;
587672
obj->layer = GetLayer(def->layer);
588673
obj->display_time = def->display_time;
589674
obj->display_mode = def->display_mode;

src/null/LvzController.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ struct LvzObject {
3434
};
3535
};
3636

37-
size_t animation_index;
37+
size_t animation_base;
38+
// This index is the index of the image stored in the lvz file.
39+
// You can get the animation index of it from animation_base + image_index.
40+
u8 image_index;
3841
Layer layer;
3942

4043
u16 display_time : 12;
@@ -94,6 +97,8 @@ struct LvzController {
9497

9598
void DisableObject(u16 id);
9699

100+
LvzObject* FindObjectById(u16 id);
101+
97102
private:
98103
void ProcessGraphicFile(const char* filename, u8* data, size_t size);
99104
void ProcessObjects(struct ObjectImageList* object_images, u8* data, size_t size);

src/null/WeaponManager.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ void WeaponManager::OnWeaponPacket(u8* pkt, size_t size) {
747747
// Player sends out position packet with their timestamp, it takes ping ticks to reach server, server re-timestamps it
748748
// and sends it to us.
749749
u32 server_timestamp = ((connection.GetServerTick() & 0x7FFF0000) | timestamp);
750-
u32 local_timestamp = server_timestamp - connection.time_diff - ping;
750+
u32 local_timestamp = MAKE_TICK(server_timestamp - connection.time_diff - ping);
751751

752752
Player* player = player_manager.GetPlayerById(pid);
753753
if (!player) return;

0 commit comments

Comments
 (0)