Skip to content

Commit f2b8877

Browse files
committed
Reimplement MathsUtils.
1 parent d61958d commit f2b8877

File tree

1 file changed

+238
-0
lines changed

1 file changed

+238
-0
lines changed
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
package net.darkhax.bookshelf.api.util;
2+
3+
import java.math.BigDecimal;
4+
import java.math.RoundingMode;
5+
import java.text.DecimalFormat;
6+
import java.util.EnumMap;
7+
import java.util.Map;
8+
import java.util.Random;
9+
10+
import net.minecraft.world.level.block.Block;
11+
import net.minecraft.core.Direction;
12+
import net.minecraft.world.phys.AABB;
13+
import net.minecraft.world.phys.shapes.VoxelShape;
14+
import net.minecraft.world.phys.Vec3;
15+
16+
public final class MathsUtils {
17+
18+
/**
19+
* A decimal format that only preserves two decimal places.
20+
*/
21+
public static final DecimalFormat DECIMAL_2 = new DecimalFormat("##.##");
22+
23+
/**
24+
* Checks if a double is within range of two other doubles.
25+
*
26+
* @param min: The smallest valid value.
27+
* @param max: The largest valid value.
28+
* @param value: The value to check.
29+
* @return boolean: Whether or not the value is within the provided scope.
30+
*/
31+
public static boolean isInRange (double min, double max, double value) {
32+
33+
return value <= max && value >= min;
34+
}
35+
36+
/**
37+
* Calculates the distance between two Vec3 positions.
38+
*
39+
* @param firstPos: The first position to work with.
40+
* @param secondPos: The second position to work with.
41+
* @return double: The distance between the two provided locations.
42+
*/
43+
public static double getDistanceBetweenPoints (Vec3 firstPos, Vec3 secondPos) {
44+
45+
final double distanceX = firstPos.x - secondPos.x;
46+
final double distanceY = firstPos.y - secondPos.y;
47+
final double distanceZ = firstPos.z - secondPos.z;
48+
49+
return Math.sqrt(distanceX * distanceX + distanceY * distanceY + distanceZ * distanceZ);
50+
}
51+
52+
/**
53+
* This method can be used to round a double to a certain amount of places.
54+
*
55+
* @param value: The double being round.
56+
* @param places: The amount of places to round the double to.
57+
* @return double: The double entered however being rounded to the amount of places
58+
* specified.
59+
*/
60+
public static double round (double value, int places) {
61+
62+
return value >= 0 && places > 0 ? BigDecimal.valueOf(value).setScale(places, RoundingMode.HALF_UP).doubleValue() : value;
63+
}
64+
65+
/**
66+
* Used to retrieve a random integer between the two provided integers. The integers
67+
* provided are also possible outcomes.
68+
*
69+
* @param rand An instance of random.
70+
* @param min The minimum value which can be returned by this method.
71+
* @param max The maximum value which can be returned by this method.
72+
*
73+
* @return An integer between the min and max, including the min and max.
74+
*/
75+
public static int nextIntInclusive (Random rand, int min, int max) {
76+
77+
return rand.nextInt(max - min + 1) + min;
78+
}
79+
80+
/**
81+
* A method which handles the calculating of percentages. While this isn't a particularly
82+
* difficult piece of code, it has been added for the sake of simplicity.
83+
*
84+
* @param percent: The percent chance that this method should return true. 1.00 = 100%
85+
* @return boolean: Returns are randomly true or false, based on the suplied percentage.
86+
*/
87+
public static boolean tryPercentage (double percent) {
88+
89+
return Math.random() < percent;
90+
}
91+
92+
/**
93+
* Gets the middle integer between two other integers. The order is not important.
94+
*
95+
* @param first: The first integer.
96+
* @param second: The second integer.
97+
* @return int: The integer that is between the two provided integers.
98+
*/
99+
public static int getAverage (int first, int second) {
100+
101+
return Math.round((first + second) / 2.0F);
102+
}
103+
104+
/**
105+
* Converts time in ticks to a human readable string.
106+
*
107+
* @param ticks: The amount of ticks to convert.
108+
* @return String: A human readable version of the time.
109+
*/
110+
public static String ticksToTime (int ticks) {
111+
112+
final int seconds = ticks / 20;
113+
final int minutes = seconds / 60;
114+
return minutes + ":" + seconds;
115+
}
116+
117+
/**
118+
* Gets the percentage of an integer. Result is an integer and decimal is lost.
119+
*
120+
* @param value The value to get the percentage of.
121+
* @param total The total/max value.
122+
* @return The percentage as an integer.
123+
*/
124+
public static int getPercentage (int value, int total) {
125+
126+
return (int) ((float) value / (float) total * 100f);
127+
}
128+
129+
/**
130+
* Gets the distance in world for an amount of pixels. A basic block is a cubic meter, and
131+
* each pixel is 1/16th of a block.
132+
*
133+
* @param pixels The amount of pixels
134+
* @return The distance in game for those pixels.
135+
*/
136+
public static double getPixelDistance (int pixels) {
137+
138+
return pixels / 16d;
139+
}
140+
141+
/**
142+
* Creates a bounding box using pixel size.
143+
*
144+
* @param minX The min X pos.
145+
* @param minY The min Y pos.
146+
* @param minZ The min Z pos.
147+
* @param maxX The max X pos.
148+
* @param maxY The max Y pos.
149+
* @param maxZ The max Z pos.
150+
* @return A bounding box that is made to a pixel specific size.
151+
*/
152+
public static AABB getBoundsForPixels (int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
153+
154+
return new AABB(getPixelDistance(minX), getPixelDistance(minY), getPixelDistance(minZ), getPixelDistance(maxX), getPixelDistance(maxY), getPixelDistance(maxZ));
155+
}
156+
157+
/**
158+
* Takes an integer value and fits it within a range. If the initial value is less than the
159+
* minimum it will be set to the minimum. If the initial value is greater than the maximum
160+
* it will be lowered to the maximum.
161+
*
162+
* @param initial The initial value.
163+
* @param min The minimum value.
164+
* @param max The maximum value.
165+
* @return The adjusted value.
166+
*/
167+
public static int adjustToRange (int initial, int min, int max) {
168+
169+
return initial < min ? min : initial > max ? max : initial;
170+
}
171+
172+
/**
173+
* Multiplies an int packed color and returns a new int packed number.
174+
*
175+
* @param color The base color.
176+
* @param factor The value to multiply the color by. Less than 1 will darken. Greater than
177+
* 1 will lighten.
178+
* @return The resulting color as a packed integer.
179+
*/
180+
public static int multiplyColor (int color, float factor) {
181+
182+
final int a = color >> 24 & 0xFF;
183+
final int r = (int) ((color >> 16 & 0xFF) * factor);
184+
final int g = (int) ((color >> 8 & 0xFF) * factor);
185+
final int b = (int) ((color & 0xFF) * factor);
186+
187+
return a << 24 | r << 16 | g << 8 | b;
188+
}
189+
190+
/**
191+
* Creates a rotated variant of a voxel shape for each horizontal direction. The
192+
* default/base input is expected to be oriented north.
193+
*
194+
* @param x1 The min x coordinate.
195+
* @param y1 The min y coordinate.
196+
* @param z1 The min z coordinate.
197+
* @param x2 The max x coordinate.
198+
* @param y2 The max y coordinate.
199+
* @param z2 The max z coordinate.
200+
* @return A map containing rotated shape variants for each horizontal direction.
201+
*/
202+
public static Map<Direction, VoxelShape> createHorizontalShapes (double x1, double y1, double z1, double x2, double y2, double z2) {
203+
204+
final Map<Direction, VoxelShape> shapes = new EnumMap<>(Direction.class);
205+
Direction.Plane.HORIZONTAL.forEach(dir -> shapes.put(dir, rotateShape(dir, x1, y1, z1, x2, y2, z2)));
206+
return shapes;
207+
}
208+
209+
/**
210+
* Creates a voxel shape that has been rotated a given direction. The default/base input is
211+
* expected to be oriented north. Thanks to Gigaherz for writing the original version of
212+
* this code.
213+
*
214+
* @param facing The direction to rotate the shape.
215+
* @param x1 The min x coordinate.
216+
* @param y1 The min y coordinate.
217+
* @param z1 The min z coordinate.
218+
* @param x2 The max x coordinate.
219+
* @param y2 The max y coordinate.
220+
* @param z2 The max z coordinate.
221+
* @return A voxel shape that has been rotated in the specified direction.
222+
*/
223+
public static VoxelShape rotateShape (Direction facing, double x1, double y1, double z1, double x2, double y2, double z2) {
224+
225+
switch (facing) {
226+
case NORTH:
227+
return Block.box(x1, y1, z1, x2, y2, z2);
228+
case EAST:
229+
return Block.box(16 - z2, y1, x1, 16 - z1, y2, x2);
230+
case SOUTH:
231+
return Block.box(16 - x2, y1, 16 - z2, 16 - x1, y2, 16 - z1);
232+
case WEST:
233+
return Block.box(z1, y1, 16 - x2, z2, y2, 16 - x1);
234+
default:
235+
throw new IllegalArgumentException("Can not rotate face in direction " + facing.name());
236+
}
237+
}
238+
}

0 commit comments

Comments
 (0)