Skip to content
This repository has been archived by the owner on Feb 26, 2019. It is now read-only.

Commit

Permalink
support item swapping
Browse files Browse the repository at this point in the history
  • Loading branch information
RobertBlackhart committed Sep 16, 2015
1 parent 54f7856 commit 77de894
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 150 deletions.
111 changes: 33 additions & 78 deletions lib/src/display/inv_dragging.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,31 @@ part of couclient;

class InvDragging {
static List<String> disablers = [];
static Service refresh = new Service(["inventoryUpdated"], (_) => init());

static Service refresh;
/// Draggable items
static Draggable draggables;
/// Drop targets
static Dropzone dropzones;

static Element currentlyDisplaced, origBox;

/**
* Map used to store *how* the item was moved.
* Keys:
* - General:
* - - item_number: element: span element containing the count label
* - - bag_btn: element: the toggle button for containers
* - On Pickup:
* - - from_bag: boolean: whether the item used to be in a bag
* - - from_bag_index: int: which slot the to_bag is in (only set if from_bag is true)
* - - from_index: int: which slot the item used to be in
* - - fromBag: boolean: whether the item used to be in a bag
* - - fromBagIndex: int: which slot the toBag is in (only set if fromBag is true)
* - - fromIndex: int: which slot the item used to be in
* - On Drop:
* - - to_bag: boolean: whether the item is going into a bag
* - - to_bag_index: int: which slot the to_bag is in (only set if to_bag is true)
* - - to_index: int: which slot the item is going to
* - - toBag: boolean: whether the item is going into a bag
* - - toBagIndex: int: which slot the toBag is in (only set if toBag is true)
* - - toIndex: int: which slot the item is going to
*/
static Map<String, dynamic> move = {};

/// Returns an element list of boxes without items
static ElementList<Element> getEmptySlots() {
return querySelectorAll("#inventory .box:empty");
/// Bag windows manage their own acceptors
}

/// Returns an element list of items inside boxes
static ElementList<Element> getItems() {
return querySelectorAll(
"#inventory > .box > .inventoryItem, "
".bagwindow-box > .inventoryItem"
);
}

/// Checks if the specified slot is empty
static bool slotIsEmpty({int index, Element box, int bagWindow}) {
if (index != null) {
Expand All @@ -55,6 +42,9 @@ class InvDragging {

/// Set up event listeners based on the current inventory
static void init() {
if (refresh == null) {
refresh = new Service(["inventoryUpdated"], (_) => init());
}
// Remove old data
if (draggables != null) {
draggables.destroy();
Expand All @@ -66,10 +56,10 @@ class InvDragging {
if (disablers.length == 0) {
// Set up draggable elements
draggables = new Draggable(
// List of item elements in boxes
getItems(),
// List of item elements in boxes
querySelectorAll('.inventoryItem'),
// Display the item on the cursor
avatarHandler: new AvatarHandler.clone(),
avatarHandler: new CustomAvatarHandler(),
// If a bag is open, allow free dragging.
// If not, only allow horizontal dragging across the inventory bar
horizontalOnly: !BagWindow.isOpen,
Expand All @@ -78,72 +68,37 @@ class InvDragging {
)
..onDragStart.listen((DraggableEvent e) => handlePickup(e));

// Set up empty acceptor slots
dropzones = new Dropzone(getEmptySlots())
..onDragEnter.listen((DropzoneEvent e) => handleZoneEntry(e))
// Set up acceptor slots
dropzones = new Dropzone(querySelectorAll("#inventory .box"))
..onDrop.listen((DropzoneEvent e) => handleDrop(e));
}
}

/// Runs when an item is picked up (drag start)
static void handlePickup(DraggableEvent e) {
Element origBox = e.draggableElement.parent;
origBox = e.draggableElement.parent;
e.draggableElement.dataset["original-slot-num"] = origBox.dataset["slot-num"];

move = {};

move["from_bag"] = querySelector("#windowHolder").contains(origBox);
if (move["from_bag"]) {
move["from_bag_index"] = origBox.parent.parent.dataset["source-bag"];
}
move["from_index"] = origBox.dataset["slot-num"];

// Remove item count/bag button and save it for later
if (origBox.querySelector(".itemCount") != null) {
move["item_count"] = origBox.querySelector(".itemCount").clone(true);
origBox.querySelector(".itemCount").remove();
}

if (origBox.querySelector(".item-container-toggle") != null) {
move["bag_btn"] = origBox.querySelector(".item-container-toggle").clone(true);
origBox.querySelector(".item-container-toggle").remove();
}
}

/// Runs when an item enters a dropzone (drag enter)
static void handleZoneEntry(DropzoneEvent e) {
if (slotIsEmpty(box: e.dropzoneElement)) {
e.dropzoneElement.children.add(e.draggableElement);
if (querySelector("#windowHolder").contains(origBox)) {
move['fromIndex'] = int.parse(origBox.parent.parent.dataset["source-bag"]);
move["fromBagIndex"] = int.parse(origBox.dataset["slot-num"]);
} else {
move['fromIndex'] = int.parse(origBox.dataset["slot-num"]);
}
}

/// Runs when an item is dropped (drop)
static void handleDrop(DropzoneEvent e) {
move["to_bag"] = querySelector("#windowHolder").contains(e.dropzoneElement);
if (move["to_bag"]) {
move["to_bag_index"] = int.parse(e.dropzoneElement.parent.parent.dataset["source-bag"]);
if (querySelector("#windowHolder").contains(e.dropzoneElement)) {
move["toIndex"] = int.parse(e.dropzoneElement.parent.parent.dataset["source-bag"]);
move["toBagIndex"] = int.parse(e.dropzoneElement.dataset["slot-num"]);
} else {
move["toIndex"] = int.parse(e.dropzoneElement.dataset["slot-num"]);
}
move["to_index"] = e.dropzoneElement.dataset["slot-num"];

Map sendData = move;
if (sendData.containsKey("item_count")) {
sendData.remove("item_count");
}
if (sendData.containsKey("bag_btn")) {
sendData.remove("bag_btn");
}
sendAction("moveItem", "global_action_monster", move);

// Reapply item count & bag button
if (move["item_count"] != null) {
e.dropzoneElement.append(move["item_count"]);
}
if (move["bag_btn"] != null) {
e.dropzoneElement.append(move["bag_btn"]);
}

// Refresh data after DOM changes finish
new Timer(new Duration(milliseconds: 50), () => init());
}
}

Expand All @@ -153,14 +108,14 @@ class BagFilterAcceptor extends Acceptor {
List<String> allowedItemTypes;

@override
bool accepts(Element item, int draggable_id, Element box) {
bool accepts(Element itemE, int draggable_id, Element box) {
ItemDef item = decode(itemE.attributes['itemmap'],type:ItemDef);
if (allowedItemTypes.length == 0) {
// Those that accept nothing learn to accept everything
return true;
// Those that accept nothing learn to accept everything (except other containers)
return !item.isContainer;
} else {
// Those that are at least somewhat accepting are fine, though
String itemType = JSON.decode(item.attributes["itemmap"])["itemType"];
return allowedItemTypes.contains(itemType);
return allowedItemTypes.contains(item.itemType);
}
}
}
90 changes: 38 additions & 52 deletions lib/src/display/windows/bag_window.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,30 @@ class BagWindow extends Modal {
Dropzone acceptors;

BagWindow(this.sourceSlotNum, ItemDef sourceItem) {
DivElement windowElement = load(sourceItem);
querySelector("#windowHolder").append(windowElement);
prepare();
open();
openWindows.add(this);
load(sourceItem).then((DivElement windowElement) {
// Handle drag and drop
new Service(["inventoryUpdated"], (_) async {
if (acceptors != null) {
acceptors.destroy();
}
acceptors = new Dropzone(
windowElement.querySelectorAll(".bagwindow-box"),
acceptor: new BagFilterAcceptor(sourceItem.subSlotFilter)
)
..onDrop.listen((DropzoneEvent e) => InvDragging.handleDrop(e));
});
new Service(['updateMetadata'], (sourceItem) async {
windowElement.querySelector("ur-well").replaceWith(await load(sourceItem, false));
transmit('inventoryUpdated',true);
});

// Handle drag and drop
transmit("inventoryUpdated");
new Service(["inventoryUpdated"], (_) {
windowElement.querySelector("ur-well").replaceWith(load(sourceItem, false));
if (acceptors != null) {
acceptors.destroy();
}
acceptors = new Dropzone(
windowElement.querySelectorAll(".bagwindow-box:empty"),
acceptor: new BagFilterAcceptor(sourceItem.subSlotFilter)
)
..onDragEnter.listen((DropzoneEvent e) => InvDragging.handleZoneEntry(e))
..onDrop.listen((DropzoneEvent e) => InvDragging.handleDrop(e));
InvDragging.init();
querySelector("#windowHolder").append(windowElement);
prepare();
open();
});
}

Element load(ItemDef sourceItem, [bool full = true]) {
Future<Element> load(ItemDef sourceItem, [bool full = true]) async {

// Header

Expand Down Expand Up @@ -100,24 +100,23 @@ class BagWindow extends Modal {
throw new StateError("Number of slots in bag does not match bag size");
} else {
int slotNum = 0;
subSlots.forEach((Map bagSlot) {
await Future.forEach(subSlots, (Map bagSlot) async {
DivElement slot = new DivElement();
// Item
DivElement itemInSlot;
if (!bagSlot["itemType"].isEmpty) {
itemInSlot = new DivElement();
ItemDef item = decode(JSON.encode(bagSlot['item']),type:ItemDef);
_sizeItem(slot,itemInSlot,item,bagSlot['count'],slotNum);
}
// Slot
slot
..classes.addAll(["box", "bagwindow-box"])
..dataset["slot-num"] = slotNum.toString();
if (itemInSlot != null) {
slot.append(itemInSlot);
well.append(slot);
document.body.append(well); //for measuring
// Item
DivElement itemInSlot = new DivElement();
slot.append(itemInSlot);
if (!bagSlot["itemType"].isEmpty) {
ItemDef item = decode(JSON.encode(bagSlot['item']),type:ItemDef);
await _sizeItem(slot,itemInSlot,item,bagSlot['count'],slotNum);
}
well.remove();

well.append(slot);
slotNum++;
});
}
Expand Down Expand Up @@ -182,37 +181,27 @@ class BagWindow extends Modal {

@override
open() {
displayElement.hidden = false;
elementOpen = true;
this.focus();
super.open();
openWindows.add(this);

transmit("inventoryUpdated");
transmit('inventoryUpdated',true);
}

@override
close() {
// Handle window closing
_destroyEscListener();
displayElement.hidden = true;
elementOpen = false;

//see if there's another window that we want to focus
for (Element modal in querySelectorAll('.window')) {
if (!modal.hidden) {
modals[modal.id].focus();
}
}
super.close();

// Delete the window
if (querySelector("#${id.toString()}") != null) {
querySelector("#${id.toString()}").remove();
Element window = querySelector("#$id");
if (window != null) {
window.remove();
}

// Update the source inventory icon
Element sourceBox = view.inventory.children.where((Element box) => box.dataset["slot-num"] == sourceSlotNum.toString()).first;
sourceBox.querySelector(".item-container-toggle").click();

transmit("inventoryUpdated");
transmit('inventoryUpdated',true);
}

// Update the inventory icons (used by the inventory)
Expand All @@ -236,8 +225,5 @@ class BagWindow extends Modal {
..add("fa-plus");
item.classes.remove("inv-item-disabled");
}

// Enable/disable inventory dragging
transmit("inventoryUpdated");
}
}
10 changes: 2 additions & 8 deletions lib/src/network/server_interop/so_item.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ itemContextMenu(ItemDef i, String slot, MouseEvent event) {
}

findNewSlot(ItemDef item, ImageElement img, int index, {bool update: false}) {
bool found = false;

Element barSlot = view.inventory.children.elementAt(index);
String cssName = item.itemType.replaceAll(" ", "_");
Element itemDiv = new DivElement();
Expand Down Expand Up @@ -99,8 +97,6 @@ findNewSlot(ItemDef item, ImageElement img, int index, {bool update: false}) {
});
itemDiv.parent.append(containerButton);
}

found = true;
}

void putInInventory(ImageElement img, ItemDef i, int index, {bool update: false}) {
Expand Down Expand Up @@ -139,8 +135,7 @@ void putInInventory(ImageElement img, ItemDef i, int index, {bool update: false}
if (!found) {
findNewSlot(i, img, index, update: update);
}
// Refresh inventory dragging
InvDragging.init();
transmit("inventoryUpdated");
}

void addItemToInventory(ItemDef item, int index, {bool update: false}) {
Expand Down Expand Up @@ -171,8 +166,7 @@ void takeItemFromInventory(String itemType, {int count: 1}) {

remaining -= uiCount;
}
// Refresh inventory dragging
InvDragging.init();
transmit("inventoryUpdated");
}

Map getDropMap(int count, int slotNum, int subSlotNum) {
Expand Down
Loading

0 comments on commit 77de894

Please sign in to comment.