Commits

Mikołaj Nowak authored and md_5 committed fa10c5029fe
SPIGOT-5784, SPIGOT-6858, #1527: Add villager reputation API
No tags

nms-patches/net/minecraft/world/entity/ai/gossip/Reputation.patch

Added
1 +--- a/net/minecraft/world/entity/ai/gossip/Reputation.java
2 ++++ b/net/minecraft/world/entity/ai/gossip/Reputation.java
3 +@@ -30,13 +30,27 @@
4 + import net.minecraft.util.VisibleForDebug;
5 + import org.slf4j.Logger;
6 +
7 ++// CraftBukkit start
8 ++import net.minecraft.world.entity.npc.EntityVillager;
9 ++import org.bukkit.craftbukkit.entity.CraftVillager.CraftReputationType;
10 ++import org.bukkit.craftbukkit.event.CraftEventFactory;
11 ++import org.bukkit.entity.Villager;
12 ++import org.bukkit.event.entity.VillagerReputationChangeEvent;
13 ++// CraftBukkit end
14 ++
15 + public class Reputation {
16 +
17 + private static final Logger LOGGER = LogUtils.getLogger();
18 + public static final int DISCARD_THRESHOLD = 2;
19 + private final Map<UUID, Reputation.a> gossips = Maps.newHashMap();
20 +
21 +- public Reputation() {}
22 ++ // CraftBukkit start - store reference to villager entity
23 ++ private final EntityVillager villager;
24 ++
25 ++ public Reputation(EntityVillager villager) {
26 ++ this.villager = villager;
27 ++ }
28 ++ // CraftBukkit end
29 +
30 + @VisibleForDebug
31 + public Map<UUID, Object2IntMap<ReputationType>> getGossipEntries() {
32 +@@ -51,15 +65,17 @@
33 + }
34 +
35 + public void decay() {
36 +- Iterator<Reputation.a> iterator = this.gossips.values().iterator();
37 ++ Iterator<Map.Entry<UUID, Reputation.a>> iterator = this.gossips.entrySet().iterator(); // CraftBukkit - iterate over entries instead of values to access entity UUID
38 +
39 + while (iterator.hasNext()) {
40 +- Reputation.a reputation_a = (Reputation.a) iterator.next();
41 ++ // CraftBukkit start - pass villager and entity UUID to decay method
42 ++ Map.Entry<UUID, Reputation.a> reputation_a = iterator.next();
43 +
44 +- reputation_a.decay();
45 +- if (reputation_a.isEmpty()) {
46 ++ reputation_a.getValue().decay(villager, reputation_a.getKey());
47 ++ if (reputation_a.getValue().isEmpty()) {
48 + iterator.remove();
49 + }
50 ++ // CraftBukkit end
51 + }
52 +
53 + }
54 +@@ -112,16 +128,27 @@
55 + int j = reputation_b.value - reputation_b.type.decayPerTransfer;
56 +
57 + if (j >= 2) {
58 +- this.getOrCreate(reputation_b.target).entries.mergeInt(reputation_b.type, j, Reputation::mergeValuesForTransfer);
59 ++ // CraftBukkit start - redirect to a method which fires an event before setting value
60 ++ this.set(reputation_b.target, reputation_b.type, Reputation.mergeValuesForTransfer(getReputation(reputation_b.target, Predicate.isEqual(reputation_b.type), false), j), Villager.ReputationEvent.GOSSIP);
61 ++ //this.getOrCreate(reputation_b.target).entries.mergeInt(reputation_b.type, j, Reputation::mergeValuesForTransfer);
62 ++ // CraftBukkit end
63 + }
64 +
65 + });
66 + }
67 +
68 + public int getReputation(UUID uuid, Predicate<ReputationType> predicate) {
69 ++ // CraftBukkit start - add getReputation overload with additional parameter
70 ++ return getReputation(uuid, predicate, true);
71 ++ }
72 ++
73 ++ public int getReputation(UUID uuid, Predicate<ReputationType> predicate, boolean weighted) {
74 ++ // CraftBukkit end
75 + Reputation.a reputation_a = (Reputation.a) this.gossips.get(uuid);
76 +
77 +- return reputation_a != null ? reputation_a.weightedValue(predicate) : 0;
78 ++ // CraftBukkit start - handle weighted parameter
79 ++ return reputation_a != null ? (weighted ? reputation_a.weightedValue(predicate) : reputation_a.unweightedValue(predicate)) : 0;
80 ++ // CraftBukkit end
81 + }
82 +
83 + public long getCountForType(ReputationType reputationtype, DoublePredicate doublepredicate) {
84 +@@ -131,27 +158,58 @@
85 + }
86 +
87 + public void add(UUID uuid, ReputationType reputationtype, int i) {
88 ++ // CraftBukkit start - add change reason parameter
89 ++ add(uuid, reputationtype, i, Villager.ReputationEvent.UNSPECIFIED);
90 ++ }
91 ++
92 ++ public void add(UUID uuid, ReputationType reputationtype, int i, Villager.ReputationEvent changeReason) {
93 ++ // CraftBukkit end
94 + Reputation.a reputation_a = this.getOrCreate(uuid);
95 +
96 ++ int oldValue = reputation_a.entries.getInt(reputationtype); // CraftBukkit - store old value
97 + reputation_a.entries.mergeInt(reputationtype, i, (j, k) -> {
98 + return this.mergeValuesForAddition(reputationtype, j, k);
99 + });
100 +- reputation_a.makeSureValueIsntTooLowOrTooHigh(reputationtype);
101 ++ // CraftBukkit start - fire reputation change event
102 ++ int newValue = reputation_a.entries.getInt(reputationtype);
103 ++ newValue = Math.max(0, Math.min(newValue, reputationtype.max));
104 ++ reputation_a.entries.replace(reputationtype, oldValue); // restore old value until the event completed processing
105 ++ VillagerReputationChangeEvent event = CraftEventFactory.callVillagerReputationChangeEvent((Villager) villager.getBukkitEntity(), uuid, changeReason, CraftReputationType.minecraftToBukkit(reputationtype), oldValue, newValue, reputationtype.max);
106 ++ if (!event.isCancelled()) {
107 ++ reputation_a.entries.replace(reputationtype, event.getNewValue());
108 ++ reputation_a.makeSureValueIsntTooLowOrTooHigh(reputationtype);
109 ++ }
110 ++ // CraftBukkit end
111 + if (reputation_a.isEmpty()) {
112 + this.gossips.remove(uuid);
113 + }
114 +
115 + }
116 +
117 +- public void remove(UUID uuid, ReputationType reputationtype, int i) {
118 +- this.add(uuid, reputationtype, -i);
119 ++ // CraftBukkit start
120 ++ public void set(UUID uuid, ReputationType reputationType, int i, Villager.ReputationEvent changeReason) {
121 ++ int addAmount = i - getReputation(uuid, Predicate.isEqual(reputationType), false);
122 ++ if (addAmount == 0) {
123 ++ return;
124 ++ }
125 ++ this.add(uuid, reputationType, addAmount, changeReason);
126 + }
127 ++ // CraftBukkit end
128 +
129 +- public void remove(UUID uuid, ReputationType reputationtype) {
130 ++ // CraftBukkit start - add change reason parameter
131 ++ public void remove(UUID uuid, ReputationType reputationtype, int i, Villager.ReputationEvent changeReason) {
132 ++ this.add(uuid, reputationtype, -i, changeReason);
133 ++ }
134 ++ // CraftBukkit end
135 ++
136 ++ public void remove(UUID uuid, ReputationType reputationtype, Villager.ReputationEvent changeReason) { // CraftBukkit - add change reason parameter
137 + Reputation.a reputation_a = (Reputation.a) this.gossips.get(uuid);
138 +
139 + if (reputation_a != null) {
140 +- reputation_a.remove(reputationtype);
141 ++ // CraftBukkit start - redirect - set to 0 instead
142 ++ set(uuid, reputationtype, 0, changeReason);
143 ++ //reputation_a.remove(reputationtype);
144 ++ // CraftBukkit end
145 + if (reputation_a.isEmpty()) {
146 + this.gossips.remove(uuid);
147 + }
148 +@@ -159,7 +217,16 @@
149 +
150 + }
151 +
152 +- public void remove(ReputationType reputationtype) {
153 ++ public void remove(ReputationType reputationtype, Villager.ReputationEvent changeReason) { // CraftBukkit - add change reason parameter
154 ++ // CraftBukkit start - replace the logic to call the other remove instead
155 ++ Set<UUID> uuids = Sets.newHashSet(this.gossips.keySet());
156 ++ for (UUID uuid : uuids) {
157 ++ remove(uuid, reputationtype, changeReason);
158 ++ }
159 ++ if (true) {
160 ++ return;
161 ++ }
162 ++ // CraftBukkit end
163 + Iterator<Reputation.a> iterator = this.gossips.values().iterator();
164 +
165 + while (iterator.hasNext()) {
166 +@@ -174,7 +241,7 @@
167 + }
168 +
169 + public <T> T store(DynamicOps<T> dynamicops) {
170 +- Optional optional = Reputation.b.LIST_CODEC.encodeStart(dynamicops, this.unpack().toList()).resultOrPartial((s) -> {
171 ++ Optional<T> optional = Reputation.b.LIST_CODEC.encodeStart(dynamicops, this.unpack().toList()).resultOrPartial((s) -> { // CraftBukkit - missing generic parameter after decompile
172 + Reputation.LOGGER.warn("Failed to serialize gossips: {}", s);
173 + });
174 +
175 +@@ -186,7 +253,7 @@
176 + Reputation.b.LIST_CODEC.decode(dynamic).resultOrPartial((s) -> {
177 + Reputation.LOGGER.warn("Failed to deserialize gossips: {}", s);
178 + }).stream().flatMap((pair) -> {
179 +- return ((List) pair.getFirst()).stream();
180 ++ return ((List<Reputation.b>) pair.getFirst()).stream(); // CraftBukkit - missing generic parameter after decompile
181 + }).forEach((reputation_b) -> {
182 + this.getOrCreate(reputation_b.target).entries.put(reputation_b.type, reputation_b.value);
183 + });
184 +@@ -216,18 +283,36 @@
185 + }).sum();
186 + }
187 +
188 ++ // CraftBukkit start
189 ++ public int unweightedValue(Predicate<ReputationType> predicate) {
190 ++ return this.entries.object2IntEntrySet().stream().filter((entry) -> {
191 ++ return predicate.test((ReputationType) entry.getKey());
192 ++ }).mapToInt((entry) -> {
193 ++ return entry.getIntValue();
194 ++ }).sum();
195 ++ }
196 ++ // CraftBukkit end
197 ++
198 + public Stream<Reputation.b> unpack(UUID uuid) {
199 + return this.entries.object2IntEntrySet().stream().map((entry) -> {
200 + return new Reputation.b(uuid, (ReputationType) entry.getKey(), entry.getIntValue());
201 + });
202 + }
203 +
204 +- public void decay() {
205 ++ public void decay(EntityVillager villager, UUID uuid) { // CraftBukkit - add villager and entity uuid parameters
206 + ObjectIterator<Entry<ReputationType>> objectiterator = this.entries.object2IntEntrySet().iterator();
207 +
208 + while (objectiterator.hasNext()) {
209 + Entry<ReputationType> entry = (Entry) objectiterator.next();
210 + int i = entry.getIntValue() - ((ReputationType) entry.getKey()).decayPerDay;
211 ++ // CraftBukkit start - fire event
212 ++ VillagerReputationChangeEvent event = CraftEventFactory.callVillagerReputationChangeEvent((Villager) villager.getBukkitEntity(), uuid, Villager.ReputationEvent.DECAY, CraftReputationType.minecraftToBukkit(entry.getKey()), entry.getIntValue(), i, entry.getKey().max);
213 ++ if (event.isCancelled()) {
214 ++ continue;
215 ++ } else {
216 ++ i = event.getNewValue();
217 ++ }
218 ++ // CraftBukkit end
219 +
220 + if (i < 2) {
221 + objectiterator.remove();

Everything looks good. We'll let you know here if there's anything you should know about.

Add shortcut