├── .gitignore
├── README.md
├── gameloop.py
├── images
├── 1721906871062.jpg
├── 1721906900270.jpg
├── avatar
│ ├── PUBG2.png
│ ├── head.ico
│ ├── pubg.png
│ ├── pubg_act.png
│ ├── steam.png
│ ├── steam_act.png
│ └── tips.png
├── chi_sim
│ ├── backhome1.jpg
│ ├── backhome1_act.jpg
│ ├── backhome2.jpg
│ ├── backhome2_act.jpg
│ ├── backhome3.jpg
│ ├── backhome3_act.jpg
│ ├── backhome4.jpg
│ ├── backhome4_act.jpg
│ ├── game.jpg
│ ├── home.jpg
│ ├── loading.jpg
│ ├── loading1.jpg
│ ├── start.jpg
│ └── start_act.jpg
├── chi_sim_1080
│ ├── backhome1.jpg
│ ├── backhome1_act.jpg
│ ├── backhome2.jpg
│ ├── backhome2_act.jpg
│ ├── backhome3.jpg
│ ├── backhome3_act.jpg
│ ├── backhome4.jpg
│ ├── backhome4_act.jpg
│ ├── game.jpg
│ ├── home.jpg
│ ├── loading.jpg
│ ├── loading1.jpg
│ ├── start.jpg
│ └── start_act.jpg
├── chi_sim_4k
│ ├── backhome1.jpg
│ ├── backhome1_act.jpg
│ ├── backhome2.jpg
│ ├── backhome2_act.jpg
│ ├── backhome3.jpg
│ ├── backhome3_act.jpg
│ ├── backhome4.jpg
│ ├── backhome4_act.jpg
│ ├── game.jpg
│ ├── home.jpg
│ ├── loading.jpg
│ ├── loading1.jpg
│ ├── start.jpg
│ └── start_act.jpg
└── test
│ └── 1.jpg
├── main.py
├── main.spec
├── myopencv
├── __init__.py
└── myopencv.py
├── requirements.txt
├── template
├── m2.py
├── tips.py
└── updatelog.py
├── test
└── test.py
├── ui
├── main.py
├── main.ui
├── tips.py
└── updatelog.py
└── upx-4.2.4-win64
├── COPYING
├── LICENSE
├── NEWS
├── README
├── THANKS.txt
├── upx-doc.html
├── upx-doc.txt
├── upx.1
└── upx.exe
/.gitignore:
--------------------------------------------------------------------------------
1 | /logs
2 | logs
3 |
4 | .venv
5 | .venv/
6 | __pycache__
7 | __pycache__/
8 |
9 | output/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1. 运行环境
4 |
5 | python3.10 以上 [下载python](python.org)
6 |
7 |
8 | ```
9 | python -m venv .venv
10 | .\.venv\Scripts\activate
11 | pip install -r requirements.txt
12 | python main.py
13 | ```
14 |
15 | 逐行执行
16 |
17 |
18 | 2. 打包
19 |
20 | ```
21 | auto-py-to-exe
22 | ```
23 |
24 | 
25 | 
--------------------------------------------------------------------------------
/gameloop.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 |
4 | import pyautogui
5 | import pydirectinput
6 | from myopencv.myopencv import ImageFinder
7 |
8 |
9 | class GameState:
10 | HOME = "home"
11 | START = "start"
12 | LOADING = "loading"
13 | LOADING1 = "loading1"
14 | GAME = "game"
15 | BACKHOME1 = "backhome1"
16 | BACKHOME2 = "backhome2"
17 | BACKHOME3 = "backhome3"
18 | BACKHOME4 = "backhome4"
19 | BACKHOMEALL = "backhomeall"
20 |
21 |
22 | class gameloop:
23 | def __init__(self):
24 | self.is_state = False
25 | self.c = None
26 |
27 | def gameLoop(self, timeout=5, flaytimeout=25, imgopcv=0.8, saveLog=True):
28 | clash = ImageFinder(imgopcv)
29 | images = self.getImagesMap()
30 | # 检查资源文件
31 | for key, value in images.items():
32 | if isinstance(value, list):
33 | for item in value:
34 | if not os.path.exists(item):
35 | print(f"资源文件不存在: {item}")
36 | self._mylogs(f"资源文件不存在: {item}")
37 | else:
38 | if not os.path.exists(value):
39 | print(f"资源文件不存在: {value}")
40 | self._mylogs(f"资源文件不存在: {value}")
41 | # 禁用掉 pyoutoui 的检测机制
42 | pyautogui.FAILSAFE = False
43 | pydirectinput.FAILSAFE = False
44 | # 游戏中等号状态
45 | running = False
46 | self.is_state = True
47 | print("game loop start")
48 | self._mylogs("game loop start")
49 | try:
50 | loopNumber = 0
51 | while self.is_state:
52 | loopNumber += 1
53 | time.sleep(timeout)
54 | # 是否在主页
55 | if clash.find_image_all(images[GameState.HOME]) and self.is_state:
56 | print("在主页")
57 | self._mylogs("在主页")
58 | # 找到开始游戏
59 | result = clash.find_images_all(images[GameState.START])
60 | if result:
61 | print(f"Found image at screen coordinates: {result}")
62 | pyautogui.moveTo(result[0], result[1])
63 | pyautogui.click()
64 |
65 | # 是否在匹配状态
66 | if clash.find_image_all(images[GameState.LOADING]) and self.is_state:
67 | print("匹配中")
68 | self._mylogs("匹配中")
69 | # 是否在等待加入玩家状态
70 | if clash.find_image_all(images[GameState.LOADING1]) and self.is_state:
71 | print("等待加入玩家")
72 | self._mylogs("等待加入玩家")
73 | # 是否在游戏中
74 | if clash.find_image_all(images[GameState.GAME]) and self.is_state:
75 | print("游戏中")
76 | self._mylogs("游戏中")
77 | time.sleep(flaytimeout)
78 | while clash.find_image_all(images[GameState.GAME]) and self.is_state:
79 | # 按下f键
80 | pydirectinput.press("f")
81 | time.sleep(1)
82 | pydirectinput.press("=")
83 | time.sleep(1)
84 | # 按下空格键
85 | pydirectinput.press("space")
86 | time.sleep(1)
87 | # 单击鼠标左键
88 | pydirectinput.click()
89 | time.sleep(7)
90 | else:
91 | # 判断是否有返回主页的按钮
92 | if clash.find_images_all(images[GameState.BACKHOMEALL]) and self.is_state:
93 | self._mylogs("返回主页中")
94 | # 等待返回主页3并点击返回主页3
95 | while self.is_state:
96 | # 点击返回主页 返回至大厅
97 | result = clash.find_image_all(images[GameState.BACKHOME1])
98 | if result and self.is_state:
99 | pyautogui.moveTo(result[0], result[1])
100 | pyautogui.click()
101 | time.sleep(1)
102 | pyautogui.moveTo(300, 300)
103 | # 点击返回主页2 确认
104 | result = clash.find_image_all(images[GameState.BACKHOME2])
105 | if result and self.is_state:
106 | pyautogui.moveTo(result[0], result[1])
107 | pyautogui.click()
108 | time.sleep(1)
109 | pyautogui.moveTo(300, 300)
110 | # 点击返回主页3 继续
111 | if clash.find_image_all(images[GameState.BACKHOME3]) and self.is_state:
112 | result = clash.find_image_all(images[GameState.BACKHOME3])
113 | if result:
114 | pyautogui.moveTo(result[0], result[1])
115 | pyautogui.click()
116 | time.sleep(1)
117 | pyautogui.moveTo(300, 300)
118 | # 点击返回主页4mm 关闭
119 | if clash.find_image_all(images[GameState.BACKHOME4]) and self.is_state:
120 | result = clash.find_image_all(images[GameState.BACKHOME4])
121 | if result:
122 | pyautogui.moveTo(result[0], result[1])
123 | pyautogui.click()
124 | time.sleep(1)
125 | # 判断是否在主页
126 | if clash.find_image_all(images[GameState.HOME]) and self.is_state:
127 | break
128 | if self.is_state:
129 | self._mylogs(f"第 {loopNumber} 次检查", 2)
130 | except Exception as e:
131 | self._mylogs("异常退出 请从新开启", 2)
132 | self._mylogs("game loop end")
133 |
134 | def getImagesMap(self):
135 | home = "./images/chi_sim/home.jpg"
136 | start = ["./images/chi_sim/start.jpg", "./images/chi_sim/start_act.jpg"]
137 | loading = "./images/chi_sim/loading.jpg"
138 | loading1 = "./images/chi_sim/loading1.jpg"
139 | game = "./images/chi_sim/game.jpg"
140 | backhome1 = "./images/chi_sim/backhome1.jpg"
141 | backhome2 = "./images/chi_sim/backhome2.jpg"
142 | backhome3 = "./images/chi_sim/backhome3.jpg"
143 | backhome4 = "./images/chi_sim/backhome4.jpg"
144 | home_1080 = "./images/chi_sim_1080/home.jpg"
145 | start_1080 = ["./images/chi_sim_1080/start.jpg", "./images/chi_sim_1080/start_act.jpg"]
146 | loading_1080 = "./images/chi_sim_1080/loading.jpg"
147 | loading1_1080 = "./images/chi_sim_1080/loading1.jpg"
148 | game_1080 = "./images/chi_sim_1080/game.jpg"
149 | backhome1_1080 = "./images/chi_sim_1080/backhome1.jpg"
150 | backhome2_1080 = "./images/chi_sim_1080/backhome2.jpg"
151 | backhome3_1080 = "./images/chi_sim_1080/backhome3.jpg"
152 | backhome4_1080 = "./images/chi_sim_1080/backhome4.jpg"
153 | home_4k = "./images/chi_sim_4k/home.jpg"
154 | start_4k = ["./images/chi_sim_4k/start.jpg", "./images/chi_sim_4k/start_act.jpg"]
155 | loading_4k = "./images/chi_sim_4k/loading.jpg"
156 | loading1_4k = "./images/chi_sim_4k/loading1.jpg"
157 | game_4k = "./images/chi_sim_4k/game.jpg"
158 | backhome1_4k = "./images/chi_sim_4k/backhome1.jpg"
159 | backhome2_4k = "./images/chi_sim_4k/backhome2.jpg"
160 | backhome3_4k = "./images/chi_sim_4k/backhome3.jpg"
161 | backhome4_4k = "./images/chi_sim_4k/backhome4.jpg"
162 | # 获取 ./images/chi_sim/home.jpg 绝对路径
163 | home = os.path.abspath(os.path.join(os.path.dirname(__file__), home))
164 | start = [os.path.abspath(os.path.join(os.path.dirname(__file__), item)) for item in start]
165 | loading = os.path.abspath(os.path.join(os.path.dirname(__file__), loading))
166 | loading1 = os.path.abspath(os.path.join(os.path.dirname(__file__), loading1))
167 | game = os.path.abspath(os.path.join(os.path.dirname(__file__), game))
168 | backhome1 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome1))
169 | backhome2 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome2))
170 | backhome3 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome3))
171 | backhome4 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome4))
172 | # 获取 ./images/chi_sim_1080/home.jpg 绝对路径
173 | home_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), home_1080))
174 | start_1080 = [os.path.abspath(os.path.join(os.path.dirname(__file__), item)) for item in start_1080]
175 | loading_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), loading_1080))
176 | loading1_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), loading1_1080))
177 | game_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), game_1080))
178 | backhome1_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome1_1080))
179 | backhome2_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome2_1080))
180 | backhome3_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome3_1080))
181 | backhome4_1080 = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome4_1080))
182 | # 获取 ./images/chi_sim_4k/home 绝对路径
183 | home_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), home_4k))
184 | start_4k = [os.path.abspath(os.path.join(os.path.dirname(__file__), item)) for item in start_4k]
185 | loading_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), loading_4k))
186 | loading1_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), loading1_4k))
187 | game_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), game_4k))
188 | backhome1_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome1_4k))
189 | backhome2_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome2_4k))
190 | backhome3_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome3_4k))
191 | backhome4_4k = os.path.abspath(os.path.join(os.path.dirname(__file__), backhome4_4k))
192 |
193 |
194 | # 获取当前屏幕宽度
195 | screen_width = pyautogui.size().width
196 | if screen_width >= 1920 and screen_width < 2560:
197 | return {
198 | "home": home_1080,
199 | "start": start_1080,
200 | "loading": loading_1080,
201 | "loading1": loading1_1080,
202 | "game": game_1080,
203 | "backhome1": backhome1_1080,
204 | "backhome2": backhome2_1080,
205 | "backhome3": backhome3_1080,
206 | "backhome4": backhome4_1080,
207 | "backhomeall": [backhome1_1080, backhome2_1080, backhome3_1080, backhome4_1080]
208 | }
209 | elif screen_width > 1920 and screen_width <= 2560:
210 | return {
211 | "home": home,
212 | "start": start,
213 | "loading": loading,
214 | "loading1": loading1,
215 | "game": game,
216 | "backhome1": backhome1,
217 | "backhome2": backhome2,
218 | "backhome3": backhome3,
219 | "backhome4": backhome4,
220 | "backhomeall": [backhome1, backhome2, backhome3, backhome4]
221 | }
222 | elif screen_width >2560:
223 | return {
224 | "home": home_4k,
225 | "start": start_4k,
226 | "loading": loading_4k,
227 | "loading1": loading1_4k,
228 | "game": game_4k,
229 | "backhome1": backhome1_4k,
230 | "backhome2": backhome2_4k,
231 | "backhome3": backhome3_4k,
232 | "backhome4": backhome4_4k,
233 | "backhomeall": [backhome1_4k, backhome2_4k, backhome3_4k, backhome4_4k]
234 | }
235 |
236 | def setState(self, state):
237 | self.is_state = state
238 |
239 | def getState(self):
240 | return self.is_state
241 |
242 | # 判断是否开启某个进程
243 | def isProcessRunning(self, processName):
244 | if os.system(f"tasklist | findstr {processName}"):
245 | return True
246 | else:
247 | return False
248 |
249 | # 通用日志方法
250 | def _mylogs(self, message, type=1):
251 | if type == 1:
252 | self.c(message)
253 | else:
254 | self.c2(message)
255 |
256 | def setCllback(self, c):
257 | self.c = c
258 |
259 | def setCllback2(self, c2):
260 | self.c2 = c2
261 |
262 |
263 | if __name__ == '__main__':
264 | game = gameloop()
265 | getimg = ImageFinder()
266 | images = game.getImagesMap()
267 | # print(images[GameState.BACKHOME3])
268 | _images = "./images/test/1.jpg"
269 | print(_images)
270 | result = getimg.find_image_all(_images)
271 | pyautogui.moveTo(result[0], result[1])
272 | print(result)
273 |
--------------------------------------------------------------------------------
/images/1721906871062.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/1721906871062.jpg
--------------------------------------------------------------------------------
/images/1721906900270.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/1721906900270.jpg
--------------------------------------------------------------------------------
/images/avatar/PUBG2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/PUBG2.png
--------------------------------------------------------------------------------
/images/avatar/head.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/head.ico
--------------------------------------------------------------------------------
/images/avatar/pubg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/pubg.png
--------------------------------------------------------------------------------
/images/avatar/pubg_act.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/pubg_act.png
--------------------------------------------------------------------------------
/images/avatar/steam.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/steam.png
--------------------------------------------------------------------------------
/images/avatar/steam_act.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/steam_act.png
--------------------------------------------------------------------------------
/images/avatar/tips.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/avatar/tips.png
--------------------------------------------------------------------------------
/images/chi_sim/backhome1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome1.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome1_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome1_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome2.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome2_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome2_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome3.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome3_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome3_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome4.jpg
--------------------------------------------------------------------------------
/images/chi_sim/backhome4_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/backhome4_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim/game.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/game.jpg
--------------------------------------------------------------------------------
/images/chi_sim/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/home.jpg
--------------------------------------------------------------------------------
/images/chi_sim/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/loading.jpg
--------------------------------------------------------------------------------
/images/chi_sim/loading1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/loading1.jpg
--------------------------------------------------------------------------------
/images/chi_sim/start.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/start.jpg
--------------------------------------------------------------------------------
/images/chi_sim/start_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim/start_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome1.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome1_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome1_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome2.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome2_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome2_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome3.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome3_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome3_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome4.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/backhome4_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/backhome4_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/game.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/game.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/home.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/loading.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/loading1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/loading1.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/start.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/start.jpg
--------------------------------------------------------------------------------
/images/chi_sim_1080/start_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_1080/start_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome1.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome1_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome1_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome2.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome2_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome2_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome3.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome3_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome3_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome4.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/backhome4_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/backhome4_act.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/game.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/game.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/home.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/loading.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/loading.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/loading1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/loading1.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/start.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/start.jpg
--------------------------------------------------------------------------------
/images/chi_sim_4k/start_act.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/chi_sim_4k/start_act.jpg
--------------------------------------------------------------------------------
/images/test/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/images/test/1.jpg
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import os
3 | from PyQt6 import QtWidgets,QtGui
4 | from template.m2 import Ui_mainWindow
5 |
6 | if __name__ == "__main__":
7 | iconPath = os.path.abspath(os.path.join(os.path.dirname(__file__), "./images/avatar/head.ico"))
8 | app = QtWidgets.QApplication(sys.argv)
9 | app.setWindowIcon(QtGui.QIcon(iconPath))
10 | mainWindow = QtWidgets.QMainWindow()
11 | ui = Ui_mainWindow()
12 | ui.setupUi(mainWindow)
13 | mainWindow.show()
14 | sys.exit(app.exec())
15 |
--------------------------------------------------------------------------------
/main.spec:
--------------------------------------------------------------------------------
1 | # -*- mode: python ; coding: utf-8 -*-
2 |
3 |
4 | a = Analysis(
5 | ['main.py'],
6 | pathex=[],
7 | binaries=[],
8 | datas=[],
9 | hiddenimports=[],
10 | hookspath=[],
11 | hooksconfig={},
12 | runtime_hooks=[],
13 | excludes=[],
14 | noarchive=False,
15 | optimize=0,
16 | )
17 | pyz = PYZ(a.pure)
18 |
19 | exe = EXE(
20 | pyz,
21 | a.scripts,
22 | [],
23 | exclude_binaries=True,
24 | name='main',
25 | debug=False,
26 | bootloader_ignore_signals=False,
27 | strip=False,
28 | upx=True,
29 | console=True,
30 | disable_windowed_traceback=False,
31 | argv_emulation=False,
32 | target_arch=None,
33 | codesign_identity=None,
34 | entitlements_file=None,
35 | )
36 | coll = COLLECT(
37 | exe,
38 | a.binaries,
39 | a.datas,
40 | strip=False,
41 | upx=True,
42 | upx_exclude=[],
43 | name='main',
44 | )
45 |
--------------------------------------------------------------------------------
/myopencv/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/myopencv/__init__.py
--------------------------------------------------------------------------------
/myopencv/myopencv.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import matplotlib.pyplot as plt
3 | import numpy as np
4 | import pyautogui
5 |
6 |
7 | class ImageFinder:
8 | def __init__(self, imgopcv):
9 | self.imgopcv = imgopcv
10 | self.screen_width, self.screen_height = pyautogui.size()
11 |
12 | # 相对于某个坐标系的屏幕截取
13 | def find_image_in_screen(
14 | self, image_path, top_left_right_pct, bottom_left_right_pct
15 | ):
16 | try:
17 | # 计算截取区域的坐标
18 | left = int(self.screen_width * top_left_right_pct[0])
19 | top = int(self.screen_height * top_left_right_pct[1])
20 | right = int(self.screen_width * bottom_left_right_pct[0])
21 | bottom = int(self.screen_height * bottom_left_right_pct[1])
22 |
23 | # 截取屏幕图像的特定区域
24 | screenshot = pyautogui.screenshot(
25 | region=(left, top, right - left, bottom - top)
26 | )
27 | screen_np = np.array(screenshot)
28 | img_rgb = cv2.cvtColor(screen_np, cv2.COLOR_RGB2BGR)
29 | image_path = plt.imread(image_path)
30 | # 读取目标图片并转换为灰度图
31 | template = cv2.imread(
32 | image_path, cv2.IMREAD_GRAYSCALE
33 | ) # 使用cv2.IMREAD_GRAYSCALE确保以灰度图读取
34 | if template is None:
35 | print(
36 | f"Error loading image '{image_path}'. Check the file path and integrity."
37 | )
38 | return None
39 | w, h = template.shape[::-1]
40 |
41 | # 将屏幕图像转换为灰度图
42 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
43 |
44 | # 模板匹配
45 | res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
46 |
47 | # 设定匹配阈值
48 | threshold = self.imgopcv
49 | loc = np.where(res >= threshold)
50 |
51 | # 寻找最佳匹配位置
52 | if len(loc[0]) > 0:
53 | # 找到最大值的索引
54 | pt = np.unravel_index(
55 | res.argmax(), res.shape
56 | ) # 使用 argmax 找到最大值的索引
57 |
58 | # 计算匹配区域的中心点坐标
59 | center_point = (
60 | pt[1] + w / 2,
61 | pt[0] + h / 2,
62 | ) # pt[1] 是列索引,pt[0] 是行索引
63 | return center_point
64 | # 如果没有找到匹配,则返回None
65 | return None
66 | except Exception as e:
67 | print(f"An error occurred: {e}")
68 | return None
69 |
70 | # 相对于整个屏幕的屏幕截取
71 | def find_image_all(self, image_path):
72 | try:
73 | # 截取屏幕图像的特定区域
74 | screenshot = pyautogui.screenshot()
75 | screen_np = np.array(screenshot)
76 | img_rgb = cv2.cvtColor(screen_np, cv2.COLOR_RGB2BGR)
77 | # 读取目标图片并转换为灰度图
78 | # image_path = plt.imread(image_path)
79 | # image_path = f"{image_path}".encode("utf-8")
80 | image_path = f"{image_path}"
81 | print("image_path", )
82 | template = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
83 | # template = cv2.imread(
84 | # np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_GRAYSCALE
85 | # ) # 使用cv2.IMREAD_GRAYSCALE确保以灰度图读取
86 | if template is None:
87 | print(
88 | f"Error loading image '{image_path}'. Check the file path and integrity."
89 | )
90 | return None
91 | w, h = template.shape[::-1]
92 |
93 | # 将屏幕图像转换为灰度图
94 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
95 |
96 | # 模板匹配
97 | res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
98 |
99 | # 设定匹配阈值
100 | threshold = self.imgopcv
101 | loc = np.where(res >= threshold)
102 |
103 | # 寻找最佳匹配位置
104 | if len(loc[0]) > 0:
105 | # 找到最大值的索引
106 | pt = np.unravel_index(
107 | res.argmax(), res.shape
108 | ) # 使用 argmax 找到最大值的索引
109 |
110 | # 计算匹配区域的中心点坐标
111 | center_point = (
112 | pt[1] + w / 2,
113 | pt[0] + h / 2,
114 | ) # pt[1] 是列索引,pt[0] 是行索引
115 | return center_point
116 | # 如果没有找到匹配,则返回None
117 | return None
118 | except Exception as e:
119 | print(f"An error occurred: {e}")
120 | return None
121 |
122 | # 相对于整个屏幕截取找多张图
123 | def find_images_all(self, image_paths):
124 | try:
125 | # 截取屏幕图像的特定区域
126 | screenshot = pyautogui.screenshot()
127 | screen_np = np.array(screenshot)
128 | img_rgb = cv2.cvtColor(screen_np, cv2.COLOR_RGB2BGR)
129 |
130 | # 循环遍历提供的图片路径列表
131 | for image_path in image_paths:
132 | # image_path = plt.imread(image_path)
133 | # 读取目标图片并转换为灰度图
134 | image_path = f"{image_path}"
135 | template = cv2.imdecode(np.fromfile(image_path, dtype=np.uint8), cv2.IMREAD_GRAYSCALE)
136 | if template is None:
137 | print(
138 | f"Error loading image '{image_path}'. Check the file path and integrity."
139 | )
140 | continue # 如果图片加载失败,跳过这张图片
141 |
142 | w, h = template.shape[::-1] # 获取图片的宽度和高度
143 |
144 | # 将屏幕图像转换为灰度图
145 | img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
146 |
147 | # 模板匹配
148 | res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
149 |
150 | # 设定匹配阈值
151 | threshold = self.imgopcv
152 | loc = np.where(res >= threshold)
153 |
154 | # 寻找最佳匹配位置
155 | if len(loc[0]) > 0:
156 | # 找到最大值的索引
157 | pt = np.unravel_index(res.argmax(), res.shape)
158 |
159 | # 计算匹配区域的中心点坐标
160 | center_point = (pt[1] + w // 2, pt[0] + h // 2)
161 | return center_point # 返回第一张找到的图片的中心点坐标
162 |
163 | # 如果没有找到匹配,则返回None
164 | return None
165 | except Exception as e:
166 | print(f"An error occurred: {e}")
167 | return None
168 |
169 |
170 | # 使用示例
171 | if __name__ == "__main__":
172 | finder = ImageFinder()
173 | target_image_path = "../images/kaishi.jpg"
174 | search_area_percentages = (
175 | (0.1, 0.1), # 顶部 left right
176 | (0.9, 0.1), # 底部 left right
177 | )
178 | result = finder.find_image_in_screen(target_image_path, search_area_percentages)
179 | if result is not None:
180 | print(f"Found image at screen coordinates: {result}")
181 | else:
182 | print("No match found.")
183 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pubg-tools/pubg-bot/c076bc46c187a2b5d3889518b2d0c00bd96befc3/requirements.txt
--------------------------------------------------------------------------------
/template/m2.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '.\ui\main.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.4.2
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | import datetime
10 | import json
11 | import logging
12 | import os
13 | import sys
14 | import threading
15 |
16 | import requests
17 | from PyQt6 import QtCore, QtGui, QtWidgets
18 | from PyQt6.QtCore import QThread, pyqtSignal
19 | from PyQt6.QtWidgets import QMainWindow
20 |
21 | # from gameloop import gameLoop
22 | # 引入 上层文件夹的 gameloop.py 中的 gameloop类
23 | from gameloop import gameloop
24 | from template.tips import Ui_Form
25 | from template.updatelog import Up_data_log
26 |
27 | # 生成 ..\config\config.json 文件的绝对路径
28 | configPath = os.path.abspath(
29 | os.path.join(os.path.dirname(__file__), "../config/config.json")
30 | )
31 |
32 | # 构建 config.json 的正确路径
33 | print("configPath:", configPath)
34 |
35 | # 读取 ../config/config.json 文件 并将变量赋值给 config
36 | globGameloop = gameloop()
37 | # 定义一个旧的窗体文案值
38 | oldText = ""
39 | oldText2 = ""
40 |
41 | try:
42 | from ctypes import windll # Only exists on Windows.
43 |
44 | myappid = "mycompany.myproduct.subproduct.version"
45 | windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid)
46 | except ImportError:
47 | pass
48 |
49 |
50 | class ChineseLogger:
51 | def __init__(self, log_name, log_dir="./logs", log_level=logging.INFO):
52 | self.log_name = log_name
53 | self.log_dir = log_dir
54 | self.log_level = log_level
55 | self._setup_logging()
56 |
57 | def _setup_logging(self):
58 | # 创建日志目录
59 | if not os.path.exists(self.log_dir):
60 | os.makedirs(self.log_dir)
61 | dt = datetime.datetime.now().strftime("%Y-%m-%d")
62 | file_name = f"{str(dt)}-{str(self.log_name)}.log"
63 | print(file_name)
64 | # 日志文件路径
65 | self.log_file = os.path.join(self.log_dir, file_name)
66 |
67 | # 创建一个logger
68 | self.logger = logging.getLogger(self.log_name)
69 | self.logger.setLevel(self.log_level)
70 |
71 | # 创建一个handler,用于写入日志文件
72 | file_handler = logging.FileHandler(self.log_file, "a", encoding="utf-8")
73 | file_handler.setLevel(self.log_level)
74 |
75 | # 创建一个formatter,用于设置日志格式
76 | formatter = logging.Formatter(
77 | "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
78 | )
79 |
80 | # 为logger添加handler
81 | self.logger.addHandler(file_handler)
82 | file_handler.setFormatter(formatter)
83 |
84 | def debug(self, msg):
85 | self.logger.debug(msg)
86 |
87 | def info(self, msg):
88 | self._setup_logging()
89 | print("info:", self.log_dir)
90 | self.logger.info(msg)
91 |
92 | def warning(self, msg):
93 | self.logger.warning(msg)
94 |
95 | def error(self, msg):
96 | self.logger.error(msg)
97 |
98 | def critical(self, msg):
99 | self.logger.critical(msg)
100 |
101 | def setLog_dir(self, log_dir):
102 | self.log_dir = log_dir
103 |
104 |
105 | class WorkerThread(QThread):
106 | finished_signal = pyqtSignal(str)
107 | # 第二个插槽
108 | finished_signal_loop = pyqtSignal(str)
109 |
110 | def run(self, timeout=5, flaytimeout=30, imgopcv=8, saveLog=True):
111 | self.gameloop = globGameloop
112 | self.gameloop.setCllback(self.callback)
113 | self.gameloop.setCllback2(self.callback2)
114 | # 创建子线程 执行 gameLoop 方法
115 | self.threadItem = threading.Thread(
116 | target=self.gameloop.gameLoop,
117 | args=(timeout, flaytimeout, imgopcv * 0.1, saveLog),
118 | )
119 | self.threadItem.start()
120 |
121 | def callback(self, message):
122 | self.finished_signal.emit(message)
123 |
124 | def callback2(self, message):
125 | self.finished_signal_loop.emit(message)
126 |
127 |
128 | class Ui_mainWindow(QMainWindow):
129 | def __init__(self, parent=None):
130 | print("进入构造方法")
131 | super(Ui_mainWindow, self).__init__(parent=parent)
132 | # pubg 状态
133 | self.pubgState = False
134 | # steam 状态
135 | self.steamState = False
136 |
137 | self.gameloop = globGameloop
138 | # 实例化 WorkerThread
139 | self.worker_thread = WorkerThread()
140 | # 绑定 finished_signal 信号到 showLogs 方法
141 | self.worker_thread.finished_signal.connect(self.setStateHooks)
142 | # 绑定 finished_signal_loop 信号到 showLogs 方法
143 | self.worker_thread.finished_signal_loop.connect(self.setStateHooks2)
144 | # 实例化日志模块
145 | self.logger = None
146 | self.setupUi(self)
147 |
148 | def setupUi(self, mainWindow):
149 | # 获取 ../images/avatar/head.ico 的绝对路径变量
150 | self.iconPath = os.path.abspath(
151 | os.path.join(os.path.dirname(__file__), "../images/avatar/head.ico")
152 | )
153 | # 获取 ../images/avatar/steam.png" 的绝对路径变量
154 | self.steamPath = os.path.abspath(
155 | os.path.join(os.path.dirname(__file__), "../images/avatar/steam.png")
156 | )
157 | # 获取 ../images/avatar/pubg.png" 的绝对路径变量
158 | self.pubgPath = os.path.abspath(
159 | os.path.join(os.path.dirname(__file__), "../images/avatar/pubg.png")
160 | )
161 | # 获取 ../images/avatar/tips.png" 的绝对路径变量
162 | self.tipsPath = os.path.abspath(
163 | os.path.join(os.path.dirname(__file__), "../images/avatar/tips.png")
164 | )
165 | # 获取 ../images/avatar/steam_act.png" 的绝对路径变量
166 | self.steamActPath = os.path.abspath(
167 | os.path.join(os.path.dirname(__file__), "../images/avatar/steam_act.png")
168 | )
169 | # 获取 ../images/avatar/pubg_act.png" 的绝对路径变量
170 | self.pubgActPath = os.path.abspath(
171 | os.path.join(os.path.dirname(__file__), "../images/avatar/pubg_act.png")
172 | )
173 | mainWindow.setObjectName("mainWindow")
174 | mainWindow.resize(756, 267)
175 | font = QtGui.QFont()
176 | font.setPointSize(9)
177 | mainWindow.setFont(font)
178 | icon = QtGui.QIcon()
179 | icon.addPixmap(
180 | QtGui.QPixmap(self.iconPath), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off
181 | )
182 | mainWindow.setWindowIcon(icon)
183 | self.centralwidget = QtWidgets.QWidget(parent=mainWindow)
184 | self.centralwidget.setObjectName("centralwidget")
185 | self.horizontalLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget)
186 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(0, 10, 171, 41))
187 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
188 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
189 | self.horizontalLayout.setContentsMargins(20, 0, 0, 0)
190 | self.horizontalLayout.setObjectName("horizontalLayout")
191 | self.label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
192 | sizePolicy = QtWidgets.QSizePolicy(
193 | QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum
194 | )
195 | sizePolicy.setHorizontalStretch(0)
196 | sizePolicy.setVerticalStretch(0)
197 | sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
198 | self.label.setSizePolicy(sizePolicy)
199 | self.label.setObjectName("label")
200 | self.horizontalLayout.addWidget(self.label)
201 | self.comboBox_2 = QtWidgets.QComboBox(parent=self.horizontalLayoutWidget)
202 | sizePolicy = QtWidgets.QSizePolicy(
203 | QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum
204 | )
205 | sizePolicy.setHorizontalStretch(0)
206 | sizePolicy.setVerticalStretch(0)
207 | sizePolicy.setHeightForWidth(self.comboBox_2.sizePolicy().hasHeightForWidth())
208 | self.comboBox_2.setSizePolicy(sizePolicy)
209 | self.comboBox_2.setObjectName("comboBox_2")
210 | self.horizontalLayout.addWidget(self.comboBox_2)
211 | self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
212 | self.label_2.setGeometry(QtCore.QRect(10, 60, 40, 40))
213 | self.label_2.setText("")
214 | self.label_2.setPixmap(QtGui.QPixmap(self.steamPath))
215 | self.label_2.setScaledContents(True)
216 | self.label_2.setObjectName("label_2")
217 | self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
218 | self.label_5.setGeometry(QtCore.QRect(68, 58, 44, 44))
219 | self.label_5.setText("")
220 | self.label_5.setPixmap(QtGui.QPixmap(self.pubgPath))
221 | self.label_5.setScaledContents(True)
222 | self.label_5.setObjectName("label_5")
223 | self.pushButton = QtWidgets.QPushButton(parent=self.centralwidget)
224 | self.pushButton.setGeometry(QtCore.QRect(130, 65, 60, 30))
225 | self.pushButton.setObjectName("pushButton")
226 | self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
227 | self.label_6.setGeometry(QtCore.QRect(20, 180, 91, 21))
228 | self.label_6.setObjectName("label_6")
229 | self.lineEdit = QtWidgets.QLineEdit(parent=self.centralwidget)
230 | self.lineEdit.setEnabled(False)
231 | self.lineEdit.setGeometry(QtCore.QRect(110, 180, 371, 20))
232 | self.lineEdit.setObjectName("lineEdit")
233 | self.pushButton_2 = QtWidgets.QPushButton(parent=self.centralwidget)
234 | self.pushButton_2.setGeometry(QtCore.QRect(490, 180, 75, 20))
235 | self.pushButton_2.setObjectName("pushButton_2")
236 | self.label_7 = QtWidgets.QLabel(parent=self.centralwidget)
237 | self.label_7.setGeometry(QtCore.QRect(210, 58, 60, 40))
238 | self.label_7.setObjectName("label_7")
239 | self.label_8 = QtWidgets.QLabel(parent=self.centralwidget)
240 | self.label_8.setGeometry(QtCore.QRect(290, 58, 211, 40))
241 | self.label_8.setObjectName("label_8")
242 | self.label_11 = QtWidgets.QLabel(parent=self.centralwidget)
243 | self.label_11.setGeometry(QtCore.QRect(490, 58, 211, 40))
244 | self.label_11.setObjectName("label_11")
245 | # 添加一个label 放置到窗体右下角
246 | self.label_12 = QtWidgets.QLabel(parent=self.centralwidget)
247 | self.label_12.setGeometry(QtCore.QRect(700, 210, 171, 21))
248 | self.label_12.setObjectName("label_12")
249 |
250 | self.formLayoutWidget_2 = QtWidgets.QWidget(parent=self.centralwidget)
251 | self.formLayoutWidget_2.setGeometry(QtCore.QRect(240, 110, 201, 51))
252 | self.formLayoutWidget_2.setObjectName("formLayoutWidget_2")
253 | self.formLayout_4 = QtWidgets.QFormLayout(self.formLayoutWidget_2)
254 | self.formLayout_4.setContentsMargins(20, 0, 0, 0)
255 | self.formLayout_4.setObjectName("formLayout_4")
256 | self.label_14 = QtWidgets.QLabel(parent=self.formLayoutWidget_2)
257 | self.label_14.setObjectName("label_14")
258 | self.formLayout_4.setWidget(
259 | 0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_14
260 | )
261 | self.label_15 = QtWidgets.QLabel(parent=self.formLayoutWidget_2)
262 | self.label_15.setObjectName("label_15")
263 | self.formLayout_4.setWidget(
264 | 1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_15
265 | )
266 | self.spinBox_5 = QtWidgets.QSpinBox(parent=self.formLayoutWidget_2)
267 | self.spinBox_5.setObjectName("spinBox_5")
268 | self.formLayout_4.setWidget(
269 | 0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox_5
270 | )
271 | self.checkBox = QtWidgets.QCheckBox(parent=self.formLayoutWidget_2)
272 | self.checkBox.setText("")
273 | self.checkBox.setObjectName("checkBox")
274 | self.formLayout_4.setWidget(
275 | 1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.checkBox
276 | )
277 |
278 | self.textBrowser = QtWidgets.QTextBrowser(parent=self.centralwidget)
279 | self.textBrowser.setGeometry(QtCore.QRect(190, 10, 541, 41))
280 | self.textBrowser.setEnabled(False)
281 | self.textBrowser.setObjectName("textBrowser")
282 | self.formLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget)
283 | self.formLayoutWidget.setGeometry(QtCore.QRect(0, 110, 201, 51))
284 | self.formLayoutWidget.setObjectName("formLayoutWidget")
285 | self.formLayout_2 = QtWidgets.QFormLayout(self.formLayoutWidget)
286 | self.formLayout_2.setContentsMargins(20, 0, 0, 0)
287 | self.formLayout_2.setObjectName("formLayout_2")
288 | self.label_3 = QtWidgets.QLabel(parent=self.formLayoutWidget)
289 | self.label_3.setObjectName("label_3")
290 | self.formLayout_2.setWidget(
291 | 0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_3
292 | )
293 | self.label_4 = QtWidgets.QLabel(parent=self.formLayoutWidget)
294 | self.label_4.setObjectName("label_4")
295 | self.formLayout_2.setWidget(
296 | 1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_4
297 | )
298 | self.spinBox = QtWidgets.QSpinBox(parent=self.formLayoutWidget)
299 | self.spinBox.setObjectName("spinBox")
300 | self.formLayout_2.setWidget(
301 | 0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox
302 | )
303 | self.spinBox_2 = QtWidgets.QSpinBox(parent=self.formLayoutWidget)
304 | self.spinBox_2.setObjectName("spinBox_2")
305 | self.formLayout_2.setWidget(
306 | 1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox_2
307 | )
308 | self.label_9 = QtWidgets.QLabel(parent=self.centralwidget)
309 | self.label_9.setGeometry(QtCore.QRect(210, 110, 20, 20))
310 | self.label_9.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WhatsThisCursor))
311 | self.label_9.setText("")
312 | self.label_9.setPixmap(QtGui.QPixmap(self.tipsPath))
313 | self.label_9.setScaledContents(True)
314 | self.label_9.setObjectName("label_9")
315 | self.label_10 = QtWidgets.QLabel(parent=self.centralwidget)
316 | self.label_10.setGeometry(QtCore.QRect(210, 140, 20, 20))
317 | self.label_10.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WhatsThisCursor))
318 | self.label_10.setText("")
319 | self.label_10.setPixmap(QtGui.QPixmap(self.tipsPath))
320 | self.label_10.setScaledContents(True)
321 | self.label_10.setObjectName("label_10")
322 | self.pushButton_3 = QtWidgets.QPushButton(parent=self.centralwidget)
323 | self.pushButton_3.setGeometry(QtCore.QRect(510, 115, 110, 40))
324 | self.pushButton_3.setObjectName("pushButton_3")
325 | mainWindow.setCentralWidget(self.centralwidget)
326 | self.menubar = QtWidgets.QMenuBar(parent=mainWindow)
327 | self.menubar.setGeometry(QtCore.QRect(0, 0, 756, 23))
328 | self.menubar.setObjectName("menubar")
329 | self.menu = QtWidgets.QMenu(parent=self.menubar)
330 | self.menu.setObjectName("menu")
331 | mainWindow.setMenuBar(self.menubar)
332 | self.statusbar = QtWidgets.QStatusBar(parent=mainWindow)
333 | self.statusbar.setObjectName("statusbar")
334 | mainWindow.setStatusBar(self.statusbar)
335 | self.action = QtGui.QAction(parent=mainWindow)
336 | self.action.setObjectName("action")
337 | self.action_2 = QtGui.QAction(parent=mainWindow)
338 | self.action_2.setObjectName("action_2")
339 | self.action_3 = QtGui.QAction(parent=mainWindow)
340 | self.action_3.setObjectName("action_3")
341 | self.menu.addAction(self.action)
342 | self.menu.addAction(self.action_2)
343 | self.menu.addAction(self.action_3)
344 | self.menubar.addAction(self.menu.menuAction())
345 |
346 | # 给 comboBox_2 添加两个选项 简体中文 和繁体中文 默认选择简体中文
347 | self.comboBox_2.addItem("简体中文")
348 | # self.comboBox_2.addItem("繁体中文")
349 | self.comboBox_2.setCurrentIndex(0)
350 | # 禁用窗体放大缩小
351 | mainWindow.setFixedSize(756, 267)
352 | # 禁用窗体最大化
353 | mainWindow.setWindowFlag(QtCore.Qt.WindowType.WindowMaximizeButtonHint, False)
354 | # 增加窗体永久置顶
355 | mainWindow.setWindowFlag(QtCore.Qt.WindowType.WindowStaysOnTopHint, True)
356 | # 禁用窗体最小化
357 | mainWindow.setWindowFlag(QtCore.Qt.WindowType.WindowMinimizeButtonHint, False)
358 |
359 | # 给 pushButton_2 添加点击事件
360 | self.pushButton_2.clicked.connect(self.seachLogsPath)
361 | # 给 日志按钮添加点击事件
362 | self.action_2.triggered.connect(self.showLogs)
363 | # 给 更新日志按钮添加点击事件
364 | self.action_3.triggered.connect(self.openUpdateLog)
365 | # 给 刷新按钮 添加 checkSteamAndPubg 点击事件
366 | self.pushButton.clicked.connect(self.checkSteamAndPubg)
367 | # 给开始挂机按钮 添加点击事件
368 | self.pushButton_3.clicked.connect(self.startGameLoop)
369 | # 给 action 添加点击事件
370 | self.action.triggered.connect(self.openAbout)
371 |
372 | # 设置 label_9 的默认值为 5
373 | self.spinBox.setValue(5)
374 | # 设置 label_10 的默认值为 30
375 | self.spinBox_2.setValue(30)
376 | # 鼠标放到 label_9 上提示文字
377 | self.label_9.setToolTip("轮询延迟:每轮状态检查中间隔的时间,单位为秒")
378 | self.label_9.setStatusTip("轮询延迟:每轮状态检查中间隔的时间,单位为秒")
379 | # 鼠标放到 label_10 上提示文字
380 | self.label_10.setToolTip("跳伞延迟:每次上飞机时等待多久跳伞,单位为秒")
381 | self.label_10.setStatusTip("跳伞延迟:每次上飞机时等待多久跳伞,单位为秒")
382 | # 默认选中 label_15
383 | self.checkBox.setChecked(True)
384 | # 设置 spinBox_5 的默认值为 8
385 | self.spinBox_5.setValue(8)
386 | # 设置 spinBox_5 的最大值为 10 最小值为 1
387 | self.spinBox_5.setMaximum(10)
388 | self.spinBox_5.setMinimum(1)
389 | self.retranslateUi(mainWindow)
390 | QtCore.QMetaObject.connectSlotsByName(mainWindow)
391 | self.initData()
392 |
393 | def retranslateUi(self, mainWindow):
394 | # 获取配置信息
395 | _translate = QtCore.QCoreApplication.translate
396 | self.label.setText(_translate("mainWindow", "语 言"))
397 | self.pushButton.setText(_translate("mainWindow", "刷新"))
398 | self.label_6.setText(_translate("mainWindow", "日志保存位置:"))
399 | self.pushButton_2.setText(_translate("mainWindow", "选择文件夹"))
400 | self.label_7.setText(_translate("mainWindow", "当前状态:"))
401 | self.label_8.setText(_translate("mainWindow", "未开启"))
402 | self.label_11.setText(_translate("mainWindow", ""))
403 | # 设置主页文本
404 | self.label_3.setText(_translate("mainWindow", "轮 询 延 迟:"))
405 | self.label_4.setText(_translate("mainWindow", "跳 伞 延 迟:"))
406 | self.label_14.setText(_translate("mainWindow", "图 片 相 似 度:"))
407 | self.label_15.setText(_translate("mainWindow", "保 存 日 志:"))
408 | self.menu.setTitle(_translate("mainWindow", "关于"))
409 | self.action.setText(_translate("mainWindow", "关于软件"))
410 | self.action_2.setText(_translate("mainWindow", "日志"))
411 | self.action_3.setText(_translate("mainWindow", "更新日志"))
412 | self.pushButton_3.setText(_translate("mainWindow", "开始挂机"))
413 | self.label_12.setText("V 1.2.0")
414 |
415 | def initData(self):
416 | # 获取用户桌面path
417 | path = os.path.join(os.path.expanduser("~"), "Desktop")
418 | path = os.path.join(path, "logs")
419 | print("path:", path)
420 | # 设置日志保存位置
421 | self.lineEdit.setText(path)
422 | self.logger = ChineseLogger("PUBG-tools")
423 | self.logger.setLog_dir(path)
424 | self.checkSteamAndPubg()
425 |
426 | # 检测是否打开了 steam 和 pubg
427 | def checkSteamAndPubg(self):
428 | print("检测是否打开了 steam 和 pubg")
429 | # 检查是否有 名为 steam.exe 的进程
430 | if os.system("tasklist | findstr steam.exe") == 0:
431 | # 如果已经打开 steam 将 label_2 的图片 替换为 steam.png
432 | self.label_2.setPixmap(QtGui.QPixmap(self.steamActPath))
433 | self.steamState = True
434 | self.label_11.setText("已开启 steam")
435 | else:
436 | # 将图片替换为 steam.png
437 | self.label_2.setPixmap(QtGui.QPixmap(self.steamPath))
438 | # 将 label_7 替换为 未开启 steam
439 | self.label_11.setText("未开启 steam")
440 | self.steamState = False
441 | # 检查是否有 名为 TslGame.exe 的进程
442 | if os.system("tasklist | findstr TslGame.exe") == 0:
443 | # 如果已经打开 pubg 将 label_5 的图片 替换为 pubg_act.png
444 | self.label_5.setPixmap(QtGui.QPixmap(self.pubgActPath))
445 | self.pubgState = True
446 | self.label_11.setText("已开启 pubg")
447 | else:
448 | # 将图片替换为 pubg.png
449 | self.label_5.setPixmap(QtGui.QPixmap(self.pubgPath))
450 | # 将 label_8 替换为 未开启 PUBG
451 | self.label_11.setText("未开启 PUBG")
452 | self.pubgState = False
453 | pass
454 |
455 | # def closeEvent(self, a0: QtGui.QCloseEvent) -> None:
456 | # print("关闭窗口")
457 | # self.gameloop.setState(False)
458 | # pass
459 | # 自定义关闭函数
460 | def closeEvent(self, event):
461 | print("closeEvent")
462 | self.gameloop.setState(False)
463 | super(Ui_mainWindow, self).closeEvent(event)
464 |
465 | # 选择日志保存位置
466 | def seachLogsPath(self):
467 | # 弹出文件选择框
468 | path = QtWidgets.QFileDialog.getExistingDirectory(self, "选择文件夹", "../")
469 | if path != "":
470 | print("有值")
471 | path = path + "/logs"
472 | else:
473 | print("没有值")
474 |
475 | # 打开日志地址
476 | def showLogs(self):
477 | print("打开日志地址")
478 | # 获取日志保存位置
479 | path = self.lineEdit.text()
480 | print(path)
481 | # 打开文件夹
482 | os.system(f"start explorer {path}")
483 |
484 | # 开始挂机
485 | def startGameLoop(self):
486 | print("游戏状态:", self.gameloop.getState())
487 | if self.gameloop.getState() == False:
488 | # 将 轮询延迟 与 跳伞延迟 传进去
489 | self.worker_thread.run(
490 | self.spinBox.value(),
491 | self.spinBox_2.value(),
492 | self.spinBox_5.value(),
493 | self.checkBox.isChecked(),
494 | )
495 | self.pushButton_3.setText("挂机中...")
496 | # 设置 label_8 的文本为 已开始
497 | self.label_8.setText("已开始")
498 | else:
499 | self.pushButton_3.setText("开始挂机")
500 | self.gameloop.setState(False)
501 | # 设置 label_8 的文本为 已开始
502 | self.label_8.setText("未开始")
503 |
504 | # 修改主窗体文案 hooks 1
505 | def setStateHooks(self, message):
506 | global oldText
507 | if message == oldText:
508 | self.label_8.setText(message)
509 | else:
510 | self.label_8.setText(message)
511 | oldText = message
512 | # 判断是否保存日志
513 | if self.checkBox.isChecked():
514 | self.logger.info(message)
515 |
516 | # 修改主窗体文案 hooks 2
517 | def setStateHooks2(self, message):
518 | global oldText2
519 | if message == oldText2:
520 | self.label_11.setText(message)
521 | else:
522 | self.label_11.setText(message)
523 | oldText2 = message
524 | # 判断是否保存日志
525 | if self.checkBox.isChecked():
526 | self.logger.info(message)
527 |
528 | # 打开关于软件
529 | def openAbout(self):
530 | self.about_ui = Ui_Form()
531 | self.about_ui.show()
532 |
533 | # 打开更新日志按钮
534 | def openUpdateLog(self):
535 | self.updateLog_ui = Up_data_log()
536 | self.updateLog_ui.show()
537 |
538 |
539 | if __name__ == "__main__":
540 | app = QtWidgets.QApplication(sys.argv)
541 | mainWindow = QtWidgets.QMainWindow()
542 | ui = Ui_mainWindow()
543 | ui.setupUi(mainWindow)
544 | mainWindow.show()
545 | sys.exit(app.exec())
546 |
--------------------------------------------------------------------------------
/template/tips.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '.\ui\关于软件.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.4.2
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | import requests
10 | from PyQt6 import QtCore, QtGui, QtWidgets
11 | from PyQt6.QtWidgets import QWidget
12 |
13 |
14 | class Ui_Form(QWidget):
15 |
16 | def __init__(self):
17 | super(Ui_Form, self).__init__()
18 | self.setupUi(self)
19 |
20 | def setupUi(self, Form):
21 | Form.setObjectName("Form")
22 | Form.resize(500, 400)
23 | font = QtGui.QFont()
24 | font.setPointSize(16)
25 | font.setBold(True)
26 | font.setWeight(75)
27 | Form.setFont(font)
28 | self.label = QtWidgets.QLabel(parent=Form)
29 | self.label.setGeometry(QtCore.QRect(200, 20, 100, 40))
30 | self.label.setObjectName("label")
31 | self.textBrowser = QtWidgets.QTextBrowser(parent=Form)
32 | self.textBrowser.setEnabled(False)
33 | self.textBrowser.setGeometry(QtCore.QRect(40, 60, 431, 121))
34 | self.textBrowser.setObjectName("textBrowser")
35 | self.label_2 = QtWidgets.QLabel(parent=Form)
36 | self.label_2.setGeometry(QtCore.QRect(150, 190, 200, 200))
37 | self.label_2.setText("")
38 | # self.label_2.setPixmap(QtGui.QPixmap(".\\ui\\f7d077c6d349c220f4293dac4c02799.jpg"))
39 | # 改为从网络地址加载图片
40 | self.label_2.setScaledContents(True)
41 | self.label_2.setObjectName("label_2")
42 |
43 | # 禁用窗体放大缩小
44 | Form.setFixedSize(500, 400)
45 | # 禁用窗体最大化
46 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowMaximizeButtonHint, False)
47 | # 增加窗体永久置顶
48 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowStaysOnTopHint, True)
49 | # 禁用窗体最小化
50 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowMinimizeButtonHint, False)
51 | self.retranslateUi(Form)
52 | QtCore.QMetaObject.connectSlotsByName(Form)
53 |
54 | def retranslateUi(self, Form):
55 | _translate = QtCore.QCoreApplication.translate
56 | Form.setWindowTitle(_translate("Form", "Form"))
57 | self.label.setText(_translate("Form", "关于软件"))
58 |
--------------------------------------------------------------------------------
/template/updatelog.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '.\ui\更新日志.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.4.2
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | import requests
10 | from PyQt6 import QtCore, QtGui, QtWidgets
11 | from PyQt6.QtWidgets import QWidget
12 | import random
13 |
14 | class Up_data_log(QWidget):
15 |
16 | def __init__(self):
17 | super(Up_data_log, self).__init__()
18 | self.setupUi(self)
19 |
20 | def setupUi(self, Form):
21 | Form.setObjectName("Form")
22 | Form.resize(380, 519)
23 | self.textBrowser = QtWidgets.QTextBrowser(parent=Form)
24 | self.textBrowser.setGeometry(QtCore.QRect(10, 10, 361, 501))
25 | self.textBrowser.setObjectName("textBrowser")
26 | # 禁用窗体最大化
27 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowMaximizeButtonHint, False)
28 | # 增加窗体永久置顶
29 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowStaysOnTopHint, True)
30 | # 禁用窗体最小化
31 | Form.setWindowFlag(QtCore.Qt.WindowType.WindowMinimizeButtonHint, False)
32 | self.retranslateUi(Form)
33 | QtCore.QMetaObject.connectSlotsByName(Form)
34 |
35 | def retranslateUi(self, Form):
36 | pass
37 |
38 |
39 | if __name__ == "__main__":
40 | import sys
41 |
42 | app = QtWidgets.QApplication(sys.argv)
43 | Form = QtWidgets.QWidget()
44 | ui = Up_data_log()
45 | ui.setupUi(Form)
46 | Form.show()
47 | sys.exit(app.exec())
48 |
--------------------------------------------------------------------------------
/test/test.py:
--------------------------------------------------------------------------------
1 | from PyQt6 import QtCore, QtWidgets
2 | from PyQt6.QtWidgets import QMainWindow
3 |
4 |
5 | class Ui_MainWindow(object):
6 | def setupUi(self, MainWindow):
7 | MainWindow.setObjectName("MainWindow")
8 | MainWindow.resize(277, 244)
9 | self.centralwidget = QtWidgets.QWidget(MainWindow)
10 | self.centralwidget.setObjectName("centralwidget")
11 | MainWindow.setCentralWidget(self.centralwidget)
12 | self.statusbar = QtWidgets.QStatusBar(MainWindow)
13 | self.statusbar.setObjectName("statusbar")
14 | MainWindow.setStatusBar(self.statusbar)
15 | QtCore.QMetaObject.connectSlotsByName(MainWindow)
16 | MainWindow.show()
17 |
18 |
19 | class MyWindow(QMainWindow):
20 | def closeEvent(self, event):
21 | print("closeEvent")
22 | pass
23 |
24 |
25 | if __name__ == "__main__":
26 | import sys
27 |
28 | app = QtWidgets.QApplication(sys.argv)
29 | MainWindow = MyWindow()
30 | ui = Ui_MainWindow()
31 | ui.setupUi(MainWindow)
32 | sys.exit(app.exec())
33 |
--------------------------------------------------------------------------------
/ui/main.py:
--------------------------------------------------------------------------------
1 | # Form implementation generated from reading ui file '.\ui\main.ui'
2 | #
3 | # Created by: PyQt6 UI code generator 6.6.1
4 | #
5 | # WARNING: Any manual changes made to this file will be lost when pyuic6 is
6 | # run again. Do not edit this file unless you know what you are doing.
7 |
8 |
9 | from PyQt6 import QtCore, QtGui, QtWidgets
10 |
11 |
12 | class Ui_mainWindow(object):
13 | def setupUi(self, mainWindow):
14 | mainWindow.setObjectName("mainWindow")
15 | mainWindow.resize(756, 267)
16 | font = QtGui.QFont()
17 | font.setPointSize(9)
18 | mainWindow.setFont(font)
19 | icon = QtGui.QIcon()
20 | icon.addPixmap(QtGui.QPixmap(".\\ui\\../images/avatar/head.ico"), QtGui.QIcon.Mode.Normal, QtGui.QIcon.State.Off)
21 | mainWindow.setWindowIcon(icon)
22 | self.centralwidget = QtWidgets.QWidget(parent=mainWindow)
23 | self.centralwidget.setObjectName("centralwidget")
24 | self.horizontalLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget)
25 | self.horizontalLayoutWidget.setGeometry(QtCore.QRect(0, 10, 171, 41))
26 | self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
27 | self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
28 | self.horizontalLayout.setContentsMargins(20, 0, 0, 0)
29 | self.horizontalLayout.setObjectName("horizontalLayout")
30 | self.label = QtWidgets.QLabel(parent=self.horizontalLayoutWidget)
31 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Minimum)
32 | sizePolicy.setHorizontalStretch(0)
33 | sizePolicy.setVerticalStretch(0)
34 | sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
35 | self.label.setSizePolicy(sizePolicy)
36 | self.label.setObjectName("label")
37 | self.horizontalLayout.addWidget(self.label)
38 | self.comboBox_2 = QtWidgets.QComboBox(parent=self.horizontalLayoutWidget)
39 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Maximum, QtWidgets.QSizePolicy.Policy.Maximum)
40 | sizePolicy.setHorizontalStretch(0)
41 | sizePolicy.setVerticalStretch(0)
42 | sizePolicy.setHeightForWidth(self.comboBox_2.sizePolicy().hasHeightForWidth())
43 | self.comboBox_2.setSizePolicy(sizePolicy)
44 | self.comboBox_2.setObjectName("comboBox_2")
45 | self.horizontalLayout.addWidget(self.comboBox_2)
46 | self.label_2 = QtWidgets.QLabel(parent=self.centralwidget)
47 | self.label_2.setGeometry(QtCore.QRect(10, 60, 40, 40))
48 | self.label_2.setText("")
49 | self.label_2.setPixmap(QtGui.QPixmap(".\\ui\\../images/avatar/steam.png"))
50 | self.label_2.setScaledContents(True)
51 | self.label_2.setObjectName("label_2")
52 | self.label_5 = QtWidgets.QLabel(parent=self.centralwidget)
53 | self.label_5.setGeometry(QtCore.QRect(68, 58, 44, 44))
54 | self.label_5.setText("")
55 | self.label_5.setPixmap(QtGui.QPixmap(".\\ui\\../images/avatar/pubg.png"))
56 | self.label_5.setScaledContents(True)
57 | self.label_5.setObjectName("label_5")
58 | self.pushButton = QtWidgets.QPushButton(parent=self.centralwidget)
59 | self.pushButton.setGeometry(QtCore.QRect(130, 65, 60, 30))
60 | self.pushButton.setObjectName("pushButton")
61 | self.label_6 = QtWidgets.QLabel(parent=self.centralwidget)
62 | self.label_6.setGeometry(QtCore.QRect(20, 180, 91, 21))
63 | self.label_6.setObjectName("label_6")
64 | self.lineEdit = QtWidgets.QLineEdit(parent=self.centralwidget)
65 | self.lineEdit.setEnabled(False)
66 | self.lineEdit.setGeometry(QtCore.QRect(110, 180, 371, 20))
67 | self.lineEdit.setObjectName("lineEdit")
68 | self.pushButton_2 = QtWidgets.QPushButton(parent=self.centralwidget)
69 | self.pushButton_2.setGeometry(QtCore.QRect(490, 180, 75, 20))
70 | self.pushButton_2.setObjectName("pushButton_2")
71 | self.label_7 = QtWidgets.QLabel(parent=self.centralwidget)
72 | self.label_7.setGeometry(QtCore.QRect(210, 58, 60, 40))
73 | self.label_7.setObjectName("label_7")
74 | self.label_8 = QtWidgets.QLabel(parent=self.centralwidget)
75 | self.label_8.setGeometry(QtCore.QRect(290, 58, 211, 40))
76 | self.label_8.setObjectName("label_8")
77 | self.textBrowser = QtWidgets.QTextBrowser(parent=self.centralwidget)
78 | self.textBrowser.setGeometry(QtCore.QRect(190, 10, 541, 41))
79 | self.textBrowser.setObjectName("textBrowser")
80 | self.formLayoutWidget = QtWidgets.QWidget(parent=self.centralwidget)
81 | self.formLayoutWidget.setGeometry(QtCore.QRect(0, 110, 201, 51))
82 | self.formLayoutWidget.setObjectName("formLayoutWidget")
83 | self.formLayout_2 = QtWidgets.QFormLayout(self.formLayoutWidget)
84 | self.formLayout_2.setContentsMargins(20, 0, 0, 0)
85 | self.formLayout_2.setObjectName("formLayout_2")
86 | self.label_3 = QtWidgets.QLabel(parent=self.formLayoutWidget)
87 | self.label_3.setObjectName("label_3")
88 | self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_3)
89 | self.label_4 = QtWidgets.QLabel(parent=self.formLayoutWidget)
90 | self.label_4.setObjectName("label_4")
91 | self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_4)
92 | self.spinBox = QtWidgets.QSpinBox(parent=self.formLayoutWidget)
93 | self.spinBox.setObjectName("spinBox")
94 | self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox)
95 | self.spinBox_2 = QtWidgets.QSpinBox(parent=self.formLayoutWidget)
96 | self.spinBox_2.setObjectName("spinBox_2")
97 | self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox_2)
98 | self.label_9 = QtWidgets.QLabel(parent=self.centralwidget)
99 | self.label_9.setGeometry(QtCore.QRect(210, 110, 20, 20))
100 | self.label_9.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WhatsThisCursor))
101 | self.label_9.setStatusTip("qwweq")
102 | self.label_9.setText("")
103 | self.label_9.setPixmap(QtGui.QPixmap(".\\ui\\../images/avatar/tips.png"))
104 | self.label_9.setScaledContents(True)
105 | self.label_9.setObjectName("label_9")
106 | self.label_10 = QtWidgets.QLabel(parent=self.centralwidget)
107 | self.label_10.setGeometry(QtCore.QRect(210, 140, 20, 20))
108 | self.label_10.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.WhatsThisCursor))
109 | self.label_10.setText("")
110 | self.label_10.setPixmap(QtGui.QPixmap(".\\ui\\../images/avatar/tips.png"))
111 | self.label_10.setScaledContents(True)
112 | self.label_10.setObjectName("label_10")
113 | self.pushButton_3 = QtWidgets.QPushButton(parent=self.centralwidget)
114 | self.pushButton_3.setGeometry(QtCore.QRect(510, 115, 110, 40))
115 | self.pushButton_3.setObjectName("pushButton_3")
116 | self.label_11 = QtWidgets.QLabel(parent=self.centralwidget)
117 | self.label_11.setGeometry(QtCore.QRect(490, 58, 211, 40))
118 | self.label_11.setObjectName("label_11")
119 | self.formLayoutWidget_2 = QtWidgets.QWidget(parent=self.centralwidget)
120 | self.formLayoutWidget_2.setGeometry(QtCore.QRect(240, 110, 201, 51))
121 | self.formLayoutWidget_2.setObjectName("formLayoutWidget_2")
122 | self.formLayout_4 = QtWidgets.QFormLayout(self.formLayoutWidget_2)
123 | self.formLayout_4.setContentsMargins(20, 0, 0, 0)
124 | self.formLayout_4.setObjectName("formLayout_4")
125 | self.label_14 = QtWidgets.QLabel(parent=self.formLayoutWidget_2)
126 | self.label_14.setObjectName("label_14")
127 | self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_14)
128 | self.label_15 = QtWidgets.QLabel(parent=self.formLayoutWidget_2)
129 | self.label_15.setObjectName("label_15")
130 | self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.ItemRole.LabelRole, self.label_15)
131 | self.spinBox_5 = QtWidgets.QSpinBox(parent=self.formLayoutWidget_2)
132 | self.spinBox_5.setObjectName("spinBox_5")
133 | self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.ItemRole.FieldRole, self.spinBox_5)
134 | self.checkBox = QtWidgets.QCheckBox(parent=self.formLayoutWidget_2)
135 | self.checkBox.setText("")
136 | self.checkBox.setObjectName("checkBox")
137 | self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.ItemRole.FieldRole, self.checkBox)
138 | mainWindow.setCentralWidget(self.centralwidget)
139 | self.menubar = QtWidgets.QMenuBar(parent=mainWindow)
140 | self.menubar.setGeometry(QtCore.QRect(0, 0, 756, 23))
141 | self.menubar.setObjectName("menubar")
142 | self.menu = QtWidgets.QMenu(parent=self.menubar)
143 | self.menu.setObjectName("menu")
144 | mainWindow.setMenuBar(self.menubar)
145 | self.statusbar = QtWidgets.QStatusBar(parent=mainWindow)
146 | self.statusbar.setObjectName("statusbar")
147 | mainWindow.setStatusBar(self.statusbar)
148 | self.action = QtGui.QAction(parent=mainWindow)
149 | self.action.setObjectName("action")
150 | self.action_2 = QtGui.QAction(parent=mainWindow)
151 | self.action_2.setObjectName("action_2")
152 | self.menu.addAction(self.action)
153 | self.menu.addAction(self.action_2)
154 | self.menubar.addAction(self.menu.menuAction())
155 |
156 | self.retranslateUi(mainWindow)
157 | QtCore.QMetaObject.connectSlotsByName(mainWindow)
158 |
159 | def retranslateUi(self, mainWindow):
160 | _translate = QtCore.QCoreApplication.translate
161 | mainWindow.setWindowTitle(_translate("mainWindow", "PUBG通行证挂机工具"))
162 | self.label.setText(_translate("mainWindow", "语 言"))
163 | self.pushButton.setText(_translate("mainWindow", "刷新"))
164 | self.label_6.setText(_translate("mainWindow", "日志保存位置:"))
165 | self.pushButton_2.setText(_translate("mainWindow", "选择文件夹"))
166 | self.label_7.setText(_translate("mainWindow", "当前状态:"))
167 | self.label_8.setText(_translate("mainWindow", "未开启"))
168 | self.label_3.setText(_translate("mainWindow", "轮 询 延 迟:"))
169 | self.label_4.setText(_translate("mainWindow", "跳 伞 延 迟:"))
170 | self.pushButton_3.setText(_translate("mainWindow", "开始挂机"))
171 | self.label_11.setText(_translate("mainWindow", "未开启"))
172 | self.label_14.setText(_translate("mainWindow", "图 片 相 似 度:"))
173 | self.label_15.setText(_translate("mainWindow", "保 存 日 志:"))
174 | self.menu.setTitle(_translate("mainWindow", "关于"))
175 | self.action.setText(_translate("mainWindow", "关于软件"))
176 | self.action_2.setText(_translate("mainWindow", "日志"))
177 |
178 |
179 | if __name__ == "__main__":
180 | import sys
181 | app = QtWidgets.QApplication(sys.argv)
182 | mainWindow = QtWidgets.QMainWindow()
183 | ui = Ui_mainWindow()
184 | ui.setupUi(mainWindow)
185 | mainWindow.show()
186 | sys.exit(app.exec())
187 |
--------------------------------------------------------------------------------
/ui/main.ui:
--------------------------------------------------------------------------------
1 |
2 |
本软件纯是因为自己要玩,按键精灵不好用所以制作的工具,已测试一周bug,以及没有封号问题,本软件不会动游戏任何数据,仅通过图片/文字分析来实现目前功能。
\n" 47 | "如果你觉得做的不错,可以考虑请我喝杯咖啡!
\n" 49 | "啦啦啦啦德玛西亚
")) 31 | 32 | 33 | if __name__ == "__main__": 34 | import sys 35 | app = QtWidgets.QApplication(sys.argv) 36 | Form = QtWidgets.QWidget() 37 | ui = Ui_Form() 38 | ui.setupUi(Form) 39 | Form.show() 40 | sys.exit(app.exec()) 41 | -------------------------------------------------------------------------------- /upx-4.2.4-win64/COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 |