Last active
March 3, 2022 05:05
-
-
Save Stuyk/6e456e6c254c12faa1b6ec4c34c2fb34 to your computer and use it in GitHub Desktop.
Drag and Drop Inventory for alt:V
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Vue.component('inventory', { | |
data: () => { | |
return { | |
inventory: [], | |
targetDrag: null, | |
hoveredItem: null, | |
targetTooltip: null, | |
mouseX: 0, | |
mouseY: 0 | |
}; | |
}, | |
methods: { | |
getMousePosition() { | |
return { top: `${this.mouseY}px`, left: `${this.mouseX}px` }; | |
}, | |
route(emitRoute, e) { | |
app.$emit(emitRoute, e, this.title); | |
}, | |
mouseMove(e) { | |
this.mouseX = e.clientX; | |
this.mouseY = e.clientY; | |
}, | |
mouseOver(e) { | |
if (this.targetDrag === null) { | |
return; | |
} | |
this.hoveredItem = parseInt(e.target.id); | |
}, | |
mouseDown(e) { | |
if (!e.target.id) { | |
return; | |
} | |
this.targetDrag = parseInt(e.target.id); | |
this.mouseMoveBind = this.mouseMove.bind(this); | |
this.mouseUpBind = this.mouseUp.bind(this); | |
window.addEventListener('mousemove', this.mouseMoveBind); | |
window.addEventListener('mouseup', this.mouseUpBind); | |
}, | |
mouseUp(e) { | |
this.updating = true; | |
if (!e.target.classList.contains('itemPlaceholder')) { | |
this.updating = false; | |
return; | |
} | |
this.hoveredItem = null; | |
window.removeEventListener('mousemove', this.mouseMoveBind); | |
window.removeEventListener('mouseup', this.mouseUpBind); | |
if (this.targetDrag === null) { | |
this.updating = false; | |
return; | |
} | |
const oldIndex = this.targetDrag; | |
const newIndex = parseInt(e.target.id); | |
if (isNaN(newIndex)) { | |
this.updating = false; | |
this.targetDrag = null; | |
const itemRef = { ...this.inventory[oldIndex] }; | |
if (!itemRef) { | |
return; | |
} | |
const id = e.target.id.replace('equip-', ''); | |
app.$emit('equipment:Slot', parseInt(id), itemRef); | |
return; | |
} | |
this.targetDrag = null; | |
if (oldIndex === newIndex) { | |
this.updating = false; | |
return; | |
} | |
const oldItem = this.inventory[oldIndex] ? { ...this.inventory[oldIndex] } : null; | |
const newItem = this.inventory[newIndex] ? { ...this.inventory[newIndex] } : null; | |
if (!oldItem) { | |
this.updating = false; | |
return; | |
} | |
this.inventory[newIndex] = oldItem; | |
this.inventory[oldIndex] = newItem; | |
this.updating = false; | |
/** | |
* Purpose: | |
* Push item indexes and values client-side. | |
* Store the item hash + index position to local storage. | |
* Fetch these positions on inventory render. | |
* Stop storing swaps on server-side. | |
*/ | |
if ('alt' in window) { | |
alt.emit('inventory:TrackItem', newIndex, this.inventory[newIndex]); | |
alt.emit('inventory:TrackItem', oldIndex, this.inventory[oldIndex]); | |
} | |
}, | |
rightClickItem(hash) { | |
const index = this.inventory.findIndex(item => item && item.hash === hash); | |
if (index <= -1) { | |
return; | |
} | |
if (!this.inventory[index]) { | |
return; | |
} | |
if ('alt' in window) { | |
alt.emit('window:Route', 'inventory:UseItem', this.inventory[index].hash); | |
} else { | |
console.log(this.inventory[index]); | |
} | |
}, | |
getHoveredClass(index) { | |
return this.hoveredItem === index ? { hovered: true } : {}; | |
}, | |
removeItem(index) { | |
this.inventory[index] = null; | |
}, | |
setInventory(items) { | |
this.inventory = items; | |
} | |
}, | |
mounted() { | |
if ('alt' in window) { | |
alt.on('inventory:SetInventory', this.setInventory); | |
alt.emit('inventory:Fetch'); | |
} else { | |
const items = new Array(48).fill(null); | |
items[1] = null; | |
items[0] = { | |
name: 'Fish Taco That Is Super Delicious Testing The Long Ass Item Name Blah Blah', | |
base: 'Food', | |
quantity: 1, | |
hash: '90840921922', | |
icon: 'fish', | |
props: { | |
level: 1, | |
fuck: { | |
level: 2, | |
shit: { | |
level: 3 | |
} | |
} | |
} | |
}; | |
items[2] = { | |
name: 'Fishing Rod', | |
base: 'Hand', | |
quantity: 1, | |
hash: '149214', | |
icon: 'fishingrod', | |
props: { | |
durability: 500 | |
} | |
}; | |
items[3] = { | |
name: 'Refined Metal', | |
base: 'metal', | |
quantity: 5000, | |
hash: '1492174', | |
icon: 'metal' | |
}; | |
for (let i = 4; i < 28; i++) { | |
items[i] = { | |
name: 'Refined Metal', | |
base: 'metal', | |
quantity: 5000, | |
hash: `afdsafds${Math.floor(Math.random() * 5000)}`, | |
icon: 'metal' | |
}; | |
} | |
this.inventory = items; | |
} | |
this.$root.$on('inventory:RemoveItem', this.removeItem); | |
}, | |
template: ` | |
<div class="inventoryContainer" v-if="inventory && !this.updating"> | |
<div v-for="(item, index) in inventory" class="item" :class="getHoveredClass(index)"> | |
<template v-if="item && item.name"> | |
<div class="itemPlaceholder" | |
:id="index" @mousedown.left="mouseDown" | |
@mouseup.right="rightClickItem(item.hash)" | |
@mouseover="mouseOver" | |
@contextmenu.prevent | |
> | |
<div v-if="index <= 3" class="hotbar">{{ index + 1 }}</div> | |
<div v-if="item.quantity >= 2" class="quantity">{{ item.quantity }}</div> | |
<component :is="'icon-' + item.icon" /> | |
</div> | |
</template> | |
<template v-else> | |
<div | |
class="itemPlaceholder" | |
:id="index" | |
@mouseover="mouseOver" | |
@contextmenu.prevent | |
> | |
<div v-if="index <= 3" class="hotbar">{{ index + 1 }}</div> | |
</div> | |
</template> | |
</div> | |
<div v-if="this.targetDrag !== null" class="draggedItem" :style="getMousePosition()"> | |
<component :is="'icon-' + this.inventory[this.targetDrag].icon" /> | |
</div> | |
</div> | |
` | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.inventoryContainer { | |
display: grid; | |
grid-template-columns: repeat(4, 1fr); | |
grid-auto-rows: 1fr; | |
row-gap: 6px; | |
column-gap: 6px; | |
background: rgba(0, 0, 0, 0.5); | |
overflow-y: visible; | |
overflow-x: hidden; | |
padding: 6px; | |
box-sizing: border-box; | |
width: 100%; | |
user-select: none; | |
.item { | |
position: relative; | |
background: rgba(0, 0, 0, 0.5); | |
border: 2px solid rgba(255, 255, 255, 0.2); | |
&:hover { | |
border-color: rgba(125, 125, 125, 1); | |
.hotbar { | |
background: rgba(125, 125, 125, 1); | |
} | |
.itemPlaceholder { | |
.quantity { | |
background-color: rgba(125, 125, 125, 1); | |
} | |
img { | |
opacity: 0.95; | |
} | |
} | |
} | |
.itemPlaceholder { | |
position: relative; | |
width: 100%; | |
height: 100%; | |
padding: 6px; | |
box-sizing: border-box; | |
.quantity { | |
position: absolute; | |
padding-left: 3px; | |
padding-top: 3px; | |
right: 0; | |
bottom: 0; | |
color: @contrast1; | |
z-index: 99; | |
background: rgba(65, 65, 65, 1); | |
border-top-left-radius: 5px; | |
pointer-events: none; | |
font-size: 12px; | |
} | |
img { | |
user-select: none; | |
pointer-events: none; | |
opacity: 0.75; | |
} | |
} | |
.hotbar { | |
position: absolute; | |
color: @success; | |
font-family: @RobotoCondensed; | |
font-weight: 700; | |
z-index: 99; | |
pointer-events: none; | |
background: rgba(65, 65, 65, 1); | |
border-bottom-right-radius: 7px; | |
min-height: 15px; | |
max-height: 15px; | |
top: 0; | |
left: -1px; | |
line-height: 1em; | |
padding: 5px; | |
} | |
} | |
.hovered { | |
border-color: @contrast1 !important; | |
} | |
.placeholder { | |
border-style: dashed !important; | |
} | |
.draggedItem { | |
display: block; | |
position: fixed; | |
width: 50px; | |
height: 50px; | |
background: rgba(45, 45, 45, 1); | |
border: 2px solid rgba(255, 255, 255, 0.5); | |
user-select: none; | |
pointer-events: none; | |
box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.5); | |
z-index: 1000 !important; | |
padding: 6px; | |
img { | |
width: 100%; | |
height: 100%; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment