Versions/source/source-1-1-2

Source code of WGPFix 1.1.2

plugin.yml

1
2
3
4
5
6
7
name: WGPFix
main: asofold.fix.wgp.WGPFix
version: 1.1.1
commands:
    wgpfix:
        description: For reloading settings
        usage: wgpfix reload

WGPRegionChecker.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package asofold.fix.wgp;

import java.util.List;

import com.sk89q.worldguard.protection.ApplicableRegionSet;

/**
 * API !
 * Register this and have the last word (unless others register too...) !
 * @author mc_dev
 *
 */
public interface WGPRegionChecker {
    /**
     * 
     * @param sets List of ApplicableRegionSet instances, this is the non-empty ones. 
     * @param hasEmpty indicates that there are locations involved that do not hit a region (i.e. empty sets).
     * @return
     */
    public boolean checkRegions(String worldName, List<ApplicableRegionSet> sets, boolean hasEmpty);
}

WGPFix.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
package asofold.fix.wgp;

import java.io.File;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Event;
import org.bukkit.event.Event.Priority;
import org.bukkit.event.block.BlockListener;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.server.PluginDisableEvent;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.event.server.ServerListener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;

import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.ApplicableRegionSet;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;

/**
 * 
 * 
 * @author mc_dev
 *
 */
public class WGPFix extends JavaPlugin {

    class WGPFixBlockListener extends BlockListener {
        long tsWG = 0;
        WorldGuardPlugin wg = null;
        // config settings:
        long tsThreshold = 4000;
        boolean monitorPistons = true;
        boolean preventNonStickyRetract = false;
        boolean popDisallowed = false;
        @Override
        public void onBlockPistonExtend(BlockPistonExtendEvent event) {
            if ( !monitorPistons) return;
            if ( event.isCancelled()) return;
            Block pistonBlock = event.getBlock();
            List<Block> affectedBlocks = event.getBlocks();

            List<Location> locs = new LinkedList<Location>();
            BlockFace dir = event.getDirection();
            locs.add(pistonBlock.getRelative(dir).getLocation());
            int bSize = affectedBlocks.size();
            if ( (affectedBlocks!=null) && (bSize>0) ){
                for ( Block block : affectedBlocks){
                    locs.add(block.getLocation());
                }
                // add empty block at end
                Block endBlock = pistonBlock.getRelative(dir,bSize+1 );
                locs.add(endBlock.getLocation());
            }
            Location pistonLoc = pistonBlock.getLocation();
            if ( !sameOwners(pistonLoc, locs)){
                event.setCancelled(true);
                if (popDisallowed) pop(pistonBlock, null, event.isSticky());
            } 
        }

        @Override
        public void onBlockPistonRetract(BlockPistonRetractEvent event) {
            if ( !monitorPistons) return;
            if ( event.isCancelled()) return;
            boolean check = event.isSticky() || preventNonStickyRetract;
            if (check){
                Block pistonBlock = event.getBlock();
                List<Location> affected = new LinkedList<Location>();
                Location affectedLoc = event.getRetractLocation(); // pulled if sticky
                if ( affectedLoc != null) affected.add(affectedLoc);
                // TODO: bug search
                affected.add(pistonBlock.getRelative(event.getDirection()).getLocation()); // piston extension
                Location pistonLoc = pistonBlock.getLocation();
                if ( !sameOwners(pistonLoc, affected)){
                    event.setCancelled(true);    
                    if (popDisallowed) pop(pistonBlock, pistonBlock.getRelative(event.getDirection()), event.isSticky() );
                } 
            }
        }

        void pop(Block pistonBlock, Block extensionBlock, boolean isSticky) {
            int itemId = isSticky ? 29:33;
            pistonBlock.setType(Material.AIR);
            pistonBlock.getState().update();
            if (extensionBlock!=null){
                extensionBlock.setType(Material.AIR);
                extensionBlock.getState().update();
            }
            pistonBlock.getWorld().dropItemNaturally(pistonBlock.getLocation(), new ItemStack(itemId, 1));
        }
        
        boolean sameOwners(Location refLoc, List<Location> locs){
            WorldGuardPlugin wg = getWorldGuard();
            if ( wg == null) return false; // security option.
            RegionManager mg = wg.getRegionManager(refLoc.getWorld());
            ApplicableRegionSet set = mg.getApplicableRegions(refLoc);
            boolean isRegion = set.size() != 0;
            boolean hasEmpty = !isRegion;
            // TODO: use some caching ?
            Set<String> mustMatch = getUserSet(set);
            int size = mustMatch.size();
            boolean hasCheckers = !regionCheckers.isEmpty();
            List<ApplicableRegionSet> applicableSets  = null;
            if ( hasCheckers){ 
                applicableSets = new LinkedList<ApplicableRegionSet>();
                if (isRegion) applicableSets.add(set);
            }
            for ( Location loc : locs){
                set = mg.getApplicableRegions(loc);
                if (set.size()==0){ // ok.
                    hasEmpty = true;
                } else if ( isRegion ){
                    // compare owner sets:
                    Set<String> ref = getUserSet(set);
                    if ( size != ref.size() ) return false;
                    if ( !mustMatch.containsAll(ref)) return false;
                    if (hasCheckers) applicableSets.add(set);
                } else {
                    // disallow from no region to unowned region !
                    return false; 
                }
                
            }
            if (hasCheckers){
                String worldName = refLoc.getWorld().getName();
                for ( WGPRegionChecker checker : regionCheckers){
                    if ( !checker.checkRegions(worldName, applicableSets, hasEmpty)) return false;
                }
            }
            return true;
        }
        Set<String> getUserSet(ApplicableRegionSet rs){
            Set<String> set = new HashSet<String>();
            if ( rs != null ){
                for ( ProtectedRegion region : rs){
                    DefaultDomain dom = region.getOwners();
                    for ( String p : dom.getPlayers()){
                        set.add(p.toLowerCase());
                    }
                    for ( String p : dom.getGroups()){
                        set.add("g:"+p.toLowerCase());
                    }
                    dom = region.getMembers();
                    for ( String p : dom.getPlayers()){
                        set.add(p.toLowerCase());
                    }
                    for ( String p : dom.getGroups()){
                        set.add("g:"+p.toLowerCase());
                    }
                }
            }
            
            return set;
        }
        final boolean setWG() {
            Plugin temp = Bukkit.getServer().getPluginManager().getPlugin("WorldGuard");
            boolean ok = true;
            if ( temp == null ) ok = false;
            if ( !temp.isEnabled() ) ok = false;
            if ( !ok){
                resetWG();
                return false;
            } 
            WorldGuardPlugin wg = (WorldGuardPlugin) temp;
            this.wg = wg;
            this.tsWG = System.currentTimeMillis();
            // TODO: maybe get region managers already here
            return true;
        }
        final WorldGuardPlugin getWorldGuard(){
            if (System.currentTimeMillis()-this.tsWG > this.tsThreshold) this.setWG();
            return this.wg;
        }
        final void resetWG(){
            this.wg = null;
            this.tsWG = 0;
        }
    }
    
    class WGPFixServerListener extends ServerListener{
        @Override
        public void onPluginDisable(PluginDisableEvent event) {
            if ( event.getPlugin().getDescription().getName().equals("WorldGuard")) blockListener.resetWG();
        }
        @Override
        public void onPluginEnable(PluginEnableEvent event) {
            if ( event.getPlugin().getDescription().getName().equals("WorldGuard")) blockListener.setWG();
        }
    }
    
    class WGPFixCommand implements CommandExecutor{
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if ( !label.equalsIgnoreCase("wgpfix")) return false;
            if ( args.length == 1 ){
                if ( args[0].equalsIgnoreCase("reload")){
                    if ( blockListener.getWorldGuard().hasPermission(sender, "wgpfix.reload" )){
                        if (loadSettings()){
                            sender.sendMessage("WGPFix - Settings reloaded.");
                            return true;
                        }
                        else{
                            sender.sendMessage("WGPFix - Failed to reload settings, fall back to paranoid settings.");
                            return true; // just to prevent showing usage.
                        }
                    }
                }
            }
            return false;
        }
    }
    
    private final WGPFixBlockListener blockListener = new WGPFixBlockListener();
    private final WGPFixServerListener serverListener = new WGPFixServerListener();
    final static List<WGPRegionChecker> regionCheckers = new LinkedList<WGPRegionChecker>();
    
    @Override
    public void onDisable() {
        blockListener.monitorPistons = false;
        blockListener.resetWG();
        System.out.println("WorldGuardPistonFix (WGPFix) 1.0.0 disabled.");
    }

    @Override
    public void onEnable() {
        loadSettings();
        getCommand("wgpfix").setExecutor(new WGPFixCommand());
        PluginManager pm = getServer().getPluginManager();
        pm.registerEvent(Event.Type.BLOCK_PISTON_EXTEND, blockListener, Priority.Low, this);
        pm.registerEvent(Event.Type.BLOCK_PISTON_RETRACT, blockListener, Priority.Low, this);
        pm.registerEvent(Event.Type.PLUGIN_DISABLE, serverListener, Priority.Monitor, this);
        pm.registerEvent(Event.Type.PLUGIN_ENABLE, serverListener, Priority.Monitor, this);
        System.out.println("WorldGuardPistonFix (WGPFix) "+getDescription().getVersion()+" enabled.");
    }
    
    /**
     * API !
     * If set to false pistons will not be monitored at all !
     * @param monitor
     */
    public void setMonitorPistons( boolean monitor){
        this.blockListener.monitorPistons = monitor;
    }
    
    /**
     * API !
     * If set to true, non sticky pistons might be prevented from retracting at some performance loss (imagine item lifting devices).
     * (For the paranoid))
     * @param prevent
     */
    public void setPreventNonStickyRetract( boolean prevent){
        this.blockListener.preventNonStickyRetract = prevent;
    }
    
    /**
     * API !
     * Set the interval in ms, at which the WorldGuard instance is set.
     * @param ms
     */
    public void setWorldGuardSetInterval(long ms){
        this.blockListener.tsThreshold = ms;
    }
    
    public void setPopDisallowed( boolean pop){
        this.blockListener.popDisallowed = pop;
    }
    
    /**
     * (API)
     * Load and apply settings from wgpfx.yml !
     */
    public boolean loadSettings(){
        File file = new File( getDataFolder(), "wgpfix.yml");
        try{
            org.bukkit.util.config.Configuration config = new org.bukkit.util.config.Configuration(file);
            if (!file.exists()){
                config.setProperty("monitor-pistons", true);
                config.setProperty("prevent-nonsticky-retract", false);
                config.setProperty("set-worldguard-interval", 4000);
                config.setProperty("pop-disallowed", false);
                config.save(); // ignore result
            } else{
                config.load();
            }
            this.setMonitorPistons(config.getBoolean("monitor-pistons", true));
            this.setPreventNonStickyRetract(config.getBoolean("prevent-nonsticky-retract", false));
            this.setWorldGuardSetInterval(config.getInt("set-worldguard-interval", 4000));
            this.setPopDisallowed(config.getBoolean("pop-disallowed", false));
            blockListener.setWG();
            return true;
        } catch (Throwable t){
            getServer().getLogger().severe("WGPFix - Could not load configuration, continue wirh paranoid settings !");
            setParanoid();
            return false;
        }
    }
    
    /**
     * (API)
     * Prevent everything that can be prevented by this plugin.
     */
    public void setParanoid(){
        this.setMonitorPistons(true);
        this.setPreventNonStickyRetract(true);
        this.setWorldGuardSetInterval(4000);
        this.setPopDisallowed(true); // PARANOID !
        blockListener.setWG();
    }
    
    /**
     * API !
     * Register implementation that will check regions just before allowing piston-action.
     */
    public static void addRegionChecker( WGPRegionChecker checker){
        regionCheckers.add(checker);
    }
    
    /**
     * API !
     * Unregister implementation for checking regions affected by piston actions.
     * @param checker
     */
    public static void removeRegionChecker( WGPRegionChecker checker){
        regionCheckers.remove(checker);
    }

}

Comments

Posts Quoted:
Reply
Clear All Quotes