mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-22 22:30:52 +01:00
Add bot inventory
This commit is contained in:
parent
7476452476
commit
f73ddf1add
86
src/views/inventory/reducers/InventoryBotReducer.tsx
Normal file
86
src/views/inventory/reducers/InventoryBotReducer.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import { BotData } from 'nitro-renderer';
|
||||
import { Reducer } from 'react';
|
||||
import { BotItem } from '../utils/BotItem';
|
||||
import { addSingleBotItem, processBotFragment, removeBotItemById } from '../utils/BotUtilities';
|
||||
|
||||
export interface IInventoryBotState
|
||||
{
|
||||
needsBotUpdate: boolean;
|
||||
botItem: BotItem;
|
||||
botItems: BotItem[];
|
||||
}
|
||||
|
||||
export interface IInventoryBotAction
|
||||
{
|
||||
type: string;
|
||||
payload: {
|
||||
flag?: boolean;
|
||||
botItem?: BotItem;
|
||||
botId?: number;
|
||||
botData?: BotData;
|
||||
fragment?: BotData[];
|
||||
}
|
||||
}
|
||||
|
||||
export class InventoryBotActions
|
||||
{
|
||||
public static SET_NEEDS_UPDATE: string = 'IBA_SET_NEEDS_UPDATE';
|
||||
public static SET_BOT_ITEM: string = 'IBA_SET_BOT_ITEM';
|
||||
public static PROCESS_FRAGMENT: string = 'IBA_PROCESS_FRAGMENT';
|
||||
public static ADD_BOT: string = 'IBA_ADD_BOT';
|
||||
public static REMOVE_BOT: string = 'IBA_REMOVE_BOT';
|
||||
}
|
||||
|
||||
export const initialInventoryBot: IInventoryBotState = {
|
||||
needsBotUpdate: true,
|
||||
botItem: null,
|
||||
botItems: []
|
||||
}
|
||||
|
||||
export const inventoryBotReducer: Reducer<IInventoryBotState, IInventoryBotAction> = (state, action) =>
|
||||
{
|
||||
switch(action.type)
|
||||
{
|
||||
case InventoryBotActions.SET_NEEDS_UPDATE:
|
||||
return { ...state, needsBotUpdate: (action.payload.flag || false) };
|
||||
case InventoryBotActions.SET_BOT_ITEM: {
|
||||
let botItem = (action.payload.botItem || state.botItem || null);
|
||||
|
||||
let index = 0;
|
||||
|
||||
if(botItem)
|
||||
{
|
||||
const foundIndex = state.botItems.indexOf(botItem);
|
||||
|
||||
if(foundIndex > -1) index = foundIndex;
|
||||
}
|
||||
|
||||
botItem = (state.botItems[index] || null);
|
||||
|
||||
return { ...state, botItem };
|
||||
}
|
||||
case InventoryBotActions.PROCESS_FRAGMENT: {
|
||||
const botItems = [ ...state.botItems ];
|
||||
|
||||
processBotFragment(botItems, action.payload.fragment);
|
||||
|
||||
return { ...state, botItems };
|
||||
}
|
||||
case InventoryBotActions.ADD_BOT: {
|
||||
const botItems = [ ...state.botItems ];
|
||||
|
||||
addSingleBotItem(action.payload.botData, botItems, true);
|
||||
|
||||
return { ...state, botItems };
|
||||
}
|
||||
case InventoryBotActions.REMOVE_BOT: {
|
||||
const botItems = [ ...state.botItems ];
|
||||
|
||||
removeBotItemById(action.payload.botId, botItems);
|
||||
|
||||
return { ...state, botItems };
|
||||
}
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
45
src/views/inventory/utils/BotItem.ts
Normal file
45
src/views/inventory/utils/BotItem.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { BotData } from 'nitro-renderer';
|
||||
|
||||
export class BotItem
|
||||
{
|
||||
private _botData: BotData;
|
||||
private _selected: boolean;
|
||||
private _isUnseen: boolean;
|
||||
|
||||
constructor(botData: BotData)
|
||||
{
|
||||
this._botData = botData;
|
||||
this._selected = false;
|
||||
this._isUnseen = false;
|
||||
}
|
||||
|
||||
public get id(): number
|
||||
{
|
||||
return this._botData.id;
|
||||
}
|
||||
|
||||
public get botData(): BotData
|
||||
{
|
||||
return this._botData;
|
||||
}
|
||||
|
||||
public get selected(): boolean
|
||||
{
|
||||
return this._selected;
|
||||
}
|
||||
|
||||
public set selected(flag: boolean)
|
||||
{
|
||||
this._selected = flag;
|
||||
}
|
||||
|
||||
public get isUnseen(): boolean
|
||||
{
|
||||
return this._isUnseen;
|
||||
}
|
||||
|
||||
public set isUnseen(flag: boolean)
|
||||
{
|
||||
this._isUnseen = flag;
|
||||
}
|
||||
}
|
2
src/views/inventory/views/bot/InventoryBotView.scss
Normal file
2
src/views/inventory/views/bot/InventoryBotView.scss
Normal file
@ -0,0 +1,2 @@
|
||||
@import './item/InventoryBotItemView';
|
||||
@import './results/InventoryBotResultsView';
|
97
src/views/inventory/views/bot/InventoryBotView.tsx
Normal file
97
src/views/inventory/views/bot/InventoryBotView.tsx
Normal file
@ -0,0 +1,97 @@
|
||||
import { GetBotInventoryComposer, RoomObjectVariable } from 'nitro-renderer';
|
||||
import { FC, useEffect } from 'react';
|
||||
import { GetRoomEngine } from '../../../../api';
|
||||
import { SendMessageHook } from '../../../../hooks/messages/message-event';
|
||||
import { LocalizeText } from '../../../../utils/LocalizeText';
|
||||
import { RoomPreviewerView } from '../../../room-previewer/RoomPreviewerView';
|
||||
import { useInventoryContext } from '../../context/InventoryContext';
|
||||
import { InventoryBotActions } from '../../reducers/InventoryBotReducer';
|
||||
import { attemptBotPlacement } from '../../utils/BotUtilities';
|
||||
import { InventoryBotViewProps } from './InventoryBotView.types';
|
||||
import { InventoryBotResultsView } from './results/InventoryBotResultsView';
|
||||
|
||||
export const InventoryBotView: FC<InventoryBotViewProps> = props =>
|
||||
{
|
||||
const { roomSession = null, roomPreviewer = null } = props;
|
||||
const { botState = null, dispatchBotState = null } = useInventoryContext();
|
||||
const { needsBotUpdate = false, botItem = null, botItems = [] } = botState;
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(needsBotUpdate)
|
||||
{
|
||||
dispatchBotState({
|
||||
type: InventoryBotActions.SET_NEEDS_UPDATE,
|
||||
payload: {
|
||||
flag: false
|
||||
}
|
||||
});
|
||||
|
||||
SendMessageHook(new GetBotInventoryComposer());
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatchBotState({
|
||||
type: InventoryBotActions.SET_BOT_ITEM,
|
||||
payload: {
|
||||
botItem: null
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}, [ needsBotUpdate, botItems, dispatchBotState ]);
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!botItem || !roomPreviewer) return;
|
||||
|
||||
const botData = botItem.botData;
|
||||
|
||||
const roomEngine = GetRoomEngine();
|
||||
|
||||
let wallType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_WALL_TYPE);
|
||||
let floorType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_FLOOR_TYPE);
|
||||
let landscapeType = roomEngine.getRoomInstanceVariable<string>(roomEngine.activeRoomId, RoomObjectVariable.ROOM_LANDSCAPE_TYPE);
|
||||
|
||||
wallType = (wallType && wallType.length) ? wallType : '101';
|
||||
floorType = (floorType && floorType.length) ? floorType : '101';
|
||||
landscapeType = (landscapeType && landscapeType.length) ? landscapeType : '1.1';
|
||||
|
||||
roomPreviewer.reset(false);
|
||||
roomPreviewer.updateRoomWallsAndFloorVisibility(true, true);
|
||||
roomPreviewer.updateObjectRoom(floorType, wallType, landscapeType);
|
||||
roomPreviewer.addAvatarIntoRoom(botData.figure, 0);
|
||||
}, [ roomPreviewer, botItem ]);
|
||||
|
||||
if(!botItems || !botItems.length)
|
||||
{
|
||||
return (
|
||||
<div className="row h-100">
|
||||
<div className="col-5 d-flex justify-content-center align-items-center">
|
||||
<div className="empty-image"></div>
|
||||
</div>
|
||||
<div className="d-flex flex-column col justify-content-center">
|
||||
<div className="h5 m-0 text-black fw-bold m-0 mb-2">
|
||||
{ LocalizeText('inventory.empty.bots.title') }
|
||||
</div>
|
||||
<div className="h6 text-black">{ LocalizeText('inventory.empty.bots.desc') }</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="row h-100">
|
||||
<div className="col-7">
|
||||
<InventoryBotResultsView botItems={ botItems } />
|
||||
</div>
|
||||
<div className="d-flex flex-column col-5 justify-space-between">
|
||||
<RoomPreviewerView roomPreviewer={ roomPreviewer } height={ 140 } />
|
||||
{ botItem && <div className="d-flex flex-column flex-grow-1">
|
||||
<p className="flex-grow-1 fs-6 text-black my-2">{ botItem.botData.name }</p>
|
||||
{ !!roomSession && <button type="button" className="btn btn-success" onClick={ event => attemptBotPlacement(botItem) }>{ LocalizeText('inventory.furni.placetoroom') }</button> }
|
||||
</div> }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
7
src/views/inventory/views/bot/InventoryBotView.types.ts
Normal file
7
src/views/inventory/views/bot/InventoryBotView.types.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { IRoomSession, RoomPreviewer } from 'nitro-renderer';
|
||||
|
||||
export interface InventoryBotViewProps
|
||||
{
|
||||
roomSession: IRoomSession;
|
||||
roomPreviewer: RoomPreviewer;
|
||||
}
|
25
src/views/inventory/views/bot/item/InventoryBotItemView.scss
Normal file
25
src/views/inventory/views/bot/item/InventoryBotItemView.scss
Normal file
@ -0,0 +1,25 @@
|
||||
.inventory-bot-item-container {
|
||||
height: 48px;
|
||||
max-height: 48px;
|
||||
|
||||
.inventory-bot-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-color: $muted !important;
|
||||
background-color: #CDD3D9;
|
||||
overflow: hidden;
|
||||
|
||||
&.active {
|
||||
border-color: $white !important;
|
||||
background-color: #ECECEC;
|
||||
}
|
||||
|
||||
.avatar-image {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-position-y: -32px !important;
|
||||
}
|
||||
}
|
||||
}
|
46
src/views/inventory/views/bot/item/InventoryBotItemView.tsx
Normal file
46
src/views/inventory/views/bot/item/InventoryBotItemView.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { MouseEventType } from 'nitro-renderer';
|
||||
import { FC, MouseEvent, useCallback, useState } from 'react';
|
||||
import { AvatarImageView } from '../../../../avatar-image/AvatarImageView';
|
||||
import { useInventoryContext } from '../../../context/InventoryContext';
|
||||
import { InventoryBotActions } from '../../../reducers/InventoryBotReducer';
|
||||
import { attemptBotPlacement } from '../../../utils/BotUtilities';
|
||||
import { InventoryBotItemViewProps } from './InventoryBotItemView.types';
|
||||
|
||||
export const InventoryBotItemView: FC<InventoryBotItemViewProps> = props =>
|
||||
{
|
||||
const { botItem } = props;
|
||||
const { botState = null, dispatchBotState = null } = useInventoryContext();
|
||||
const [ isMouseDown, setMouseDown ] = useState(false);
|
||||
const isActive = (botState.botItem === botItem);
|
||||
|
||||
const onMouseEvent = useCallback((event: MouseEvent) =>
|
||||
{
|
||||
switch(event.type)
|
||||
{
|
||||
case MouseEventType.MOUSE_DOWN:
|
||||
dispatchBotState({
|
||||
type: InventoryBotActions.SET_BOT_ITEM,
|
||||
payload: { botItem }
|
||||
});
|
||||
|
||||
setMouseDown(true);
|
||||
return;
|
||||
case MouseEventType.MOUSE_UP:
|
||||
setMouseDown(false);
|
||||
return;
|
||||
case MouseEventType.ROLL_OUT:
|
||||
if(!isMouseDown || !isActive) return;
|
||||
|
||||
attemptBotPlacement(botItem);
|
||||
return;
|
||||
}
|
||||
}, [ isActive, isMouseDown, botItem, dispatchBotState ]);
|
||||
|
||||
return (
|
||||
<div className="col pe-1 pb-1 inventory-bot-item-container">
|
||||
<div className={ 'position-relative border border-2 rounded inventory-bot-item cursor-pointer ' + (isActive ? 'active' : '') } onMouseDown={ onMouseEvent } onMouseUp={ onMouseEvent } onMouseOut={ onMouseEvent }>
|
||||
<AvatarImageView figure={ botItem.botData.figure } direction={ 3 } headOnly={ true } />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { BotItem } from '../../../utils/BotItem';
|
||||
|
||||
export interface InventoryBotItemViewProps
|
||||
{
|
||||
botItem: BotItem;
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
.bot-item-container {
|
||||
height: 226px;
|
||||
max-height: 226px;
|
||||
overflow-y: auto;
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { FC } from 'react';
|
||||
import { InventoryBotItemView } from '../item/InventoryBotItemView';
|
||||
import { InventoryBotResultsViewProps } from './InventoryBotResultsView.types';
|
||||
|
||||
export const InventoryBotResultsView: FC<InventoryBotResultsViewProps> = props =>
|
||||
{
|
||||
const { botItems = [] } = props;
|
||||
|
||||
return (
|
||||
<div className="row row-cols-5 align-content-start g-0 bot-item-container">
|
||||
{ (botItems && botItems.length && botItems.map((item, index) =>
|
||||
{
|
||||
return <InventoryBotItemView key={ index } botItem={ item } />
|
||||
})) || null }
|
||||
</div>
|
||||
);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
import { BotItem } from '../../../utils/BotItem';
|
||||
|
||||
export interface InventoryBotResultsViewProps
|
||||
{
|
||||
botItems: BotItem[];
|
||||
}
|
Loading…
Reference in New Issue
Block a user