Skip to content

Instantly share code, notes, and snippets.

@Stuyk
Last active Oct 3, 2021
Embed
What would you like to do?
Drag and Drop Inventory for alt:V
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>
`
});
.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