Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/api/version/v13.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ API version 13 adds entity-spawn lookup support while retaining all API version

## Upgrading from API v12

- `LookupOptions` supports material inclusion/exclusion filters for typed container, item, and inventory lookups.
- `LookupOptions` supports material inclusion/exclusion filters for typed container, item, and inventory lookups, and `users(List<String>)` / `excludeUsers(List<String>)` filters for all typed lookups.
- Added `CoreProtectAction.ENTITY_SPAWN` with action ID `13`.
- Added `CoreProtectPreLogEvent.Action.ENTITY_SPAWN`.
- `BlockResult#getEntityType()` recognizes entity-spawn results.
Expand Down
1 change: 1 addition & 0 deletions src/main/java/net/coreprotect/api/BlockAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public static List<BlockResult> performLookup(Block block, LookupOptions options
if (userId != null) {
query.append(" AND ").append(ConfigHandler.databaseType.getUserColumn()).append(" = ?");
}
LookupFilter.appendUserWhere(query, "", LookupFilter.userIds(connection, options.getUsers()), LookupFilter.userIds(connection, options.getExcludeUsers()));
query.append(" ORDER BY ").append(ConfigHandler.getDescendingEventOrder());
if (options.hasLimit()) {
query.append(" LIMIT ").append(options.getLimitCount()).append(" OFFSET ").append(options.getLimitOffset());
Expand Down
37 changes: 35 additions & 2 deletions src/main/java/net/coreprotect/api/LookupFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ final class LookupFilter {
private final List<Material> includeMaterials;
private final List<Material> excludeMaterials;
private final Map<Integer, Material> materialTypes;
private final String includeUserIds;
private final String excludeUserIds;

private LookupFilter(Integer userId, int checkTime, Location location, int radius, int limitOffset, int limitCount, List<Material> includeMaterials, List<Material> excludeMaterials, Map<Integer, Material> materialTypes) {
private LookupFilter(Integer userId, int checkTime, Location location, int radius, int limitOffset, int limitCount, List<Material> includeMaterials, List<Material> excludeMaterials, Map<Integer, Material> materialTypes, String includeUserIds, String excludeUserIds) {
this.userId = userId;
this.checkTime = checkTime;
this.location = location;
Expand All @@ -41,6 +43,8 @@ private LookupFilter(Integer userId, int checkTime, Location location, int radiu
this.includeMaterials = includeMaterials;
this.excludeMaterials = excludeMaterials;
this.materialTypes = materialTypes;
this.includeUserIds = includeUserIds;
this.excludeUserIds = excludeUserIds;
}

static LookupFilter fromOptions(Connection connection, LookupOptions options) throws Exception {
Expand All @@ -65,7 +69,8 @@ static LookupFilter fromOptions(Connection connection, LookupOptions options) th
}

return new LookupFilter(userId, checkTime, options.getLocation(), options.getRadius(), options.getLimitOffset(), options.getLimitCount(),
options.getIncludeMaterials(), options.getExcludeMaterials(), materialTypes);
options.getIncludeMaterials(), options.getExcludeMaterials(), materialTypes,
userIds(connection, options.getUsers()), userIds(connection, options.getExcludeUsers()));
}

boolean hasInvalidUser() {
Expand Down Expand Up @@ -111,6 +116,7 @@ void appendWhere(StringBuilder query, String alias) {
if (userId != null) {
query.append(" AND ").append(qualifier).append(ConfigHandler.databaseType.getUserColumn()).append(" = ?");
}
appendUserWhere(query, alias, includeUserIds, excludeUserIds);

if (location != null) {
query.append(" AND ").append(qualifier).append("wid = ?");
Expand All @@ -130,6 +136,7 @@ void appendEntityContainerWhere(StringBuilder query, String transactionAlias, St
if (userId != null) {
query.append(" AND ").append(transaction).append(ConfigHandler.databaseType.getUserColumn()).append(" = ?");
}
appendUserWhere(query, transactionAlias, includeUserIds, excludeUserIds);
if (location == null) {
return;
}
Expand Down Expand Up @@ -338,6 +345,32 @@ int bindEntityContainer(PreparedStatement statement, int parameterIndex) throws
return parameterIndex;
}

static String userIds(Connection connection, List<String> users) throws Exception {
StringJoiner result = new StringJoiner(",");
for (String user : users) {
Integer id = MessageAPI.getUserId(connection, user);
if (id == null) {
// An empty name or #global matches every user.
return null;
}
result.add(String.valueOf(id));
}
return result.toString();
}

static void appendUserWhere(StringBuilder query, String alias, String includeUserIds, String excludeUserIds) {
String column = (alias.isEmpty() ? "" : alias + ".") + ConfigHandler.databaseType.getUserColumn();
if (includeUserIds != null && !includeUserIds.isEmpty()) {
query.append(" AND ").append(column).append(" IN (").append(includeUserIds).append(")");
}
if (excludeUserIds == null) {
query.append(" AND 1 = 0");
}
else if (!excludeUserIds.isEmpty()) {
query.append(" AND ").append(column).append(" NOT IN (").append(excludeUserIds).append(")");
}
}

private String materialIds(List<Material> materials, boolean inventoryBlock) {
StringJoiner result = new StringJoiner(",");
for (Map.Entry<Integer, Material> entry : materialTypes.entrySet()) {
Expand Down
24 changes: 24 additions & 0 deletions src/main/java/net/coreprotect/api/LookupOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public final class LookupOptions {
private final int limitCount;
private final List<Material> includeMaterials;
private final List<Material> excludeMaterials;
private final List<String> users;
private final List<String> excludeUsers;

private LookupOptions(Builder builder) {
this.user = builder.user;
Expand All @@ -27,6 +29,8 @@ private LookupOptions(Builder builder) {
this.limitCount = builder.limitCount;
this.includeMaterials = builder.includeMaterials;
this.excludeMaterials = builder.excludeMaterials;
this.users = builder.users;
this.excludeUsers = builder.excludeUsers;
}

public static Builder builder() {
Expand Down Expand Up @@ -69,6 +73,14 @@ public List<Material> getExcludeMaterials() {
return excludeMaterials;
}

public List<String> getUsers() {
return users;
}

public List<String> getExcludeUsers() {
return excludeUsers;
}

public static final class Builder {
private String user;
private int time;
Expand All @@ -78,6 +90,8 @@ public static final class Builder {
private int limitCount = -1;
private List<Material> includeMaterials = List.of();
private List<Material> excludeMaterials = List.of();
private List<String> users = List.of();
private List<String> excludeUsers = List.of();

private Builder() {
}
Expand Down Expand Up @@ -120,6 +134,16 @@ public Builder excludeMaterials(List<Material> materials) {
return this;
}

public Builder users(List<String> users) {
this.users = List.copyOf(users);
return this;
}

public Builder excludeUsers(List<String> users) {
this.excludeUsers = List.copyOf(users);
return this;
}

public LookupOptions build() {
return new LookupOptions(this);
}
Expand Down
51 changes: 50 additions & 1 deletion src/main/java/net/coreprotect/api/UsernameAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ public static List<UsernameResult> performLookup(LookupOptions options) {
return result;
}

Set<String> uuids = getUuids(connection, options.getUser());
Set<String> uuids = getUuids(connection, options);
if (uuids == null) {
return result;
}

Set<String> excludedUuids = getUuids(connection, options.getExcludeUsers());
if (excludedUuids == null) {
return result;
}
// A NULL in NOT IN would also exclude unrelated users.
excludedUuids.remove(null);

int checkTime = 0;
if (options.getTime() > 0) {
checkTime = (int) (System.currentTimeMillis() / 1000L) - options.getTime();
Expand All @@ -62,6 +69,11 @@ public static List<UsernameResult> performLookup(LookupOptions options) {
appendPlaceholders(query, uuids.size());
query.append(")");
}
if (!excludedUuids.isEmpty()) {
query.append(" AND uuid NOT IN (");
appendPlaceholders(query, excludedUuids.size());
query.append(")");
}
query.append(" ORDER BY ").append(ConfigHandler.getDescendingEventOrder());
if (options.hasLimit()) {
query.append(" LIMIT ").append(options.getLimitCount()).append(" OFFSET ").append(options.getLimitOffset());
Expand All @@ -73,6 +85,9 @@ public static List<UsernameResult> performLookup(LookupOptions options) {
for (String uuid : uuids) {
statement.setString(parameterIndex++, uuid);
}
for (String uuid : excludedUuids) {
statement.setString(parameterIndex++, uuid);
}

try (ResultSet results = statement.executeQuery()) {
while (results.next()) {
Expand All @@ -97,6 +112,25 @@ private static void appendPlaceholders(StringBuilder query, int count) {
}
}

private static Set<String> getUuids(Connection connection, LookupOptions options) throws Exception {
Set<String> result = getUuids(connection, options.getUser());
if (result == null || options.getUsers().isEmpty()) {
return result;
}

Set<String> includedUuids = getUuids(connection, options.getUsers());
if (includedUuids == null) {
return result;
}
if (result.isEmpty()) {
result.addAll(includedUuids);
}
else {
result.retainAll(includedUuids);
}
return result.isEmpty() ? null : result;
}

private static Set<String> getUuids(Connection connection, String user) throws Exception {
Set<String> result = new LinkedHashSet<>();

Expand Down Expand Up @@ -130,6 +164,21 @@ private static Set<String> getUuids(Connection connection, String user) throws E
return result.isEmpty() ? null : result;
}

private static Set<String> getUuids(Connection connection, List<String> users) throws Exception {
Set<String> result = new LinkedHashSet<>();
for (String user : users) {
Set<String> matches = getUuids(connection, user);
if (matches != null) {
if (matches.isEmpty()) {
// An empty name or #global matches every user.
return null;
}
result.addAll(matches);
}
}
return result;
}

private static boolean looksLikeUuid(String value) {
return value.length() == 36 && value.charAt(8) == '-' && value.charAt(13) == '-' && value.charAt(18) == '-' && value.charAt(23) == '-';
}
Expand Down
Loading