Skip to content

Commit b7f40f8

Browse files
committed
✨ Add ViewStrategy parsing enhancements; update version to 4.5.1-SNAPSHOT and dependencies for compatibility
1 parent 0d20b02 commit b7f40f8

5 files changed

Lines changed: 197 additions & 14 deletions

File tree

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88

99
# 💻 For Developers
1010

11-
This library is designed to work specifically with PaperMC version 1.21.8.<br/>
11+
This library is designed to work specifically with PaperMC version 1.21.11.<br/>
1212
Running on Java 21. Use with other Minecraft versions at your own risk.
1313

1414
Based on our testing, version 4.2.0 of Plus is the most compatible with older versions of Minecraft.
15-
If you are using a Minecraft version other than 1.21.3, we recommend using Plus version 4.5-SNAPSHOT.
16-
For Minecraft 1.21.8 or newer, use the latest version of Plus for optimal compatibility.
15+
If you are using a Minecraft version other than 1.21.11, we recommend using Plus version 4.5.1-SNAPSHOT.
16+
For Minecraft 1.21.11 or newer, use the latest version of Plus for optimal compatibility.
1717

1818
## 🐘 Gradle
1919
### Groovy
@@ -23,7 +23,7 @@ repositories {
2323
maven { url = 'https://central.sonatype.com/repository/maven-snapshots/' }
2424
}
2525
dependencies {
26-
implementation 'com.marcusslover:plus:4.5-SNAPSHOT'
26+
implementation 'com.marcusslover:plus:4.5.1-SNAPSHOT'
2727
}
2828
```
2929
### Kotlin
@@ -33,7 +33,7 @@ repositories {
3333
maven("https://central.sonatype.com/repository/maven-snapshots/")
3434
}
3535
dependencies {
36-
implementation("com.marcusslover:plus:4.5-SNAPSHOT")
36+
implementation("com.marcusslover:plus:4.5.1-SNAPSHOT")
3737
}
3838
```
3939
## 🦢 Maven
@@ -45,6 +45,6 @@ dependencies {
4545
<dependency>
4646
<groupId>com.marcusslover</groupId>
4747
<artifactId>plus</artifactId>
48-
<version>4.5-SNAPSHOT</version>
48+
<version>4.5.1-SNAPSHOT</version>
4949
</dependency>
5050
```

build.gradle

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = 'com.marcusslover'
8-
version = '4.5-SNAPSHOT'
8+
version = '4.5.1-SNAPSHOT'
99

1010
ext {
1111
isRelease = !version.toString().endsWith("SNAPSHOT")
@@ -14,20 +14,19 @@ ext {
1414
repositories {
1515
mavenCentral()
1616
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
17-
maven { url = 'https://repo.dmulloy2.net/repository/public/' }
1817
}
1918

2019
dependencies {
2120
compileOnly 'org.jetbrains:annotations:26.0.2-1'
22-
compileOnly 'io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT'
23-
compileOnly 'com.comphenix.protocol:ProtocolLib:5.3.0'
21+
compileOnly 'io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT'
22+
compileOnly 'net.dmulloy2:ProtocolLib:5.4.0'
2423

2524
compileOnly 'org.projectlombok:lombok:1.18.42'
2625
annotationProcessor 'org.projectlombok:lombok:1.18.42'
2726

2827
testImplementation 'org.junit.jupiter:junit-jupiter:6.0.0'
2928
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
30-
testImplementation 'io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT'
29+
testImplementation 'io.papermc.paper:paper-api:1.21.11-R0.1-SNAPSHOT'
3130
}
3231

3332
java {

src/main/java/com/marcusslover/plus/lib/item/Canvas.java

Lines changed: 146 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,131 @@ class PopulatorContext<T> {
646646
@FunctionalInterface
647647
public interface ViewStrategy {
648648
/**
649+
* Parses an array of strings to create a {@link ViewStrategy} for rendering elements on a canvas.
650+
*
651+
* <p>The provided array of strings represents a grid layout, where each character indicates the
652+
* presence or absence of an element at a specific position.</p>
653+
*
654+
* <ul>
655+
* <li>Use any letter (e.g. {@code 'x'}) to indicate the presence of an element.</li>
656+
* <li>Use {@code '-'} to indicate the absence of an element.</li>
657+
* <li>Grouping is supported: multiple identical letters may represent a single element. This is
658+
* useful for creating components larger than one slot (e.g., a button occupying 4 cells).</li>
659+
* </ul>
660+
*
661+
* <p><b>Examples:</b></p>
662+
*
663+
* <p>Example 1: A simple layout with 10 individual slots (no grouping).</p>
664+
* <pre>{@code
665+
* String[] rows = {
666+
* "---------",
667+
* "--xxxxx--",
668+
* "--xxxxx--",
669+
* "---------",
670+
* "---------",
671+
* "---------"
672+
* };
673+
*
674+
* ViewStrategy viewStrategy = ViewStrategy.parseLayout(false, rows);
675+
* canvas.viewStrategy(viewStrategy);
676+
* }</pre>
677+
*
678+
* <p>Example 2: A grouped layout with two buttons, each occupying four slots.</p>
679+
* <pre>{@code
680+
* String[] rows = {
681+
* "---------",
682+
* "--aa-bb--",
683+
* "--aa-bb--",
684+
* "---------",
685+
* "---------",
686+
* "---------"
687+
* };
688+
*
689+
* ViewStrategy viewStrategy = ViewStrategy.parseLayout(true, rows);
690+
* canvas.viewStrategy(viewStrategy);
691+
* }</pre>
692+
*
693+
* @param groupLetters whether identical letters should be treated as grouped elements
694+
* or as individual slots
695+
* @param rows an array of strings representing the grid layout
696+
* @return a {@link ViewStrategy} defining the rendering behavior based on the parsed layout
697+
* @throws IllegalArgumentException if any row does not have a length of exactly 9
698+
*/
699+
static ViewStrategy parseLayout(boolean groupLetters, String... rows) {
700+
// Precompute the button areas once
701+
final List<Button.DetectableArea> areas = new ArrayList<>();
702+
703+
if (groupLetters) {
704+
// letter → bounding box
705+
Map<Character, Bounds> groups = new LinkedHashMap<>();
706+
707+
// Iterate through each row in the grid
708+
for (int y = 0; y < rows.length; y++) {
709+
String row = rows[y];
710+
711+
// Check if the length of the row is 9, throw an exception if not
712+
if (row.length() != 9) {
713+
throw new IllegalArgumentException("Row length must be 9");
714+
}
715+
716+
// Iterate through each character in the row
717+
for (int x = 0; x < 9; x++) {
718+
char c = row.charAt(x);
719+
720+
// Skip empty slots
721+
if (c == '-') {
722+
continue;
723+
}
724+
725+
// Expand bounding box
726+
int finalX = x;
727+
int finalY = y;
728+
groups.computeIfAbsent(c, k -> new Bounds(finalX, finalY))
729+
.expand(x, y);
730+
}
731+
}
732+
733+
// Convert bounding boxes into detectable areas
734+
for (Bounds b : groups.values()) {
735+
areas.add(
736+
Button.DetectableArea.of(
737+
new org.bukkit.util.Vector(b.minX, 0, b.minY),
738+
new org.bukkit.util.Vector(b.maxX, 0, b.maxY)
739+
)
740+
);
741+
}
742+
743+
} else {
744+
// Treat each non '-' character as an individual button slot
745+
for (int y = 0; y < rows.length; y++) {
746+
String row = rows[y];
747+
748+
if (row.length() != 9) {
749+
throw new IllegalArgumentException("Row length must be 9");
750+
}
751+
752+
for (int x = 0; x < 9; x++) {
753+
if (row.charAt(x) != '-') {
754+
areas.add(Button.DetectableArea.of(x, y));
755+
}
756+
}
757+
}
758+
}
759+
760+
// Define a ViewStrategy using a lambda expression
761+
return (ctx) -> {
762+
// Set the button area based on the counter
763+
if (ctx.counter < areas.size()) {
764+
ctx.button.detectableArea(areas.get(ctx.counter));
765+
}
766+
767+
// Return the total number of elements per page
768+
return areas.size();
769+
};
770+
}
771+
772+
/**
773+
* This method is deprecated and will be removed in future versions. Use {@link #parseLayout(boolean, String...)} instead.
649774
* Parses an array of strings to create a {@link ViewStrategy} for rendering elements on a canvas.
650775
* <p>
651776
* The provided array of strings represents a grid, where each character in the strings
@@ -672,6 +797,7 @@ public interface ViewStrategy {
672797
* @return A {@link ViewStrategy} that defines the rendering behavior based on the parsed grid.
673798
* @throws IllegalArgumentException If the length of any row is not equal to 9.
674799
*/
800+
@Deprecated // Use parseLayout instead
675801
static ViewStrategy parse(String[] rows) {
676802
// Define a ViewStrategy using a lambda expression
677803
return (ctx) -> {
@@ -724,9 +850,28 @@ static ViewStrategy parse(String[] rows) {
724850
@Accessors(fluent = true, chain = true)
725851
class ViewStrategyContext {
726852
private final int counter;
727-
private final @NotNull Canvas canvas;
853+
private final /*@NotNull*/ Canvas canvas;
728854
private final @NotNull Button button;
729855
}
856+
857+
/**
858+
* A helper class to calculate bounds.
859+
*/
860+
final class Bounds {
861+
int minX, minY, maxX, maxY;
862+
863+
Bounds(int x, int y) {
864+
this.minX = this.maxX = x;
865+
this.minY = this.maxY = y;
866+
}
867+
868+
void expand(int x, int y) {
869+
minX = Math.min(minX, x);
870+
minY = Math.min(minY, y);
871+
maxX = Math.max(maxX, x);
872+
maxY = Math.max(maxY, y);
873+
}
874+
}
730875
}
731876
}
732877

src/main/resources/plugin.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Plus
22
main: com.marcusslover.plus.PlusPlugin
3-
version: 4.5-SNAPSHOT
3+
version: 4.5.1-SNAPSHOT
44
description: "A set of tools used for programming Minecraft plugins."
55
website: "https://github.com/MarcusSlover/Plus"
6-
api-version: 1.21.1
6+
api-version: 1.21.11
77
author: MarcusSlover
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package tests;
2+
3+
import com.marcusslover.plus.lib.item.Button;
4+
import com.marcusslover.plus.lib.item.Canvas.BasicPopulator.ViewStrategy;
5+
import com.marcusslover.plus.lib.item.Canvas.BasicPopulator.ViewStrategy.ViewStrategyContext;
6+
import org.junit.jupiter.api.Test;
7+
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
public class ViewStrategyTest {
12+
13+
@Test
14+
public void test() {
15+
ViewStrategy viewStrategy = ViewStrategy.parseLayout(false, new String[]{
16+
"---------",
17+
"--aaaaa--",
18+
"--aaaaa--",
19+
"--ccccc--",
20+
"--ddddd--",
21+
"---------",
22+
});
23+
List<Integer> elements = new ArrayList<>();
24+
elements.add(100);
25+
elements.add(200);
26+
elements.add(300);
27+
elements.add(400);
28+
elements.add(500);
29+
int counter = 0;
30+
for (Integer element : elements) {
31+
Button button = Button.create(counter); // creating the button
32+
ViewStrategyContext ctx = ViewStrategyContext.of(counter, null, button);
33+
int handle = viewStrategy.handle(ctx);
34+
System.out.println("Button: " + button);
35+
System.out.println("Element: " + element + ", Handle: " + handle);
36+
counter++;
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)