Skip to content

Commit 27cb91e

Browse files
committed
refactor GenericListSyncHandler & add GenericSetSyncHandler
1 parent 5f6cce2 commit 27cb91e

File tree

3 files changed

+268
-74
lines changed

3 files changed

+268
-74
lines changed
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package com.cleanroommc.modularui.value.sync;
2+
3+
import com.cleanroommc.modularui.utils.ICopy;
4+
import com.cleanroommc.modularui.utils.ObjectList;
5+
import com.cleanroommc.modularui.utils.serialization.IByteBufAdapter;
6+
import com.cleanroommc.modularui.utils.serialization.IByteBufDeserializer;
7+
import com.cleanroommc.modularui.utils.serialization.IByteBufSerializer;
8+
import com.cleanroommc.modularui.utils.serialization.IEquals;
9+
10+
import net.minecraft.network.PacketBuffer;
11+
12+
import org.jetbrains.annotations.NotNull;
13+
import org.jetbrains.annotations.Nullable;
14+
15+
import java.io.IOException;
16+
import java.util.*;
17+
import java.util.function.Consumer;
18+
import java.util.function.Supplier;
19+
20+
public abstract class GenericCollectionSyncHandler<T, C extends Collection<T>> extends ValueSyncHandler<C> {
21+
22+
private final Supplier<C> getter;
23+
private final Consumer<C> setter;
24+
private final IByteBufDeserializer<T> deserializer;
25+
private final IByteBufSerializer<T> serializer;
26+
private final IEquals<T> equals;
27+
private final ICopy<T> copy;
28+
29+
protected GenericCollectionSyncHandler(@NotNull Supplier<C> getter,
30+
@Nullable Consumer<C> setter,
31+
@NotNull IByteBufDeserializer<T> deserializer,
32+
@NotNull IByteBufSerializer<T> serializer,
33+
@Nullable IEquals<T> equals,
34+
@Nullable ICopy<T> copy) {
35+
this.getter = Objects.requireNonNull(getter);
36+
setCache(getter.get());
37+
this.setter = setter;
38+
this.deserializer = deserializer;
39+
this.serializer = serializer;
40+
this.equals = equals != null ? IEquals.wrapNullSafe(equals) : Objects::equals;
41+
this.copy = copy != null ? copy : ICopy.ofSerializer(serializer, deserializer);
42+
}
43+
44+
@Override
45+
public void setValue(C value, boolean setSource, boolean sync) {
46+
setCache(value);
47+
onSetCache(value, setSource, sync);
48+
}
49+
50+
protected abstract void setCache(C value);
51+
52+
protected void onSetCache(C value, boolean setSource, boolean sync) {
53+
if (setSource && this.setter != null) {
54+
this.setter.accept(value);
55+
}
56+
if (sync) {
57+
sync(0, this::write);
58+
}
59+
}
60+
61+
@Override
62+
public boolean updateCacheFromSource(boolean isFirstSync) {
63+
C c = this.getter.get();
64+
if (isFirstSync || didValuesChange(c)) {
65+
setValue(c, false, false);
66+
return true;
67+
}
68+
return false;
69+
}
70+
71+
protected abstract boolean didValuesChange(C newValues);
72+
73+
@Override
74+
public void write(PacketBuffer buffer) throws IOException {
75+
C c = getValue();
76+
buffer.writeVarInt(c.size());
77+
for (T t : c) {
78+
this.serializer.serialize(buffer, t);
79+
}
80+
}
81+
82+
@Override
83+
public abstract C getValue();
84+
85+
public boolean areValuesEqual(T a, T b) {
86+
return this.equals.areEqual(a, b);
87+
}
88+
89+
protected T deserializeValue(PacketBuffer buffer) throws IOException {
90+
return this.deserializer.deserialize(buffer);
91+
}
92+
93+
protected T copyValue(T value) {
94+
return this.copy.createDeepCopy(value);
95+
}
96+
97+
public static class Builder<T, C extends Collection<T>, B extends Builder<T, C, B>> {
98+
99+
protected Supplier<C> getter;
100+
protected Consumer<C> setter;
101+
protected IByteBufDeserializer<T> deserializer;
102+
protected IByteBufSerializer<T> serializer;
103+
protected IEquals<T> equals;
104+
protected ICopy<T> copy;
105+
106+
public B getter(Supplier<C> getter) {
107+
this.getter = getter;
108+
return getSelf();
109+
}
110+
111+
public B setter(Consumer<C> setter) {
112+
this.setter = setter;
113+
return getSelf();
114+
}
115+
116+
public B deserializer(IByteBufDeserializer<T> deserializer) {
117+
this.deserializer = deserializer;
118+
return getSelf();
119+
}
120+
121+
public B serializer(IByteBufSerializer<T> serializer) {
122+
this.serializer = serializer;
123+
return getSelf();
124+
}
125+
126+
// protected, because for sets the objects equals and hash code is used
127+
protected B equals(IEquals<T> equals) {
128+
this.equals = equals;
129+
return getSelf();
130+
}
131+
132+
public B adapter(IByteBufAdapter<T> adapter) {
133+
return deserializer(adapter).serializer(adapter).equals(adapter);
134+
}
135+
136+
public B copy(ICopy<T> copy) {
137+
this.copy = copy;
138+
return getSelf();
139+
}
140+
141+
public B immutableCopy() {
142+
return copy(ICopy.immutable());
143+
}
144+
145+
protected B getSelf() {
146+
return (B) this;
147+
}
148+
}
149+
}
Lines changed: 46 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package com.cleanroommc.modularui.value.sync;
22

3+
import com.cleanroommc.modularui.utils.ICopy;
34
import com.cleanroommc.modularui.utils.ObjectList;
4-
import com.cleanroommc.modularui.utils.serialization.IByteBufAdapter;
5+
56
import com.cleanroommc.modularui.utils.serialization.IByteBufDeserializer;
67
import com.cleanroommc.modularui.utils.serialization.IByteBufSerializer;
78
import com.cleanroommc.modularui.utils.serialization.IEquals;
@@ -12,108 +13,79 @@
1213
import org.jetbrains.annotations.Nullable;
1314

1415
import java.io.IOException;
16+
import java.util.Arrays;
1517
import java.util.Collections;
1618
import java.util.List;
17-
import java.util.Objects;
1819
import java.util.function.Consumer;
20+
import java.util.function.IntFunction;
1921
import java.util.function.Supplier;
2022

21-
public class GenericListSyncHandler<T> extends ValueSyncHandler<List<T>> {
23+
public class GenericListSyncHandler<T> extends GenericCollectionSyncHandler<T, List<T>> {
2224

23-
private final Supplier<List<T>> getter;
24-
private final Consumer<List<T>> setter;
25-
private final IByteBufDeserializer<T> deserializer;
26-
private final IByteBufSerializer<T> serializer;
27-
private final IEquals<T> equals;
2825
private final ObjectList<T> cache = ObjectList.create();
2926

30-
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter,
31-
@Nullable Consumer<List<T>> setter,
32-
@NotNull IByteBufAdapter<T> adapter) {
33-
this(getter, setter, adapter, adapter, adapter);
34-
}
35-
36-
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter,
37-
@Nullable Consumer<List<T>> setter,
38-
@NotNull IByteBufDeserializer<T> deserializer,
39-
@NotNull IByteBufSerializer<T> serializer) {
40-
this(getter, setter, deserializer, serializer, null);
41-
}
42-
43-
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter,
44-
@NotNull IByteBufAdapter<T> adapter) {
45-
this(getter, null, adapter, adapter, adapter);
46-
}
47-
48-
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter,
49-
@NotNull IByteBufDeserializer<T> deserializer,
50-
@NotNull IByteBufSerializer<T> serializer) {
51-
this(getter, null, deserializer, serializer, null);
52-
}
53-
54-
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter,
55-
@Nullable Consumer<List<T>> setter,
56-
@NotNull IByteBufDeserializer<T> deserializer,
57-
@NotNull IByteBufSerializer<T> serializer,
58-
@Nullable IEquals<T> equals) {
59-
this.getter = Objects.requireNonNull(getter);
60-
this.cache.addAll(getter.get());
61-
this.setter = setter;
62-
this.deserializer = deserializer;
63-
this.serializer = serializer;
64-
this.equals = equals != null ? IEquals.wrapNullSafe(equals) : Objects::equals;
27+
public GenericListSyncHandler(@NotNull Supplier<List<T>> getter, @Nullable Consumer<List<T>> setter, @NotNull IByteBufDeserializer<T> deserializer, @NotNull IByteBufSerializer<T> serializer, @Nullable IEquals<T> equals, @Nullable ICopy<T> copy) {
28+
super(getter, setter, deserializer, serializer, equals, copy);
6529
}
6630

6731
@Override
68-
public void setValue(List<T> value, boolean setSource, boolean sync) {
32+
protected void setCache(List<T> value) {
6933
this.cache.clear();
70-
this.cache.addAll(value);
71-
if (setSource && this.setter != null) {
72-
this.setter.accept(value);
73-
}
74-
if (sync) {
75-
sync(0, this::write);
34+
for (T item : value) {
35+
this.cache.add(copyValue(item));
7636
}
7737
}
7838

7939
@Override
80-
public boolean updateCacheFromSource(boolean isFirstSync) {
81-
List<T> i = this.getter.get();
82-
if (isFirstSync || didValuesChange(i)) {
83-
setValue(i, false, false);
84-
return true;
85-
}
86-
return false;
87-
}
88-
89-
private boolean didValuesChange(List<T> newValues) {
40+
protected boolean didValuesChange(List<T> newValues) {
9041
if (this.cache.size() != newValues.size()) return true;
91-
for (int i = 0, n = newValues.size(); i < n; i++) {
92-
if (!this.equals.areEqual(this.cache.get(i), newValues.get(i))) {
93-
return true;
94-
}
42+
for (int i = 0; i < this.cache.size(); i++) {
43+
if (!areValuesEqual(this.cache.get(i), newValues.get(i))) return true;
9544
}
9645
return false;
9746
}
9847

9948
@Override
100-
public void write(PacketBuffer buffer) throws IOException {
101-
buffer.writeVarInt(this.cache.size());
102-
for (T t : this.cache) {
103-
this.serializer.serialize(buffer, t);
104-
}
49+
public List<T> getValue() {
50+
return Collections.unmodifiableList(this.cache);
10551
}
10652

10753
@Override
10854
public void read(PacketBuffer buffer) throws IOException {
10955
this.cache.clear();
110-
for (int i = 0, n = buffer.readVarInt(); i < n; i++) {
111-
this.cache.add(this.deserializer.deserialize(buffer));
56+
for (int i = 0; i < buffer.readVarInt(); i++) {
57+
this.cache.add(deserializeValue(buffer));
11258
}
59+
onSetCache(getValue(), true, false);
11360
}
11461

115-
@Override
116-
public List<T> getValue() {
117-
return Collections.unmodifiableList(this.cache);
62+
public static <T> Builder<T> builder() {
63+
return new Builder<>();
64+
}
65+
66+
public static class Builder<T> extends GenericCollectionSyncHandler.Builder<T, List<T>, Builder<T>> {
67+
68+
public Builder<T> getterArray(Supplier<T[]> getter) {
69+
getter(() -> Arrays.asList(getter.get()));
70+
return this;
71+
}
72+
73+
public Builder<T> setterArray(Consumer<T[]> setter, IntFunction<T[]> arrayFactory) {
74+
setter(c -> setter.accept(c.toArray(arrayFactory.apply(c.size()))));
75+
return this;
76+
}
77+
78+
@Override
79+
public Builder<T> equals(IEquals<T> equals) {
80+
super.equals(equals);
81+
return this;
82+
}
83+
84+
public GenericListSyncHandler<T> build() {
85+
if (this.getter == null) throw new NullPointerException("Getter in GenericListSyncHandler must not be null");
86+
if (this.deserializer == null) throw new NullPointerException("Deserializer in GenericListSyncHandler must not be null");
87+
if (this.serializer == null) throw new NullPointerException("Serializer in GenericListSyncHandler must not be null");
88+
return new GenericListSyncHandler<>(this.getter, this.setter, this.deserializer, this.serializer, this.equals, this.copy);
89+
}
11890
}
11991
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package com.cleanroommc.modularui.value.sync;
2+
3+
import com.cleanroommc.modularui.utils.ICopy;
4+
import com.cleanroommc.modularui.utils.ObjectList;
5+
import com.cleanroommc.modularui.utils.serialization.IByteBufDeserializer;
6+
import com.cleanroommc.modularui.utils.serialization.IByteBufSerializer;
7+
import com.cleanroommc.modularui.utils.serialization.IEquals;
8+
9+
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
10+
11+
import net.minecraft.network.PacketBuffer;
12+
import org.jetbrains.annotations.NotNull;
13+
import org.jetbrains.annotations.Nullable;
14+
15+
import java.io.IOException;
16+
import java.util.Arrays;
17+
import java.util.Collections;
18+
import java.util.List;
19+
import java.util.Set;
20+
import java.util.function.Consumer;
21+
import java.util.function.IntFunction;
22+
import java.util.function.Supplier;
23+
24+
public class GenericSetSyncHandler<T> extends GenericCollectionSyncHandler<T, Set<T>> {
25+
26+
private final Set<T> cache = new ObjectOpenHashSet<>();
27+
28+
public GenericSetSyncHandler(@NotNull Supplier<Set<T>> getter, @Nullable Consumer<Set<T>> setter, @NotNull IByteBufDeserializer<T> deserializer, @NotNull IByteBufSerializer<T> serializer, @Nullable ICopy<T> copy) {
29+
super(getter, setter, deserializer, serializer, null, copy);
30+
}
31+
32+
@Override
33+
protected void setCache(Set<T> value) {
34+
this.cache.clear();
35+
for (T item : value) {
36+
this.cache.add(copyValue(item));
37+
}
38+
}
39+
40+
@Override
41+
protected boolean didValuesChange(Set<T> newValues) {
42+
if (this.cache.size() != newValues.size()) return true;
43+
return cache.containsAll(newValues);
44+
}
45+
46+
@Override
47+
public Set<T> getValue() {
48+
return Collections.unmodifiableSet(this.cache);
49+
}
50+
51+
@Override
52+
public void read(PacketBuffer buffer) throws IOException {
53+
this.cache.clear();
54+
for (int i = 0; i < buffer.readVarInt(); i++) {
55+
this.cache.add(deserializeValue(buffer));
56+
}
57+
onSetCache(getValue(), true, false);
58+
}
59+
60+
public static <T> Builder<T> builder() {
61+
return new Builder<>();
62+
}
63+
64+
public static class Builder<T> extends GenericCollectionSyncHandler.Builder<T, Set<T>, Builder<T>> {
65+
66+
public GenericSetSyncHandler<T> build() {
67+
if (this.getter == null) throw new NullPointerException("Getter in GenericListSyncHandler must not be null");
68+
if (this.deserializer == null) throw new NullPointerException("Deserializer in GenericListSyncHandler must not be null");
69+
if (this.serializer == null) throw new NullPointerException("Serializer in GenericListSyncHandler must not be null");
70+
return new GenericSetSyncHandler<>(this.getter, this.setter, this.deserializer, this.serializer, this.copy);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)