2
2
3
3
import com .google .common .collect .Sets ;
4
4
import me .desht .modularrouters .ModularRouters ;
5
+ import me .desht .modularrouters .api .event .AddModuleTargetEvent ;
5
6
import me .desht .modularrouters .block .tile .ModularRouterBlockEntity ;
6
7
import me .desht .modularrouters .client .util .ClientUtil ;
7
8
import me .desht .modularrouters .config .ConfigHolder ;
31
32
import net .minecraft .world .item .ItemStack ;
32
33
import net .minecraft .world .item .context .UseOnContext ;
33
34
import net .minecraft .world .level .Level ;
35
+ import net .neoforged .neoforge .common .NeoForge ;
36
+ import org .jetbrains .annotations .ApiStatus ;
34
37
35
38
import java .util .List ;
36
39
import java .util .Set ;
@@ -50,25 +53,37 @@ protected TargetedModule(Item.Properties props, BiFunction<ModularRouterBlockEnt
50
53
@ Override
51
54
public InteractionResult useOn (UseOnContext ctx ) {
52
55
if (ctx .getPlayer () != null && ctx .getPlayer ().isShiftKeyDown ()) {
53
- if (isValidTarget ( ctx ) ) {
54
- if (getMaxTargets () == 1 ) {
56
+ if (getMaxTargets () == 1 ) {
57
+ if (canSelectTarget ( ctx ) ) {
55
58
handleSingleTarget (ctx .getItemInHand (), ctx .getPlayer (), ctx .getLevel (), ctx .getClickedPos (), ctx .getClickedFace ());
56
- } else {
57
- handleMultiTarget (ctx .getItemInHand (), ctx .getPlayer (), ctx .getLevel (), ctx .getClickedPos (), ctx .getClickedFace ());
59
+ return InteractionResult .SUCCESS ;
58
60
}
59
- return InteractionResult .SUCCESS ;
60
61
} else {
61
- return super .useOn (ctx );
62
+ var res = handleMultiTarget (ctx .getItemInHand (), ctx , ctx .getPlayer (), ctx .getLevel (), ctx .getClickedPos (), ctx .getClickedFace ());
63
+ if (res == InteractionResult .PASS ) return res ;
62
64
}
65
+ return super .useOn (ctx );
63
66
} else {
64
67
return InteractionResult .PASS ;
65
68
}
66
69
}
67
70
71
+ /**
72
+ * <strong>Override-only</strong> method that checks whether this module can have the block of the context selected.
73
+ * <p>Note: it is not guaranteed that the module will only have blocks that pass this test selected, see {@link AddModuleTargetEvent}.
74
+ */
75
+ @ ApiStatus .OverrideOnly
68
76
protected boolean isValidTarget (UseOnContext ctx ) {
69
77
return InventoryUtils .getInventory (ctx .getLevel (), ctx .getClickedPos (), ctx .getClickedFace ()).isPresent ();
70
78
}
71
79
80
+ /**
81
+ * Checks if the module can select the target of the {@code context}.
82
+ */
83
+ public boolean canSelectTarget (UseOnContext context ) {
84
+ return NeoForge .EVENT_BUS .post (new AddModuleTargetEvent (this , context , isValidTarget (context ))).isValid ();
85
+ }
86
+
72
87
private void handleSingleTarget (ItemStack stack , Player player , Level world , BlockPos pos , Direction face ) {
73
88
if (!world .isClientSide ) {
74
89
setTarget (stack , world , pos , face );
@@ -82,34 +97,44 @@ private void handleSingleTarget(ItemStack stack, Player player, Level world, Blo
82
97
}
83
98
}
84
99
85
- private void handleMultiTarget (ItemStack stack , Player player , Level world , BlockPos pos , Direction face ) {
86
- if (!world .isClientSide ) {
87
- boolean removing = false ;
88
- String invName = BlockUtil .getBlockName (world , pos );
89
- GlobalPos gPos = MiscUtil .makeGlobalPos (world , pos );
90
- ModuleTarget tgt = new ModuleTarget (gPos , face , invName );
91
- Set <ModuleTarget > targets = getTargets (stack , true );
92
- if (targets .contains (tgt )) {
93
- targets .remove (tgt );
94
- removing = true ;
95
- player .displayClientMessage (Component .translatable ("modularrouters.chatText.misc.targetRemoved" , targets .size (), getMaxTargets ())
96
- .append (tgt .getTextComponent ()).withStyle (ChatFormatting .YELLOW ), true );
97
- } else if (targets .size () < getMaxTargets ()) {
100
+ private InteractionResult handleMultiTarget (ItemStack stack , UseOnContext context , Player player , Level world , BlockPos pos , Direction face ) {
101
+ Set <ModuleTarget > targets = getTargets (stack , !world .isClientSide );
102
+ String invName = BlockUtil .getBlockName (world , pos );
103
+ GlobalPos gPos = MiscUtil .makeGlobalPos (world , pos );
104
+ ModuleTarget tgt = new ModuleTarget (gPos , face , invName );
105
+
106
+ // Allow removing targets without checking if they're valid
107
+ if (targets .contains (tgt )) {
108
+ if (world .isClientSide ) return InteractionResult .SUCCESS ;
109
+ targets .remove (tgt );
110
+
111
+ player .displayClientMessage (Component .translatable ("modularrouters.chatText.misc.targetRemoved" , targets .size (), getMaxTargets ())
112
+ .append (tgt .getTextComponent ()).withStyle (ChatFormatting .YELLOW ), true );
113
+ world .playSound (null , pos , ModSounds .SUCCESS .get (), SoundSource .BLOCKS , ConfigHolder .common .sound .bleepVolume .get ().floatValue (), 1.1f );
114
+ setTargetList (stack , targets );
115
+ return InteractionResult .SUCCESS ;
116
+ }
117
+
118
+ if (canSelectTarget (context )) {
119
+ if (world .isClientSide ) return InteractionResult .SUCCESS ;
120
+ if (targets .size () < getMaxTargets ()) {
98
121
targets .add (tgt );
99
122
player .displayClientMessage (Component .translatable ("modularrouters.chatText.misc.targetAdded" , targets .size (), getMaxTargets ())
100
123
.append (tgt .getTextComponent ()).withStyle (ChatFormatting .YELLOW ), true );
124
+
125
+ world .playSound (null , pos , ModSounds .SUCCESS .get (), SoundSource .BLOCKS ,
126
+ ConfigHolder .common .sound .bleepVolume .get ().floatValue (), 1.3f );
127
+ setTargetList (stack , targets );
101
128
} else {
102
129
// too many targets already
103
130
player .displayClientMessage (Component .translatable ("modularrouters.chatText.misc.tooManyTargets" , getMaxTargets ())
104
131
.withStyle (ChatFormatting .RED ), true );
105
132
world .playSound (null , pos , ModSounds .ERROR .get (), SoundSource .BLOCKS , 1.0f , 1.3f );
106
- return ;
107
133
}
108
134
109
- world .playSound (null , pos , ModSounds .SUCCESS .get (), SoundSource .BLOCKS ,
110
- ConfigHolder .common .sound .bleepVolume .get ().floatValue (), removing ? 1.1f : 1.3f );
111
- setTargetList (stack , targets );
135
+ return InteractionResult .SUCCESS ;
112
136
}
137
+ return InteractionResult .PASS ;
113
138
}
114
139
115
140
0 commit comments