Skip to content

Commit

Permalink
Implement predicate strategies
Browse files Browse the repository at this point in the history
  • Loading branch information
eclipseisoffline committed Jan 10, 2025
1 parent 094ff41 commit 7af9518
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.GeyserApi;
import org.geysermc.geyser.api.item.custom.v2.predicate.CustomItemPredicate;
import org.geysermc.geyser.api.item.custom.v2.predicate.PredicateStrategy;
import org.geysermc.geyser.api.util.Identifier;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;

Expand Down Expand Up @@ -84,10 +85,15 @@ public interface CustomItemDefinition {
}

/**
* The predicates that have to match for this item to be used. These predicates are similar to the Java item model predicates.
* The predicates that have to match for this item definition to be used. These predicates are similar to the Java item model predicates.
*/
@NonNull List<CustomItemPredicate> predicates();

/**
* The predicate strategy to be used. Determines if one of, or all of the predicates have to pass for this item definition to be used. Defaults to {@link PredicateStrategy#AND}.
*/
PredicateStrategy predicateStrategy();

/**
* The priority of this definition. For all definitions for a single Java item model, definitions with a higher priority will be matched first. Defaults to 0.
*/
Expand Down Expand Up @@ -125,11 +131,13 @@ interface Builder {

Builder displayName(String displayName);

Builder predicate(@NonNull CustomItemPredicate predicate);
Builder priority(int priority);

Builder bedrockOptions(CustomItemBedrockOptions.@NonNull Builder options);

Builder priority(int priority);
Builder predicate(@NonNull CustomItemPredicate predicate);

Builder predicateStrategy(@NonNull PredicateStrategy strategy);

// TODO do we want a component(Type, Value) method instead?
Builder components(@NonNull DataComponents components);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2025 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.geyser.api.item.custom.v2.predicate;

public enum PredicateStrategy {
/**
* Require all predicates to pass for the item to be used.
*/
AND,
/**
* Require only one of the predicates to pass for the item to be used.
*/
OR
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.geysermc.geyser.api.item.custom.v2.CustomItemBedrockOptions;
import org.geysermc.geyser.api.item.custom.v2.CustomItemDefinition;
import org.geysermc.geyser.api.item.custom.v2.predicate.CustomItemPredicate;
import org.geysermc.geyser.api.item.custom.v2.predicate.PredicateStrategy;
import org.geysermc.geyser.api.util.Identifier;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;

Expand All @@ -37,15 +38,18 @@
import java.util.List;

public record GeyserCustomItemDefinition(@NonNull Identifier bedrockIdentifier, String displayName, @NonNull Identifier model, @NonNull List<CustomItemPredicate> predicates,
PredicateStrategy predicateStrategy,
int priority, @NonNull CustomItemBedrockOptions bedrockOptions, @NonNull DataComponents components) implements CustomItemDefinition {

public static class Builder implements CustomItemDefinition.Builder {
private final Identifier bedrockIdentifier;
private final Identifier model;
private final List<CustomItemPredicate> predicates = new ArrayList<>();
private int priority = 0;

private String displayName;
private int priority = 0;
private CustomItemBedrockOptions bedrockOptions = CustomItemBedrockOptions.builder().build();
private PredicateStrategy predicateStrategy = PredicateStrategy.AND;
private DataComponents components = new DataComponents(new HashMap<>());

public Builder(Identifier bedrockIdentifier, Identifier model) {
Expand All @@ -60,12 +64,6 @@ public CustomItemDefinition.Builder displayName(String displayName) {
return this;
}

@Override
public CustomItemDefinition.Builder predicate(@NonNull CustomItemPredicate predicate) {
predicates.add(predicate);
return this;
}

@Override
public CustomItemDefinition.Builder priority(int priority) {
this.priority = priority;
Expand All @@ -78,6 +76,18 @@ public CustomItemDefinition.Builder bedrockOptions(CustomItemBedrockOptions.@Non
return this;
}

@Override
public CustomItemDefinition.Builder predicate(@NonNull CustomItemPredicate predicate) {
predicates.add(predicate);
return this;
}

@Override
public CustomItemDefinition.Builder predicateStrategy(@NonNull PredicateStrategy strategy) {
predicateStrategy = strategy;
return this;
}

@Override
public CustomItemDefinition.Builder components(@NonNull DataComponents components) {
this.components = components;
Expand All @@ -86,7 +96,7 @@ public CustomItemDefinition.Builder components(@NonNull DataComponents component

@Override
public CustomItemDefinition build() {
return new GeyserCustomItemDefinition(bedrockIdentifier, displayName, model, List.copyOf(predicates), priority, bedrockOptions, components);
return new GeyserCustomItemDefinition(bedrockIdentifier, displayName, model, List.copyOf(predicates), predicateStrategy, priority, bedrockOptions, components);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import net.kyori.adventure.key.Key;
import org.cloudburstmc.protocol.bedrock.data.TrimMaterial;
import org.geysermc.geyser.api.item.custom.v2.predicate.CustomItemPredicate;
import org.geysermc.geyser.api.item.custom.v2.predicate.PredicateStrategy;
import org.geysermc.geyser.item.custom.v2.predicate.ConditionPredicate;
import org.geysermc.geyser.item.custom.v2.predicate.RangeDispatchPredicate;
import org.geysermc.geyser.api.item.custom.v2.predicate.match.ChargeType;
Expand Down Expand Up @@ -82,12 +83,16 @@ public static ItemDefinition getCustomItem(GeyserSession session, int stackSize,
// Cache predicate values so they're not recalculated every time when there are multiple item definitions using the same predicates
Object2BooleanMap<CustomItemPredicate> calculatedPredicates = new Object2BooleanOpenHashMap<>();
for (GeyserCustomMappingData customMapping : customItems) {
boolean needsOnlyOneMatch = customMapping.definition().predicateStrategy() == PredicateStrategy.OR;
boolean allMatch = true;

for (CustomItemPredicate predicate : customMapping.definition().predicates()) {
boolean value = calculatedPredicates.computeIfAbsent(predicate, x -> predicateMatches(session, predicate, stackSize, components));
if (!value) {
allMatch = false;
break;
} else if (needsOnlyOneMatch) {
break;
}
}
if (allMatch) {
Expand Down

0 comments on commit 7af9518

Please sign in to comment.