diff --git a/src/Camera.c b/src/Camera.c index 1925eb4fe..0d957f3f9 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -12,6 +12,7 @@ #include "Options.h" #include "Picking.h" #include "Platform.h" +#include "Protocol.h" struct _CameraData Camera; static struct RayTracer cameraClipPos; @@ -302,6 +303,12 @@ void Camera_CycleActive(void) { } cam_isForwardThird = Camera.Active == &cam_ForwardThird; + int cycle = 0; + if (Camera.Active == &cam_FirstPerson) cycle = 0; + else if (Camera.Active == &cam_ThirdPerson) cycle = 1; + else if (cam_isForwardThird) cycle = 2; + CPE_SendNotifyAction(NOTIFY_ACTION_THIRD_PERSON_CHANGED, cycle); + /* reset rotation offset when changing cameras */ cam_rotOffset.x = 0.0f; cam_rotOffset.y = 0.0f; Camera_UpdateProjection(); diff --git a/src/Entity.c b/src/Entity.c index a63754660..ed03bb638 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -22,6 +22,7 @@ #include "Errors.h" #include "Utils.h" #include "EntityRenderers.h" +#include "Protocol.h" const char* const NameMode_Names[NAME_MODE_COUNT] = { "None", "Hovered", "All", "AllHovered", "AllUnscaled" }; const char* const ShadowMode_Names[SHADOW_MODE_COUNT] = { "None", "SnapToBlock", "Circle", "CircleAll" }; @@ -800,6 +801,7 @@ static void LocalPlayers_OnNewMap(void) { } static cc_bool LocalPlayer_IsSolidCollide(BlockID b) { return Blocks.Collide[b] == COLLIDE_SOLID; } + static void LocalPlayer_DoRespawn(struct LocalPlayer* p) { struct LocationUpdate update; struct AABB bb; @@ -829,6 +831,9 @@ static void LocalPlayer_DoRespawn(struct LocalPlayer* p) { } } + struct EntityLocation* prev = &p->Base.prev; + CPE_SendNotifyPositionAction(3, prev->pos.x, prev->pos.y, prev->pos.z); + /* Adjust the position to be slightly above the ground, so that */ /* it's obvious to the player that they are being respawned */ spawn.y += 2.0f/16.0f; @@ -884,6 +889,8 @@ static cc_bool LocalPlayer_HandleSetSpawn(int key, struct InputDevice* device) { p->SpawnYaw = p->Base.Yaw; if (!Game_ClassicMode) p->SpawnPitch = p->Base.Pitch; + + CPE_SendNotifyPositionAction(4, p->Spawn.x, p->Spawn.y, p->Spawn.z); } return LocalPlayer_HandleRespawn(key, device); } diff --git a/src/Inventory.c b/src/Inventory.c index a7f00c13f..817a0b725 100644 --- a/src/Inventory.c +++ b/src/Inventory.c @@ -4,6 +4,7 @@ #include "Block.h" #include "Event.h" #include "Chat.h" +#include "Protocol.h" struct _InventoryData Inventory; @@ -45,6 +46,7 @@ void Inventory_SetSelectedBlock(BlockID block) { Inventory_Set(Inventory.SelectedIndex, block); Event_RaiseVoid(&UserEvents.HeldBlockChanged); + CPE_SendNotifyAction(NOTIFY_ACTION_BLOCK_LIST_SELECTED, block); } void Inventory_PickBlock(BlockID block) { diff --git a/src/Menus.c b/src/Menus.c index 0bccc80fd..2e46b0d24 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -36,6 +36,7 @@ #include "SystemFonts.h" #include "Lighting.h" #include "InputHandler.h" +#include "Protocol.h" /*########################################################################################################################* *--------------------------------------------------------Menu base--------------------------------------------------------* @@ -1407,11 +1408,15 @@ static void SaveLevelScreen_Save(void* screen, void* widget) { SaveLevelScreen_RemoveOverwrites(s); if ((res = SaveLevelScreen_SaveMap(&path))) return; Chat_Add1("&eSaved map to: %s", &path); + CPE_SendNotifyAction(NOTIFY_ACTION_LEVEL_SAVED, 0); } static void SaveLevelScreen_UploadCallback(const cc_string* path) { cc_result res = SaveLevelScreen_SaveMap(path); - if (!res) Chat_Add1("&eSaved map to: %s", path); + if (!res) { + Chat_Add1("&eSaved map to: %s", path); + CPE_SendNotifyAction(NOTIFY_ACTION_LEVEL_SAVED, 0); + } } static void SaveLevelScreen_File(void* screen, void* b) { @@ -1556,6 +1561,8 @@ static void TexturePackScreen_EntryClick(void* screen, void* widget) { TexturePack_Url.length = 0; res = TexturePack_ExtractCurrent(true); + CPE_SendNotifyAction(NOTIFY_ACTION_TEXTURE_PACK_CHANGED, 0); + /* FileNotFound error may be because user deleted .zips from disc */ if (res != ReturnCode_FileNotFound) return; Chat_AddRaw("&eReloading texture pack list as it may be out of date"); @@ -2733,6 +2740,9 @@ static void TexPackOverlay_YesClick(void* screen, void* widget) { TexturePack_Extract(&s->url); if (TexPackOverlay_IsAlways(s, widget)) TextureCache_Accept(&s->url); Gui_Remove((struct Screen*)s); + + if (TexPackOverlay_IsAlways(s, widget)) CPE_SendNotifyAction(NOTIFY_ACTION_TEXTURE_PROMPT_RESPONDED, 3); + else CPE_SendNotifyAction(NOTIFY_ACTION_TEXTURE_PROMPT_RESPONDED, 2); } static void TexPackOverlay_NoClick(void* screen, void* widget) { @@ -2746,6 +2756,9 @@ static void TexPackOverlay_ConfirmNoClick(void* screen, void* b) { struct TexPackOverlay* s = (struct TexPackOverlay*)screen; if (s->alwaysDeny) TextureCache_Deny(&s->url); Gui_Remove((struct Screen*)s); + + if (s->alwaysDeny) CPE_SendNotifyAction(NOTIFY_ACTION_TEXTURE_PROMPT_RESPONDED, 0); + else CPE_SendNotifyAction(NOTIFY_ACTION_TEXTURE_PROMPT_RESPONDED, 1); } static void TexPackOverlay_GoBackClick(void* screen, void* b) { diff --git a/src/Protocol.c b/src/Protocol.c index 3068f6947..fbac6459f 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -92,7 +92,9 @@ static struct CpeExt pluginMessages_Ext = { "PluginMessages", 1 }, extTeleport_Ext = { "ExtEntityTeleport", 1 }, lightingMode_Ext = { "LightingMode", 1 }, - cinematicGui_Ext = { "CinematicGui", 1 }, + cinematicGui_Ext = { "CinematicGui", 1 }, + notifyAction_Ext = { "NotifyAction", 1 }, + notifyPositionAction_Ext = { "NotifyPositionAction", 1 }, extTextures_Ext = { "ExtendedTextures", 1 }, extBlocks_Ext = { "ExtendedBlocks", 1 }; @@ -102,7 +104,8 @@ static struct CpeExt* cpe_clientExtensions[] = { &messageTypes_Ext, &hackControl_Ext, &playerClick_Ext, &fullCP437_Ext, &longerMessages_Ext, &blockDefs_Ext, &blockDefsExt_Ext, &bulkBlockUpdate_Ext, &textColors_Ext, &envMapAspect_Ext, &entityProperty_Ext, &extEntityPos_Ext, &twoWayPing_Ext, &invOrder_Ext, &instantMOTD_Ext, &fastMap_Ext, &setHotbar_Ext, &setSpawnpoint_Ext, &velControl_Ext, - &customParticles_Ext, &pluginMessages_Ext, &extTeleport_Ext, &lightingMode_Ext, &cinematicGui_Ext, + &customParticles_Ext, &pluginMessages_Ext, &extTeleport_Ext, &lightingMode_Ext, &cinematicGui_Ext, ¬ifyAction_Ext, + ¬ifyPositionAction_Ext, #ifdef CUSTOM_MODELS &customModels_Ext, #endif @@ -900,6 +903,30 @@ void CPE_SendPluginMessage(cc_uint8 channel, cc_uint8* data) { Server.SendData(buffer, 66); } +void CPE_SendNotifyAction(int action, cc_uint16 value) { + cc_uint8 data[5]; + + data[0] = OPCODE_NOTIFY_ACTION; + { + Stream_SetU16_BE(data + 1, action); + Stream_SetU16_BE(data + 3, value); + } + Server.SendData(data, 5); +} + +void CPE_SendNotifyPositionAction(int action, int x, int y, int z) { + cc_uint8 data[9]; + + data[0] = OPCODE_NOTIFY_POSITION_ACTION; + { + Stream_SetU16_BE(data + 1, action); + Stream_SetU16_BE(data + 3, x); + Stream_SetU16_BE(data + 5, y); + Stream_SetU16_BE(data + 7, z); + } + Server.SendData(data, 9); +} + static void CPE_SendExtInfo(int extsCount) { cc_uint8 data[67]; data[0] = OPCODE_EXT_INFO; diff --git a/src/Protocol.h b/src/Protocol.h index d2ed388e9..a78976d2e 100644 --- a/src/Protocol.h +++ b/src/Protocol.h @@ -39,7 +39,8 @@ enum OPCODE_ { OPCODE_DEFINE_EFFECT, OPCODE_SPAWN_EFFECT, OPCODE_DEFINE_MODEL, OPCODE_DEFINE_MODEL_PART, OPCODE_UNDEFINE_MODEL, OPCODE_PLUGIN_MESSAGE, OPCODE_ENTITY_TELEPORT_EXT, - OPCODE_LIGHTING_MODE, OPCODE_CINEMATIC_GUI, + OPCODE_LIGHTING_MODE, OPCODE_CINEMATIC_GUI, OPCODE_NOTIFY_ACTION, + OPCODE_NOTIFY_POSITION_ACTION, OPCODE_COUNT }; @@ -49,6 +50,11 @@ enum PROTOCOL_VERSION_ { PROTOCOL_0020 = 6, PROTOCOL_0030 = 7, }; +enum NOTIFY_ACTION_TYPE { + NOTIFY_ACTION_BLOCK_LIST_SELECTED = 0, NOTIFY_ACTION_BLOCK_LIST_TOGGLED = 1, NOTIFY_ACTION_LEVEL_SAVED = 2, + NOTIFY_ACTION_RESPAWNED = 3, NOTIFY_ACTION_SPAWN_UPDATED = 4, NOTIFY_ACTION_TEXTURE_PACK_CHANGED = 5, + NOTIFY_ACTION_TEXTURE_PROMPT_RESPONDED = 6, NOTIFY_ACTION_THIRD_PERSON_CHANGED = 7 +}; typedef void (*Net_Handler)(cc_uint8* data); #define Net_Set(opcode, handler, size) Protocol.Handlers[opcode] = handler; Protocol.Sizes[opcode] = size; @@ -71,6 +77,8 @@ void Classic_SendChat(const cc_string* text, cc_bool partial); void Classic_SendSetBlock(int x, int y, int z, cc_bool place, BlockID block); void Classic_SendLogin(void); void CPE_SendPlayerClick(int button, cc_bool pressed, cc_uint8 targetId, struct RayTracer* t); +void CPE_SendNotifyAction(int action, cc_uint16 value); +void CPE_SendNotifyPositionAction(int action, int x, int y, int z); /* Send a PluginMessage to the server; data must contain 64 bytes. */ CC_API void CPE_SendPluginMessage(cc_uint8 channel, cc_uint8* data); diff --git a/src/Screens.c b/src/Screens.c index e27de0a64..6345824a9 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -23,6 +23,7 @@ #include "Utils.h" #include "Options.h" #include "InputHandler.h" +#include "Protocol.h" #define CHAT_MAX_STATUS Array_Elems(Chat_Status) #define CHAT_MAX_BOTTOMRIGHT Array_Elems(Chat_BottomRight) @@ -1732,9 +1733,11 @@ static int InventoryScreen_KeyDown(void* screen, int key, struct InputDevice* de /* Accuracy: Original classic doesn't close inventory menu when B is pressed */ if (InputBind_Claims(BIND_INVENTORY, key, device) && s->releasedInv && !Game_ClassicMode) { Gui_Remove((struct Screen*)s); + CPE_SendNotifyAction(NOTIFY_ACTION_BLOCK_LIST_TOGGLED, 0); } else if (InputDevice_IsEnter(key, device) && table->selectedIndex != -1) { Inventory_SetSelectedBlock(table->blocks[table->selectedIndex]); Gui_Remove((struct Screen*)s); + CPE_SendNotifyAction(NOTIFY_ACTION_BLOCK_LIST_TOGGLED, 0); } else if (Elem_HandlesKeyDown(table, key, device)) { } else { return Elem_HandlesKeyDown(&HUDScreen_Instance.hotbar, key, device); @@ -1764,7 +1767,10 @@ static int InventoryScreen_PointerDown(void* screen, int id, int x, int y) { if (!handled || table->pendingClose) { hotbar = Input_IsCtrlPressed() || Input_IsShiftPressed(); - if (!hotbar) Gui_Remove((struct Screen*)s); + if (!hotbar) { + Gui_Remove((struct Screen*)s); + CPE_SendNotifyAction(NOTIFY_ACTION_BLOCK_LIST_TOGGLED, 0); + } } return TOUCH_TYPE_GUI; } @@ -1808,6 +1814,7 @@ void InventoryScreen_Show(void) { s->VTABLE = &InventoryScreen_VTABLE; Gui_Add((struct Screen*)s, GUI_PRIORITY_INVENTORY); + CPE_SendNotifyAction(NOTIFY_ACTION_BLOCK_LIST_TOGGLED, 1); }