the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "UI.h"
3#include "UIScene_AbstractContainerMenu.h"
4
5#include "..\..\..\Minecraft.World\net.minecraft.world.inventory.h"
6#include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
7#include "..\..\MultiplayerLocalPlayer.h"
8#ifdef _WINDOWS64
9#include "..\..\Windows64\KeyboardMouseInput.h"
10#endif
11
12UIScene_AbstractContainerMenu::UIScene_AbstractContainerMenu(int iPad, UILayer *parentLayer) : UIScene(iPad, parentLayer)
13{
14 m_focusSection = eSectionNone;
15 // in this scene, we override the press sound with our own for crafting success or fail
16 ui.OverrideSFX(m_iPad,ACTION_MENU_A,true);
17 ui.OverrideSFX(m_iPad,ACTION_MENU_OK,true);
18#ifdef __ORBIS__
19 ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,true);
20#endif
21 ui.OverrideSFX(m_iPad,ACTION_MENU_X,true);
22 ui.OverrideSFX(m_iPad,ACTION_MENU_Y,true);
23 ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,true);
24 ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,true);
25 ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,true);
26 ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,true);
27 ui.OverrideSFX(m_iPad,ACTION_MENU_UP,true);
28 ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,true);
29
30 m_bIgnoreInput=false;
31#ifdef _WINDOWS64
32 m_bMouseDragSlider=false;
33 m_bHasMousePosition = false;
34 m_lastMouseX = 0;
35 m_lastMouseY = 0;
36#endif
37}
38
39UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu()
40{
41 app.DebugPrintf("UIScene_AbstractContainerMenu::~UIScene_AbstractContainerMenu\n");
42}
43
44void UIScene_AbstractContainerMenu::handleDestroy()
45{
46 app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n");
47 Minecraft *pMinecraft = Minecraft::GetInstance();
48 if( pMinecraft->localgameModes[m_iPad] != NULL )
49 {
50 TutorialMode *gameMode = (TutorialMode *)pMinecraft->localgameModes[m_iPad];
51 if(gameMode != NULL) gameMode->getTutorial()->changeTutorialState(m_previousTutorialState);
52 }
53
54 // 4J Stu - Fix for #11302 - TCR 001: Network Connectivity: Host crashed after being killed by the client while accessing a chest during burst packet loss.
55 // We need to make sure that we call closeContainer() anytime this menu is closed, even if it is forced to close by some other reason (like the player dying)
56 if(pMinecraft->localplayers[m_iPad] != NULL && pMinecraft->localplayers[m_iPad]->containerMenu->containerId == m_menu->containerId)
57 {
58 pMinecraft->localplayers[m_iPad]->closeContainer();
59 }
60
61 ui.OverrideSFX(m_iPad,ACTION_MENU_A,false);
62 ui.OverrideSFX(m_iPad,ACTION_MENU_OK,false);
63#ifdef __ORBIS__
64 ui.OverrideSFX(m_iPad,ACTION_MENU_TOUCHPAD_PRESS,false);
65#endif
66 ui.OverrideSFX(m_iPad,ACTION_MENU_X,false);
67 ui.OverrideSFX(m_iPad,ACTION_MENU_Y,false);
68 ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT_SCROLL,false);
69 ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT_SCROLL,false);
70 ui.OverrideSFX(m_iPad,ACTION_MENU_LEFT,false);
71 ui.OverrideSFX(m_iPad,ACTION_MENU_RIGHT,false);
72 ui.OverrideSFX(m_iPad,ACTION_MENU_UP,false);
73 ui.OverrideSFX(m_iPad,ACTION_MENU_DOWN,false);
74}
75
76void UIScene_AbstractContainerMenu::InitDataAssociations(int iPad, AbstractContainerMenu *menu, int startIndex)
77{
78}
79
80void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
81{
82
83 m_labelInventory.init( app.GetString(IDS_INVENTORY) );
84
85 if(startIndex >= 0)
86 {
87 m_slotListInventory.addSlots(startIndex, 27);
88 m_slotListHotbar.addSlots(startIndex + 27, 9);
89 }
90
91 // Determine min and max extents for pointer, it needs to be able to move off the container to drop items.
92 float fPanelWidth, fPanelHeight;
93 float fPanelX, fPanelY;
94 float fPointerWidth, fPointerHeight;
95
96 // We may have varying depths of controls here, so base off the pointers parent
97#if TO_BE_IMPLEMENTED
98 HXUIOBJ parent;
99 XuiElementGetBounds( m_pointerControl->m_hObj, &fPointerWidth, &fPointerHeight );
100#else
101 fPointerWidth = 50;
102 fPointerHeight = 50;
103#endif
104
105 fPanelWidth = m_controlBackgroundPanel.getWidth();
106 fPanelHeight = m_controlBackgroundPanel.getHeight();
107 fPanelX = m_controlBackgroundPanel.getXPos();
108 fPanelY = m_controlBackgroundPanel.getYPos();
109 // Get size of pointer
110 m_fPointerImageOffsetX = 0; //floor(fPointerWidth/2.0f);
111 m_fPointerImageOffsetY = 0; //floor(fPointerHeight/2.0f);
112
113 m_fPanelMinX = fPanelX;
114 m_fPanelMaxX = fPanelX + fPanelWidth;
115 m_fPanelMinY = fPanelY;
116 m_fPanelMaxY = fPanelY + fPanelHeight;
117
118#ifdef __ORBIS__
119 // we need to map the touchpad rectangle to the UI rectangle. While it works great for the creative menu, it is much too sensitive for the smaller menus.
120 //X coordinate of the touch point (0 to 1919)
121 //Y coordinate of the touch point (0 to 941: DUALSHOCK�4 wireless controllers and the CUH-ZCT1J/CAP-ZCT1J/CAP-ZCT1U controllers for the PlayStation�4 development tool,
122 //0 to 753: JDX-1000x series controllers for the PlayStation�4 development tool,)
123 m_fTouchPadMulX=fPanelWidth/1919.0f;
124 m_fTouchPadMulY=fPanelHeight/941.0f;
125 m_fTouchPadDeadZoneX=15.0f*m_fTouchPadMulX;
126 m_fTouchPadDeadZoneY=15.0f*m_fTouchPadMulY;
127
128#endif
129
130 // 4J-PB - need to limit this in splitscreen
131 if(app.GetLocalPlayerCount()>1)
132 {
133 // don't let the pointer go into someone's screen
134 m_fPointerMinY = floor(fPointerHeight/2.0f);
135 }
136 else
137 {
138 m_fPointerMinY = fPanelY -fPointerHeight;
139 }
140 m_fPointerMinX = fPanelX - fPointerWidth;
141 m_fPointerMaxX = m_fPanelMaxX + fPointerWidth;
142 m_fPointerMaxY = m_fPanelMaxY + (fPointerHeight/2);
143
144// m_hPointerText=NULL;
145// m_hPointerTextBkg=NULL;
146
147 // Put the pointer over first item in use row to start with.
148 UIVec2D itemPos;
149 UIVec2D itemSize;
150 GetItemScreenData( m_eCurrSection, 0, &( itemPos ), &( itemSize ) );
151
152 UIVec2D sectionPos;
153 GetPositionOfSection( m_eCurrSection, &( sectionPos ) );
154
155 UIVec2D vPointerPos = sectionPos;
156 vPointerPos += itemPos;
157 vPointerPos.x += ( itemSize.x / 2.0f );
158 vPointerPos.y += ( itemSize.y / 2.0f );
159
160 vPointerPos.x -= m_fPointerImageOffsetX;
161 vPointerPos.y -= m_fPointerImageOffsetY;
162
163 //m_pointerControl->SetPosition( &vPointerPos );
164 m_pointerPos = vPointerPos;
165
166 IggyEvent mouseEvent;
167 S32 width, height;
168 m_parentLayer->getRenderDimensions(width, height);
169 S32 x = m_pointerPos.x*((float)width/m_movieWidth);
170 S32 y = m_pointerPos.y*((float)height/m_movieHeight);
171 IggyMakeEventMouseMove( &mouseEvent, x, y);
172
173 IggyEventResult result;
174 IggyPlayerDispatchEventRS ( getMovie() , &mouseEvent , &result );
175
176#ifdef USE_POINTER_ACCEL
177 m_fPointerVelX = 0.0f;
178 m_fPointerVelY = 0.0f;
179 m_fPointerAccelX = 0.0f;
180 m_fPointerAccelY = 0.0f;
181#endif
182}
183
184void UIScene_AbstractContainerMenu::tick()
185{
186 UIScene::tick();
187
188#ifdef _WINDOWS64
189 bool mouseActive = (m_iPad == 0 && !KMInput.IsCaptured());
190 bool drivePointerFromMouse = false;
191 float rawMouseMovieX = 0, rawMouseMovieY = 0;
192 int scrollDelta = 0;
193 // Map Windows mouse position to the virtual pointer in movie coordinates
194 if (mouseActive)
195 {
196 RECT clientRect;
197 GetClientRect(KMInput.GetHWnd(), &clientRect);
198 int clientWidth = clientRect.right;
199 int clientHeight = clientRect.bottom;
200 if (clientWidth > 0 && clientHeight > 0)
201 {
202 int mouseX = KMInput.GetMouseX();
203 int mouseY = KMInput.GetMouseY();
204 bool mouseMoved = !m_bHasMousePosition || mouseX != m_lastMouseX || mouseY != m_lastMouseY;
205
206 m_bHasMousePosition = true;
207 m_lastMouseX = mouseX;
208 m_lastMouseY = mouseY;
209 scrollDelta = KMInput.ConsumeScrollDelta();
210
211 // Convert mouse position to movie coordinates using the movie/client ratio
212 float mx = (float)mouseX * ((float)m_movieWidth / (float)clientWidth);
213 float my = (float)mouseY * ((float)m_movieHeight / (float)clientHeight);
214
215 rawMouseMovieX = mx;
216 rawMouseMovieY = my;
217
218 // Once the mouse has taken over the container cursor, keep following the OS cursor
219 // until explicit controller input takes ownership back.
220 drivePointerFromMouse = m_bPointerDrivenByMouse || mouseMoved || KMInput.IsMouseDown(0) || KMInput.IsMouseDown(1) || KMInput.IsMouseDown(2) || scrollDelta != 0;
221 if (drivePointerFromMouse)
222 {
223 m_bPointerDrivenByMouse = true;
224 m_eCurrTapState = eTapStateNoInput;
225 m_pointerPos.x = mx;
226 m_pointerPos.y = my;
227 }
228 }
229 }
230#endif
231
232 onMouseTick();
233
234#ifdef _WINDOWS64
235 // Dispatch mouse clicks AFTER onMouseTick() has updated m_eCurrSection from the new pointer position
236 if (mouseActive)
237 {
238 if (KMInput.ConsumeMousePress(0))
239 {
240 if (m_eCurrSection == eSectionInventoryCreativeSlider)
241 {
242 // Scrollbar click: use raw mouse position (onMouseTick may have snapped m_pointerPos)
243 m_bMouseDragSlider = true;
244 m_pointerPos.x = rawMouseMovieX;
245 m_pointerPos.y = rawMouseMovieY;
246 handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
247 }
248 else
249 {
250 handleKeyDown(m_iPad, ACTION_MENU_A, false);
251 }
252 }
253 else if (m_bMouseDragSlider && KMInput.IsMouseDown(0))
254 {
255 // Continue scrollbar drag: update scroll position from current mouse Y
256 m_pointerPos.x = rawMouseMovieX;
257 m_pointerPos.y = rawMouseMovieY;
258 handleOtherClicked(m_iPad, eSectionInventoryCreativeSlider, 0, false);
259 }
260
261 if (!KMInput.IsMouseDown(0))
262 m_bMouseDragSlider = false;
263
264 if (KMInput.ConsumeMousePress(1))
265 {
266 handleKeyDown(m_iPad, ACTION_MENU_X, false);
267 }
268 if (KMInput.ConsumeMousePress(2))
269 {
270 handleKeyDown(m_iPad, ACTION_MENU_Y, false);
271 }
272
273 // Mouse scroll wheel for page scrolling
274 if (scrollDelta > 0)
275 {
276 handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_UP, false);
277 }
278 else if (scrollDelta < 0)
279 {
280 handleKeyDown(m_iPad, ACTION_MENU_OTHER_STICK_DOWN, false);
281 }
282
283 // ESC to close — must be last since it may destroy this scene
284 if (KMInput.ConsumeKeyPress(VK_ESCAPE))
285 {
286 handleKeyDown(m_iPad, ACTION_MENU_B, false);
287 return;
288 }
289 }
290#endif
291
292 IggyEvent mouseEvent;
293 S32 width, height;
294 m_parentLayer->getRenderDimensions(width, height);
295
296#ifdef _WINDOWS64
297 S32 x, y;
298 if (mouseActive && m_bPointerDrivenByMouse)
299 {
300 // Send raw mouse position directly as Iggy event to avoid coordinate round-trip errors
301 // Scale mouse client coords to the Iggy display space (which was set to getRenderDimensions())
302 RECT clientRect;
303 GetClientRect(KMInput.GetHWnd(), &clientRect);
304 x = (S32)((float)KMInput.GetMouseX() * ((float)width / (float)clientRect.right));
305 y = (S32)((float)KMInput.GetMouseY() * ((float)height / (float)clientRect.bottom));
306 }
307 else
308 {
309 x = (S32)(m_pointerPos.x * ((float)width / m_movieWidth));
310 y = (S32)(m_pointerPos.y * ((float)height / m_movieHeight));
311 }
312#else
313 S32 x = m_pointerPos.x*((float)width/m_movieWidth);
314 S32 y = m_pointerPos.y*((float)height/m_movieHeight);
315#endif
316 IggyMakeEventMouseMove( &mouseEvent, x, y);
317
318 // 4J Stu - This seems to be broken on Durango, so do it ourself
319#ifdef _DURANGO
320 //mouseEvent.x = x;
321 //mouseEvent.y = y;
322#endif
323
324 IggyEventResult result;
325 IggyPlayerDispatchEventRS ( getMovie() , &mouseEvent , &result );
326}
327
328void UIScene_AbstractContainerMenu::render(S32 width, S32 height, C4JRender::eViewportType viewpBort)
329{
330 m_cacheSlotRenders = true;
331
332 m_needsCacheRendered = m_needsCacheRendered || m_menu->needsRendered();
333
334 if(m_needsCacheRendered)
335 {
336 m_expectedCachedSlotCount = GetBaseSlotCount();
337 unsigned int count = m_menu->getSize();
338 for(unsigned int i = 0; i < count; ++i)
339 {
340 if(m_menu->getSlot(i)->hasItem())
341 {
342 ++m_expectedCachedSlotCount;
343 }
344 }
345 }
346
347 UIScene::render(width, height, viewpBort);
348
349 m_needsCacheRendered = false;
350}
351
352void UIScene_AbstractContainerMenu::customDraw(IggyCustomDrawCallbackRegion *region)
353{
354 Minecraft *pMinecraft = Minecraft::GetInstance();
355 if(pMinecraft->localplayers[m_iPad] == NULL || pMinecraft->localgameModes[m_iPad] == NULL) return;
356
357 shared_ptr<ItemInstance> item = nullptr;
358 int slotId = -1;
359 if(wcscmp((wchar_t *)region->name,L"pointerIcon")==0)
360 {
361 m_cacheSlotRenders = false;
362 item = pMinecraft->localplayers[m_iPad]->inventory->getCarried();
363 }
364 else
365 {
366 swscanf((wchar_t*)region->name,L"slot_%d",&slotId);
367 if (slotId == -1)
368 {
369 app.DebugPrintf("This is not the control we are looking for\n");
370 }
371 else
372 {
373 m_cacheSlotRenders = true;
374 Slot *slot = m_menu->getSlot(slotId);
375 item = slot->getItem();
376 }
377 }
378
379 if(item != NULL) customDrawSlotControl(region,m_iPad,item,m_menu->isValidIngredient(item, slotId)?1.0f:0.5f,item->isFoil(),true);
380}
381
382void UIScene_AbstractContainerMenu::handleInput(int iPad, int key, bool repeat, bool pressed, bool released, bool &handled)
383{
384 if(m_bIgnoreInput) return;
385
386 //app.DebugPrintf("UIScene_InventoryMenu handling input for pad %d, key %d, down- %s, pressed- %s, released- %s\n", iPad, key, down?"TRUE":"FALSE", pressed?"TRUE":"FALSE", released?"TRUE":"FALSE");
387 ui.AnimateKeyPress(m_iPad, key, repeat, pressed, released);
388
389 if(pressed)
390 {
391 m_bPointerDrivenByMouse = false;
392 handled = handleKeyDown(m_iPad, key, repeat);
393 }
394}
395
396void UIScene_AbstractContainerMenu::SetPointerText(vector<HtmlString> *description, bool newSlot)
397{
398 m_cursorPath.setLabel(HtmlString::Compose(description), false, newSlot);
399}
400
401void UIScene_AbstractContainerMenu::setSectionFocus(ESceneSection eSection, int iPad)
402{
403 UIControl *newFocus = getSection(eSection);
404 if(newFocus) newFocus->setFocus(true);
405
406 if(m_focusSection != eSectionNone)
407 {
408 UIControl *currentFocus = getSection(m_focusSection);
409 // 4J-TomK only set current focus to false if it differs from last (previously this continuously fired iggy functions when they were identical!
410 if(currentFocus != newFocus)
411 if(currentFocus) currentFocus->setFocus(false);
412 }
413
414 m_focusSection = eSection;
415}
416
417void UIScene_AbstractContainerMenu::setFocusToPointer(int iPad)
418{
419 if(m_focusSection != eSectionNone)
420 {
421 UIControl *currentFocus = getSection(m_focusSection);
422 if(currentFocus) currentFocus->setFocus(false);
423 }
424 m_focusSection = eSectionNone;
425}
426
427shared_ptr<ItemInstance> UIScene_AbstractContainerMenu::getSlotItem(ESceneSection eSection, int iSlot)
428{
429 Slot *slot = m_menu->getSlot( getSectionStartOffset(eSection) + iSlot );
430 if(slot) return slot->getItem();
431 else return nullptr;
432}
433
434Slot *UIScene_AbstractContainerMenu::getSlot(ESceneSection eSection, int iSlot)
435{
436 Slot *slot = m_menu->getSlot( getSectionStartOffset(eSection) + iSlot );
437 if(slot) return slot;
438 else return NULL;
439}
440
441bool UIScene_AbstractContainerMenu::isSlotEmpty(ESceneSection eSection, int iSlot)
442{
443 Slot *slot = m_menu->getSlot( getSectionStartOffset(eSection) + iSlot );
444 if(slot) return !slot->hasItem();
445 else return false;
446}
447
448void UIScene_AbstractContainerMenu::adjustPointerForSafeZone()
449{
450 // Handled by AS
451}