001package polaris.sdk.ui.samples;
002
003import polaris.sdk.ui.*;
004import polaris.sdk.ui.controls.*;
005import java.util.*;
006import static polaris.sdk.ui.samples.SceneSupport.*;
007
008/** ClickGUI-like game-client configuration. UI state only: no injection, game hooks or network. */
009public final class ClientScene extends SceneSupport.AppScene {
010 public static final class Module {
011  public final String name,description;public final int category;public boolean enabled,hold;
012  public double strength=50,low=25,high=75;public int mode;public String shortcut="";
013  Module(String n,String d,int c,boolean e){name=n;description=d;category=c;enabled=e;}
014 }
015 private final List<Module> modules=new ArrayList<Module>();private final List<ModuleTile> tiles=new ArrayList<ModuleTile>();
016 private final ListBox categories=new ListBox("战斗","移动","视觉","世界","杂项");
017 private final SearchField search=new SearchField();private final ComboSelect profile=new ComboSelect("默认演示","录制布局","全部关闭");
018 private final Button save=new Button("保存快照");private final Label count=caption("");private final Panel grid=new Panel(),inspector=new Panel();
019 private final ScrollPane modulesScroll=new ScrollPane();private final ModuleGrid content=new ModuleGrid();
020 private final Label selectedName=title("HUD"),selectedNote=caption(""),strengthLabel=caption("参数强度  /  50"),rangeLabel=caption("区间  /  25 – 75");
021 private final Switch enabled=new Switch("启用此模块");private final Slider strength=new Slider();private final RangeSlider range=new RangeSlider();
022 private final ComboSelect mode=new ComboSelect("标准","平滑","自定义");private final KeyBindingField key=new KeyBindingField();private final CheckBox hold=new CheckBox("仅按住时启用");
023 private final Button reset=new Button("重置当前参数"),restore=new Button("载入快照");
024 private int category;private Module selected;private List<Snapshot> snapshot;
025 private static final class Snapshot {final boolean enabled,hold;final double strength,low,high;final int mode;final String shortcut;Snapshot(Module m){enabled=m.enabled;hold=m.hold;strength=m.strength;low=m.low;high=m.high;mode=m.mode;shortcut=m.shortcut;}void apply(Module m){m.enabled=enabled;m.hold=hold;m.strength=strength;m.low=low;m.high=high;m.mode=mode;m.shortcut=shortcut;}}
026 public ClientScene(){super("POLARIS / ClickGUI","外挂风格客户端面板 / 仅演示配置界面,不接入游戏或执行模块");id("scene.client");
027  modules.add(new Module("KillAura","目标配置界面 · 无游戏逻辑",0,false));modules.add(new Module("Velocity","受击参数界面 · 无游戏逻辑",0,false));modules.add(new Module("AutoClicker","点击参数界面 · 不执行点击",0,false));
028  modules.add(new Module("Sprint","疾跑选项界面",1,true));modules.add(new Module("Speed","移动选项界面",1,false));modules.add(new Module("Flight","飞行选项界面",1,false));
029  modules.add(new Module("HUD","屏幕信息组件",2,true));modules.add(new Module("ESP","轮廓显示选项",2,false));modules.add(new Module("Fullbright","亮度选项界面",2,false));
030  modules.add(new Module("Scaffold","方块放置选项",3,false));modules.add(new Module("AutoTool","工具选项界面",3,false));modules.add(new Module("ChestStealer","容器选项界面",3,false));
031  modules.add(new Module("Notifications","消息与状态提示",4,true));modules.add(new Module("Theme","外观参数界面",4,true));modules.add(new Module("IRC","聊天配置界面 · 不联网",4,false));
032  mount(this,search,"client.search");search.placeholder("搜索模块…");search.onChange(v->filter());mount(this,profile,"client.profile");profile.onChange(v->applyProfile(profile.selectedIndex()));mount(this,save,"client.save");save.onClick(v->{snapshot=new ArrayList<Snapshot>();for(Module m:modules)snapshot.add(new Snapshot(m));restore.enabled(true);notice(this,"配置快照已保存","仅保存在本次展示窗口中。");});mount(this,count,"client.count");
033  mount(this,categories,"client.categories");categories.glass(false).padding(0).rowHeight(45).rowGap(8);categories.onSelection(i->{category=Math.max(0,i);filter();});
034  mount(this,grid,"client.modules");mount(grid,modulesScroll,"client.moduleScroll");modulesScroll.glass(false).padding(0).layout(Panel.Layout.COLUMN);modulesScroll.add(content);
035  for(Module m:modules){ModuleTile t=new ModuleTile(m);tiles.add(t);content.add(t);}
036  mount(this,inspector,"client.inspector");mount(inspector,selectedName,"client.selected");mount(inspector,selectedNote,null);mount(inspector,enabled,"client.enabled");
037  enabled.onChange(v->{if(selected!=null){selected.enabled=enabled.selected();refresh();}});
038  strength.range(0,100).continuous();mount(inspector,strengthLabel,null);mount(inspector,strength,"client.strength");strength.onChange(v->{selected.strength=strength.value();refreshLabels();});
039  range.range(0,100);mount(inspector,rangeLabel,null);mount(inspector,range,"client.range");range.onChange(v->{selected.low=range.low();selected.high=range.high();refreshLabels();});
040  mount(inspector,mode,"client.mode");mode.onChange(v->{if(selected!=null)selected.mode=mode.selectedIndex();});
041  mount(inspector,key,"client.key");key.onChange(v->{if(selected!=null)selected.shortcut=key.value();});
042  mount(inspector,hold,"client.hold");hold.onChange(v->selected.hold=hold.selected());
043  mount(inspector,reset,"client.reset");reset.onClick(v->{selected.strength=50;selected.low=25;selected.high=75;selected.mode=0;selected.shortcut="";selected.hold=false;selectModule(selected.name);});
044  mount(inspector,restore,"client.restore");restore.enabled(false);restore.onClick(v->{if(snapshot!=null){for(int i=0;i<modules.size();i++)snapshot.get(i).apply(modules.get(i));selectModule(selected.name);refresh();}});
045  categories.select(0);selectModule("KillAura");refresh();
046 }
047 public List<Module> modules(){return Collections.unmodifiableList(modules);}
048 public Module selectedModule(){return selected;}
049 public int enabledCount(){int n=0;for(Module m:modules)if(m.enabled)n++;return n;}
050 public void selectModule(String name){for(Module m:modules)if(m.name.equals(name)){selected=m;selectedName.text(m.name);selectedNote.text(m.description);enabled.selected(m.enabled);strength.value(m.strength);range.values(m.low,m.high);mode.select(m.mode);key.value(m.shortcut);hold.selected(m.hold);refreshLabels();return;}throw new IllegalArgumentException(name);}
051 private void refreshLabels(){strengthLabel.text("参数强度  /  "+Math.round(selected.strength));rangeLabel.text("区间  /  "+Math.round(selected.low)+" – "+Math.round(selected.high));}
052 private void refresh(){for(ModuleTile tile:tiles)tile.toggle.selected(tile.model.enabled);count.text(enabledCount()+" / "+modules.size()+" 已启用 · 界面模拟");if(selected!=null)enabled.selected(selected.enabled);}
053 private void filter(){String query=search.value().trim().toLowerCase(Locale.ROOT);for(ModuleTile t:tiles)t.visible((query.isEmpty()?t.model.category==category:true)&&(t.model.name.toLowerCase(Locale.ROOT).contains(query)||t.model.description.contains(query)));}
054 private void applyProfile(int index){for(Module m:modules)m.enabled=index==0?(m.name.equals("HUD")||m.name.equals("Sprint")||m.name.equals("Theme")||m.name.equals("Notifications")):index==1?(m.category==2||m.name.equals("Notifications")):false;refresh();}
055 @Override public float preferredHeight(float width){return width<900?1060:630;}
056 @Override protected void layoutChildren(){header();boolean stacked=w<900;float inspectorWidth=stacked?w:270,side=132,main=stacked?w-side-GAP:w-side-inspectorWidth-2*GAP;
057  place(search,0,76,Math.max(120,w-346),36);place(profile,w-334,76,186,36);place(save,w-136,76,136,36);
058  place(categories,0,132,side,360);place(grid,side+GAP,132,main,414);place(modulesScroll,16,16,main-32,382);content.bounds(0,0,modulesScroll.contentWidth(),content.height());
059  place(inspector,stacked?0:w-inspectorWidth,stacked?562:132,inspectorWidth,414);float iw=inspectorWidth;
060  place(selectedName,16,16,iw-32,28);place(selectedNote,16,49,iw-32,22);place(enabled,16,82,iw-32,32);
061  place(strengthLabel,16,128,iw-32,20);place(strength,16,153,iw-32,28);place(rangeLabel,16,193,iw-32,20);place(range,16,217,iw-32,28);
062  place(mode,16,257,iw-32,32);place(key,16,301,iw-32,32);place(hold,16,345,iw-32,27);
063  // Buttons sit below the inspector to preserve a consistent 16 px inset.
064  inspector.bounds(inspector.x(),inspector.y(),iw,458);place(reset,16,399,(iw-44)/2,36);place(restore,28+(iw-44)/2,399,(iw-44)/2,36);
065  float bottom=Math.max(grid.y()+grid.height(),inspector.y()+inspector.height());place(count,0,bottom+12,w,22);h=bottom+40;
066 }
067 private final class ModuleGrid extends Panel {
068  ModuleGrid(){glass(false);padding(0);clipChildren(false);}
069  @Override protected void layoutChildren(){int columns=w>=420?2:1,n=0;float each=(w-(columns-1)*GAP)/columns;for(ModuleTile t:tiles)if(t.visible()){place(t,(n%columns)*(each+GAP),(n/columns)*112,each,100);n++;}h=Math.max(1,((n+columns-1)/columns)*112);}
070 }
071 private final class ModuleTile extends Panel {
072  final Module model;final Switch toggle;final Label note;final Button settings=new Button("参数");
073  ModuleTile(Module m){model=m;toggle=new Switch(m.name);toggle.selected(m.enabled);note=caption(m.description);mount(this,toggle,"client.toggle."+m.name);mount(this,note,null);mount(this,settings,"client.inspect."+m.name);
074   toggle.onChange(v->{m.enabled=toggle.selected();refresh();});settings.onClick(v->selectModule(m.name));}
075  @Override protected void layoutChildren(){place(toggle,12,10,w-24,30);place(note,12,47,w-24,20);place(settings,w-74,71,62,24);}
076 }
077}