Skip to content

Commit df35a73

Browse files
committed
Import graph backing datastructure
1 parent ef11fac commit df35a73

8 files changed

Lines changed: 586 additions & 9 deletions

File tree

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ moddev_version = 2.0.80
88
minivan_version = 0.5
99
versioning_version = 1.0.0
1010
kpublish_version = 1.0.0
11-
submodule_version = 0.9.1
11+
submodule_version = 0.9.3
1212
remapcheck_version = 0.3.4
1313

1414
# Fabric Properties
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package com.kneelawk.graphlib.v3.api.datastructure;
2+
3+
import java.util.Objects;
4+
5+
// Translated from 2xsaiko's HCTM-Base Graph code:
6+
// https://github.com/2xsaiko/hctm-base/blob/119df440743543b8b4979b450452d73f2c3c4c47/src/main/kotlin/common/graph/Graph.kt
7+
8+
/**
9+
* Link in a general purpose graph data structure.
10+
* <p>
11+
* This link is non-directional. A link from node 'A' to node 'B' is equal to a link from node 'B' to node 'A'. This is
12+
* upheld in this type's {@link #equals(Object)} and {@link #hashCode()}.
13+
* <p>
14+
* If a link needs to be directional, then its data should reference one of the nodes, making it asymmetrical.
15+
* Referencing a node can be done with a {@link com.kneelawk.graphlib.v3.api.pos.NodePos}.
16+
*
17+
* @param first the first node in this link.
18+
* @param second the second node in this link.
19+
* @param key the key that makes this link unique out of all the links between the same two nodes.
20+
* @param <K> the type of key used to index each node.
21+
* @param <L> the type of link data contained in this link.
22+
*/
23+
public record KeyedLink<K, L>(KeyedNode<K, L> first, KeyedNode<K, L> second, L key) {
24+
/**
25+
* Checks to see if the given node is either of the two nodes in this link.
26+
*
27+
* @param node the node to check.
28+
* @return <code>true</code> if the given node is either of the nodes in this link.
29+
*/
30+
public boolean contains(KeyedNode<K, L> node) {
31+
return Objects.equals(first, node) || Objects.equals(second, node);
32+
}
33+
34+
/**
35+
* Checks to see if the given key is for either of the two nodes in this link.
36+
*
37+
* @param key the key to check.
38+
* @return <code>true</code> if a node with the given key is wither of the nodes in this link.
39+
*/
40+
public boolean contains(K key) {
41+
return Objects.equals(first.key(), key) || Objects.equals(second.key(), key);
42+
}
43+
44+
/**
45+
* Gets the node opposite the given node.
46+
*
47+
* @param node the node to get the other end of the link from.
48+
* @return the node at the other end of the link from the given node.
49+
*/
50+
public KeyedNode<K, L> other(KeyedNode<K, L> node) {
51+
if (Objects.equals(first, node)) {
52+
return second;
53+
} else {
54+
return first;
55+
}
56+
}
57+
58+
/**
59+
* Gets the node opposite the node with the given key.
60+
*
61+
* @param key the key of the node to get the other end of hte link from.
62+
* @return the node at the other end of the link from the node with the given key.
63+
*/
64+
public KeyedNode<K, L> other(K key) {
65+
if (Objects.equals(first.key(), key)) {
66+
return second;
67+
} else {
68+
return first;
69+
}
70+
}
71+
72+
@Override
73+
public boolean equals(Object o) {
74+
if (this == o) return true;
75+
if (o == null || getClass() != o.getClass()) return false;
76+
77+
KeyedLink<?, ?> linkKey = (KeyedLink<?, ?>) o;
78+
79+
if (!key.equals(linkKey.key)) return false;
80+
81+
// note: hashCode and equals are symmetrical regardless of node order
82+
if (first.equals(linkKey.first)) {
83+
return second.equals(linkKey.second);
84+
} else if (second.equals(linkKey.first)) {
85+
return first.equals(linkKey.second);
86+
}
87+
88+
return false;
89+
}
90+
91+
@Override
92+
public int hashCode() {
93+
// note: hashCode and equals are symmetrical regardless of node order
94+
int result = first.hashCode();
95+
result = result ^ second.hashCode();
96+
result = 31 * result + key.hashCode();
97+
return result;
98+
}
99+
100+
@Override
101+
public String toString() {
102+
return "link(" + first + " <-> " + second + ", " + key + ')';
103+
}
104+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package com.kneelawk.graphlib.v3.api.datastructure;
2+
3+
import java.util.Objects;
4+
import java.util.Set;
5+
6+
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
7+
8+
// Translated from 2xsaiko's HCTM-Base Graph code:
9+
// https://github.com/2xsaiko/hctm-base/blob/119df440743543b8b4979b450452d73f2c3c4c47/src/main/kotlin/common/graph/Graph.kt
10+
11+
/**
12+
* Node in a general purpose graph data structure.
13+
*
14+
* @param <K> the key of this node.
15+
* @param <L> the type of link data contained in links between nodes.
16+
*/
17+
public final class KeyedNode<K, L> {
18+
private final K key;
19+
private final Set<KeyedLink<K, L>> connections;
20+
21+
/**
22+
* Constructs a new node containing the given data.
23+
*
24+
* @param key the data for this node to contain.
25+
*/
26+
public KeyedNode(K key) {
27+
this.key = key;
28+
this.connections = new ObjectLinkedOpenHashSet<>();
29+
}
30+
31+
/**
32+
* Gets this node's key.
33+
*
34+
* @return this node's key.
35+
*/
36+
public K key() {
37+
return key;
38+
}
39+
40+
/**
41+
* Gets this node's connections.
42+
*
43+
* @return this node's connections.
44+
*/
45+
public Set<KeyedLink<K, L>> connections() {
46+
return connections;
47+
}
48+
49+
/**
50+
* Called when another node is added to the graph.
51+
*
52+
* @param other the other node added to the graph.
53+
*/
54+
public void onAdded(KeyedNode<K, L> other) {
55+
}
56+
57+
/**
58+
* Called when another node is removed from the graph so that this node can remove it from its connections.
59+
*
60+
* @param other the other node removed from the graph.
61+
*/
62+
public void onRemoved(KeyedNode<K, L> other) {
63+
connections.removeIf(link -> link.contains(other));
64+
}
65+
66+
/**
67+
* Adds the given link as a connection this node has.
68+
*
69+
* @param link the link between this node and another node.
70+
* @return <code>true</code> if the link did not already exist.
71+
*/
72+
public boolean onLink(KeyedLink<K, L> link) {
73+
return connections.add(link);
74+
}
75+
76+
/**
77+
* Removes the given link as a connection this node has.
78+
* <p>
79+
* Note: links are technically directional and must be removed twice, once in each direction, to make sure the link
80+
* has actually been removed.
81+
*
82+
* @param link the link to remove.
83+
* @return <code>true</code> if the link existed before being removed.
84+
*/
85+
public boolean onUnlink(KeyedLink<K, L> link) {
86+
return connections.remove(link);
87+
}
88+
89+
@Override
90+
public boolean equals(Object obj) {
91+
if (obj == this) return true;
92+
if (obj == null || obj.getClass() != this.getClass()) return false;
93+
@SuppressWarnings("rawtypes") var that = (KeyedNode) obj;
94+
return Objects.equals(this.key, that.key);
95+
}
96+
97+
@Override
98+
public int hashCode() {
99+
return Objects.hash(key);
100+
}
101+
102+
@Override
103+
public String toString() {
104+
return "node[" + key + ']';
105+
}
106+
}

0 commit comments

Comments
 (0)