]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/common/models/BoundingBoxVillage.java
25192cdd57dc653c54274724dba8b62ddc2aefea
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / common / models / BoundingBoxVillage.java
1 package com.irtimaled.bbor.common.models;
2
3 import com.irtimaled.bbor.common.BoundingBoxType;
4 import com.irtimaled.bbor.common.VillageColorCache;
5 import net.minecraft.util.math.BlockPos;
6 import net.minecraft.village.Village;
7 import net.minecraft.village.VillageDoorInfo;
8
9 import java.awt.*;
10 import java.util.HashSet;
11 import java.util.List;
12 import java.util.Set;
13
14 public class BoundingBoxVillage extends BoundingBox {
15     private final BlockPos center;
16     private final Integer radius;
17     private final boolean spawnsIronGolems;
18     private final Color color;
19     private Set<BlockPos> doors;
20     private Double centerOffsetX;
21     private Double centerOffsetZ;
22     private int villageHash;
23
24     private BoundingBoxVillage(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors, BlockPos minBlockPos, BlockPos maxBlockPos) {
25         super(minBlockPos, maxBlockPos, BoundingBoxType.Village);
26         this.center = center;
27         this.radius = radius;
28         this.color = color;
29         this.spawnsIronGolems = spawnsIronGolems;
30         this.doors = doors;
31         this.villageHash = computeHash(center, radius, spawnsIronGolems, doors);
32         calculateCenterOffsets(doors);
33     }
34
35     public static BoundingBoxVillage from(BlockPos center, Integer radius, Color color, boolean spawnsIronGolems, Set<BlockPos> doors) {
36         BlockPos minBlockPos = new BlockPos(center.getX() - radius,
37                 center.getY() - 4,
38                 center.getZ() - radius);
39         BlockPos maxBlockPos = new BlockPos(center.getX() + radius,
40                 center.getY() + 4,
41                 center.getZ() + radius);
42         return new BoundingBoxVillage(center, radius, color, spawnsIronGolems, doors, minBlockPos, maxBlockPos);
43     }
44
45     public static BoundingBoxVillage from(BlockPos center, Integer radius, int villageId, int population, Set<BlockPos> doors) {
46         Boolean spawnsIronGolems = shouldSpawnIronGolems(population, doors.size());
47         Color color = VillageColorCache.getColor(villageId);
48         return from(center, radius, color, spawnsIronGolems, doors);
49     }
50
51     private static boolean shouldSpawnIronGolems(int population, int doorCount) {
52         return population >= 10 && doorCount >= 21;
53     }
54
55     public static BoundingBoxVillage from(Village village) {
56         BlockPos center = village.getCenter();
57         int radius = village.getVillageRadius();
58         Set<BlockPos> doors = getDoorsFromVillage(village);
59         return from(center, radius, village.hashCode(), village.getNumVillagers(), doors);
60     }
61
62     private static Set<BlockPos> getDoorsFromVillage(Village village) {
63         Set<BlockPos> doors = new HashSet<>();
64         List<VillageDoorInfo> doorInfoList = village.getVillageDoorInfoList();
65         for (int i = 0; i < doorInfoList.size(); i++) {
66             VillageDoorInfo doorInfo = doorInfoList.get(i);
67             doors.add(doorInfo.getDoorBlockPos());
68         }
69         return doors;
70     }
71
72     private void calculateCenterOffsets(Set<BlockPos> doors) {
73         boolean processedFirstDoor = false;
74         int minX = 0;
75         int maxX = 0;
76         int minZ = 0;
77         int maxZ = 0;
78         for (BlockPos door : doors) {
79             if (!processedFirstDoor ||
80                     (minX > door.getX()))
81                 minX = door.getX();
82             if (!processedFirstDoor ||
83                     maxX < door.getX())
84                 maxX = door.getX();
85             if (!processedFirstDoor ||
86                     minZ > door.getZ())
87                 minZ = door.getZ();
88             if (!processedFirstDoor ||
89                     maxZ < door.getZ())
90                 maxZ = door.getZ();
91
92             processedFirstDoor = true;
93         }
94         centerOffsetX = Math.abs(maxX - minX) % 2 == 0 ? 0.5 : (minX < 0 ? 0 : 1);
95         centerOffsetZ = Math.abs(maxZ - minZ) % 2 == 0 ? 0.5 : (minZ < 0 ? 0 : 1);
96     }
97
98     @Override
99     public String toString() {
100         return "(" + center.toString() + "; " + radius.toString() + ")";
101     }
102
103     public Integer getRadius() {
104         return radius;
105     }
106
107     public BlockPos getCenter() {
108         return center;
109     }
110
111     public Color getColor() { return color; }
112
113     public Double getCenterOffsetX() {
114         return centerOffsetX;
115     }
116
117     public Double getCenterOffsetZ() {
118         return centerOffsetZ;
119     }
120
121     private static int computeHash(BlockPos center, Integer radius, boolean spawnsIronGolems, Set<BlockPos> doors) {
122         int result = (center.hashCode() * 31) + radius;
123         for (BlockPos door : doors) {
124             result = (31 * result) + door.hashCode();
125         }
126         if (spawnsIronGolems) {
127             result = 31 * result;
128         }
129         return result;
130     }
131
132     public boolean matches(Village village) {
133         return this.villageHash == computeHash(village.getCenter(),
134                 village.getVillageRadius(),
135                 shouldSpawnIronGolems(village.getNumVillagers(), village.getNumVillageDoors()),
136                 getDoorsFromVillage(village));
137     }
138
139     @Override
140     public int hashCode() {
141         return (super.hashCode() * 31) + villageHash;
142     }
143
144     public boolean getSpawnsIronGolems() {
145         return spawnsIronGolems;
146     }
147
148     public Set<BlockPos> getDoors() {
149         return doors;
150     }
151 }